From d8e1ba0c8263e5d818d40dc8bc1bfcbcb07a7c7b Mon Sep 17 00:00:00 2001 From: Xanadu Date: Sat, 17 Jul 2010 03:28:20 +0200 Subject: Correctly redo file moves/renames from revs 8469, 8470, 8471, 8472, 8473. --HG-- branch : trunk rename : sql/realmd.sql => sql/auth_database.sql rename : sql/characters.sql => sql/character_database.sql rename : sql/CMakeLists.txt => sql/tools/CMakeLists.txt rename : sql/create_mysql.sql => sql/tools/create_mysql.sql rename : sql/drop_mysql.sql => sql/tools/drop_mysql.sql rename : sql/world.sql => sql/world_database.sql rename : src/server/game/CollisionDetection/BIH.cpp => src/server/game/CollisionDetection/BoundingIntervalHierarchy.cpp rename : src/server/game/CollisionDetection/BIH.h => src/server/game/CollisionDetection/BoundingIntervalHierarchy.h rename : src/server/game/Entities/Transport/Transports.cpp => src/server/game/Entities/Transport/Transport.cpp rename : src/server/game/Entities/Transport/Transports.h => src/server/game/Entities/Transport/Transport.h rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h rename : src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp => src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_epoch.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp => src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp => src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp => src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp => src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp => src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h => src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h rename : src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp => src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp => src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_aeonus.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp => src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_chrono_lord_deja.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp => src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_temporus.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h => src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.h rename : src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp => src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp => src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp => src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp => src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp => src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp => src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp rename : src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h => src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h rename : src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h => src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h rename : src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp => src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp rename : src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp => src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp rename : src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp => src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp rename : src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp => src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp rename : src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp => src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp rename : src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp => src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp rename : src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp => src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp rename : src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp => src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp rename : src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp => src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp rename : src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h => src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h rename : src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp => src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp rename : src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp => src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp rename : src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp => src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp rename : src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h => src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h rename : src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp => src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp rename : src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp => src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp rename : src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp => src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp rename : src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp => src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp rename : src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h => src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h rename : src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp => src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp rename : src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp => src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp rename : src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp => src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp rename : src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp => src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp rename : src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp => src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp rename : src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp => src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp rename : src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h => src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h rename : src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp => src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp rename : src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h => src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h rename : src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp => src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp rename : src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp => src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp rename : src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp => src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp rename : src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp => src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp rename : src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp => src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp rename : src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp => src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp rename : src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp => src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp rename : src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp => src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp rename : src/server/scripts/Northrend/TheNexus/nexus/nexus.h => src/server/scripts/Northrend/Nexus/Nexus/nexus.h rename : src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp => src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp rename : src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp => src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp rename : src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp => src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp rename : src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp => src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp rename : src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp => src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp rename : src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp => src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp rename : src/server/scripts/Northrend/TheNexus/oculus/oculus.h => src/server/scripts/Northrend/Nexus/Oculus/oculus.h rename : src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp => src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp => src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp => src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp => src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h => src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h rename : src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp => src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp => src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp => src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp => src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp => src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp rename : src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h => src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h rename : src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp => src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h => src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp => src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp rename : src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h => src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h rename : src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp => src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp rename : src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp => src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp rename : src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp => src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp rename : src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp => src/server/scripts/Outland/Auchindoun/ManaTombs/boss_pandemonius.cpp rename : src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp => src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp rename : src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp => src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp rename : src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp => src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp rename : src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h => src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h rename : src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp => src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp rename : src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp => src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp rename : src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp => src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp rename : src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp => src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp rename : src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp => src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp rename : src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h => src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h rename : src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp => src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp rename : src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp => src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp rename : src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp => src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp rename : src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp => src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp rename : src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp => src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp rename : src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp => src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp rename : src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp => src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp rename : src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h => src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h rename : src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp => src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp rename : src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp => src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp rename : src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp => src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_warlord_kalithresh.cpp rename : src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp => src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp rename : src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h => src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h rename : src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h => src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h rename : src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp => src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp rename : src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp => src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp rename : src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp => src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp rename : src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp => src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp rename : src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp => src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp rename : src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp => src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp rename : src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp => src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_watchkeeper_gargolmar.cpp rename : src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h => src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/hellfire_ramparts.h rename : src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp => src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/instance_hellfire_ramparts.cpp rename : src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp => src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp rename : src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp => src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp rename : src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h => src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h rename : src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp => src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp rename : src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp => src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp rename : src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp => src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp rename : src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp => src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp rename : src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h => src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h rename : src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp => src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp rename : src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp => src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp rename : src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp => src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp rename : src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp => src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp rename : src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp => src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp rename : src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp => src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp rename : src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h => src/server/scripts/Outland/TempestKeep/Eye/the_eye.h rename : src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp => src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_gyrokill.cpp rename : src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp => src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp rename : src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp => src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp rename : src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp => src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp rename : src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp => src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp rename : src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h => src/server/scripts/Outland/TempestKeep/Mechanar/mechanar.h rename : src/tools/vmap3_assembler/vmap_assembler.cpp => src/tools/vmap3_assembler/VMapAssembler.cpp --- src/server/game/CollisionDetection/BIH.cpp | 304 ---- src/server/game/CollisionDetection/BIH.h | 391 ----- .../BoundingIntervalHierarchy.cpp | 304 ++++ .../CollisionDetection/BoundingIntervalHierarchy.h | 391 +++++ src/server/game/Entities/Transport/Transport.cpp | 589 ++++++++ src/server/game/Entities/Transport/Transport.h | 108 ++ src/server/game/Entities/Transport/Transports.cpp | 589 -------- src/server/game/Entities/Transport/Transports.h | 108 -- .../BattleForMountHyjal/boss_anetheron.cpp | 309 ++++ .../BattleForMountHyjal/boss_archimonde.cpp | 635 +++++++++ .../BattleForMountHyjal/boss_azgalor.cpp | 285 ++++ .../BattleForMountHyjal/boss_kazrogal.cpp | 197 +++ .../BattleForMountHyjal/boss_rage_winterchill.cpp | 192 +++ .../CavernsOfTime/BattleForMountHyjal/hyjal.cpp | 247 ++++ .../CavernsOfTime/BattleForMountHyjal/hyjal.h | 38 + .../CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp | 1157 +++++++++++++++ .../CavernsOfTime/BattleForMountHyjal/hyjalAI.h | 248 ++++ .../BattleForMountHyjal/hyjal_trash.cpp | 1440 +++++++++++++++++++ .../BattleForMountHyjal/hyjal_trash.h | 35 + .../BattleForMountHyjal/instance_hyjal.cpp | 324 +++++ .../CullingOfStratholme/boss_epoch.cpp | 156 ++ .../CullingOfStratholme/boss_infinite.cpp | 88 ++ .../CullingOfStratholme/boss_mal_ganis.cpp | 262 ++++ .../CullingOfStratholme/boss_meathook.cpp | 140 ++ .../CullingOfStratholme/boss_salramm.cpp | 170 +++ .../CullingOfStratholme/culling_of_stratholme.cpp | 1210 ++++++++++++++++ .../CullingOfStratholme/culling_of_stratholme.h | 68 + .../instance_culling_of_stratholme.cpp | 244 ++++ .../CavernsOfTime/DarkPortal/boss_aeonus.cpp | 145 ++ .../DarkPortal/boss_chrono_lord_deja.cpp | 154 ++ .../CavernsOfTime/DarkPortal/boss_temporus.cpp | 152 ++ .../CavernsOfTime/DarkPortal/dark_portal.cpp | 404 ++++++ .../CavernsOfTime/DarkPortal/dark_portal.h | 35 + .../DarkPortal/instance_dark_portal.cpp | 346 +++++ .../boss_captain_skarloc.cpp | 152 ++ .../EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp | 138 ++ .../boss_leutenant_drake.cpp | 190 +++ .../instance_old_hillsbrad.cpp | 238 ++++ .../EscapeFromDurnholdeKeep/old_hillsbrad.cpp | 658 +++++++++ .../EscapeFromDurnholdeKeep/old_hillsbrad.h | 19 + .../culling_of_stratholme/boss_epoch.cpp | 156 -- .../culling_of_stratholme/boss_infinite.cpp | 88 -- .../culling_of_stratholme/boss_mal_ganis.cpp | 262 ---- .../culling_of_stratholme/boss_meathook.cpp | 140 -- .../culling_of_stratholme/boss_salramm.cpp | 170 --- .../culling_of_stratholme.cpp | 1210 ---------------- .../culling_of_stratholme/culling_of_stratholme.h | 68 - .../instance_culling_of_stratholme.cpp | 244 ---- .../CavernsOfTime/dark_portal/boss_aeonus.cpp | 145 -- .../dark_portal/boss_chrono_lord_deja.cpp | 154 -- .../CavernsOfTime/dark_portal/boss_temporus.cpp | 152 -- .../CavernsOfTime/dark_portal/dark_portal.cpp | 404 ------ .../CavernsOfTime/dark_portal/dark_portal.h | 35 - .../dark_portal/instance_dark_portal.cpp | 346 ----- .../CavernsOfTime/hyjal/boss_anetheron.cpp | 309 ---- .../CavernsOfTime/hyjal/boss_archimonde.cpp | 635 --------- .../Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp | 285 ---- .../Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp | 197 --- .../CavernsOfTime/hyjal/boss_rage_winterchill.cpp | 192 --- .../scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp | 247 ---- .../scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h | 38 - .../Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp | 1157 --------------- .../scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h | 248 ---- .../Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp | 1440 ------------------- .../Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h | 35 - .../CavernsOfTime/hyjal/instance_hyjal.cpp | 324 ----- .../old_hillsbrad/boss_captain_skarloc.cpp | 152 -- .../old_hillsbrad/boss_epoch_hunter.cpp | 138 -- .../old_hillsbrad/boss_leutenant_drake.cpp | 190 --- .../old_hillsbrad/instance_old_hillsbrad.cpp | 238 ---- .../CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp | 658 --------- .../CavernsOfTime/old_hillsbrad/old_hillsbrad.h | 19 - .../Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h | 38 + .../AzjolNerub/AzjolNerub/boss_anubarak.cpp | 360 +++++ .../AzjolNerub/AzjolNerub/boss_hadronox.cpp | 206 +++ .../AzjolNerub/boss_krikthir_the_gatewatcher.cpp | 553 ++++++++ .../AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp | 215 +++ .../Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h | 38 - .../AzjolNerub/azjol_nerub/boss_anubarak.cpp | 360 ----- .../AzjolNerub/azjol_nerub/boss_hadronox.cpp | 206 --- .../azjol_nerub/boss_krikthir_the_gatewatcher.cpp | 553 -------- .../azjol_nerub/instance_azjol_nerub.cpp | 215 --- .../TrialOfTheChampion/boss_argent_challenge.cpp | 512 +++++++ .../TrialOfTheChampion/boss_black_knight.cpp | 373 +++++ .../TrialOfTheChampion/boss_grand_champions.cpp | 993 +++++++++++++ .../instance_trial_of_the_champion.cpp | 340 +++++ .../TrialOfTheChampion/trial_of_the_champion.cpp | 512 +++++++ .../TrialOfTheChampion/trial_of_the_champion.h | 115 ++ .../boss_argent_challenge.cpp | 512 ------- .../trial_of_the_champion/boss_black_knight.cpp | 373 ----- .../trial_of_the_champion/boss_grand_champions.cpp | 993 ------------- .../instance_trial_of_the_champion.cpp | 340 ----- .../trial_of_the_champion.cpp | 512 ------- .../trial_of_the_champion/trial_of_the_champion.h | 115 -- .../FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp | 263 ++++ .../ForgeOfSouls/boss_devourer_of_souls.cpp | 349 +++++ .../FrozenHalls/ForgeOfSouls/forge_of_souls.cpp | 899 ++++++++++++ .../FrozenHalls/ForgeOfSouls/forge_of_souls.h | 52 + .../ForgeOfSouls/instance_forge_of_souls.cpp | 168 +++ .../FrozenHalls/HallsOfReflection/boss_falric.cpp | 142 ++ .../FrozenHalls/HallsOfReflection/boss_marwyn.cpp | 133 ++ .../HallsOfReflection/halls_of_reflection.cpp | 1022 +++++++++++++ .../HallsOfReflection/halls_of_reflection.h | 156 ++ .../instance_halls_of_reflection.cpp | 431 ++++++ .../PitOfSaron/boss_forgemaster_garfrost.cpp | 209 +++ .../FrozenHalls/PitOfSaron/boss_krickandick.cpp | 482 +++++++ .../PitOfSaron/boss_scourgelord_tyrannus.cpp | 273 ++++ .../PitOfSaron/instance_pit_of_saron.cpp | 236 +++ .../FrozenHalls/PitOfSaron/pit_of_saron.cpp | 1101 ++++++++++++++ .../FrozenHalls/PitOfSaron/pit_of_saron.h | 63 + .../FrozenHalls/forge_of_souls/boss_bronjahm.cpp | 263 ---- .../forge_of_souls/boss_devourer_of_souls.cpp | 349 ----- .../FrozenHalls/forge_of_souls/forge_of_souls.cpp | 899 ------------ .../FrozenHalls/forge_of_souls/forge_of_souls.h | 52 - .../forge_of_souls/instance_forge_of_souls.cpp | 168 --- .../halls_of_reflection/boss_falric.cpp | 142 -- .../halls_of_reflection/boss_marwyn.cpp | 133 -- .../halls_of_reflection/halls_of_reflection.cpp | 1022 ------------- .../halls_of_reflection/halls_of_reflection.h | 156 -- .../instance_halls_of_reflection.cpp | 431 ------ .../pit_of_saron/boss_forgemaster_garfrost.cpp | 209 --- .../FrozenHalls/pit_of_saron/boss_krickandick.cpp | 482 ------- .../pit_of_saron/boss_scourgelord_tyrannus.cpp | 273 ---- .../pit_of_saron/instance_pit_of_saron.cpp | 236 --- .../FrozenHalls/pit_of_saron/pit_of_saron.cpp | 1101 -------------- .../FrozenHalls/pit_of_saron/pit_of_saron.h | 63 - .../Northrend/Nexus/EyeOfEternity/boss_malygos.cpp | 175 +++ .../Nexus/EyeOfEternity/eye_of_eternity.h | 4 + .../EyeOfEternity/instance_eye_of_eternity.cpp | 21 + .../Northrend/Nexus/Nexus/boss_anomalus.cpp | 253 ++++ .../Northrend/Nexus/Nexus/boss_keristrasza.cpp | 247 ++++ .../Northrend/Nexus/Nexus/boss_magus_telestra.cpp | 327 +++++ .../scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp | 298 ++++ .../Northrend/Nexus/Nexus/commander_kolurg.cpp | 58 + .../Northrend/Nexus/Nexus/commander_stoutbeard.cpp | 64 + .../Northrend/Nexus/Nexus/instance_nexus.cpp | 259 ++++ src/server/scripts/Northrend/Nexus/Nexus/nexus.h | 35 + .../scripts/Northrend/Nexus/Oculus/boss_drakos.cpp | 218 +++ .../scripts/Northrend/Nexus/Oculus/boss_eregos.cpp | 129 ++ .../scripts/Northrend/Nexus/Oculus/boss_urom.cpp | 356 +++++ .../scripts/Northrend/Nexus/Oculus/boss_varos.cpp | 105 ++ .../Northrend/Nexus/Oculus/instance_oculus.cpp | 205 +++ .../scripts/Northrend/Nexus/Oculus/oculus.cpp | 174 +++ src/server/scripts/Northrend/Nexus/Oculus/oculus.h | 34 + .../TheNexus/eye_of_eternity/boss_malygos.cpp | 175 --- .../TheNexus/eye_of_eternity/eye_of_eternity.h | 4 - .../eye_of_eternity/instance_eye_of_eternity.cpp | 21 - .../Northrend/TheNexus/nexus/boss_anomalus.cpp | 253 ---- .../Northrend/TheNexus/nexus/boss_keristrasza.cpp | 247 ---- .../TheNexus/nexus/boss_magus_telestra.cpp | 327 ----- .../Northrend/TheNexus/nexus/boss_ormorok.cpp | 298 ---- .../Northrend/TheNexus/nexus/commander_kolurg.cpp | 58 - .../TheNexus/nexus/commander_stoutbeard.cpp | 64 - .../Northrend/TheNexus/nexus/instance_nexus.cpp | 259 ---- .../scripts/Northrend/TheNexus/nexus/nexus.h | 35 - .../Northrend/TheNexus/oculus/boss_drakos.cpp | 218 --- .../Northrend/TheNexus/oculus/boss_eregos.cpp | 129 -- .../Northrend/TheNexus/oculus/boss_urom.cpp | 356 ----- .../Northrend/TheNexus/oculus/boss_varos.cpp | 105 -- .../Northrend/TheNexus/oculus/instance_oculus.cpp | 205 --- .../scripts/Northrend/TheNexus/oculus/oculus.cpp | 174 --- .../scripts/Northrend/TheNexus/oculus/oculus.h | 34 - .../Ulduar/HallsOfLightning/boss_bjarngrim.cpp | 432 ++++++ .../Ulduar/HallsOfLightning/boss_ionar.cpp | 388 +++++ .../Ulduar/HallsOfLightning/boss_loken.cpp | 222 +++ .../Ulduar/HallsOfLightning/boss_volkhan.cpp | 478 +++++++ .../Ulduar/HallsOfLightning/halls_of_lightning.h | 34 + .../instance_halls_of_lightning.cpp | 248 ++++ .../Ulduar/HallsOfStone/boss_krystallus.cpp | 148 ++ .../Ulduar/HallsOfStone/boss_maiden_of_grief.cpp | 166 +++ .../Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp | 300 ++++ .../Ulduar/HallsOfStone/halls_of_stone.cpp | 724 ++++++++++ .../Northrend/Ulduar/HallsOfStone/halls_of_stone.h | 48 + .../HallsOfStone/instance_halls_of_stone.cpp | 254 ++++ .../Ulduar/halls_of_lightning/boss_bjarngrim.cpp | 432 ------ .../Ulduar/halls_of_lightning/boss_ionar.cpp | 388 ----- .../Ulduar/halls_of_lightning/boss_loken.cpp | 222 --- .../Ulduar/halls_of_lightning/boss_volkhan.cpp | 478 ------- .../Ulduar/halls_of_lightning/halls_of_lightning.h | 34 - .../instance_halls_of_lightning.cpp | 248 ---- .../Ulduar/halls_of_stone/boss_krystallus.cpp | 148 -- .../Ulduar/halls_of_stone/boss_maiden_of_grief.cpp | 166 --- .../Ulduar/halls_of_stone/boss_sjonnir.cpp | 300 ---- .../Ulduar/halls_of_stone/halls_of_stone.cpp | 724 ---------- .../Ulduar/halls_of_stone/halls_of_stone.h | 48 - .../halls_of_stone/instance_halls_of_stone.cpp | 254 ---- .../UtgardeKeep/boss_ingvar_the_plunderer.cpp | 442 ++++++ .../UtgardeKeep/UtgardeKeep/boss_keleseth.cpp | 361 +++++ .../UtgardeKeep/boss_skarvald_dalronn.cpp | 389 +++++ .../UtgardeKeep/instance_utgarde_keep.cpp | 312 ++++ .../UtgardeKeep/UtgardeKeep/utgarde_keep.cpp | 160 +++ .../UtgardeKeep/UtgardeKeep/utgarde_keep.h | 35 + .../UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp | 830 +++++++++++ .../UtgardeKeep/UtgardePinnacle/boss_skadi.cpp | 477 +++++++ .../UtgardeKeep/UtgardePinnacle/boss_svala.cpp | 408 ++++++ .../UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp | 367 +++++ .../UtgardePinnacle/instance_pinnacle.cpp | 241 ++++ .../UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h | 42 + .../utgarde_keep/boss_ingvar_the_plunderer.cpp | 442 ------ .../UtgardeKeep/utgarde_keep/boss_keleseth.cpp | 361 ----- .../utgarde_keep/boss_skarvald_dalronn.cpp | 389 ----- .../utgarde_keep/instance_utgarde_keep.cpp | 312 ---- .../UtgardeKeep/utgarde_keep/utgarde_keep.cpp | 160 --- .../UtgardeKeep/utgarde_keep/utgarde_keep.h | 35 - .../UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp | 830 ----------- .../UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp | 477 ------- .../UtgardeKeep/utgarde_pinnacle/boss_svala.cpp | 408 ------ .../UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp | 367 ----- .../utgarde_pinnacle/instance_pinnacle.cpp | 241 ---- .../utgarde_pinnacle/utgarde_pinnacle.h | 42 - .../AuchenaiCrypts/boss_exarch_maladaar.cpp | 348 +++++ .../boss_shirrak_the_dead_watcher.cpp | 211 +++ .../ManaTombs/boss_nexusprince_shaffar.cpp | 358 +++++ .../Auchindoun/ManaTombs/boss_pandemonius.cpp | 126 ++ .../SethekkHalls/boss_darkweaver_syth.cpp | 414 ++++++ .../SethekkHalls/boss_tailonking_ikiss.cpp | 213 +++ .../SethekkHalls/instance_sethekk_halls.cpp | 91 ++ .../Auchindoun/SethekkHalls/sethekk_halls.h | 14 + .../ShadowLabyrinth/boss_ambassador_hellmaw.cpp | 206 +++ .../boss_blackheart_the_inciter.cpp | 169 +++ .../ShadowLabyrinth/boss_grandmaster_vorpil.cpp | 313 ++++ .../Auchindoun/ShadowLabyrinth/boss_murmur.cpp | 205 +++ .../ShadowLabyrinth/instance_shadow_labyrinth.cpp | 227 +++ .../Auchindoun/ShadowLabyrinth/shadow_labyrinth.h | 15 + .../auchenai_crypts/boss_exarch_maladaar.cpp | 348 ----- .../boss_shirrak_the_dead_watcher.cpp | 211 --- .../mana_tombs/boss_nexusprince_shaffar.cpp | 358 ----- .../Auchindoun/mana_tombs/boss_pandemonius.cpp | 126 -- .../sethekk_halls/boss_darkweaver_syth.cpp | 414 ------ .../sethekk_halls/boss_tailonking_ikiss.cpp | 213 --- .../sethekk_halls/instance_sethekk_halls.cpp | 91 -- .../Auchindoun/sethekk_halls/sethekk_halls.h | 14 - .../shadow_labyrinth/boss_ambassador_hellmaw.cpp | 206 --- .../boss_blackheart_the_inciter.cpp | 169 --- .../shadow_labyrinth/boss_grandmaster_vorpil.cpp | 313 ---- .../Auchindoun/shadow_labyrinth/boss_murmur.cpp | 205 --- .../shadow_labyrinth/instance_shadow_labyrinth.cpp | 227 --- .../Auchindoun/shadow_labyrinth/shadow_labyrinth.h | 15 - .../SerpentShrine/boss_fathomlord_karathress.cpp | 746 ++++++++++ .../SerpentShrine/boss_hydross_the_unstable.cpp | 379 +++++ .../SerpentShrine/boss_lady_vashj.cpp | 1039 ++++++++++++++ .../SerpentShrine/boss_leotheras_the_blind.cpp | 787 ++++++++++ .../SerpentShrine/boss_lurker_below.cpp | 458 ++++++ .../SerpentShrine/boss_morogrim_tidewalker.cpp | 369 +++++ .../SerpentShrine/instance_serpent_shrine.cpp | 398 ++++++ .../SerpentShrine/serpent_shrine.h | 45 + .../SteamVault/boss_hydromancer_thespia.cpp | 187 +++ .../SteamVault/boss_mekgineer_steamrigger.cpp | 264 ++++ .../SteamVault/boss_warlord_kalithresh.cpp | 204 +++ .../SteamVault/instance_steam_vault.cpp | 231 +++ .../CoilfangReservoir/SteamVault/steam_vault.h | 17 + .../serpent_shrine/boss_fathomlord_karathress.cpp | 746 ---------- .../serpent_shrine/boss_hydross_the_unstable.cpp | 379 ----- .../serpent_shrine/boss_lady_vashj.cpp | 1039 -------------- .../serpent_shrine/boss_leotheras_the_blind.cpp | 787 ---------- .../serpent_shrine/boss_lurker_below.cpp | 458 ------ .../serpent_shrine/boss_morogrim_tidewalker.cpp | 369 ----- .../serpent_shrine/instance_serpent_shrine.cpp | 398 ------ .../serpent_shrine/serpent_shrine.h | 45 - .../steam_vault/boss_hydromancer_thespia.cpp | 187 --- .../steam_vault/boss_mekgineer_steamrigger.cpp | 264 ---- .../steam_vault/boss_warlord_kalithresh.cpp | 204 --- .../steam_vault/instance_steam_vault.cpp | 231 --- .../CoilfangReservoir/steam_vault/steam_vault.h | 17 - .../HellfireCitadel/BloodFurnace/blood_furnace.h | 29 + .../HellfireCitadel/BloodFurnace/boss_broggok.cpp | 131 ++ .../BloodFurnace/boss_kelidan_the_breaker.cpp | 356 +++++ .../BloodFurnace/boss_the_maker.cpp | 152 ++ .../BloodFurnace/instance_blood_furnace.cpp | 232 +++ .../HellfireRamparts/boss_omor_the_unscarred.cpp | 206 +++ .../HellfireRamparts/boss_vazruden_the_herald.cpp | 467 ++++++ .../boss_watchkeeper_gargolmar.cpp | 156 ++ .../HellfireRamparts/hellfire_ramparts.h | 16 + .../instance_hellfire_ramparts.cpp | 84 ++ .../MagtheridonsLair/boss_magtheridon.cpp | 570 ++++++++ .../instance_magtheridons_lair.cpp | 254 ++++ .../MagtheridonsLair/magtheridons_lair.h | 14 + .../ShatteredHalls/boss_nethekurse.cpp | 396 ++++++ .../ShatteredHalls/boss_warbringer_omrogg.cpp | 404 ++++++ .../boss_warchief_kargath_bladefist.cpp | 288 ++++ .../ShatteredHalls/instance_shattered_halls.cpp | 114 ++ .../ShatteredHalls/shattered_halls.h | 14 + .../HellfireCitadel/blood_furnace/blood_furnace.h | 29 - .../HellfireCitadel/blood_furnace/boss_broggok.cpp | 131 -- .../blood_furnace/boss_kelidan_the_breaker.cpp | 356 ----- .../blood_furnace/boss_the_maker.cpp | 152 -- .../blood_furnace/instance_blood_furnace.cpp | 232 --- .../hellfire_ramparts/boss_omor_the_unscarred.cpp | 206 --- .../hellfire_ramparts/boss_vazruden_the_herald.cpp | 467 ------ .../boss_watchkeeper_gargolmar.cpp | 156 -- .../hellfire_ramparts/hellfire_ramparts.h | 16 - .../instance_hellfire_ramparts.cpp | 84 -- .../magtheridons_lair/boss_magtheridon.cpp | 570 -------- .../instance_magtheridons_lair.cpp | 254 ---- .../magtheridons_lair/magtheridons_lair.h | 14 - .../shattered_halls/boss_nethekurse.cpp | 396 ------ .../shattered_halls/boss_warbringer_omrogg.cpp | 404 ------ .../boss_warchief_kargath_bladefist.cpp | 288 ---- .../shattered_halls/instance_shattered_halls.cpp | 114 -- .../shattered_halls/shattered_halls.h | 14 - .../scripts/Outland/TempestKeep/Eye/boss_alar.cpp | 523 +++++++ .../Outland/TempestKeep/Eye/boss_astromancer.cpp | 466 ++++++ .../Outland/TempestKeep/Eye/boss_kaelthas.cpp | 1498 ++++++++++++++++++++ .../Outland/TempestKeep/Eye/boss_void_reaver.cpp | 179 +++ .../Outland/TempestKeep/Eye/instance_the_eye.cpp | 176 +++ .../scripts/Outland/TempestKeep/Eye/the_eye.cpp | 98 ++ .../scripts/Outland/TempestKeep/Eye/the_eye.h | 20 + .../Mechanar/boss_gatewatcher_gyrokill.cpp | 39 + .../Mechanar/boss_gatewatcher_ironhand.cpp | 130 ++ .../Mechanar/boss_nethermancer_sepethrea.cpp | 245 ++++ .../Mechanar/boss_pathaleon_the_calculator.cpp | 246 ++++ .../TempestKeep/Mechanar/instance_mechanar.cpp | 86 ++ .../Outland/TempestKeep/Mechanar/mechanar.h | 6 + .../Outland/TempestKeep/the_eye/boss_alar.cpp | 523 ------- .../TempestKeep/the_eye/boss_astromancer.cpp | 466 ------ .../Outland/TempestKeep/the_eye/boss_kaelthas.cpp | 1498 -------------------- .../TempestKeep/the_eye/boss_void_reaver.cpp | 179 --- .../TempestKeep/the_eye/instance_the_eye.cpp | 176 --- .../Outland/TempestKeep/the_eye/the_eye.cpp | 98 -- .../scripts/Outland/TempestKeep/the_eye/the_eye.h | 20 - .../the_mechanar/boss_gatewatcher_gyrokill.cpp | 39 - .../the_mechanar/boss_gatewatcher_ironhand.cpp | 130 -- .../the_mechanar/boss_nethermancer_sepethrea.cpp | 245 ---- .../the_mechanar/boss_pathaleon_the_calculator.cpp | 246 ---- .../TempestKeep/the_mechanar/instance_mechanar.cpp | 86 -- .../Outland/TempestKeep/the_mechanar/mechanar.h | 6 - src/tools/vmap3_assembler/VMapAssembler.cpp | 120 ++ src/tools/vmap3_assembler/vmap_assembler.cpp | 120 -- 328 files changed, 47881 insertions(+), 47881 deletions(-) delete mode 100644 src/server/game/CollisionDetection/BIH.cpp delete mode 100644 src/server/game/CollisionDetection/BIH.h create mode 100644 src/server/game/CollisionDetection/BoundingIntervalHierarchy.cpp create mode 100644 src/server/game/CollisionDetection/BoundingIntervalHierarchy.h create mode 100644 src/server/game/Entities/Transport/Transport.cpp create mode 100644 src/server/game/Entities/Transport/Transport.h delete mode 100644 src/server/game/Entities/Transport/Transports.cpp delete mode 100644 src/server/game/Entities/Transport/Transports.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_epoch.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_aeonus.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_chrono_lord_deja.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_temporus.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.h create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp create mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp delete mode 100644 src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h create mode 100644 src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h create mode 100644 src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp create mode 100644 src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp delete mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h delete mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp delete mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp delete mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp delete mode 100644 src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp create mode 100644 src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h delete mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp delete mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp delete mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp delete mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp delete mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp delete mode 100644 src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h create mode 100644 src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h create mode 100644 src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h create mode 100644 src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp create mode 100644 src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h delete mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h delete mode 100644 src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h delete mode 100644 src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp delete mode 100644 src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h create mode 100644 src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp create mode 100644 src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h create mode 100644 src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Nexus/nexus.h create mode 100644 src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp create mode 100644 src/server/scripts/Northrend/Nexus/Oculus/oculus.h delete mode 100644 src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h delete mode 100644 src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/nexus/nexus.h delete mode 100644 src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp delete mode 100644 src/server/scripts/Northrend/TheNexus/oculus/oculus.h create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h create mode 100644 src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h delete mode 100644 src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp create mode 100644 src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp delete mode 100644 src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h create mode 100644 src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/ManaTombs/boss_pandemonius.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h create mode 100644 src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp create mode 100644 src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h delete mode 100644 src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h delete mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp delete mode 100644 src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_warlord_kalithresh.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp create mode 100644 src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp delete mode 100644 src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h create mode 100644 src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h create mode 100644 src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_watchkeeper_gargolmar.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/hellfire_ramparts.h create mode 100644 src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/instance_hellfire_ramparts.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h create mode 100644 src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp create mode 100644 src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h delete mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h delete mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h delete mode 100644 src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h delete mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp delete mode 100644 src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h create mode 100644 src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Eye/the_eye.h create mode 100644 src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_gyrokill.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp create mode 100644 src/server/scripts/Outland/TempestKeep/Mechanar/mechanar.h delete mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h delete mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp delete mode 100644 src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h create mode 100644 src/tools/vmap3_assembler/VMapAssembler.cpp delete mode 100644 src/tools/vmap3_assembler/vmap_assembler.cpp (limited to 'src') diff --git a/src/server/game/CollisionDetection/BIH.cpp b/src/server/game/CollisionDetection/BIH.cpp deleted file mode 100644 index 4bd6b3c701e..00000000000 --- a/src/server/game/CollisionDetection/BIH.cpp +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "BIH.h" - -void BIH::buildHierarchy(std::vector &tempTree, buildData &dat, BuildStats &stats) -{ - // create space for the first node - tempTree.push_back(3 << 30); // dummy leaf - tempTree.insert(tempTree.end(), 2, 0); - //tempTree.add(0); - - // seed bbox - AABound gridBox = { bounds.low(), bounds.high() }; - AABound nodeBox = gridBox; - // seed subdivide function - subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats); -} - -void BIH::subdivide(int left, int right, std::vector &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats) -{ - if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE) - { - // write leaf node - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - // calculate extents - int axis = -1, prevAxis, rightOrig; - float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan(); - float split = G3D::fnan(), prevSplit; - bool wasLeft = true; - while (true) - { - prevAxis = axis; - prevSplit = split; - // perform quick consistency checks - Vector3 d( gridBox.hi - gridBox.lo ); - if (d.x < 0 || d.y < 0 || d.z < 0) - throw std::logic_error("negative node extents"); - for (int i = 0; i < 3; i++) - { - if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i]) - { - //UI.printError(Module.ACCEL, "Reached tree area in error - discarding node with: %d objects", right - left + 1); - throw std::logic_error("invalid node overlap"); - } - } - // find longest axis - axis = d.primaryAxis(); - split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]); - // partition L/R subsets - clipL = -G3D::inf(); - clipR = G3D::inf(); - rightOrig = right; // save this for later - float nodeL = G3D::inf(); - float nodeR = -G3D::inf(); - for (int i = left; i <= right;) - { - int obj = dat.indices[i]; - float minb = dat.primBound[obj].low()[axis]; - float maxb = dat.primBound[obj].high()[axis]; - float center = (minb + maxb) * 0.5f; - if (center <= split) - { - // stay left - i++; - if (clipL < maxb) - clipL = maxb; - } - else - { - // move to the right most - int t = dat.indices[i]; - dat.indices[i] = dat.indices[right]; - dat.indices[right] = t; - right--; - if (clipR > minb) - clipR = minb; - } - nodeL = std::min(nodeL, minb); - nodeR = std::max(nodeR, maxb); - } - // check for empty space - if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis]) - { - float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis]; - float nodeNewW = nodeR - nodeL; - // node box is too big compare to space occupied by primitives? - if (1.3f * nodeNewW < nodeBoxW) - { - stats.updateBVH2(); - int nextIndex = tempTree.size(); - // allocate child - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - // write bvh2 clip node - stats.updateInner(); - tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(nodeL); - tempTree[nodeIndex + 2] = floatToRawIntBits(nodeR); - // update nodebox and recurse - nodeBox.lo[axis] = nodeL; - nodeBox.hi[axis] = nodeR; - subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats); - return; - } - } - // ensure we are making progress in the subdivision - if (right == rightOrig) - { - // all left - if (prevAxis == axis && prevSplit == split) { - // we are stuck here - create a leaf - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - if (clipL <= split) { - // keep looping on left half - gridBox.hi[axis] = split; - prevClip = clipL; - wasLeft = true; - continue; - } - gridBox.hi[axis] = split; - prevClip = G3D::fnan(); - } - else if (left > right) - { - // all right - if (prevAxis == axis && prevSplit == split) { - // we are stuck here - create a leaf - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - right = rightOrig; - if (clipR >= split) { - // keep looping on right half - gridBox.lo[axis] = split; - prevClip = clipR; - wasLeft = false; - continue; - } - gridBox.lo[axis] = split; - prevClip = G3D::fnan(); - } - else - { - // we are actually splitting stuff - if (prevAxis != -1 && !isnan(prevClip)) - { - // second time through - lets create the previous split - // since it produced empty space - int nextIndex = tempTree.size(); - // allocate child node - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - if (wasLeft) { - // create a node with a left child - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip); - tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf()); - } else { - // create a node with a right child - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3); - tempTree[nodeIndex + 1] = floatToRawIntBits(-G3D::inf()); - tempTree[nodeIndex + 2] = floatToRawIntBits(prevClip); - } - // count stats for the unused leaf - depth++; - stats.updateLeaf(depth, 0); - // now we keep going as we are, with a new nodeIndex: - nodeIndex = nextIndex; - } - break; - } - } - // compute index of child nodes - int nextIndex = tempTree.size(); - // allocate left node - int nl = right - left + 1; - int nr = rightOrig - (right + 1) + 1; - if (nl > 0) { - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - } else - nextIndex -= 3; - // allocate right node - if (nr > 0) { - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - } - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (axis << 30) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(clipL); - tempTree[nodeIndex + 2] = floatToRawIntBits(clipR); - // prepare L/R child boxes - AABound gridBoxL(gridBox), gridBoxR(gridBox); - AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox); - gridBoxL.hi[axis] = gridBoxR.lo[axis] = split; - nodeBoxL.hi[axis] = clipL; - nodeBoxR.lo[axis] = clipR; - // recurse - if (nl > 0) - subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats); - else - stats.updateLeaf(depth + 1, 0); - if (nr > 0) - subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats); - else - stats.updateLeaf(depth + 1, 0); -} - -bool BIH::writeToFile(FILE *wf) const -{ - uint32 treeSize = tree.size(); - uint32 check=0, count=0; - check += fwrite(&bounds.low(), sizeof(float), 3, wf); - check += fwrite(&bounds.high(), sizeof(float), 3, wf); - check += fwrite(&treeSize, sizeof(uint32), 1, wf); - check += fwrite(&tree[0], sizeof(uint32), treeSize, wf); - count = objects.size(); - check += fwrite(&count, sizeof(uint32), 1, wf); - check += fwrite(&objects[0], sizeof(uint32), count, wf); - return check == (3 + 3 + 2 + treeSize + count); -} - -bool BIH::readFromFile(FILE *rf) -{ - uint32 treeSize; - Vector3 lo, hi; - uint32 check=0, count=0; - check += fread(&lo, sizeof(float), 3, rf); - check += fread(&hi, sizeof(float), 3, rf); - bounds = AABox(lo, hi); - check += fread(&treeSize, sizeof(uint32), 1, rf); - tree.resize(treeSize); - check += fread(&tree[0], sizeof(uint32), treeSize, rf); - check += fread(&count, sizeof(uint32), 1, rf); - objects.resize(count); // = new uint32[nObjects]; - check += fread(&objects[0], sizeof(uint32), count, rf); - return check == (3 + 3 + 2 + treeSize + count); -} - -void BIH::BuildStats::updateLeaf(int depth, int n) -{ - numLeaves++; - minDepth = std::min(depth, minDepth); - maxDepth = std::max(depth, maxDepth); - sumDepth += depth; - minObjects = std::min(n, minObjects); - maxObjects = std::max(n, maxObjects); - sumObjects += n; - int nl = std::min(n, 5); - ++numLeavesN[nl]; -} - -void BIH::BuildStats::printStats() -{ - printf("Tree stats:\n"); - printf(" * Nodes: %d\n", numNodes); - printf(" * Leaves: %d\n", numLeaves); - printf(" * Objects: min %d\n", minObjects); - printf(" avg %.2f\n", (float) sumObjects / numLeaves); - printf(" avg(n>0) %.2f\n", (float) sumObjects / (numLeaves - numLeavesN[0])); - printf(" max %d\n", maxObjects); - printf(" * Depth: min %d\n", minDepth); - printf(" avg %.2f\n", (float) sumDepth / numLeaves); - printf(" max %d\n", maxDepth); - printf(" * Leaves w/: N=0 %3d%%\n", 100 * numLeavesN[0] / numLeaves); - printf(" N=1 %3d%%\n", 100 * numLeavesN[1] / numLeaves); - printf(" N=2 %3d%%\n", 100 * numLeavesN[2] / numLeaves); - printf(" N=3 %3d%%\n", 100 * numLeavesN[3] / numLeaves); - printf(" N=4 %3d%%\n", 100 * numLeavesN[4] / numLeaves); - printf(" N>4 %3d%%\n", 100 * numLeavesN[5] / numLeaves); - printf(" * BVH2 nodes: %d (%3d%%)\n", numBVH2, 100 * numBVH2 / (numNodes + numLeaves - 2 * numBVH2)); -} diff --git a/src/server/game/CollisionDetection/BIH.h b/src/server/game/CollisionDetection/BIH.h deleted file mode 100644 index 15ae90c23eb..00000000000 --- a/src/server/game/CollisionDetection/BIH.h +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright (C) 2005-2010 MaNGOS - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _BIH_H -#define _BIH_H - -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#define MAX_STACK_SIZE 64 - -#ifdef _MSC_VER - #define isnan(x) _isnan(x) -#endif - -using G3D::Vector3; -using G3D::AABox; -using G3D::Ray; - -static inline uint32 floatToRawIntBits(float f) -{ - union - { - uint32 ival; - float fval; - } temp; - temp.fval=f; - return temp.ival; -} - -static inline float intBitsToFloat(uint32 i) -{ - union - { - uint32 ival; - float fval; - } temp; - temp.ival=i; - return temp.fval; -} - -struct AABound -{ - Vector3 lo, hi; -}; - -/** Bounding Interval Hierarchy Class. - Building and Ray-Intersection functions based on BIH from - Sunflow, a Java Raytracer, released under MIT/X11 License - http://sunflow.sourceforge.net/ - Copyright (c) 2003-2007 Christopher Kulla -*/ - -class BIH -{ - public: - BIH() {}; - template< class T, class BoundsFunc > - void build(const std::vector &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false) - { - if(primitives.size() == 0) - return; - buildData dat; - dat.maxPrims = leafSize; - dat.numPrims = primitives.size(); - dat.indices = new uint32[dat.numPrims]; - dat.primBound = new AABox[dat.numPrims]; - getBounds(primitives[0], bounds); - for (uint32 i=0; i tempTree; - BuildStats stats; - buildHierarchy(tempTree, dat, stats); - if (printStats) - stats.printStats(); - - objects.resize(dat.numPrims); - for (uint32 i=0; i - void intersectRay(const Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const - { - float intervalMin = 0.f; - float intervalMax = maxDist; - Vector3 org = r.origin(); - Vector3 dir = r.direction(); - Vector3 invDir; - float t1, t2; - for(int i=0; i<3; ++i) - { - invDir[i] = 1.f / dir[i]; - t1 = (bounds.low()[i] - org[i]) * invDir[i]; - t2 = (bounds.high()[i] - org[i]) * invDir[i]; - if (invDir[i] > 0) { - if (t1 > intervalMin) - intervalMin = t1; - if (t2 < intervalMax) - intervalMax = t2; - } else { - if (t2 > intervalMin) - intervalMin = t2; - if (t1 < intervalMax) - intervalMax = t1; - } - if (intervalMin > intervalMax) - return; - } - - uint32 offsetFront[3]; - uint32 offsetBack[3]; - uint32 offsetFront3[3]; - uint32 offsetBack3[3]; - // compute custom offsets from direction sign bit - - for(int i=0; i<3; ++i) - { - offsetFront[i] = floatToRawIntBits(dir[i]) >> 31; - offsetBack[i] = offsetFront[i] ^ 1; - offsetFront3[i] = offsetFront[i] * 3; - offsetBack3[i] = offsetBack[i] * 3; - - // avoid always adding 1 during the inner loop - ++offsetFront[i]; - ++offsetBack[i]; - } - - StackNode stack[MAX_STACK_SIZE]; - int stackPos = 0; - int node = 0; - - while (true) { - while (true) - { - uint32 tn = tree[node]; - uint32 axis = (tn & (3 << 30)) >> 30; - bool BVH2 = tn & (1 << 29); - int offset = tn & ~(7 << 29); - if (!BVH2) - { - if (axis < 3) - { - // "normal" interior node - float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; - float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; - // ray passes between clip zones - if (tf < intervalMin && tb > intervalMax) - break; - int back = offset + offsetBack3[axis]; - node = back; - // ray passes through far node only - if (tf < intervalMin) { - intervalMin = (tb >= intervalMin) ? tb : intervalMin; - continue; - } - node = offset + offsetFront3[axis]; // front - // ray passes through near node only - if (tb > intervalMax) { - intervalMax = (tf <= intervalMax) ? tf : intervalMax; - continue; - } - // ray passes through both nodes - // push back node - stack[stackPos].node = back; - stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin; - stack[stackPos].tfar = intervalMax; - stackPos++; - // update ray interval for front node - intervalMax = (tf <= intervalMax) ? tf : intervalMax; - continue; - } - else - { - // leaf - test some objects - int n = tree[node + 1]; - while (n > 0) { - bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirst); - if(stopAtFirst && hit) return; - --n; - ++offset; - } - break; - } - } - else - { - if (axis>2) - return; // should not happen - float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; - float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; - node = offset; - intervalMin = (tf >= intervalMin) ? tf : intervalMin; - intervalMax = (tb <= intervalMax) ? tb : intervalMax; - if (intervalMin > intervalMax) - break; - continue; - } - } // traversal loop - do - { - // stack is empty? - if (stackPos == 0) - return; - // move back up the stack - stackPos--; - intervalMin = stack[stackPos].tnear; - if (maxDist < intervalMin) - continue; - node = stack[stackPos].node; - intervalMax = stack[stackPos].tfar; - break; - } while (true); - } - } - - template - void intersectPoint(const Vector3 &p, IsectCallback& intersectCallback) const - { - if (!bounds.contains(p)) - return; - - StackNode stack[MAX_STACK_SIZE]; - int stackPos = 0; - int node = 0; - - while (true) { - while (true) - { - uint32 tn = tree[node]; - uint32 axis = (tn & (3 << 30)) >> 30; - bool BVH2 = tn & (1 << 29); - int offset = tn & ~(7 << 29); - if (!BVH2) - { - if (axis < 3) - { - // "normal" interior node - float tl = intBitsToFloat(tree[node + 1]); - float tr = intBitsToFloat(tree[node + 2]); - // point is between clip zones - if (tl < p[axis] && tr > p[axis]) - break; - int right = offset + 3; - node = right; - // point is in right node only - if (tl < p[axis]) { - continue; - } - node = offset; // left - // point is in left node only - if (tr > p[axis]) { - continue; - } - // point is in both nodes - // push back right node - stack[stackPos].node = right; - stackPos++; - continue; - } - else - { - // leaf - test some objects - int n = tree[node + 1]; - while (n > 0) { - intersectCallback(p, objects[offset]); // !!! - --n; - ++offset; - } - break; - } - } - else // BVH2 node (empty space cut off left and right) - { - if (axis>2) - return; // should not happen - float tl = intBitsToFloat(tree[node + 1]); - float tr = intBitsToFloat(tree[node + 2]); - node = offset; - if (tl > p[axis] || tr < p[axis]) - break; - continue; - } - } // traversal loop - - // stack is empty? - if (stackPos == 0) - return; - // move back up the stack - stackPos--; - node = stack[stackPos].node; - } - } - - bool writeToFile(FILE *wf) const; - bool readFromFile(FILE *rf); - - protected: - std::vector tree; - std::vector objects; - AABox bounds; - - struct buildData - { - uint32 *indices; - AABox *primBound; - uint32 numPrims; - int maxPrims; - }; - struct StackNode - { - uint32 node; - float tnear; - float tfar; - }; - - class BuildStats - { - private: - int numNodes; - int numLeaves; - int sumObjects; - int minObjects; - int maxObjects; - int sumDepth; - int minDepth; - int maxDepth; - int numLeavesN[6]; - int numBVH2; - - public: - BuildStats(): - numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF), - maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF), - maxDepth(0xFFFFFFFF), numBVH2(0) - { - for(int i=0; i<6; ++i) numLeavesN[i] = 0; - } - - void updateInner() { numNodes++; } - void updateBVH2() { numBVH2++; } - void updateLeaf(int depth, int n); - void printStats(); - }; - - void buildHierarchy(std::vector &tempTree, buildData &dat, BuildStats &stats); - - void createNode(std::vector &tempTree, int nodeIndex, uint32 left, uint32 right) { - // write leaf node - tempTree[nodeIndex + 0] = (3 << 30) | left; - tempTree[nodeIndex + 1] = right - left + 1; - } - - void subdivide(int left, int right, std::vector &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats); -}; - -#endif // _BIH_H diff --git a/src/server/game/CollisionDetection/BoundingIntervalHierarchy.cpp b/src/server/game/CollisionDetection/BoundingIntervalHierarchy.cpp new file mode 100644 index 00000000000..4bd6b3c701e --- /dev/null +++ b/src/server/game/CollisionDetection/BoundingIntervalHierarchy.cpp @@ -0,0 +1,304 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "BIH.h" + +void BIH::buildHierarchy(std::vector &tempTree, buildData &dat, BuildStats &stats) +{ + // create space for the first node + tempTree.push_back(3 << 30); // dummy leaf + tempTree.insert(tempTree.end(), 2, 0); + //tempTree.add(0); + + // seed bbox + AABound gridBox = { bounds.low(), bounds.high() }; + AABound nodeBox = gridBox; + // seed subdivide function + subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats); +} + +void BIH::subdivide(int left, int right, std::vector &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats) +{ + if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE) + { + // write leaf node + stats.updateLeaf(depth, right - left + 1); + createNode(tempTree, nodeIndex, left, right); + return; + } + // calculate extents + int axis = -1, prevAxis, rightOrig; + float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan(); + float split = G3D::fnan(), prevSplit; + bool wasLeft = true; + while (true) + { + prevAxis = axis; + prevSplit = split; + // perform quick consistency checks + Vector3 d( gridBox.hi - gridBox.lo ); + if (d.x < 0 || d.y < 0 || d.z < 0) + throw std::logic_error("negative node extents"); + for (int i = 0; i < 3; i++) + { + if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i]) + { + //UI.printError(Module.ACCEL, "Reached tree area in error - discarding node with: %d objects", right - left + 1); + throw std::logic_error("invalid node overlap"); + } + } + // find longest axis + axis = d.primaryAxis(); + split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]); + // partition L/R subsets + clipL = -G3D::inf(); + clipR = G3D::inf(); + rightOrig = right; // save this for later + float nodeL = G3D::inf(); + float nodeR = -G3D::inf(); + for (int i = left; i <= right;) + { + int obj = dat.indices[i]; + float minb = dat.primBound[obj].low()[axis]; + float maxb = dat.primBound[obj].high()[axis]; + float center = (minb + maxb) * 0.5f; + if (center <= split) + { + // stay left + i++; + if (clipL < maxb) + clipL = maxb; + } + else + { + // move to the right most + int t = dat.indices[i]; + dat.indices[i] = dat.indices[right]; + dat.indices[right] = t; + right--; + if (clipR > minb) + clipR = minb; + } + nodeL = std::min(nodeL, minb); + nodeR = std::max(nodeR, maxb); + } + // check for empty space + if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis]) + { + float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis]; + float nodeNewW = nodeR - nodeL; + // node box is too big compare to space occupied by primitives? + if (1.3f * nodeNewW < nodeBoxW) + { + stats.updateBVH2(); + int nextIndex = tempTree.size(); + // allocate child + tempTree.push_back(0); + tempTree.push_back(0); + tempTree.push_back(0); + // write bvh2 clip node + stats.updateInner(); + tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex; + tempTree[nodeIndex + 1] = floatToRawIntBits(nodeL); + tempTree[nodeIndex + 2] = floatToRawIntBits(nodeR); + // update nodebox and recurse + nodeBox.lo[axis] = nodeL; + nodeBox.hi[axis] = nodeR; + subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats); + return; + } + } + // ensure we are making progress in the subdivision + if (right == rightOrig) + { + // all left + if (prevAxis == axis && prevSplit == split) { + // we are stuck here - create a leaf + stats.updateLeaf(depth, right - left + 1); + createNode(tempTree, nodeIndex, left, right); + return; + } + if (clipL <= split) { + // keep looping on left half + gridBox.hi[axis] = split; + prevClip = clipL; + wasLeft = true; + continue; + } + gridBox.hi[axis] = split; + prevClip = G3D::fnan(); + } + else if (left > right) + { + // all right + if (prevAxis == axis && prevSplit == split) { + // we are stuck here - create a leaf + stats.updateLeaf(depth, right - left + 1); + createNode(tempTree, nodeIndex, left, right); + return; + } + right = rightOrig; + if (clipR >= split) { + // keep looping on right half + gridBox.lo[axis] = split; + prevClip = clipR; + wasLeft = false; + continue; + } + gridBox.lo[axis] = split; + prevClip = G3D::fnan(); + } + else + { + // we are actually splitting stuff + if (prevAxis != -1 && !isnan(prevClip)) + { + // second time through - lets create the previous split + // since it produced empty space + int nextIndex = tempTree.size(); + // allocate child node + tempTree.push_back(0); + tempTree.push_back(0); + tempTree.push_back(0); + if (wasLeft) { + // create a node with a left child + // write leaf node + stats.updateInner(); + tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex; + tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip); + tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf()); + } else { + // create a node with a right child + // write leaf node + stats.updateInner(); + tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3); + tempTree[nodeIndex + 1] = floatToRawIntBits(-G3D::inf()); + tempTree[nodeIndex + 2] = floatToRawIntBits(prevClip); + } + // count stats for the unused leaf + depth++; + stats.updateLeaf(depth, 0); + // now we keep going as we are, with a new nodeIndex: + nodeIndex = nextIndex; + } + break; + } + } + // compute index of child nodes + int nextIndex = tempTree.size(); + // allocate left node + int nl = right - left + 1; + int nr = rightOrig - (right + 1) + 1; + if (nl > 0) { + tempTree.push_back(0); + tempTree.push_back(0); + tempTree.push_back(0); + } else + nextIndex -= 3; + // allocate right node + if (nr > 0) { + tempTree.push_back(0); + tempTree.push_back(0); + tempTree.push_back(0); + } + // write leaf node + stats.updateInner(); + tempTree[nodeIndex + 0] = (axis << 30) | nextIndex; + tempTree[nodeIndex + 1] = floatToRawIntBits(clipL); + tempTree[nodeIndex + 2] = floatToRawIntBits(clipR); + // prepare L/R child boxes + AABound gridBoxL(gridBox), gridBoxR(gridBox); + AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox); + gridBoxL.hi[axis] = gridBoxR.lo[axis] = split; + nodeBoxL.hi[axis] = clipL; + nodeBoxR.lo[axis] = clipR; + // recurse + if (nl > 0) + subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats); + else + stats.updateLeaf(depth + 1, 0); + if (nr > 0) + subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats); + else + stats.updateLeaf(depth + 1, 0); +} + +bool BIH::writeToFile(FILE *wf) const +{ + uint32 treeSize = tree.size(); + uint32 check=0, count=0; + check += fwrite(&bounds.low(), sizeof(float), 3, wf); + check += fwrite(&bounds.high(), sizeof(float), 3, wf); + check += fwrite(&treeSize, sizeof(uint32), 1, wf); + check += fwrite(&tree[0], sizeof(uint32), treeSize, wf); + count = objects.size(); + check += fwrite(&count, sizeof(uint32), 1, wf); + check += fwrite(&objects[0], sizeof(uint32), count, wf); + return check == (3 + 3 + 2 + treeSize + count); +} + +bool BIH::readFromFile(FILE *rf) +{ + uint32 treeSize; + Vector3 lo, hi; + uint32 check=0, count=0; + check += fread(&lo, sizeof(float), 3, rf); + check += fread(&hi, sizeof(float), 3, rf); + bounds = AABox(lo, hi); + check += fread(&treeSize, sizeof(uint32), 1, rf); + tree.resize(treeSize); + check += fread(&tree[0], sizeof(uint32), treeSize, rf); + check += fread(&count, sizeof(uint32), 1, rf); + objects.resize(count); // = new uint32[nObjects]; + check += fread(&objects[0], sizeof(uint32), count, rf); + return check == (3 + 3 + 2 + treeSize + count); +} + +void BIH::BuildStats::updateLeaf(int depth, int n) +{ + numLeaves++; + minDepth = std::min(depth, minDepth); + maxDepth = std::max(depth, maxDepth); + sumDepth += depth; + minObjects = std::min(n, minObjects); + maxObjects = std::max(n, maxObjects); + sumObjects += n; + int nl = std::min(n, 5); + ++numLeavesN[nl]; +} + +void BIH::BuildStats::printStats() +{ + printf("Tree stats:\n"); + printf(" * Nodes: %d\n", numNodes); + printf(" * Leaves: %d\n", numLeaves); + printf(" * Objects: min %d\n", minObjects); + printf(" avg %.2f\n", (float) sumObjects / numLeaves); + printf(" avg(n>0) %.2f\n", (float) sumObjects / (numLeaves - numLeavesN[0])); + printf(" max %d\n", maxObjects); + printf(" * Depth: min %d\n", minDepth); + printf(" avg %.2f\n", (float) sumDepth / numLeaves); + printf(" max %d\n", maxDepth); + printf(" * Leaves w/: N=0 %3d%%\n", 100 * numLeavesN[0] / numLeaves); + printf(" N=1 %3d%%\n", 100 * numLeavesN[1] / numLeaves); + printf(" N=2 %3d%%\n", 100 * numLeavesN[2] / numLeaves); + printf(" N=3 %3d%%\n", 100 * numLeavesN[3] / numLeaves); + printf(" N=4 %3d%%\n", 100 * numLeavesN[4] / numLeaves); + printf(" N>4 %3d%%\n", 100 * numLeavesN[5] / numLeaves); + printf(" * BVH2 nodes: %d (%3d%%)\n", numBVH2, 100 * numBVH2 / (numNodes + numLeaves - 2 * numBVH2)); +} diff --git a/src/server/game/CollisionDetection/BoundingIntervalHierarchy.h b/src/server/game/CollisionDetection/BoundingIntervalHierarchy.h new file mode 100644 index 00000000000..15ae90c23eb --- /dev/null +++ b/src/server/game/CollisionDetection/BoundingIntervalHierarchy.h @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2005-2010 MaNGOS + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _BIH_H +#define _BIH_H + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define MAX_STACK_SIZE 64 + +#ifdef _MSC_VER + #define isnan(x) _isnan(x) +#endif + +using G3D::Vector3; +using G3D::AABox; +using G3D::Ray; + +static inline uint32 floatToRawIntBits(float f) +{ + union + { + uint32 ival; + float fval; + } temp; + temp.fval=f; + return temp.ival; +} + +static inline float intBitsToFloat(uint32 i) +{ + union + { + uint32 ival; + float fval; + } temp; + temp.ival=i; + return temp.fval; +} + +struct AABound +{ + Vector3 lo, hi; +}; + +/** Bounding Interval Hierarchy Class. + Building and Ray-Intersection functions based on BIH from + Sunflow, a Java Raytracer, released under MIT/X11 License + http://sunflow.sourceforge.net/ + Copyright (c) 2003-2007 Christopher Kulla +*/ + +class BIH +{ + public: + BIH() {}; + template< class T, class BoundsFunc > + void build(const std::vector &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false) + { + if(primitives.size() == 0) + return; + buildData dat; + dat.maxPrims = leafSize; + dat.numPrims = primitives.size(); + dat.indices = new uint32[dat.numPrims]; + dat.primBound = new AABox[dat.numPrims]; + getBounds(primitives[0], bounds); + for (uint32 i=0; i tempTree; + BuildStats stats; + buildHierarchy(tempTree, dat, stats); + if (printStats) + stats.printStats(); + + objects.resize(dat.numPrims); + for (uint32 i=0; i + void intersectRay(const Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const + { + float intervalMin = 0.f; + float intervalMax = maxDist; + Vector3 org = r.origin(); + Vector3 dir = r.direction(); + Vector3 invDir; + float t1, t2; + for(int i=0; i<3; ++i) + { + invDir[i] = 1.f / dir[i]; + t1 = (bounds.low()[i] - org[i]) * invDir[i]; + t2 = (bounds.high()[i] - org[i]) * invDir[i]; + if (invDir[i] > 0) { + if (t1 > intervalMin) + intervalMin = t1; + if (t2 < intervalMax) + intervalMax = t2; + } else { + if (t2 > intervalMin) + intervalMin = t2; + if (t1 < intervalMax) + intervalMax = t1; + } + if (intervalMin > intervalMax) + return; + } + + uint32 offsetFront[3]; + uint32 offsetBack[3]; + uint32 offsetFront3[3]; + uint32 offsetBack3[3]; + // compute custom offsets from direction sign bit + + for(int i=0; i<3; ++i) + { + offsetFront[i] = floatToRawIntBits(dir[i]) >> 31; + offsetBack[i] = offsetFront[i] ^ 1; + offsetFront3[i] = offsetFront[i] * 3; + offsetBack3[i] = offsetBack[i] * 3; + + // avoid always adding 1 during the inner loop + ++offsetFront[i]; + ++offsetBack[i]; + } + + StackNode stack[MAX_STACK_SIZE]; + int stackPos = 0; + int node = 0; + + while (true) { + while (true) + { + uint32 tn = tree[node]; + uint32 axis = (tn & (3 << 30)) >> 30; + bool BVH2 = tn & (1 << 29); + int offset = tn & ~(7 << 29); + if (!BVH2) + { + if (axis < 3) + { + // "normal" interior node + float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; + float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; + // ray passes between clip zones + if (tf < intervalMin && tb > intervalMax) + break; + int back = offset + offsetBack3[axis]; + node = back; + // ray passes through far node only + if (tf < intervalMin) { + intervalMin = (tb >= intervalMin) ? tb : intervalMin; + continue; + } + node = offset + offsetFront3[axis]; // front + // ray passes through near node only + if (tb > intervalMax) { + intervalMax = (tf <= intervalMax) ? tf : intervalMax; + continue; + } + // ray passes through both nodes + // push back node + stack[stackPos].node = back; + stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin; + stack[stackPos].tfar = intervalMax; + stackPos++; + // update ray interval for front node + intervalMax = (tf <= intervalMax) ? tf : intervalMax; + continue; + } + else + { + // leaf - test some objects + int n = tree[node + 1]; + while (n > 0) { + bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirst); + if(stopAtFirst && hit) return; + --n; + ++offset; + } + break; + } + } + else + { + if (axis>2) + return; // should not happen + float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; + float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; + node = offset; + intervalMin = (tf >= intervalMin) ? tf : intervalMin; + intervalMax = (tb <= intervalMax) ? tb : intervalMax; + if (intervalMin > intervalMax) + break; + continue; + } + } // traversal loop + do + { + // stack is empty? + if (stackPos == 0) + return; + // move back up the stack + stackPos--; + intervalMin = stack[stackPos].tnear; + if (maxDist < intervalMin) + continue; + node = stack[stackPos].node; + intervalMax = stack[stackPos].tfar; + break; + } while (true); + } + } + + template + void intersectPoint(const Vector3 &p, IsectCallback& intersectCallback) const + { + if (!bounds.contains(p)) + return; + + StackNode stack[MAX_STACK_SIZE]; + int stackPos = 0; + int node = 0; + + while (true) { + while (true) + { + uint32 tn = tree[node]; + uint32 axis = (tn & (3 << 30)) >> 30; + bool BVH2 = tn & (1 << 29); + int offset = tn & ~(7 << 29); + if (!BVH2) + { + if (axis < 3) + { + // "normal" interior node + float tl = intBitsToFloat(tree[node + 1]); + float tr = intBitsToFloat(tree[node + 2]); + // point is between clip zones + if (tl < p[axis] && tr > p[axis]) + break; + int right = offset + 3; + node = right; + // point is in right node only + if (tl < p[axis]) { + continue; + } + node = offset; // left + // point is in left node only + if (tr > p[axis]) { + continue; + } + // point is in both nodes + // push back right node + stack[stackPos].node = right; + stackPos++; + continue; + } + else + { + // leaf - test some objects + int n = tree[node + 1]; + while (n > 0) { + intersectCallback(p, objects[offset]); // !!! + --n; + ++offset; + } + break; + } + } + else // BVH2 node (empty space cut off left and right) + { + if (axis>2) + return; // should not happen + float tl = intBitsToFloat(tree[node + 1]); + float tr = intBitsToFloat(tree[node + 2]); + node = offset; + if (tl > p[axis] || tr < p[axis]) + break; + continue; + } + } // traversal loop + + // stack is empty? + if (stackPos == 0) + return; + // move back up the stack + stackPos--; + node = stack[stackPos].node; + } + } + + bool writeToFile(FILE *wf) const; + bool readFromFile(FILE *rf); + + protected: + std::vector tree; + std::vector objects; + AABox bounds; + + struct buildData + { + uint32 *indices; + AABox *primBound; + uint32 numPrims; + int maxPrims; + }; + struct StackNode + { + uint32 node; + float tnear; + float tfar; + }; + + class BuildStats + { + private: + int numNodes; + int numLeaves; + int sumObjects; + int minObjects; + int maxObjects; + int sumDepth; + int minDepth; + int maxDepth; + int numLeavesN[6]; + int numBVH2; + + public: + BuildStats(): + numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF), + maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF), + maxDepth(0xFFFFFFFF), numBVH2(0) + { + for(int i=0; i<6; ++i) numLeavesN[i] = 0; + } + + void updateInner() { numNodes++; } + void updateBVH2() { numBVH2++; } + void updateLeaf(int depth, int n); + void printStats(); + }; + + void buildHierarchy(std::vector &tempTree, buildData &dat, BuildStats &stats); + + void createNode(std::vector &tempTree, int nodeIndex, uint32 left, uint32 right) { + // write leaf node + tempTree[nodeIndex + 0] = (3 << 30) | left; + tempTree[nodeIndex + 1] = right - left + 1; + } + + void subdivide(int left, int right, std::vector &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats); +}; + +#endif // _BIH_H diff --git a/src/server/game/Entities/Transport/Transport.cpp b/src/server/game/Entities/Transport/Transport.cpp new file mode 100644 index 00000000000..444e115f8b9 --- /dev/null +++ b/src/server/game/Entities/Transport/Transport.cpp @@ -0,0 +1,589 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "Common.h" + +#include "Transports.h" +#include "MapManager.h" +#include "ObjectMgr.h" +#include "Path.h" + +#include "WorldPacket.h" +#include "DBCStores.h" +#include "ProgressBar.h" + +#include "World.h" + +void MapManager::LoadTransports() +{ + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, name, period FROM transports"); + + uint32 count = 0; + + if (!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded %u transports", count); + return; + } + + barGoLink bar(result->GetRowCount()); + + do + { + bar.step(); + + Transport *t = new Transport; + + Field *fields = result->Fetch(); + + uint32 entry = fields[0].GetUInt32(); + std::string name = fields[1].GetCppString(); + t->m_period = fields[2].GetUInt32(); + + const GameObjectInfo *goinfo = objmgr.GetGameObjectInfo(entry); + + if (!goinfo) + { + sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str()); + delete t; + continue; + } + + if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT) + { + sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str()); + delete t; + continue; + } + + // sLog.outString("Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name); + + std::set mapsUsed; + + if (!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed)) + // skip transports with empty waypoints list + { + sLog.outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.",goinfo->moTransport.taxiPathId); + delete t; + continue; + } + + float x, y, z, o; + uint32 mapid; + x = t->m_WayPoints[0].x; y = t->m_WayPoints[0].y; z = t->m_WayPoints[0].z; mapid = t->m_WayPoints[0].mapid; o = 1; + + // creates the Gameobject + if (!t->Create(entry, mapid, x, y, z, o, 100, 0)) + { + delete t; + continue; + } + + m_Transports.insert(t); + + for (std::set::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i) + m_TransportsByMap[*i].insert(t); + + //If we someday decide to use the grid to track transports, here: + t->SetMap(MapManager::Instance().CreateMap(mapid, t, 0)); + + //t->GetMap()->Add((GameObject *)t); + ++count; + } while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u transports", count); + + // check transport data DB integrity + result = WorldDatabase.Query("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); + if (result) // wrong data found + { + do + { + Field *fields = result->Fetch(); + + uint32 guid = fields[0].GetUInt32(); + uint32 entry = fields[1].GetUInt32(); + std::string name = fields[2].GetCppString(); + sLog.outErrorDb("Transport %u '%s' have record (GUID: %u) in `gameobject`. Transports DON'T must have any records in `gameobject` or its behavior will be unpredictable/bugged.",entry,name.c_str(),guid); + } + while (result->NextRow()); + } +} + +Transport::Transport() : GameObject() +{ + m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_ROTATION); +} + +bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) +{ + Relocate(x,y,z,ang); + // instance id and phaseMask isn't set to values different from std. + + if (!IsPositionValid()) + { + sLog.outError("Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", + guidlow,x,y); + return false; + } + + Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT); + + GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(guidlow); + + if (!goinfo) + { + sLog.outErrorDb("Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f",guidlow, mapid, x, y, z, ang); + return false; + } + + m_goInfo = goinfo; + + SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); + + SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); + //SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); + SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64)); + SetUInt32Value(GAMEOBJECT_LEVEL, m_period); + SetEntry(goinfo->id); + + SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); + + SetGoState(GO_STATE_READY); + SetGoType(GameobjectTypes(goinfo->type)); + + SetGoAnimProgress(animprogress); + if (dynflags) + SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags)); + + SetName(goinfo->name); + + return true; +} + +struct keyFrame +{ + keyFrame(float _x, float _y, float _z, uint32 _mapid, int _actionflag, int _delay) + { + x = _x; y = _y; z = _z; mapid = _mapid; actionflag = _actionflag; delay = _delay; distFromPrev = -1; distSinceStop = -1; distUntilStop = -1; + tFrom = 0; tTo = 0; + } + + float x; + float y; + float z; + uint32 mapid; + int actionflag; + int delay; + float distSinceStop; + float distUntilStop; + float distFromPrev; + float tFrom, tTo; +}; + +bool Transport::GenerateWaypoints(uint32 pathid, std::set &mapids) +{ + TransportPath path; + objmgr.GetTransportPathNodes(pathid, path); + + if (path.Empty()) + return false; + + std::vector keyFrames; + int mapChange = 0; + mapids.clear(); + for (size_t i = 1; i < path.Size() - 1; ++i) + { + if (mapChange == 0) + { + if ((path[i].mapid == path[i+1].mapid)) + { + keyFrame k(path[i].x, path[i].y, path[i].z, path[i].mapid, path[i].actionFlag, path[i].delay); + keyFrames.push_back(k); + mapids.insert(k.mapid); + } + else + { + mapChange = 1; + } + } + else + { + --mapChange; + } + } + + int lastStop = -1; + int firstStop = -1; + + // first cell is arrived at by teleportation :S + keyFrames[0].distFromPrev = 0; + if (keyFrames[0].actionflag == 2) + { + lastStop = 0; + } + + // find the rest of the distances between key points + for (size_t i = 1; i < keyFrames.size(); ++i) + { + if ((keyFrames[i].actionflag == 1) || (keyFrames[i].mapid != keyFrames[i-1].mapid)) + { + keyFrames[i].distFromPrev = 0; + } + else + { + keyFrames[i].distFromPrev = + sqrt(pow(keyFrames[i].x - keyFrames[i - 1].x, 2) + + pow(keyFrames[i].y - keyFrames[i - 1].y, 2) + + pow(keyFrames[i].z - keyFrames[i - 1].z, 2)); + } + if (keyFrames[i].actionflag == 2) + { + // remember first stop frame + if (firstStop == -1) + firstStop = i; + lastStop = i; + } + } + + float tmpDist = 0; + for (size_t i = 0; i < keyFrames.size(); ++i) + { + int j = (i + lastStop) % keyFrames.size(); + if (keyFrames[j].actionflag == 2) + tmpDist = 0; + else + tmpDist += keyFrames[j].distFromPrev; + keyFrames[j].distSinceStop = tmpDist; + } + + for (int i = int(keyFrames.size()) - 1; i >= 0; i--) + { + int j = (i + (firstStop+1)) % keyFrames.size(); + tmpDist += keyFrames[(j + 1) % keyFrames.size()].distFromPrev; + keyFrames[j].distUntilStop = tmpDist; + if (keyFrames[j].actionflag == 2) + tmpDist = 0; + } + + for (size_t i = 0; i < keyFrames.size(); ++i) + { + if (keyFrames[i].distSinceStop < (30 * 30 * 0.5f)) + keyFrames[i].tFrom = sqrt(2 * keyFrames[i].distSinceStop); + else + keyFrames[i].tFrom = ((keyFrames[i].distSinceStop - (30 * 30 * 0.5f)) / 30) + 30; + + if (keyFrames[i].distUntilStop < (30 * 30 * 0.5f)) + keyFrames[i].tTo = sqrt(2 * keyFrames[i].distUntilStop); + else + keyFrames[i].tTo = ((keyFrames[i].distUntilStop - (30 * 30 * 0.5f)) / 30) + 30; + + keyFrames[i].tFrom *= 1000; + keyFrames[i].tTo *= 1000; + } + + // for (int i = 0; i < keyFrames.size(); ++i) { + // sLog.outString("%f, %f, %f, %f, %f, %f, %f", keyFrames[i].x, keyFrames[i].y, keyFrames[i].distUntilStop, keyFrames[i].distSinceStop, keyFrames[i].distFromPrev, keyFrames[i].tFrom, keyFrames[i].tTo); + // } + + // Now we're completely set up; we can move along the length of each waypoint at 100 ms intervals + // speed = max(30, t) (remember x = 0.5s^2, and when accelerating, a = 1 unit/s^2 + int t = 0; + bool teleport = false; + if (keyFrames[keyFrames.size() - 1].mapid != keyFrames[0].mapid) + teleport = true; + + WayPoint pos(keyFrames[0].mapid, keyFrames[0].x, keyFrames[0].y, keyFrames[0].z, teleport, 0); + m_WayPoints[0] = pos; + t += keyFrames[0].delay * 1000; + + uint32 cM = keyFrames[0].mapid; + for (size_t i = 0; i < keyFrames.size() - 1; ++i) + { + float d = 0; + float tFrom = keyFrames[i].tFrom; + float tTo = keyFrames[i].tTo; + + // keep the generation of all these points; we use only a few now, but may need the others later + if (((d < keyFrames[i + 1].distFromPrev) && (tTo > 0))) + { + while ((d < keyFrames[i + 1].distFromPrev) && (tTo > 0)) + { + tFrom += 100; + tTo -= 100; + + if (d > 0) + { + float newX, newY, newZ; + newX = keyFrames[i].x + (keyFrames[i + 1].x - keyFrames[i].x) * d / keyFrames[i + 1].distFromPrev; + newY = keyFrames[i].y + (keyFrames[i + 1].y - keyFrames[i].y) * d / keyFrames[i + 1].distFromPrev; + newZ = keyFrames[i].z + (keyFrames[i + 1].z - keyFrames[i].z) * d / keyFrames[i + 1].distFromPrev; + + bool teleport = false; + if (keyFrames[i].mapid != cM) + { + teleport = true; + cM = keyFrames[i].mapid; + } + + // sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ); + WayPoint pos(keyFrames[i].mapid, newX, newY, newZ, teleport, i); + if (teleport) + m_WayPoints[t] = pos; + } + + if (tFrom < tTo) // caught in tFrom dock's "gravitational pull" + { + if (tFrom <= 30000) + { + d = 0.5f * (tFrom / 1000) * (tFrom / 1000); + } + else + { + d = 0.5f * 30 * 30 + 30 * ((tFrom - 30000) / 1000); + } + d = d - keyFrames[i].distSinceStop; + } + else + { + if (tTo <= 30000) + { + d = 0.5f * (tTo / 1000) * (tTo / 1000); + } + else + { + d = 0.5f * 30 * 30 + 30 * ((tTo - 30000) / 1000); + } + d = keyFrames[i].distUntilStop - d; + } + t += 100; + } + t -= 100; + } + + if (keyFrames[i + 1].tFrom > keyFrames[i + 1].tTo) + t += 100 - ((long)keyFrames[i + 1].tTo % 100); + else + t += (long)keyFrames[i + 1].tTo % 100; + + bool teleport = false; + if ((keyFrames[i + 1].actionflag == 1) || (keyFrames[i + 1].mapid != keyFrames[i].mapid)) + { + teleport = true; + cM = keyFrames[i + 1].mapid; + } + + WayPoint pos(keyFrames[i + 1].mapid, keyFrames[i + 1].x, keyFrames[i + 1].y, keyFrames[i + 1].z, teleport, i); + + // sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport); +/* + if (keyFrames[i+1].delay > 5) + pos.delayed = true; +*/ + //if (teleport) + m_WayPoints[t] = pos; + + t += keyFrames[i + 1].delay * 1000; + // sLog.outString("------"); + } + + uint32 timer = t; + + // sLog.outDetail(" Generated %lu waypoints, total time %u.", (unsigned long)m_WayPoints.size(), timer); + + m_curr = m_WayPoints.begin(); + m_curr = GetNextWayPoint(); + m_next = GetNextWayPoint(); + m_pathTime = timer; + + m_nextNodeTime = m_curr->first; + + return true; +} + +Transport::WayPointMap::const_iterator Transport::GetNextWayPoint() +{ + WayPointMap::const_iterator iter = m_curr; + ++iter; + if (iter == m_WayPoints.end()) + iter = m_WayPoints.begin(); + return iter; +} + +void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) +{ + Map const* oldMap = GetMap(); + Relocate(x, y, z); + + for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) + { + Player *plr = *itr; + ++itr; + + if (plr->isDead() && !plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) + { + plr->ResurrectPlayer(1.0); + } + plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT); + + //WorldPacket data(SMSG_811, 4); + //data << uint32(0); + //plr->GetSession()->SendPacket(&data); + } + + //we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference... + //player far teleport would try to create same instance, but we need it NOW for transport... + //correct me if I'm wrong O.o + //yes, you're right + + ResetMap(); + Map * newMap = MapManager::Instance().CreateMap(newMapid, this, 0); + SetMap(newMap); + assert (GetMap()); + + if (oldMap != newMap) + { + UpdateForMap(oldMap); + UpdateForMap(newMap); + } +} + +bool Transport::AddPassenger(Player* passenger) +{ + if (m_passengers.insert(passenger).second) + sLog.outDetail("Player %s boarded transport %s.", passenger->GetName(), GetName()); + return true; +} + +bool Transport::RemovePassenger(Player* passenger) +{ + if (m_passengers.erase(passenger)) + sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), GetName()); + return true; +} + +void Transport::CheckForEvent(uint32 entry, uint32 wp_id) +{ + uint32 key = entry*100+wp_id; + if (objmgr.TransportEventMap.find(key) != objmgr.TransportEventMap.end()) + GetMap()->ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL); +} + +void Transport::Update(uint32 /*p_time*/) +{ + if (m_WayPoints.size() <= 1) + return; + + m_timer = getMSTime() % m_period; + while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime)) + { + m_curr = GetNextWayPoint(); + m_next = GetNextWayPoint(); + + // first check help in case client-server transport coordinates de-synchronization + if (m_curr->second.mapid != GetMapId() || m_curr->second.teleport) + { + TeleportTransport(m_curr->second.mapid, m_curr->second.x, m_curr->second.y, m_curr->second.z); + } + else + { + Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z); + } +/* + if (m_curr->second.delayed) + { + switch (GetEntry()) + { + case 176495: + case 164871: + case 175080: + SendPlaySound(11804, false); break; // ZeppelinDocked + case 20808: + case 181646: + case 176231: + case 176244: + case 176310: + case 177233: + SendPlaySound(5495, false);break; // BoatDockingWarning + default: + SendPlaySound(5154, false); break; // ShipDocked + } + } +*/ + /* + for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) + { + PlayerSet::const_iterator it2 = itr; + ++itr; + //(*it2)->SetPosition(m_curr->second.x + (*it2)->GetTransOffsetX(), m_curr->second.y + (*it2)->GetTransOffsetY(), m_curr->second.z + (*it2)->GetTransOffsetZ(), (*it2)->GetTransOffsetO()); + } + */ + + m_nextNodeTime = m_curr->first; + + if (m_curr == m_WayPoints.begin() && (sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES) == 0) + sLog.outDetail(" ************ BEGIN ************** %s", this->m_name.c_str()); + + if ((sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES) == 0) + sLog.outDetail("%s moved to %d %f %f %f %d", this->m_name.c_str(), m_curr->second.id, m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid); + + //Transport Event System + CheckForEvent(this->GetEntry(), m_curr->second.id); + } +} + +void Transport::UpdateForMap(Map const* targetMap) +{ + Map::PlayerList const& pl = targetMap->GetPlayers(); + if (pl.isEmpty()) + return; + + if (GetMapId() == targetMap->GetId()) + { + for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) + { + if (this != itr->getSource()->GetTransport()) + { + UpdateData transData; + BuildCreateUpdateBlockForPlayer(&transData, itr->getSource()); + WorldPacket packet; + transData.BuildPacket(&packet); + itr->getSource()->SendDirectMessage(&packet); + } + } + } + else + { + UpdateData transData; + BuildOutOfRangeUpdateBlock(&transData); + WorldPacket out_packet; + transData.BuildPacket(&out_packet); + + for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) + if (this != itr->getSource()->GetTransport()) + itr->getSource()->SendDirectMessage(&out_packet); + } +} + diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h new file mode 100644 index 00000000000..25b9ade1461 --- /dev/null +++ b/src/server/game/Entities/Transport/Transport.h @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005-2009 MaNGOS + * + * Copyright (C) 2008-2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef TRANSPORTS_H +#define TRANSPORTS_H + +#include "GameObject.h" + +#include +#include +#include + +class TransportPath +{ + public: + struct PathNode + { + uint32 mapid; + float x,y,z; + uint32 actionFlag; + uint32 delay; + }; + + void SetLength(const unsigned int sz) + { + i_nodes.resize(sz); + } + + unsigned int Size(void) const { return i_nodes.size(); } + bool Empty(void) const { return i_nodes.empty(); } + void Resize(unsigned int sz) { i_nodes.resize(sz); } + void Clear(void) { i_nodes.clear(); } + PathNode* GetNodes(void) { return static_cast(&i_nodes[0]); } + + PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } + const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } + + protected: + std::vector i_nodes; +}; + +class Transport : public GameObject +{ + public: + explicit Transport(); + + bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags); + bool GenerateWaypoints(uint32 pathid, std::set &mapids); + void Update(uint32 p_time); + bool AddPassenger(Player* passenger); + bool RemovePassenger(Player* passenger); + void CheckForEvent(uint32 entry, uint32 wp_id); + + typedef std::set PlayerSet; + PlayerSet const& GetPassengers() const { return m_passengers; } + + private: + struct WayPoint + { + WayPoint() : mapid(0), x(0), y(0), z(0), teleport(false), id(0) {} + WayPoint(uint32 _mapid, float _x, float _y, float _z, bool _teleport, uint32 _id) : + mapid(_mapid), x(_x), y(_y), z(_z), teleport(_teleport), id(_id) {} + uint32 mapid; + float x; + float y; + float z; + bool teleport; + uint32 id; + }; + + typedef std::map WayPointMap; + + WayPointMap::const_iterator m_curr; + WayPointMap::const_iterator m_next; + uint32 m_pathTime; + uint32 m_timer; + + PlayerSet m_passengers; + + public: + WayPointMap m_WayPoints; + uint32 m_nextNodeTime; + uint32 m_period; + + private: + void TeleportTransport(uint32 newMapid, float x, float y, float z); + void UpdateForMap(Map const* map); + WayPointMap::const_iterator GetNextWayPoint(); +}; +#endif + diff --git a/src/server/game/Entities/Transport/Transports.cpp b/src/server/game/Entities/Transport/Transports.cpp deleted file mode 100644 index 444e115f8b9..00000000000 --- a/src/server/game/Entities/Transport/Transports.cpp +++ /dev/null @@ -1,589 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "Common.h" - -#include "Transports.h" -#include "MapManager.h" -#include "ObjectMgr.h" -#include "Path.h" - -#include "WorldPacket.h" -#include "DBCStores.h" -#include "ProgressBar.h" - -#include "World.h" - -void MapManager::LoadTransports() -{ - QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, name, period FROM transports"); - - uint32 count = 0; - - if (!result) - { - barGoLink bar(1); - bar.step(); - - sLog.outString(); - sLog.outString(">> Loaded %u transports", count); - return; - } - - barGoLink bar(result->GetRowCount()); - - do - { - bar.step(); - - Transport *t = new Transport; - - Field *fields = result->Fetch(); - - uint32 entry = fields[0].GetUInt32(); - std::string name = fields[1].GetCppString(); - t->m_period = fields[2].GetUInt32(); - - const GameObjectInfo *goinfo = objmgr.GetGameObjectInfo(entry); - - if (!goinfo) - { - sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template missing", entry, name.c_str()); - delete t; - continue; - } - - if (goinfo->type != GAMEOBJECT_TYPE_MO_TRANSPORT) - { - sLog.outErrorDb("Transport ID:%u, Name: %s, will not be loaded, gameobject_template type wrong", entry, name.c_str()); - delete t; - continue; - } - - // sLog.outString("Loading transport %d between %s, %s", entry, name.c_str(), goinfo->name); - - std::set mapsUsed; - - if (!t->GenerateWaypoints(goinfo->moTransport.taxiPathId, mapsUsed)) - // skip transports with empty waypoints list - { - sLog.outErrorDb("Transport (path id %u) path size = 0. Transport ignored, check DBC files or transport GO data0 field.",goinfo->moTransport.taxiPathId); - delete t; - continue; - } - - float x, y, z, o; - uint32 mapid; - x = t->m_WayPoints[0].x; y = t->m_WayPoints[0].y; z = t->m_WayPoints[0].z; mapid = t->m_WayPoints[0].mapid; o = 1; - - // creates the Gameobject - if (!t->Create(entry, mapid, x, y, z, o, 100, 0)) - { - delete t; - continue; - } - - m_Transports.insert(t); - - for (std::set::const_iterator i = mapsUsed.begin(); i != mapsUsed.end(); ++i) - m_TransportsByMap[*i].insert(t); - - //If we someday decide to use the grid to track transports, here: - t->SetMap(MapManager::Instance().CreateMap(mapid, t, 0)); - - //t->GetMap()->Add((GameObject *)t); - ++count; - } while (result->NextRow()); - - sLog.outString(); - sLog.outString(">> Loaded %u transports", count); - - // check transport data DB integrity - result = WorldDatabase.Query("SELECT gameobject.guid,gameobject.id,transports.name FROM gameobject,transports WHERE gameobject.id = transports.entry"); - if (result) // wrong data found - { - do - { - Field *fields = result->Fetch(); - - uint32 guid = fields[0].GetUInt32(); - uint32 entry = fields[1].GetUInt32(); - std::string name = fields[2].GetCppString(); - sLog.outErrorDb("Transport %u '%s' have record (GUID: %u) in `gameobject`. Transports DON'T must have any records in `gameobject` or its behavior will be unpredictable/bugged.",entry,name.c_str(),guid); - } - while (result->NextRow()); - } -} - -Transport::Transport() : GameObject() -{ - m_updateFlag = (UPDATEFLAG_TRANSPORT | UPDATEFLAG_HIGHGUID | UPDATEFLAG_HAS_POSITION | UPDATEFLAG_ROTATION); -} - -bool Transport::Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags) -{ - Relocate(x,y,z,ang); - // instance id and phaseMask isn't set to values different from std. - - if (!IsPositionValid()) - { - sLog.outError("Transport (GUID: %u) not created. Suggested coordinates isn't valid (X: %f Y: %f)", - guidlow,x,y); - return false; - } - - Object::_Create(guidlow, 0, HIGHGUID_MO_TRANSPORT); - - GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(guidlow); - - if (!goinfo) - { - sLog.outErrorDb("Transport not created: entry in `gameobject_template` not found, guidlow: %u map: %u (X: %f Y: %f Z: %f) ang: %f",guidlow, mapid, x, y, z, ang); - return false; - } - - m_goInfo = goinfo; - - SetFloatValue(OBJECT_FIELD_SCALE_X, goinfo->size); - - SetUInt32Value(GAMEOBJECT_FACTION, goinfo->faction); - //SetUInt32Value(GAMEOBJECT_FLAGS, goinfo->flags); - SetUInt32Value(GAMEOBJECT_FLAGS, MAKE_PAIR32(0x28, 0x64)); - SetUInt32Value(GAMEOBJECT_LEVEL, m_period); - SetEntry(goinfo->id); - - SetUInt32Value(GAMEOBJECT_DISPLAYID, goinfo->displayId); - - SetGoState(GO_STATE_READY); - SetGoType(GameobjectTypes(goinfo->type)); - - SetGoAnimProgress(animprogress); - if (dynflags) - SetUInt32Value(GAMEOBJECT_DYNAMIC, MAKE_PAIR32(0, dynflags)); - - SetName(goinfo->name); - - return true; -} - -struct keyFrame -{ - keyFrame(float _x, float _y, float _z, uint32 _mapid, int _actionflag, int _delay) - { - x = _x; y = _y; z = _z; mapid = _mapid; actionflag = _actionflag; delay = _delay; distFromPrev = -1; distSinceStop = -1; distUntilStop = -1; - tFrom = 0; tTo = 0; - } - - float x; - float y; - float z; - uint32 mapid; - int actionflag; - int delay; - float distSinceStop; - float distUntilStop; - float distFromPrev; - float tFrom, tTo; -}; - -bool Transport::GenerateWaypoints(uint32 pathid, std::set &mapids) -{ - TransportPath path; - objmgr.GetTransportPathNodes(pathid, path); - - if (path.Empty()) - return false; - - std::vector keyFrames; - int mapChange = 0; - mapids.clear(); - for (size_t i = 1; i < path.Size() - 1; ++i) - { - if (mapChange == 0) - { - if ((path[i].mapid == path[i+1].mapid)) - { - keyFrame k(path[i].x, path[i].y, path[i].z, path[i].mapid, path[i].actionFlag, path[i].delay); - keyFrames.push_back(k); - mapids.insert(k.mapid); - } - else - { - mapChange = 1; - } - } - else - { - --mapChange; - } - } - - int lastStop = -1; - int firstStop = -1; - - // first cell is arrived at by teleportation :S - keyFrames[0].distFromPrev = 0; - if (keyFrames[0].actionflag == 2) - { - lastStop = 0; - } - - // find the rest of the distances between key points - for (size_t i = 1; i < keyFrames.size(); ++i) - { - if ((keyFrames[i].actionflag == 1) || (keyFrames[i].mapid != keyFrames[i-1].mapid)) - { - keyFrames[i].distFromPrev = 0; - } - else - { - keyFrames[i].distFromPrev = - sqrt(pow(keyFrames[i].x - keyFrames[i - 1].x, 2) + - pow(keyFrames[i].y - keyFrames[i - 1].y, 2) + - pow(keyFrames[i].z - keyFrames[i - 1].z, 2)); - } - if (keyFrames[i].actionflag == 2) - { - // remember first stop frame - if (firstStop == -1) - firstStop = i; - lastStop = i; - } - } - - float tmpDist = 0; - for (size_t i = 0; i < keyFrames.size(); ++i) - { - int j = (i + lastStop) % keyFrames.size(); - if (keyFrames[j].actionflag == 2) - tmpDist = 0; - else - tmpDist += keyFrames[j].distFromPrev; - keyFrames[j].distSinceStop = tmpDist; - } - - for (int i = int(keyFrames.size()) - 1; i >= 0; i--) - { - int j = (i + (firstStop+1)) % keyFrames.size(); - tmpDist += keyFrames[(j + 1) % keyFrames.size()].distFromPrev; - keyFrames[j].distUntilStop = tmpDist; - if (keyFrames[j].actionflag == 2) - tmpDist = 0; - } - - for (size_t i = 0; i < keyFrames.size(); ++i) - { - if (keyFrames[i].distSinceStop < (30 * 30 * 0.5f)) - keyFrames[i].tFrom = sqrt(2 * keyFrames[i].distSinceStop); - else - keyFrames[i].tFrom = ((keyFrames[i].distSinceStop - (30 * 30 * 0.5f)) / 30) + 30; - - if (keyFrames[i].distUntilStop < (30 * 30 * 0.5f)) - keyFrames[i].tTo = sqrt(2 * keyFrames[i].distUntilStop); - else - keyFrames[i].tTo = ((keyFrames[i].distUntilStop - (30 * 30 * 0.5f)) / 30) + 30; - - keyFrames[i].tFrom *= 1000; - keyFrames[i].tTo *= 1000; - } - - // for (int i = 0; i < keyFrames.size(); ++i) { - // sLog.outString("%f, %f, %f, %f, %f, %f, %f", keyFrames[i].x, keyFrames[i].y, keyFrames[i].distUntilStop, keyFrames[i].distSinceStop, keyFrames[i].distFromPrev, keyFrames[i].tFrom, keyFrames[i].tTo); - // } - - // Now we're completely set up; we can move along the length of each waypoint at 100 ms intervals - // speed = max(30, t) (remember x = 0.5s^2, and when accelerating, a = 1 unit/s^2 - int t = 0; - bool teleport = false; - if (keyFrames[keyFrames.size() - 1].mapid != keyFrames[0].mapid) - teleport = true; - - WayPoint pos(keyFrames[0].mapid, keyFrames[0].x, keyFrames[0].y, keyFrames[0].z, teleport, 0); - m_WayPoints[0] = pos; - t += keyFrames[0].delay * 1000; - - uint32 cM = keyFrames[0].mapid; - for (size_t i = 0; i < keyFrames.size() - 1; ++i) - { - float d = 0; - float tFrom = keyFrames[i].tFrom; - float tTo = keyFrames[i].tTo; - - // keep the generation of all these points; we use only a few now, but may need the others later - if (((d < keyFrames[i + 1].distFromPrev) && (tTo > 0))) - { - while ((d < keyFrames[i + 1].distFromPrev) && (tTo > 0)) - { - tFrom += 100; - tTo -= 100; - - if (d > 0) - { - float newX, newY, newZ; - newX = keyFrames[i].x + (keyFrames[i + 1].x - keyFrames[i].x) * d / keyFrames[i + 1].distFromPrev; - newY = keyFrames[i].y + (keyFrames[i + 1].y - keyFrames[i].y) * d / keyFrames[i + 1].distFromPrev; - newZ = keyFrames[i].z + (keyFrames[i + 1].z - keyFrames[i].z) * d / keyFrames[i + 1].distFromPrev; - - bool teleport = false; - if (keyFrames[i].mapid != cM) - { - teleport = true; - cM = keyFrames[i].mapid; - } - - // sLog.outString("T: %d, D: %f, x: %f, y: %f, z: %f", t, d, newX, newY, newZ); - WayPoint pos(keyFrames[i].mapid, newX, newY, newZ, teleport, i); - if (teleport) - m_WayPoints[t] = pos; - } - - if (tFrom < tTo) // caught in tFrom dock's "gravitational pull" - { - if (tFrom <= 30000) - { - d = 0.5f * (tFrom / 1000) * (tFrom / 1000); - } - else - { - d = 0.5f * 30 * 30 + 30 * ((tFrom - 30000) / 1000); - } - d = d - keyFrames[i].distSinceStop; - } - else - { - if (tTo <= 30000) - { - d = 0.5f * (tTo / 1000) * (tTo / 1000); - } - else - { - d = 0.5f * 30 * 30 + 30 * ((tTo - 30000) / 1000); - } - d = keyFrames[i].distUntilStop - d; - } - t += 100; - } - t -= 100; - } - - if (keyFrames[i + 1].tFrom > keyFrames[i + 1].tTo) - t += 100 - ((long)keyFrames[i + 1].tTo % 100); - else - t += (long)keyFrames[i + 1].tTo % 100; - - bool teleport = false; - if ((keyFrames[i + 1].actionflag == 1) || (keyFrames[i + 1].mapid != keyFrames[i].mapid)) - { - teleport = true; - cM = keyFrames[i + 1].mapid; - } - - WayPoint pos(keyFrames[i + 1].mapid, keyFrames[i + 1].x, keyFrames[i + 1].y, keyFrames[i + 1].z, teleport, i); - - // sLog.outString("T: %d, x: %f, y: %f, z: %f, t:%d", t, pos.x, pos.y, pos.z, teleport); -/* - if (keyFrames[i+1].delay > 5) - pos.delayed = true; -*/ - //if (teleport) - m_WayPoints[t] = pos; - - t += keyFrames[i + 1].delay * 1000; - // sLog.outString("------"); - } - - uint32 timer = t; - - // sLog.outDetail(" Generated %lu waypoints, total time %u.", (unsigned long)m_WayPoints.size(), timer); - - m_curr = m_WayPoints.begin(); - m_curr = GetNextWayPoint(); - m_next = GetNextWayPoint(); - m_pathTime = timer; - - m_nextNodeTime = m_curr->first; - - return true; -} - -Transport::WayPointMap::const_iterator Transport::GetNextWayPoint() -{ - WayPointMap::const_iterator iter = m_curr; - ++iter; - if (iter == m_WayPoints.end()) - iter = m_WayPoints.begin(); - return iter; -} - -void Transport::TeleportTransport(uint32 newMapid, float x, float y, float z) -{ - Map const* oldMap = GetMap(); - Relocate(x, y, z); - - for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) - { - Player *plr = *itr; - ++itr; - - if (plr->isDead() && !plr->HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST)) - { - plr->ResurrectPlayer(1.0); - } - plr->TeleportTo(newMapid, x, y, z, GetOrientation(), TELE_TO_NOT_LEAVE_TRANSPORT); - - //WorldPacket data(SMSG_811, 4); - //data << uint32(0); - //plr->GetSession()->SendPacket(&data); - } - - //we need to create and save new Map object with 'newMapid' because if not done -> lead to invalid Map object reference... - //player far teleport would try to create same instance, but we need it NOW for transport... - //correct me if I'm wrong O.o - //yes, you're right - - ResetMap(); - Map * newMap = MapManager::Instance().CreateMap(newMapid, this, 0); - SetMap(newMap); - assert (GetMap()); - - if (oldMap != newMap) - { - UpdateForMap(oldMap); - UpdateForMap(newMap); - } -} - -bool Transport::AddPassenger(Player* passenger) -{ - if (m_passengers.insert(passenger).second) - sLog.outDetail("Player %s boarded transport %s.", passenger->GetName(), GetName()); - return true; -} - -bool Transport::RemovePassenger(Player* passenger) -{ - if (m_passengers.erase(passenger)) - sLog.outDetail("Player %s removed from transport %s.", passenger->GetName(), GetName()); - return true; -} - -void Transport::CheckForEvent(uint32 entry, uint32 wp_id) -{ - uint32 key = entry*100+wp_id; - if (objmgr.TransportEventMap.find(key) != objmgr.TransportEventMap.end()) - GetMap()->ScriptsStart(sEventScripts, objmgr.TransportEventMap[key], this, NULL); -} - -void Transport::Update(uint32 /*p_time*/) -{ - if (m_WayPoints.size() <= 1) - return; - - m_timer = getMSTime() % m_period; - while (((m_timer - m_curr->first) % m_pathTime) > ((m_next->first - m_curr->first) % m_pathTime)) - { - m_curr = GetNextWayPoint(); - m_next = GetNextWayPoint(); - - // first check help in case client-server transport coordinates de-synchronization - if (m_curr->second.mapid != GetMapId() || m_curr->second.teleport) - { - TeleportTransport(m_curr->second.mapid, m_curr->second.x, m_curr->second.y, m_curr->second.z); - } - else - { - Relocate(m_curr->second.x, m_curr->second.y, m_curr->second.z); - } -/* - if (m_curr->second.delayed) - { - switch (GetEntry()) - { - case 176495: - case 164871: - case 175080: - SendPlaySound(11804, false); break; // ZeppelinDocked - case 20808: - case 181646: - case 176231: - case 176244: - case 176310: - case 177233: - SendPlaySound(5495, false);break; // BoatDockingWarning - default: - SendPlaySound(5154, false); break; // ShipDocked - } - } -*/ - /* - for (PlayerSet::const_iterator itr = m_passengers.begin(); itr != m_passengers.end();) - { - PlayerSet::const_iterator it2 = itr; - ++itr; - //(*it2)->SetPosition(m_curr->second.x + (*it2)->GetTransOffsetX(), m_curr->second.y + (*it2)->GetTransOffsetY(), m_curr->second.z + (*it2)->GetTransOffsetZ(), (*it2)->GetTransOffsetO()); - } - */ - - m_nextNodeTime = m_curr->first; - - if (m_curr == m_WayPoints.begin() && (sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES) == 0) - sLog.outDetail(" ************ BEGIN ************** %s", this->m_name.c_str()); - - if ((sLog.getLogFilter() & LOG_FILTER_TRANSPORT_MOVES) == 0) - sLog.outDetail("%s moved to %d %f %f %f %d", this->m_name.c_str(), m_curr->second.id, m_curr->second.x, m_curr->second.y, m_curr->second.z, m_curr->second.mapid); - - //Transport Event System - CheckForEvent(this->GetEntry(), m_curr->second.id); - } -} - -void Transport::UpdateForMap(Map const* targetMap) -{ - Map::PlayerList const& pl = targetMap->GetPlayers(); - if (pl.isEmpty()) - return; - - if (GetMapId() == targetMap->GetId()) - { - for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) - { - if (this != itr->getSource()->GetTransport()) - { - UpdateData transData; - BuildCreateUpdateBlockForPlayer(&transData, itr->getSource()); - WorldPacket packet; - transData.BuildPacket(&packet); - itr->getSource()->SendDirectMessage(&packet); - } - } - } - else - { - UpdateData transData; - BuildOutOfRangeUpdateBlock(&transData); - WorldPacket out_packet; - transData.BuildPacket(&out_packet); - - for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr) - if (this != itr->getSource()->GetTransport()) - itr->getSource()->SendDirectMessage(&out_packet); - } -} - diff --git a/src/server/game/Entities/Transport/Transports.h b/src/server/game/Entities/Transport/Transports.h deleted file mode 100644 index 25b9ade1461..00000000000 --- a/src/server/game/Entities/Transport/Transports.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2005-2009 MaNGOS - * - * Copyright (C) 2008-2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef TRANSPORTS_H -#define TRANSPORTS_H - -#include "GameObject.h" - -#include -#include -#include - -class TransportPath -{ - public: - struct PathNode - { - uint32 mapid; - float x,y,z; - uint32 actionFlag; - uint32 delay; - }; - - void SetLength(const unsigned int sz) - { - i_nodes.resize(sz); - } - - unsigned int Size(void) const { return i_nodes.size(); } - bool Empty(void) const { return i_nodes.empty(); } - void Resize(unsigned int sz) { i_nodes.resize(sz); } - void Clear(void) { i_nodes.clear(); } - PathNode* GetNodes(void) { return static_cast(&i_nodes[0]); } - - PathNode& operator[](const unsigned int idx) { return i_nodes[idx]; } - const PathNode& operator()(const unsigned int idx) const { return i_nodes[idx]; } - - protected: - std::vector i_nodes; -}; - -class Transport : public GameObject -{ - public: - explicit Transport(); - - bool Create(uint32 guidlow, uint32 mapid, float x, float y, float z, float ang, uint32 animprogress, uint32 dynflags); - bool GenerateWaypoints(uint32 pathid, std::set &mapids); - void Update(uint32 p_time); - bool AddPassenger(Player* passenger); - bool RemovePassenger(Player* passenger); - void CheckForEvent(uint32 entry, uint32 wp_id); - - typedef std::set PlayerSet; - PlayerSet const& GetPassengers() const { return m_passengers; } - - private: - struct WayPoint - { - WayPoint() : mapid(0), x(0), y(0), z(0), teleport(false), id(0) {} - WayPoint(uint32 _mapid, float _x, float _y, float _z, bool _teleport, uint32 _id) : - mapid(_mapid), x(_x), y(_y), z(_z), teleport(_teleport), id(_id) {} - uint32 mapid; - float x; - float y; - float z; - bool teleport; - uint32 id; - }; - - typedef std::map WayPointMap; - - WayPointMap::const_iterator m_curr; - WayPointMap::const_iterator m_next; - uint32 m_pathTime; - uint32 m_timer; - - PlayerSet m_passengers; - - public: - WayPointMap m_WayPoints; - uint32 m_nextNodeTime; - uint32 m_period; - - private: - void TeleportTransport(uint32 newMapid, float x, float y, float z); - void UpdateForMap(Map const* map); - WayPointMap::const_iterator GetNextWayPoint(); -}; -#endif - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp new file mode 100644 index 00000000000..14ce4a59b37 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp @@ -0,0 +1,309 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_CARRION_SWARM 31306 +#define SPELL_SLEEP 31298 +#define SPELL_VAMPIRIC_AURA 38196 +#define SPELL_INFERNO 31299 + +#define SAY_ONDEATH "The clock... is still... ticking." +#define SOUND_ONDEATH 10982 + +#define SAY_ONSLAY1 "Your hopes are lost!" +#define SAY_ONSLAY2 "Scream for me!" +#define SAY_ONSLAY3 "Pity, no time for a slow death!" +#define SOUND_ONSLAY1 10981 +#define SOUND_ONSLAY2 11038 +#define SOUND_ONSLAY3 11039 + +#define SAY_SWARM1 "The swarm is eager to feed!" +#define SAY_SWARM2 "Pestilence upon you!" +#define SOUND_SWARM1 10979 +#define SOUND_SWARM2 11037 + +#define SAY_SLEEP1 "You look tired..." +#define SAY_SLEEP2 "Sweet dreams..." +#define SOUND_SLEEP1 10978 +#define SOUND_SLEEP2 11545 + +#define SAY_INFERNO1 "Let fire rain from above!" +#define SAY_INFERNO2 "Earth and sky shall burn!" +#define SOUND_INFERNO1 10980 +#define SOUND_INFERNO2 11036 + +#define SAY_ONAGGRO "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!" +#define SOUND_ONAGGRO 10977 + +struct boss_anetheronAI : public hyjal_trashAI +{ + boss_anetheronAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_SLEEP); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) + { + TempSpell->EffectImplicitTargetA[0] = 1; + TempSpell->EffectImplicitTargetB[0] = 0; + } + } + + uint32 SwarmTimer; + uint32 SleepTimer; + uint32 AuraTimer; + uint32 InfernoTimer; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + SwarmTimer = 45000; + SleepTimer = 60000; + AuraTimer = 5000; + InfernoTimer = 45000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_ANETHERONEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, 0); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 4896.08, -1576.35, 1333.65); + AddWaypoint(1, 4898.68, -1615.02, 1329.48); + AddWaypoint(2, 4907.12, -1667.08, 1321.00); + AddWaypoint(3, 4963.18, -1699.35, 1340.51); + AddWaypoint(4, 4989.16, -1716.67, 1335.74); + AddWaypoint(5, 5026.27, -1736.89, 1323.02); + AddWaypoint(6, 5037.77, -1770.56, 1324.36); + AddWaypoint(7, 5067.23, -1789.95, 1321.17); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (SwarmTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CARRION_SWARM); + + SwarmTimer = urand(45000,60000); + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_SWARM1); + me->MonsterYell(SAY_SWARM1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_SWARM2); + me->MonsterYell(SAY_SWARM2, LANG_UNIVERSAL, 0); + break; + } + } else SwarmTimer -= diff; + + if (SleepTimer <= diff) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + pTarget->CastSpell(pTarget,SPELL_SLEEP,true); + } + SleepTimer = 60000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_SLEEP1); + me->MonsterYell(SAY_SLEEP1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_SLEEP2); + me->MonsterYell(SAY_SLEEP2, LANG_UNIVERSAL, 0); + break; + } + } else SleepTimer -= diff; + if (AuraTimer <= diff) + { + DoCast(me, SPELL_VAMPIRIC_AURA, true); + AuraTimer = urand(10000,20000); + } else AuraTimer -= diff; + if (InfernoTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_INFERNO); + InfernoTimer = 45000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_INFERNO1); + me->MonsterYell(SAY_INFERNO1, LANG_UNIVERSAL, 0); + break; + case 1: + DoPlaySoundToSet(me, SOUND_INFERNO2); + me->MonsterYell(SAY_INFERNO2, LANG_UNIVERSAL, 0); + break; + } + } else InfernoTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_anetheron(Creature* pCreature) +{ + return new boss_anetheronAI (pCreature); +} + +#define SPELL_IMMOLATION 31303 +#define SPELL_INFERNO_EFFECT 31302 + +struct mob_towering_infernalAI : public ScriptedAI +{ + mob_towering_infernalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + AnetheronGUID = pInstance->GetData64(DATA_ANETHERON); + } + + uint32 ImmolationTimer; + uint32 CheckTimer; + uint64 AnetheronGUID; + ScriptedInstance* pInstance; + + void Reset() + { + DoCast(me, SPELL_INFERNO_EFFECT); + ImmolationTimer = 5000; + CheckTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + } + + void JustDied(Unit * /*victim*/) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) + AttackStart(who); + } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (AnetheronGUID) + { + Creature* boss = Unit::GetCreature((*me),AnetheronGUID); + if (!boss || (boss && boss->isDead())) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + return; + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (ImmolationTimer <= diff) + { + DoCast(me, SPELL_IMMOLATION); + ImmolationTimer = 5000; + } else ImmolationTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_towering_infernal(Creature* pCreature) +{ + return new mob_towering_infernalAI (pCreature); +} + +void AddSC_boss_anetheron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_anetheron"; + newscript->GetAI = &GetAI_boss_anetheron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_towering_infernal"; + newscript->GetAI = &GetAI_mob_towering_infernal; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp new file mode 100644 index 00000000000..8e1fa378e07 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_archimonde.cpp @@ -0,0 +1,635 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Archimonde +SD%Complete: 85 +SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented. +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "SpellAuras.h" +#include "hyjal_trash.h" + +//text id -1534018 are the text used when previous events complete. Not part of this script. +#define SAY_AGGRO -1534019 +#define SAY_DOOMFIRE1 -1534020 +#define SAY_DOOMFIRE2 -1534021 +#define SAY_AIR_BURST1 -1534022 +#define SAY_AIR_BURST2 -1534023 +#define SAY_SLAY1 -1534024 +#define SAY_SLAY2 -1534025 +#define SAY_SLAY3 -1534026 +#define SAY_ENRAGE -1534027 +#define SAY_DEATH -1534028 +#define SAY_SOUL_CHARGE1 -1534029 +#define SAY_SOUL_CHARGE2 -1534030 + +#define SPELL_DENOUEMENT_WISP 32124 +#define SPELL_ANCIENT_SPARK 39349 +#define SPELL_PROTECTION_OF_ELUNE 38528 + +#define SPELL_DRAIN_WORLD_TREE 39140 +#define SPELL_DRAIN_WORLD_TREE_2 39141 + +#define SPELL_FINGER_OF_DEATH 31984 +#define SPELL_HAND_OF_DEATH 35354 +#define SPELL_AIR_BURST 32014 +#define SPELL_GRIP_OF_THE_LEGION 31972 +#define SPELL_DOOMFIRE_STRIKE 31903 //summons two creatures +#define SPELL_DOOMFIRE_SPAWN 32074 +#define SPELL_DOOMFIRE 31945 +#define SPELL_SOUL_CHARGE_YELLOW 32045 +#define SPELL_SOUL_CHARGE_GREEN 32051 +#define SPELL_SOUL_CHARGE_RED 32052 +#define SPELL_UNLEASH_SOUL_YELLOW 32054 +#define SPELL_UNLEASH_SOUL_GREEN 32057 +#define SPELL_UNLEASH_SOUL_RED 32053 +#define SPELL_FEAR 31970 + +#define CREATURE_ARCHIMONDE 17968 +#define CREATURE_DOOMFIRE 18095 +#define CREATURE_DOOMFIRE_SPIRIT 18104 +#define CREATURE_ANCIENT_WISP 17946 +#define CREATURE_CHANNEL_TARGET 22418 + +#define NORDRASSIL_X 5503.713 +#define NORDRASSIL_Y -3523.436 +#define NORDRASSIL_Z 1608.781 + +struct mob_ancient_wispAI : public ScriptedAI +{ + mob_ancient_wispAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + ArchimondeGUID = 0; + } + + ScriptedInstance* pInstance; + uint64 ArchimondeGUID; + uint32 CheckTimer; + + void Reset() + { + CheckTimer = 1000; + + if (pInstance) + ArchimondeGUID = pInstance->GetData64(DATA_ARCHIMONDE); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void EnterCombat(Unit* /*who*/) {} + + void DamageTaken(Unit* /*done_by*/, uint32 &damage) { damage = 0; } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (Unit* Archimonde = Unit::GetUnit((*me), ArchimondeGUID)) + { + if ((((Archimonde->GetHealth()*100) / Archimonde->GetMaxHealth()) < 2) || !Archimonde->isAlive()) + DoCast(me, SPELL_DENOUEMENT_WISP); + else + DoCast(Archimonde, SPELL_ANCIENT_SPARK); + } + CheckTimer = 1000; + } else CheckTimer -= diff; + } +}; + +/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will + MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */ +struct mob_doomfireAI : public ScriptedAI +{ + mob_doomfireAI(Creature* c) : ScriptedAI(c) {} + + void Reset() { } + + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit* /*who*/) {} + void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } +}; + +/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or + travels in random directions if pTarget cannot be found. */ +struct mob_doomfire_targettingAI : public ScriptedAI +{ + mob_doomfire_targettingAI(Creature* c) : ScriptedAI(c) {} + + uint64 TargetGUID; + uint32 ChangeTargetTimer; + + void Reset() + { + TargetGUID = 0; + ChangeTargetTimer = 5000; + } + + void MoveInLineOfSight(Unit* who) + { + //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0 + //when UpdateAI needs it, it will be forced to select randomPoint + if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER) + TargetGUID = who->GetGUID(); + } + + void EnterCombat(Unit* /*who*/) {} + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } + + void UpdateAI(const uint32 diff) + { + if (ChangeTargetTimer <= diff) + { + if (Unit *temp = Unit::GetUnit(*me,TargetGUID)) + { + me->GetMotionMaster()->MoveFollow(temp,0.0f,0.0f); + TargetGUID = 0; + } + else + { + Position pos; + me->GetRandomNearPosition(pos, 40); + me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ); + } + + ChangeTargetTimer = 5000; + } else ChangeTargetTimer -= diff; + } +}; + +/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers. + The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the + hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then + select a random pTarget and cast the spell on them. However, if someone IS in melee range, and this + is NOT the main tank (creature's victim), then we aggro that player and they become the new victim. + For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will + randomly select it's pTarget to follow and then we create the random movement making it unpredictable. */ + +struct boss_archimondeAI : public hyjal_trashAI +{ + boss_archimondeAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 DoomfireSpiritGUID; + uint64 WorldTreeGUID; + + uint32 DrainNordrassilTimer; + uint32 FearTimer; + uint32 AirBurstTimer; + uint32 GripOfTheLegionTimer; + uint32 DoomfireTimer; + uint32 SoulChargeTimer; + uint32 SoulChargeCount; + uint32 MeleeRangeCheckTimer; + uint32 HandOfDeathTimer; + uint32 SummonWispTimer; + uint32 WispCount; + uint32 EnrageTimer; + uint32 CheckDistanceTimer; + + bool Enraged; + bool BelowTenPercent; + bool HasProtected; + bool IsChanneling; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); + + DoomfireSpiritGUID = 0; + damageTaken = 0; + WorldTreeGUID = 0; + + DrainNordrassilTimer = 0; + FearTimer = 42000; + AirBurstTimer = 30000; + GripOfTheLegionTimer = urand(5000,25000); + DoomfireTimer = 20000; + SoulChargeTimer = urand(2000,30000); + SoulChargeCount = 0; + MeleeRangeCheckTimer = 15000; + HandOfDeathTimer = 2000; + WispCount = 0; // When ~30 wisps are summoned, Archimonde dies + EnrageTimer = 600000; // 10 minutes + CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage + SummonWispTimer = 0; + + Enraged = false; + BelowTenPercent = false; + HasProtected = false; + IsChanneling = false; + } + + void EnterCombat(Unit * /*who*/) + { + me->InterruptSpell(CURRENT_CHANNELED_SPELL); + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * victim) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + + if (victim && (victim->GetTypeId() == TYPEID_PLAYER)) + GainSoulCharge(CAST_PLR(victim)); + } + + void GainSoulCharge(Player* victim) + { + switch(victim->getClass()) + { + case CLASS_PRIEST: + case CLASS_PALADIN: + case CLASS_WARLOCK: + victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); + break; + case CLASS_MAGE: + case CLASS_ROGUE: + case CLASS_WARRIOR: + victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); + break; + case CLASS_DRUID: + case CLASS_SHAMAN: + case CLASS_HUNTER: + victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); + break; + } + + SoulChargeTimer = urand(2000,30000); + ++SoulChargeCount; + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_ARCHIMONDEEVENT, DONE); + } + + bool CanUseFingerOfDeath() + { + // First we check if our current victim is in melee range or not. + Unit* victim = me->getVictim(); + if (victim && me->IsWithinDistInMap(victim, me->GetAttackDistance(victim))) + return false; + + std::list& m_threatlist = me->getThreatManager().getThreatList(); + if (m_threatlist.empty()) + return false; + + std::list targets; + std::list::const_iterator itr = m_threatlist.begin(); + for (; itr != m_threatlist.end(); ++itr) + { + Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); + if (pUnit && pUnit->isAlive()) + targets.push_back(pUnit); + } + + if (targets.empty()) + return false; + + targets.sort(Trinity::ObjectDistanceOrderPred(me)); + Unit *pTarget = targets.front(); + if (pTarget) + { + if (!me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) + return true; // Cast Finger of Death + else // This target is closest, he is our new tank + me->AddThreat(pTarget, me->getThreatManager().getThreat(me->getVictim())); + } + + return false; + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == CREATURE_ANCIENT_WISP) + summoned->AI()->AttackStart(me); + else + { + summoned->setFaction(me->getFaction()); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) + { + DoomfireSpiritGUID = summoned->GetGUID(); + } + + if (summoned->GetEntry() == CREATURE_DOOMFIRE) + { + summoned->CastSpell(summoned,SPELL_DOOMFIRE_SPAWN,false); + summoned->CastSpell(summoned,SPELL_DOOMFIRE,true,0,0,me->GetGUID()); + + if (Unit *DoomfireSpirit = Unit::GetUnit(*me, DoomfireSpiritGUID)) + { + summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit,0.0f,0.0f); + DoomfireSpiritGUID = 0; + } + } + } + + //this is code doing close to what the summoning spell would do (spell 31903) + void SummonDoomfire(Unit *pTarget) + { + me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, + pTarget->GetPositionX()+15.0,pTarget->GetPositionY()+15.0,pTarget->GetPositionZ(),0, + TEMPSUMMON_TIMED_DESPAWN, 27000); + + me->SummonCreature(CREATURE_DOOMFIRE, + pTarget->GetPositionX()-15.0,pTarget->GetPositionY()-15.0,pTarget->GetPositionZ(),0, + TEMPSUMMON_TIMED_DESPAWN, 27000); + } + + void UnleashSoulCharge() + { + me->InterruptNonMeleeSpells(false); + + bool HasCast = false; + uint32 chargeSpell = 0; + uint32 unleashSpell = 0; + + switch (urand(0,2)) + { + case 0: + chargeSpell = SPELL_SOUL_CHARGE_RED; + unleashSpell = SPELL_UNLEASH_SOUL_RED; + break; + case 1: + chargeSpell = SPELL_SOUL_CHARGE_YELLOW; + unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; + break; + case 2: + chargeSpell = SPELL_SOUL_CHARGE_GREEN; + unleashSpell = SPELL_UNLEASH_SOUL_GREEN; + break; + } + + if (me->HasAura(chargeSpell)) + { + me->RemoveAuraFromStack(chargeSpell); + DoCast(me->getVictim(), unleashSpell); + HasCast = true; + SoulChargeCount--; + } + + if (HasCast) + SoulChargeTimer = urand(2000,30000); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + { + if (pInstance) + { + // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. + if ((pInstance->GetData(DATA_AZGALOREVENT) < DONE) && ((me->GetVisibility() != VISIBILITY_OFF) || (me->getFaction() != 35))) + { + me->SetVisibility(VISIBILITY_OFF); + me->setFaction(35); + } + else if ((pInstance->GetData(DATA_AZGALOREVENT) >= DONE) && ((me->GetVisibility() != VISIBILITY_ON) || (me->getFaction() == 35))) + { + me->setFaction(1720); + me->SetVisibility(VISIBILITY_ON); + } + } + + if (DrainNordrassilTimer <= diff) + { + if (!IsChanneling) + { + Creature *temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 1200000); + + if (temp) + WorldTreeGUID = temp->GetGUID(); + + if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) + { + Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Nordrassil->SetDisplayId(11686); + DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); + IsChanneling = true; + } + } + + if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) + { + Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); + DrainNordrassilTimer = 1000; + } + } else DrainNordrassilTimer -= diff; + } + + if (!UpdateVictim()) + return; + + if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !BelowTenPercent && !Enraged) + BelowTenPercent = true; + + if (!Enraged) + { + if (EnrageTimer <= diff) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) > 10) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + Enraged = true; + DoScriptText(SAY_ENRAGE, me); + } + } else EnrageTimer -= diff; + + if (CheckDistanceTimer <= diff) + { + // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature + Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000); + if (Check) + { + Check->SetVisibility(VISIBILITY_OFF); + + if (me->IsWithinDistInMap(Check, 75)) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + Enraged = true; + DoScriptText(SAY_ENRAGE, me); + } + } + CheckDistanceTimer = 5000; + } else CheckDistanceTimer -= diff; + } + + if (BelowTenPercent) + { + if (!HasProtected) + { + me->GetMotionMaster()->Clear(false); + me->GetMotionMaster()->MoveIdle(); + + //all members of raid must get this buff + DoCast(me->getVictim(), SPELL_PROTECTION_OF_ELUNE); + HasProtected = true; + Enraged = true; + } + + if (SummonWispTimer <= diff) + { + DoSpawnCreature(CREATURE_ANCIENT_WISP, rand()%40, rand()%40, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + SummonWispTimer = 1500; + ++WispCount; + } else SummonWispTimer -= diff; + + if (WispCount >= 30) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (Enraged) + { + if (HandOfDeathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_HAND_OF_DEATH); + HandOfDeathTimer = 2000; + } else HandOfDeathTimer -= diff; + return; // Don't do anything after this point. + } + + if (SoulChargeCount) + { + if (SoulChargeTimer <= diff) + UnleashSoulCharge(); + else SoulChargeTimer -= diff; + } + + if (GripOfTheLegionTimer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); + GripOfTheLegionTimer = urand(5000,25000); + } else GripOfTheLegionTimer -= diff; + + if (AirBurstTimer <= diff) + { + if (urand(0,1)) + DoScriptText(SAY_AIR_BURST1, me); + else + DoScriptText(SAY_AIR_BURST2, me); + + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank + AirBurstTimer = urand(25000,40000); + } else AirBurstTimer -= diff; + + if (FearTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FEAR); + FearTimer = 42000; + } else FearTimer -= diff; + + if (DoomfireTimer <= diff) + { + if (urand(0,1)) + DoScriptText(SAY_DOOMFIRE1, me); + else + DoScriptText(SAY_DOOMFIRE2, me); + + Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 1); + if (!temp) + temp = me->getVictim(); + + //replace with spell cast 31903 once implicitTarget 73 implemented + SummonDoomfire(temp); + + //supposedly three doomfire can be up at the same time + DoomfireTimer = 20000; + } else DoomfireTimer -= diff; + + if (MeleeRangeCheckTimer <= diff) + { + if (CanUseFingerOfDeath()) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); + MeleeRangeCheckTimer = 1000; + } + + MeleeRangeCheckTimer = 5000; + } else MeleeRangeCheckTimer -= diff; + + DoMeleeAttackIfReady(); + } + void WaypointReached(uint32 /*i*/){} +}; + +CreatureAI* GetAI_boss_archimonde(Creature* pCreature) +{ + return new boss_archimondeAI (pCreature); +} + +CreatureAI* GetAI_mob_doomfire(Creature* pCreature) +{ + return new mob_doomfireAI(pCreature); +} + +CreatureAI* GetAI_mob_doomfire_targetting(Creature* pCreature) +{ + return new mob_doomfire_targettingAI(pCreature); +} + +CreatureAI* GetAI_mob_ancient_wisp(Creature* pCreature) +{ + return new mob_ancient_wispAI(pCreature); +} + +void AddSC_boss_archimonde() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_archimonde"; + newscript->GetAI = &GetAI_boss_archimonde; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_doomfire"; + newscript->GetAI = &GetAI_mob_doomfire; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_doomfire_targetting"; + newscript->GetAI = &GetAI_mob_doomfire_targetting; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ancient_wisp"; + newscript->GetAI = &GetAI_mob_ancient_wisp; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp new file mode 100644 index 00000000000..69e37f7f740 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp @@ -0,0 +1,285 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_RAIN_OF_FIRE 31340 +#define SPELL_DOOM 31347 +#define SPELL_HOWL_OF_AZGALOR 31344 +#define SPELL_CLEAVE 31345 +#define SPELL_BERSERK 26662 + +#define SAY_ONDEATH "Your time is almost... up" +#define SOUND_ONDEATH 11002 + +#define SAY_ONSLAY1 "Reesh, hokta!" +#define SAY_ONSLAY2 "Don't fight it" +#define SAY_ONSLAY3 "No one is going to save you" +#define SOUND_ONSLAY1 11001 +#define SOUND_ONSLAY2 11048 +#define SOUND_ONSLAY3 11047 + +#define SAY_DOOM1 "Just a taste... of what awaits you" +#define SAY_DOOM2 "Suffer you despicable insect!" +#define SOUND_DOOM1 11046 +#define SOUND_DOOM2 11000 + +#define SAY_ONAGGRO "Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!" +#define SOUND_ONAGGRO 10999 + +struct boss_azgalorAI : public hyjal_trashAI +{ + boss_azgalorAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_HOWL_OF_AZGALOR); + if (TempSpell) + TempSpell->EffectRadiusIndex[0] = 12;//100yards instead of 50000?! + } + + uint32 RainTimer; + uint32 DoomTimer; + uint32 HowlTimer; + uint32 CleaveTimer; + uint32 EnrageTimer; + bool enraged; + + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + RainTimer = 20000; + DoomTimer = 50000; + HowlTimer = 30000; + CleaveTimer = 10000; + EnrageTimer = 600000; + enraged = false; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_AZGALOREVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 5492.91, -2404.61, 1462.63); + AddWaypoint(1, 5531.76, -2460.87, 1469.55); + AddWaypoint(2, 5554.58, -2514.66, 1476.12); + AddWaypoint(3, 5554.16, -2567.23, 1479.90); + AddWaypoint(4, 5540.67, -2625.99, 1480.89); + AddWaypoint(5, 5508.16, -2659.2, 1480.15); + AddWaypoint(6, 5489.62, -2704.05, 1482.18); + AddWaypoint(7, 5457.04, -2726.26, 1485.10); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (RainTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,30,true), SPELL_RAIN_OF_FIRE); + RainTimer = 20000+rand()%15000; + } else RainTimer -= diff; + + if (DoomTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,100,true), SPELL_DOOM);//never on tank + DoomTimer = 45000+rand()%5000; + } else DoomTimer -= diff; + + if (HowlTimer <= diff) + { + DoCast(me, SPELL_HOWL_OF_AZGALOR); + HowlTimer = 30000; + } else HowlTimer -= diff; + + if (CleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + CleaveTimer = 10000+rand()%5000; + } else CleaveTimer -= diff; + + if (EnrageTimer < diff && !enraged) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_BERSERK, true); + enraged = true; + EnrageTimer = 600000; + } else EnrageTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_azgalor(Creature* pCreature) +{ + return new boss_azgalorAI (pCreature); +} + +#define SPELL_THRASH 12787 +#define SPELL_CRIPPLE 31406 +#define SPELL_WARSTOMP 31408 + +struct mob_lesser_doomguardAI : public hyjal_trashAI +{ + mob_lesser_doomguardAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + AzgalorGUID = pInstance->GetData64(DATA_AZGALOR); + } + + uint32 CrippleTimer; + uint32 WarstompTimer; + uint32 CheckTimer; + uint64 AzgalorGUID; + ScriptedInstance* pInstance; + + void Reset() + { + CrippleTimer = 50000; + WarstompTimer = 10000; + DoCast(me, SPELL_THRASH); + CheckTimer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void KilledUnit(Unit * /*victim*/) + { + } + + void WaypointReached(uint32 /*i*/) + { + } + + void MoveInLineOfSight(Unit *who) + { + if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) + AttackStart(who); + } + + void JustDied(Unit * /*victim*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (CheckTimer <= diff) + { + if (AzgalorGUID) + { + Creature* boss = Unit::GetCreature((*me),AzgalorGUID); + if (!boss || (boss && boss->isDead())) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + return; + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (WarstompTimer <= diff) + { + DoCast(me, SPELL_WARSTOMP); + WarstompTimer = 10000+rand()%5000; + } else WarstompTimer -= diff; + + if (CrippleTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_CRIPPLE); + CrippleTimer = 25000+rand()%5000; + } else CrippleTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_lesser_doomguard(Creature* pCreature) +{ + return new mob_lesser_doomguardAI (pCreature); +} + +void AddSC_boss_azgalor() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_azgalor"; + newscript->GetAI = &GetAI_boss_azgalor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lesser_doomguard"; + newscript->GetAI = &GetAI_mob_lesser_doomguard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp new file mode 100644 index 00000000000..b52d22842e3 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp @@ -0,0 +1,197 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_CLEAVE 31436 +#define SPELL_WARSTOMP 31480 +#define SPELL_MARK 31447 + +#define SOUND_ONDEATH 11018 + +#define SAY_ONSLAY1 "Shaza-Kiel!" +#define SAY_ONSLAY2 "You... are nothing!" +#define SAY_ONSLAY3 "Miserable nuisance!" +#define SOUND_ONSLAY1 11017 +#define SOUND_ONSLAY2 11053 +#define SOUND_ONSLAY3 11054 + +#define SAY_MARK1 "Your death will be a painful one." +#define SAY_MARK2 "You... are marked." +#define SOUND_MARK1 11016 +#define SOUND_MARK2 11052 + +#define SAY_ONAGGRO "Cry for mercy! Your meaningless lives will soon be forfeit." +#define SOUND_ONAGGRO 11015 + +struct boss_kazrogalAI : public hyjal_trashAI +{ + boss_kazrogalAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + SpellEntry *TempSpell = GET_SPELL(SPELL_MARK); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) + { + TempSpell->EffectImplicitTargetA[0] = 1; + TempSpell->EffectImplicitTargetB[0] = 0; + } + } + + uint32 CleaveTimer; + uint32 WarStompTimer; + uint32 MarkTimer; + uint32 MarkTimerBase; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + CleaveTimer = 5000; + WarStompTimer = 15000; + MarkTimer = 45000; + MarkTimerBase = 45000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + case 2: + DoPlaySoundToSet(me, SOUND_ONSLAY3); + me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_KAZROGALEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 5492.91, -2404.61, 1462.63); + AddWaypoint(1, 5531.76, -2460.87, 1469.55); + AddWaypoint(2, 5554.58, -2514.66, 1476.12); + AddWaypoint(3, 5554.16, -2567.23, 1479.90); + AddWaypoint(4, 5540.67, -2625.99, 1480.89); + AddWaypoint(5, 5508.16, -2659.2, 1480.15); + AddWaypoint(6, 5489.62, -2704.05, 1482.18); + AddWaypoint(7, 5457.04, -2726.26, 1485.10); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (CleaveTimer <= diff) + { + DoCast(me, SPELL_CLEAVE); + CleaveTimer = 6000+rand()%15000; + } else CleaveTimer -= diff; + + if (WarStompTimer <= diff) + { + DoCast(me, SPELL_WARSTOMP); + WarStompTimer = 60000; + } else WarStompTimer -= diff; + + if (me->HasAura(SPELL_MARK)) + me->RemoveAurasDueToSpell(SPELL_MARK); + if (MarkTimer <= diff) + { + //cast dummy, useful for bos addons + me->CastCustomSpell(me, SPELL_MARK, NULL, NULL, NULL, false, NULL, NULL, me->GetGUID()); + + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->getPowerType() == POWER_MANA) + { + pTarget->CastSpell(pTarget, SPELL_MARK,true);//only cast on mana users + } + } + MarkTimerBase -= 5000; + if (MarkTimerBase < 5500) + MarkTimerBase = 5500; + MarkTimer = MarkTimerBase; + switch (urand(0,2)) + { + case 0: + DoPlaySoundToSet(me, SOUND_MARK1); + me->MonsterYell(SAY_MARK1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_MARK2); + me->MonsterYell(SAY_MARK2, LANG_UNIVERSAL, NULL); + break; + } + } else MarkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kazrogal(Creature* pCreature) +{ + return new boss_kazrogalAI (pCreature); +} + +void AddSC_boss_kazrogal() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kazrogal"; + newscript->GetAI = &GetAI_boss_kazrogal; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp new file mode 100644 index 00000000000..7465b997117 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp @@ -0,0 +1,192 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +#define SPELL_FROST_ARMOR 31256 +#define SPELL_DEATH_AND_DECAY 31258 + +#define SPELL_FROST_NOVA 31250 +#define SPELL_ICEBOLT 31249 + +#define SAY_ONDEATH "You have won this battle, but not... the... war" +#define SOUND_ONDEATH 11026 + +#define SAY_ONSLAY1 "All life must perish!" +#define SAY_ONSLAY2 "Victory to the Legion!" +#define SOUND_ONSLAY1 11025 +#define SOUND_ONSLAY2 11057 + +#define SAY_DECAY1 "Crumble and rot!" +#define SAY_DECAY2 "Ashes to ashes, dust to dust" +#define SOUND_DECAY1 11023 +#define SOUND_DECAY2 11055 + +#define SAY_NOVA1 "Succumb to the icy chill... of death!" +#define SAY_NOVA2 "It will be much colder in your grave" +#define SOUND_NOVA1 11024 +#define SOUND_NOVA2 11058 + +#define SAY_ONAGGRO "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!" +#define SOUND_ONAGGRO 11022 + +struct boss_rage_winterchillAI : public hyjal_trashAI +{ + boss_rage_winterchillAI(Creature *c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + } + + uint32 FrostArmorTimer; + uint32 DecayTimer; + uint32 NovaTimer; + uint32 IceboltTimer; + bool pGo; + uint32 pos; + + void Reset() + { + damageTaken = 0; + FrostArmorTimer = 37000; + DecayTimer = 45000; + NovaTimer = 15000; + IceboltTimer = 10000; + + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS); + DoPlaySoundToSet(me, SOUND_ONAGGRO); + me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); + } + + void KilledUnit(Unit * /*victim*/) + { + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_ONSLAY1); + me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_ONSLAY2); + me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); + break; + } + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0f); + } + } + + void JustDied(Unit *victim) + { + hyjal_trashAI::JustDied(victim); + if (pInstance && IsEvent) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE); + DoPlaySoundToSet(me, SOUND_ONDEATH); + me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, NULL); + } + + void UpdateAI(const uint32 diff) + { + if (IsEvent) + { + //Must update npc_escortAI + npc_escortAI::UpdateAI(diff); + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, 4896.08, -1576.35, 1333.65); + AddWaypoint(1, 4898.68, -1615.02, 1329.48); + AddWaypoint(2, 4907.12, -1667.08, 1321.00); + AddWaypoint(3, 4963.18, -1699.35, 1340.51); + AddWaypoint(4, 4989.16, -1716.67, 1335.74); + AddWaypoint(5, 5026.27, -1736.89, 1323.02); + AddWaypoint(6, 5037.77, -1770.56, 1324.36); + AddWaypoint(7, 5067.23, -1789.95, 1321.17); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (FrostArmorTimer <= diff) + { + DoCast(me, SPELL_FROST_ARMOR); + FrostArmorTimer = 40000+rand()%20000; + } else FrostArmorTimer -= diff; + if (DecayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_DEATH_AND_DECAY); + DecayTimer = 60000+rand()%20000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_DECAY1); + me->MonsterYell(SAY_DECAY1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_DECAY2); + me->MonsterYell(SAY_DECAY2, LANG_UNIVERSAL, NULL); + break; + } + } else DecayTimer -= diff; + if (NovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_NOVA); + NovaTimer = 30000+rand()%15000; + switch (urand(0,1)) + { + case 0: + DoPlaySoundToSet(me, SOUND_NOVA1); + me->MonsterYell(SAY_NOVA1, LANG_UNIVERSAL, NULL); + break; + case 1: + DoPlaySoundToSet(me, SOUND_NOVA2); + me->MonsterYell(SAY_NOVA2, LANG_UNIVERSAL, NULL); + break; + } + } else NovaTimer -= diff; + if (IceboltTimer <= diff) + { + DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,40,true), SPELL_ICEBOLT); + IceboltTimer = 11000+rand()%20000; + } else IceboltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_rage_winterchill(Creature* pCreature) +{ + return new boss_rage_winterchillAI (pCreature); +} + +void AddSC_boss_rage_winterchill() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_rage_winterchill"; + newscript->GetAI = &GetAI_boss_rage_winterchill; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp new file mode 100644 index 00000000000..16a050939cc --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.cpp @@ -0,0 +1,247 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Hyjal +SD%Complete: 80 +SDComment: gossip text id's unknown +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +/* ContentData +npc_jaina_proudmoore +npc_thrall +npc_tyrande_whisperwind +EndContentData */ + +#include "ScriptedPch.h" +#include "hyjalAI.h" + +#define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore." +#define GOSSIP_ITEM_ANETHERON "We are ready for whatever Archimonde might send our way, Lady Proudmoore." + +#define GOSSIP_ITEM_BEGIN_HORDE "I am with you, Thrall." +#define GOSSIP_ITEM_AZGALOR "We have nothing to fear." + +#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!" + +#define GOSSIP_ITEM_TYRANDE "Aid us in defending Nordrassil" +#define ITEM_TEAR_OF_GODDESS 24494 + +#define GOSSIP_ITEM_GM1 "[GM] Toggle Debug Timers" + +CreatureAI* GetAI_npc_jaina_proudmoore(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + + ai->Reset(); + ai->EnterEvadeMode(); + + ai->Spell[0].SpellId = SPELL_BLIZZARD; + ai->Spell[0].Cooldown = 15000 + rand()%20000; + ai->Spell[0].TargetType = TARGETTYPE_RANDOM; + + ai->Spell[1].SpellId = SPELL_PYROBLAST; + ai->Spell[1].Cooldown = 5500 + rand()%4000; + ai->Spell[1].TargetType = TARGETTYPE_RANDOM; + + ai->Spell[2].SpellId = SPELL_SUMMON_ELEMENTALS; + ai->Spell[2].Cooldown = 15000 + rand()%30000; + ai->Spell[2].TargetType = TARGETTYPE_SELF; + + return ai; +} + +bool GossipHello_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + if (ai->EventBegun) + return false; + + uint32 RageEncounter = ai->GetInstanceData(DATA_RAGEWINTERCHILLEVENT); + uint32 AnetheronEncounter = ai->GetInstanceData(DATA_ANETHERONEVENT); + if (RageEncounter == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + else if (RageEncounter == DONE && AnetheronEncounter == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + else if (RageEncounter == DONE && AnetheronEncounter == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + if (pPlayer->isGameMaster()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + ai->FirstBossDead = true; + ai->WaveCount = 9; + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + ai->Retreat(); + break; + case GOSSIP_ACTION_INFO_DEF: + ai->Debug = !ai->Debug; + debug_log("TSCR: HyjalAI - Debug mode has been toggled"); + break; + } + return true; +} + +CreatureAI* GetAI_npc_thrall(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + + ai->Reset(); + ai->EnterEvadeMode(); + + ai->Spell[0].SpellId = SPELL_CHAIN_LIGHTNING; + ai->Spell[0].Cooldown = 3000 + rand()%5000; + ai->Spell[0].TargetType = TARGETTYPE_VICTIM; + + ai->Spell[1].SpellId = SPELL_SUMMON_DIRE_WOLF; + ai->Spell[1].Cooldown = 6000 + rand()%35000; + ai->Spell[1].TargetType = TARGETTYPE_RANDOM; + + return ai; +} + +bool GossipHello_npc_thrall(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + if (ai->EventBegun) + return false; + + uint32 AnetheronEvent = ai->GetInstanceData(DATA_ANETHERONEVENT); + // Only let them start the Horde phases if Anetheron is dead. + if (AnetheronEvent == DONE && ai->GetInstanceData(DATA_ALLIANCE_RETREAT)) + { + uint32 KazrogalEvent = ai->GetInstanceData(DATA_KAZROGALEVENT); + uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); + if (KazrogalEvent == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + else if (KazrogalEvent == DONE && AzgalorEvent == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + else if (AzgalorEvent == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + } + + if (pPlayer->isGameMaster()) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_thrall(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + ai->DeSpawnVeins();//despawn the alliance veins + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + ai->FirstBossDead = true; + ai->WaveCount = 9; + ai->StartEvent(pPlayer); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + ai->Retreat(); + break; + case GOSSIP_ACTION_INFO_DEF: + ai->Debug = !ai->Debug; + debug_log("TSCR: HyjalAI - Debug mode has been toggled"); + break; + } + return true; +} + +CreatureAI* GetAI_npc_tyrande_whisperwind(Creature* pCreature) +{ + hyjalAI* ai = new hyjalAI(pCreature); + ai->Reset(); + ai->EnterEvadeMode(); + return ai; +} + +bool GossipHello_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature) +{ + hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); + uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); + + // Only let them get item if Azgalor is dead. + if (AzgalorEvent == DONE && !pPlayer->HasItemCount(ITEM_TEAR_OF_GODDESS,1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TYRANDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_TEAR_OF_GODDESS, 1); + if (msg == EQUIP_ERR_OK) + { + Item* item = pPlayer->StoreNewItem(dest, ITEM_TEAR_OF_GODDESS, true); + if (item && pPlayer) + pPlayer->SendNewItem(item,1,true,false,true); + } + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + CAST_AI(hyjalAI, pCreature->AI()); + } + return true; +} + +void AddSC_hyjal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_jaina_proudmoore"; + newscript->GetAI = &GetAI_npc_jaina_proudmoore; + newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore; + newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thrall"; + newscript->GetAI = &GetAI_npc_thrall; + newscript->pGossipHello = &GossipHello_npc_thrall; + newscript->pGossipSelect = &GossipSelect_npc_thrall; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tyrande_whisperwind"; + newscript->pGossipHello = &GossipHello_npc_tyrande_whisperwind; + newscript->pGossipSelect = &GossipSelect_npc_tyrande_whisperwind; + newscript->GetAI = &GetAI_npc_tyrande_whisperwind; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h new file mode 100644 index 00000000000..bfc9a54dfd9 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal.h @@ -0,0 +1,38 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_HYJAL_H +#define DEF_HYJAL_H + +#define ERROR_INST_DATA "TSCR: Instance data not set properly for Mount Hyjal. Encounters will be buggy." + +enum eTypes +{ + WORLD_STATE_WAVES = 2842, + WORLD_STATE_ENEMY = 2453, + WORLD_STATE_ENEMYCOUNT = 2454, + + DATA_ANETHERON = 1, + DATA_ANETHERONEVENT = 2, + DATA_ARCHIMONDE = 3, + DATA_ARCHIMONDEEVENT = 4, + DATA_AZGALOR = 5, + DATA_AZGALOREVENT = 6, + DATA_JAINAPROUDMOORE = 7, + DATA_KAZROGAL = 8, + DATA_KAZROGALEVENT = 9, + DATA_RAGEWINTERCHILL = 10, + DATA_RAGEWINTERCHILLEVENT = 11, + DATA_THRALL = 12, + DATA_TYRANDEWHISPERWIND = 13, + DATA_TRASH = 14, + DATA_RESET_TRASH_COUNT = 15, + DATA_ALLIANCE_RETREAT = 16, + DATA_HORDE_RETREAT = 17, + DATA_RAIDDAMAGE = 18, + DATA_RESET_RAIDDAMAGE = 19, + TYPE_RETREAT = 20 +}; +#endif + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp new file mode 100644 index 00000000000..3c12b54f3f4 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp @@ -0,0 +1,1157 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: HyjalAI +SD%Complete: 90 +SDComment: +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjalAI.h" +#include "hyjal_trash.h" +#include "MapManager.h" +#include "Language.h" +#include "Chat.h" +#include "Object.h" + +#define SPAWN_GARG_GATE 0 +#define SPAWN_WYRM_GATE 1 +#define SPAWN_NEAR_TOWER 2 + +#define YELL_HURRY "Hurry, we don't have much time" + +// Locations for summoning gargoyls and frost wyrms in special cases +float SpawnPointSpecial[3][3]= +{ + {5497.08, -2493.23, 1535.72}, //spawn point for the gargoyles near the horde gate + {5624.53, -2548.12, 1551.54}, //spawn point for the frost wyrm near the horde gate + {5604.41, -2811.98, 1547.77} //spawn point for the gargoyles and wyrms near the horde tower +}; + +// Locations for summoning waves in Alliance base +float AllianceBase[4][3]= +{ + {4928.48, -1526.38, 1326.83}, + {4923.54, -1514.29, 1327.98}, + {4928.41, -1510.35, 1327.99}, + {4938.35, -1521.00, 1326.69} +}; + +float JainaDummySpawn[2][4]= +{ + {5497.01, -2719.03, 1483.08, 2.90426}, + {5484.98, -2721.69, 1483.39, 6.00656} +}; + +// Locations for summoning waves in Horde base +float HordeBase[4][3]= +{ + {5458.01, -2340.27, 1459.60}, + {5466.01, -2334.69, 1460.06}, + {5468.45, -2355.13, 1459.99}, + {5479.06, -2344.16, 1461.74} +}; + +// Lady Jaina's waypoints when retreathing +float JainaWPs[2][3]= +{ + {5078.56, -1789.79, 1320.73},//next to the small stairs + {5037.38, -1778.39, 1322.61},//center of alliance base +}; + +float InfernalPos[8][3]=//spawn points for the infernals in the horde base +{ + {5453.59, -2764.52, 1493.50}, + {5478.4, -2781.77, 1497.52}, + {5506.09, -2780.53, 1496.32}, + {5532.1, -2763.42, 1492.37}, + {5544.16, -2733.99, 1487.14}, + {5536.19, -2708.18, 1480.01}, + {5510.16, -2691.75, 1479.66}, + {5482.39, -2689.19, 1481.09} +}; + +float InfernalSPWP[26][4]=//spawn points for the infernals in the horde base used in the cleaning wave +{ + {5490.96, -2718.72, 1482.96, 0.49773}, + {5449.51, -2723.32, 1485.69, 2.69685}, + {5520.83, -2624.68, 1483.82, 1.20459}, + {5558.28, -2629.26, 1485.76, 0.37992}, + {5567.97, -2758.69, 1494.10, 5.04125}, + {5384.90, -2793.47, 1503.90, 5.55412}, + {5495.33, -2814.06, 1501.56, 1.12055}, + {5472.63, -2929.39, 1538.31, 1.95777}, + {5334.72, -2952.29, 1534.34, 0.50869}, + {5398.36, -2872.46, 1512.38, 0.76787}, + {5514.39, -2768.63, 1492.30, 1.55721}, + {5598.91, -2703.75, 1495.64, 2.56644}, + {5467.80, -2655.93, 1482.27, 0.85819}, + {5399.83, -2985.24, 1545.04, 5.92559}, + {5232.13, -2967.05, 1553.09, 5.41351}, + {5272.02, -3082.52, 1567.09, 3.40681}, + {5343.26, -3120.71, 1582.92, 3.16727}, + {5371.26, -3175.24, 1587.41, 6.10466}, + {5434.67, -3177.91, 1579.25, 2.77850}, + {5237.39, -3149.25, 1593.59, 0.83855}, + {5202.15, -3016.64, 1566.28, 3.31256}, + {5302.54, -2914.37, 1528.53, 3.37146}, + {5439.04, -2834.81, 1508.80, 2.14231}, + {5421.33, -2771.04, 1494.28, 6.06223}, + {5549.76, -2692.93, 1482.68, 2.19414}, + {5459.78, -2755.71, 1490.68, 1.05139} +}; + +float VeinPos[14][8]=//spawn points of the ancient gem veins +{ + {5184.84, -1982.59, 1382.66, 2.58079, 0, 0, 0.960944, 0.276742}, //alliance + {5107.66, -2071.16, 1368.37, 2.65148, 0, 0, 0.970124, 0.242611}, //alliance + {5040.53, -2227.65, 1403.17, 3.35049, 0, 0, 0.99455, -0.104257}, //alliance + {5187.59, -2453.12, 1455.51, 5.87943, 0, 0, 0.20051, -0.979692}, //alliance + {5429.43, -2340.65, 1465.38, 4.7681, 0, 0, 0.687138, -0.726527}, //alliance + {5463.99, -2315.95, 1470.29, 1.52045, 0, 0, 0.689084, 0.724682}, //alliance + {5624.65, -2495.09, 1510.11, 0.0124869, 0, 0, 0.00624342, 0.999981}, //alliance + {5285.41, -3348.32, 1663.01, 1.57152, 0, 0, 0.707362, 0.706852}, //horde + {5417.69, -3372.52, 1656.31, 0.361993, 0, 0, 0.18001, 0.983665}, //horde + {5315.34, -3238.32, 1622.88, 3.03627, 0, 0, 0.998614, 0.0526347}, //horde + {5303.4, -3096.44, 1596.41, 1.72073, 0, 0, 0.758081, 0.65216}, //horde + {5265.13, -3177.27, 1616.22, 0.813604, 0, 0, 0.395674, 0.918391}, //horde + {5374.3, -3420.59, 1653.43, 1.45762, 0, 0, 0.665981, 0.745969}, //horde + {5441.54, -3321.59, 1651.55, 0.258306, 0, 0, 0.128794, 0.991671} //horde +}; + +float AllianceOverrunGargPos[5][4]=//gargoyle spawn points in the alliance overrun +{ + {5279.94, -2049.68, 1311.38, 0},//garg1 + {5289.15, -2219.06, 1291.12, 0},//garg2 + {5202.07, -2136.10, 1305.07, 2.8},//garg3 + {5071.52, -2425.63, 1454.48, 5.54},//garg4 + {5120.65, -2467.92, 1463.93, 2.54}//garg5 +}; + +float AllianceFirePos[92][8]=//spawn points for the fire visuals (GO) in the alliance base +{ + {5039.9, -1796.84, 1323.88, 2.59222, 0, 0, 0.962511, 0.271243}, + {5087.2, -1795.2, 1320.68, 1.03946, 0, 0, 0.496644, 0.867954}, + {5112.68, -1806.66, 1359.93, 1.37799, 0, 0, 0.63576, 0.771887}, + {5095.61, -1793.27, 1359.78, 0.580806, 0, 0, 0.286338, 0.958129}, + {5090.43, -1784.45, 1360.44, 0.796784, 0, 0, 0.387937, 0.921686}, + {5139.25, -1783.11, 1359.39, 3.30849, 0, 0, 0.99652, -0.0833509}, + {5112.16, -1763.72, 1361.35, 5.10312, 0, 0, 0.556388, -0.830922}, + {4981.18, -1793.98, 1335.7, 3.23072, 0, 0, 0.999007, -0.0445498}, + {4996.57, -1766.75, 1341.62, 3.5331, 0, 0, 0.980902, -0.194505}, + {4983.74, -1769.25, 1345.75, 3.79228, 0, 0, 0.947541, -0.319635}, + {4996.01, -1774.43, 1330.71, 3.07364, 0, 0, 0.999423, 0.0339693}, + {5094.2, -1726.13, 1330.55, 1.56175, 0, 0, 0.703901, 0.710298}, + {5079.82, -1721.24, 1336.26, 1.18868, 0, 0, 0.559964, 0.828517}, + {5077.68, -1717.15, 1327.78, 0.0145145, 0, 0, 0.00725717, 0.999974}, + {5122.27, -1738.22, 1341.67, 0.835256, 0, 0, 0.405593, 0.914054}, + {5131.88, -1741.15, 1335.25, 2.15472, 0, 0, 0.880712, 0.473653}, + {5196.93, -1772.99, 1345.2, 0.128397, 0, 0, 0.0641544, 0.99794}, + {5225.33, -1756.06, 1344.17, 3.04223, 0, 0, 0.998766, 0.0496599}, + {5224.84, -1767.05, 1360.06, 3.19538, 0, 0, 0.999638, -0.0268922}, + {5202.05, -1763.47, 1361.68, 2.59455, 0, 0, 0.962826, 0.270122}, + {5194.74, -1766.66, 1356.94, 0.0734191, 0, 0, 0.0367013, 0.999326}, + {5159.67, -1832.97, 1344.5, 5.17457, 0, 0, 0.526356, -0.850264}, + {5096.17, -1858.73, 1332.46, 5.30021, 0, 0, 0.471939, -0.881631}, + {5110.7, -1856.59, 1342.84, 5.97564, 0, 0, 0.153167, -0.9882}, + {5109.76, -1855.3, 1332.38, 4.89572, 0, 0, 0.639411, -0.768865}, + {5068.95, -1837.37, 1328.81, 2.61569, 0, 0, 0.965628, 0.25993}, + {5064.4, -1824.77, 1329.02, 2.16409, 0, 0, 0.88292, 0.469524}, + {5059.89, -1848.79, 1329.59, 0.0709955, 0, 0, 0.0354903, 0.99937}, + {5014.37, -1851.39, 1322.56, 4.66949, 0, 0, 0.722111, -0.691777}, + {5025.1, -1848.27, 1323.39, 4.44565, 0, 0, 0.794854, -0.606801}, + {4942.63, -1890.13, 1326.59, 3.28719, 0, 0, 0.997351, -0.0727343}, + {4937.95, -1888.71, 1352.41, 3.41678, 0, 0, 0.990549, -0.13716}, + {4922.48, -1881.92, 1352.41, 5.03077, 0, 0, 0.586075, -0.810257}, + {4915.35, -1894.32, 1351.24, 6.22457, 0, 0, 0.0293048, -0.999571}, + {4922.71, -1904.84, 1352.56, 1.37866, 0, 0, 0.63602, 0.771672}, + {4932.89, -1905.49, 1352.56, 1.89702, 0, 0, 0.812549, 0.582893}, + {5011.83, -1861.05, 1345.86, 4.43777, 0, 0, 0.797239, -0.603664}, + {5011.83, -1861.05, 1363.26, 4.748, 0, 0, 0.694406, -0.719583}, + {5021.46, -1858.35, 1342.17, 4.86188, 0, 0, 0.652329, -0.757936}, + {4995.02, -1698.3, 1370.38, 6.15779, 0, 0, 0.0626579, -0.998035}, + {5119.85, -1728.9, 1336.04, 5.87112, 0, 0, 0.204579, -0.97885}, + {5214.75, -1751.02, 1342.5, 5.08965, 0, 0, 0.561972, -0.827156}, + {5075.04, -1822.43, 1328.87, 3.99951, 0, 0, 0.9094, -0.415924}, + {5057.09, -1823.32, 1350.35, 3.88169, 0, 0, 0.93231, -0.361659}, + {4984.6, -1816.99, 1329.21, 3.05308, 0, 0, 0.999021, 0.0442417}, + {4983.35, -1811.55, 1356.82, 3.33975, 0, 0, 0.995096, -0.098917}, + {4984.11, -1825.73, 1350.76, 2.26375, 0, 0, 0.905211, 0.424962}, + {4968.47, -1786.46, 1354.09, 3.07663, 0, 0, 0.999473, 0.0324733}, + {5061.82, -1751.16, 1339.07, 5.94727, 0, 0, 0.167171, -0.985928}, + {5063.75, -1763, 1351.91, 0.759707, 0, 0, 0.370784, 0.928719}, + {5078.65, -1708.26, 1353.9, 1.27022, 0, 0, 0.593264, 0.805008}, + {4983.19, -1755.96, 1331.13, 4.28221, 0, 0, 0.841733, -0.539894}, + {4972.76, -1755.3, 1332.5, 4.21938, 0, 0, 0.858276, -0.513188}, + {4961.65, -1760.82, 1351.69, 3.56515, 0, 0, 0.977659, -0.210198}, + {5086.45, -1779.83, 1321.62, 6.23157, 0, 0, 0.0258051, -0.999667}, + {5063.15, -1756.74, 1328.56, 0.886926, 0, 0, 0.42907, 0.903271}, + {5042.45, -1800.61, 1323.88, 2.50093, 0, 0, 0.949131, 0.31488}, + {5084.74, -1725.35, 1327.89, 1.65034, 0, 0, 0.734663, 0.678432}, + {4993.25, -1758.1, 1331.07, 3.49995, 0, 0, 0.98399, -0.178223}, + {5078.53, -1867.85, 1348.91, 5.85612, 0, 0, 0.211913, -0.977288}, + {5080.74, -1869.73, 1333.18, 6.18206, 0, 0, 0.0505424, -0.998722}, + {5089.55, -1894.13, 1356.08, 1.52072, 0, 0, 0.689181, 0.724589}, + {5113.24, -1899.49, 1363.77, 1.50108, 0, 0, 0.682034, 0.731321}, + {4984.18, -1907.69, 1325.62, 3.82193, 0, 0, 0.942698, -0.333646}, + {5094.14, -2432.08, 1429.38, 4.70083, 0, 0, 0.711182, -0.703007}, + {5329.89, -2113.30, 1281.06, 5.60560, 0, 0, 0.332347, -0.943157}, + {5170.87, -2148.13, 1278.32, 1.63540, 0, 0, 0.729573, 0.683903 }, + {5132.94, -1960.25, 1367.8, 3.69787, 0, 0, 0.961568, -0.274566}, + {5280.82, -2351.55, 1431.57, 4.46913, 0, 0, 0.787677, -0.616088}, + {5176.78, -2121.43, 1295.27, 3.24153, 0, 0, 0.998752, -0.04995}, + {5332.75, -2101.41, 1296.37, 5.50350, 0, 0, 0.380043, -0.924969}, + {5265.70, -2050.27, 1287.57, 0.50051, 0, 0, 0.247655, 0.968848 }, + {5194.21, -2129.89, 1274.04, 3.08053, 0, 0, 0.999534, 0.0305272}, + {5225.81, -1985.50, 1364.15, 0.37247, 0, 0, 0.185163, 0.982708 }, + {5339.46, -2204.47, 1280.45, 0.99921, 0, 0, 0.479081, 0.877771 }, + {5269.63, -2020.57, 1299.62, 3.00201, 0, 0, 0.997566, 0.0697332}, + {5111.54, -2445.70, 1435.31, 2.70983, 0, 0, 0.976788, 0.214207 }, + {5111.24, -1901.14, 1355.33, 1.61028, 0, 0, 0.720929, 0.693009 }, + {5310.42, -2207.82, 1277.46, 0.50441, 0, 0, 0.249544, 0.968363 }, + {5150.81, -2042.13, 1394.3, 2.21031, 0, 0, 0.893534, 0.448995 }, + {5224.84, -2376.61, 1366.33, 5.0621, 0, 0, 0.573311, -0.819338}, + {5105.41, -2454.86, 1446.16, 4.64584, 0, 0, 0.730239, -0.683191}, + {5309.65, -2188.28, 1266.84, 5.56631, 0, 0, 0.350811, -0.936446}, + {5281.46, -2047.82, 1287.67, 2.44909, 0, 0, 0.940652, 0.339373 }, + {5325.45, -2189.41, 1309.6, 6.23783, 0, 0, 0.0226771, -0.999743}, + {5190.96, -2142.54, 1293.03, 6.25668, 0, 0, 0.0132544, -0.999912}, + {5089.99, -2467.49, 1441.8, 0.77381, 0, 0, 0.377326, 0.92608 }, + {5195.08, -2129.01, 1285.36, 3.55727, 0, 0, 0.978480, -0.206344}, + {5353.76, -2116.28, 1299.27, 6.17894, 0, 0, 0.0521006, -0.998642}, + {5271.14, -2037.38, 1299.24, 4.07879, 0, 0, 0.892201, -0.451638}, + {5332.5 , -2181.28, 1279.95, 4.6906, 0, 0, 0.714768, -0.699362}, + {5108.2 , -2429.84, 1427.73, 4.5194, 0, 0, 0.771943, -0.635691} +}; + +float HordeFirePos[65][8]=//spawn points for the fire visuals (GO) in the horde base +{ + {5524.11, -2612.73, 1483.38, 1.96198, 0, 0, 0.831047, 0.556202}, + {5514.42, -2617.19, 1505.77, 1.82453, 0, 0, 0.790892, 0.611956}, + {5510.21, -2624.77, 1485.34, 1.71065, 0, 0, 0.754783, 0.655974}, + {5570.72, -2619.04, 1487.62, 0.728898, 0, 0, 0.356435, 0.93432}, + {5570.29, -2639.37, 1487.31, 1.49308, 0, 0, 0.679104, 0.734042}, + {5583.56, -2637.2, 1503.78, 1.46559, 0, 0, 0.668951, 0.743307}, + {5571.53, -2626.81, 1510.99, 0.362107, 0, 0, 0.180066, 0.983654}, + {5545.97, -2659.62, 1489.64, 5.07055, 0, 0, 0.569845, -0.821752}, + {5557.44, -2675.91, 1482.58, 1.70118, 0, 0, 0.751671, 0.659539}, + {5594.98, -2742.31, 1495.51, 4.5993, 0, 0, 0.74594, -0.666013}, + {5599.65, -2755.6, 1505.05, 1.66896, 0, 0, 0.740947, 0.671564}, + {5565.95, -2774.75, 1499.48, 6.22425, 0, 0, 0.0294611, -0.999566}, + {5567.1, -2769.7, 1511.17, 5.99257, 0, 0, 0.144799, -0.989461}, + {5572.84, -2774.16, 1527.06, 0.836428, 0, 0, 0.406129, 0.913816}, + {5538.32, -2805.94, 1498.87, 4.30082, 0, 0, 0.836674, -0.547701}, + {5515.66, -2801.74, 1503.53, 5.57316, 0, 0, 0.347602, -0.937642}, + {5516.76, -2827.14, 1501.15, 0.35026, 0, 0, 0.174236, 0.984704}, + {5536.13, -2813.51, 1537.21, 4.51681, 0, 0, 0.772765, -0.634692}, + {5525.05, -2825.16, 1538.53, 0.489275, 0, 0, 0.242205, 0.970225}, + {5534.42, -2815.45, 1562.84, 4.62834, 0, 0, 0.736191, -0.676774}, + {5519.64, -2831.12, 1526.46, 0.611008, 0, 0, 0.300774, 0.953696}, + {5551.04, -2827.55, 1523.5, 3.35206, 0, 0, 0.994468, -0.10504}, + {5469.22, -2802.87, 1503.5, 4.99509, 0, 0, 0.600436, -0.799673}, + {5427.8, -2737.26, 1487.12, 1.78673, 0, 0, 0.779186, 0.626793}, + {5454.1, -2709.1, 1485.92, 3.03552, 0, 0, 0.998594, 0.0530137}, + {5436.3, -2718.2, 1506.02, 2.7567, 0, 0, 0.981539, 0.191261}, + {5412.6, -2740.55, 1510.79, 2.98446, 0, 0, 0.996915, 0.0784832}, + {5406.12, -2752.48, 1521.01, 2.05769, 0, 0, 0.856705, 0.515807}, + {5445.24, -2676.35, 1521.89, 2.91378, 0, 0, 0.99352, 0.113661}, + {5481.4, -2665.08, 1482.23, 4.30001, 0, 0, 0.836895, -0.547363}, + {5443.51, -2675.44, 1487.12, 2.90986, 0, 0, 0.993295, 0.115606}, + {5391.72, -2647.3, 1528.9, 3.76987, 0, 0, 0.951063, -0.308997}, + {5421.09, -2734.12, 1521.01, 2.70567, 0, 0, 0.97634, 0.216242}, + {5405.39, -2710.33, 1533.77, 2.51324, 0, 0, 0.951052, 0.309032}, + {5423.96, -2703.76, 1516.34, 2.79206, 0, 0, 0.984767, 0.173879}, + {5444.75, -2735.23, 1486.37, 2.22657, 0, 0, 0.897155, 0.441715}, + {5570.98, -2747.91, 1495.7, 5.14433, 0, 0, 0.53915, -0.84221}, + {5567.79, -2673.9, 1484.66, 2.72529, 0, 0, 0.978415, 0.20665}, + {5600.71, -2696.8, 1500.42, 0.443704, 0, 0, 0.220036, 0.975492}, + {5600.7, -2693.04, 1515.2, 5.16003, 0, 0, 0.532522, -0.846416}, + {5627.56, -2839.66, 1510.53, 5.41527, 0, 0, 0.420463, -0.907309}, + {5622.02, -2868.71, 1516.22, 2.25482, 0, 0, 0.903303, 0.429002}, + {5586.61, -2878.97, 1510.34, 4.55604, 0, 0, 0.76017, -0.649724}, + {5583.78, -2843.71, 1509.54, 5.35715, 0, 0, 0.44665, -0.894709}, + {5580.95, -2811.3, 1513.3, 3.57587, 0, 0, 0.976518, -0.215434}, + {5542.52, -2869.31, 1523.13, 5.23304, 0, 0, 0.501275, -0.865288}, + {5557.35, -2866.36, 1518.76, 4.48299, 0, 0, 0.783388, -0.621533}, + {5380.91, -2849.36, 1512.81, 3.90962, 0, 0, 0.927168, -0.374646}, + {5395.76, -2881.41, 1521.11, 4.28426, 0, 0, 0.84118, -0.540755}, + {5374.87, -2859.63, 1528.98, 3.30252, 0, 0, 0.996765, -0.0803745}, + {5356.07, -2854.66, 1520.34, 5.83933, 0, 0, 0.220108, -0.975475}, + {5363.01, -2975.72, 1539.02, 4.13738, 0, 0, 0.87859, -0.477576}, + {5336.85, -2980.74, 1561.24, 5.11126, 0, 0, 0.553001, -0.83318}, + {5335.23, -2974.62, 1540.05, 5.04451, 0, 0, 0.580496, -0.814263}, + {5422.37, -2998.87, 1549.98, 4.51831, 0, 0, 0.772288, -0.635272}, + {5405.54, -3014.6, 1562.16, 5.86761, 0, 0, 0.206298, -0.978489}, + {5427.96, -3019.4, 1561.58, 3.53498, 0, 0, 0.980718, -0.19543}, + {5348.12, -2977.84, 1582.47, 3.94025, 0, 0, 0.921323, -0.388799}, + {5331.12, -2993.71, 1576.14, 0.0642734, 0, 0, 0.0321311, 0.999484}, + {5321.63, -2986.55, 1552.2, 5.29503, 0, 0, 0.474219, -0.880407}, + {5292.1, -2914.36, 1529.52, 2.9742, 0, 0, 0.996499, 0.083601}, + {5281.77, -2926.5, 1530.62, 1.67829, 0, 0, 0.744071, 0.6681}, + {5287.19, -2909.94, 1543.49, 3.31192, 0, 0, 0.996376, -0.0850591}, + {5534.15, -2679.35, 1483.61, 0.428685, 0, 0, 0.212705, 0.977116}, + {5545.43, -2647.82, 1483.05, 5.38848, 0, 0, 0.432578, -0.901596} +}; + +hyjalAI::hyjalAI(Creature *c) : npc_escortAI(c), Summons(me) +{ + pInstance = c->GetInstanceData(); + VeinsSpawned[0] = false; + VeinsSpawned[1] = false; + for (uint8 i=0; i<14; ++i) + VeinGUID[i] = 0; + InfernalCount = 0; + TeleportTimer = 1000; + Overrun = false; + Teleported = false; + WaitForTeleport = false; + OverrunCounter = 0; + OverrunCounter2 = 0; + InfernalPoint = 0; + RespawnTimer = 10000; + DoRespawn = false; + DoHide = false; + MassTeleportTimer = 0; + DoMassTeleport = false; +} + +void hyjalAI::JustSummoned(Creature *summoned) +{ + Summons.Summon(summoned); +} + +void hyjalAI::SummonedCreatureDespawn(Creature* summoned) +{ + Summons.Despawn(summoned); +} + +void hyjalAI::Reset() +{ + IsDummy = false; + me->setActive(true); + // GUIDs + PlayerGUID = 0; + BossGUID[0] = 0; + BossGUID[1] = 0; + + // Timers + NextWaveTimer = 10000; + CheckTimer = 0; + RetreatTimer = 1000; + + // Misc + WaveCount = 0; + EnemyCount = 0; + + // Set faction properly based on Creature entry + switch(me->GetEntry()) + { + case JAINA: + Faction = 0; + DoCast(me, SPELL_BRILLIANCE_AURA, true); + break; + + case THRALL: + Faction = 1; + break; + + case TYRANDE: + Faction = 2; + break; + } + + //Bools + EventBegun = false; + FirstBossDead = false; + SecondBossDead = false; + Summon = false; + bRetreat = false; + Debug = false; + + //Flags + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + //Initialize spells + memset(Spell, 0, sizeof(Spell)); + + //Reset Instance Data for trash count + if (pInstance) + { + if ((!pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == JAINA) || (pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == THRALL)) + { + //Reset World States + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); + pInstance->SetData(DATA_RESET_TRASH_COUNT, 0); + } + } else error_log(ERROR_INST_DATA); + + //Visibility + DoHide = true; +} + +void hyjalAI::EnterEvadeMode() +{ + if (me->GetEntry() != JAINA) + me->RemoveAllAuras(); + me->DeleteThreatList(); + me->CombatStop(true); + me->LoadCreaturesAddon(); + + if (me->isAlive()) + me->GetMotionMaster()->MoveTargetedHome(); + + me->SetLootRecipient(NULL); +} + +void hyjalAI::EnterCombat(Unit * /*who*/) +{ + if (IsDummy)return; + for (uint8 i = 0; i < 3; ++i) + if (Spell[i].Cooldown) + SpellTimer[i] = Spell[i].Cooldown; + + Talk(ATTACKED); +} + +void hyjalAI::MoveInLineOfSight(Unit *who) +{ + if (IsDummy) + return; + + npc_escortAI::MoveInLineOfSight(who); +} + +void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) +{ + uint32 random = rand()%4; + float SpawnLoc[3]; + + for (uint8 i = 0; i < 3; ++i) + { + SpawnLoc[i] = Base[random][i]; + } + Creature* pCreature = NULL; + switch(entry) + { + case 17906: //GARGOYLE + + if (!FirstBossDead && (WaveCount == 1 || WaveCount == 3)) + {//summon at tower + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][1]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + if (pCreature) + CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; + }else{//summon at gate + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_GARG_GATE][0]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][1]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + } + break; + case 17907: //FROST_WYRM , + if (FirstBossDead && WaveCount == 1) //summon at gate + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_WYRM_GATE][0],SpawnPointSpecial[SPAWN_WYRM_GATE][1],SpawnPointSpecial[SPAWN_WYRM_GATE][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + else + { + pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0], SpawnPointSpecial[SPAWN_NEAR_TOWER][1],SpawnPointSpecial[SPAWN_NEAR_TOWER][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + if (pCreature) + CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; + } + break; + case 17908: //GIANT_INFERNAL + ++InfernalCount; + if (InfernalCount > 7) + InfernalCount = 0; + pCreature = me->SummonCreature(entry, InfernalPos[InfernalCount][0], InfernalPos[InfernalCount][1], InfernalPos[InfernalCount][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + default: + pCreature = me->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); + break; + + } + + if (pCreature) + { + // Increment Enemy Count to be used in World States and instance script + ++EnemyCount; + + pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCreature->setActive(true); + switch(entry) + { + case NECROMANCER: + case ABOMINATION: + case GHOUL: + case BANSHEE: + case CRYPT_FIEND: + case GARGOYLE: + case FROST_WYRM: + case GIANT_INFERNAL: + case FEL_STALKER: + case RAGE_WINTERCHILL: + case ANETHERON: + case KAZROGAL: + case AZGALOR: + CAST_AI(hyjal_trashAI, pCreature->AI())->IsEvent = true; + break; + } + if (pInstance) + { + if (pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE) + pCreature->SetDisableReputationGain(true);//no repu for solo farming + } + // Check if Creature is a boss. + if (pCreature->isWorldBoss()) + { + if (!FirstBossDead) BossGUID[0] = pCreature->GetGUID(); + else BossGUID[1] = pCreature->GetGUID(); + CheckTimer = 5000; + } + } +} + +void hyjalAI::SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]) +{ + // 1 in 4 chance we give a rally yell. Not sure if the chance is offilike. + if (rand()%4 == 0) + Talk(RALLY); + + if (!pInstance) + { + error_log(ERROR_INST_DATA); + return; + } + InfernalCount = 0;//reset infernal count every new wave + + EnemyCount = pInstance->GetData(DATA_TRASH); + for (uint8 i = 0; i < 18; ++i) + { + if (wave[Count].Mob[i]) + SummonCreature(wave[Count].Mob[i], Base); + } + + if (!wave[Count].IsBoss) + { + uint32 stateValue = Count+1; + if (FirstBossDead) + stateValue -= 9; // Subtract 9 from it to give the proper wave number if we are greater than 8 + + // Set world state to our current wave number + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, stateValue); // Set world state to our current wave number + // Enable world state + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); // Enable world state + + pInstance->SetData(DATA_TRASH, EnemyCount); // Send data for instance script to update count + + if (!Debug) + NextWaveTimer = wave[Count].WaveTimer; + else + { + NextWaveTimer = 15000; + debug_log("TSCR: HyjalAI: debug mode is enabled. Next Wave in 15 seconds"); + } + } + else + { + // Set world state for waves to 0 to disable it. + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); + + // Set World State for enemies invading to 1. + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 1); + + Summon = false; + } + CheckTimer = 5000; +} + +void hyjalAI::StartEvent(Player* pPlayer) +{ + if (!pPlayer || IsDummy || !pInstance) + return; + + Talk(BEGIN); + + EventBegun = true; + Summon = true; + + NextWaveTimer = 15000; + CheckTimer = 5000; + PlayerGUID = pPlayer->GetGUID(); + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); + + DeSpawnVeins(); +} + +uint32 hyjalAI::GetInstanceData(uint32 Event) +{ + if (pInstance) + return pInstance->GetData(Event); + else error_log(ERROR_INST_DATA); + + return 0; +} + +void hyjalAI::Talk(uint32 id) +{ + std::list index; + for (uint8 i = 0; i < 9; ++i) + { + if (Faction == 0) // Alliance + { + if (JainaQuotes[i].id == id) + index.push_back(i); + } + else if (Faction == 1) // Horde + { + if (ThrallQuotes[i].id == id) + index.push_back(i); + } + } + + if (index.empty()) + return; // No quotes found, no use to continue + + uint8 ind = *(index.begin()) + rand()%index.size(); + + int32 YellId = 0; + if (Faction == 0) // Alliance + { + YellId = JainaQuotes[ind].textid; + } + else if (Faction == 1) // Horde + { + YellId = ThrallQuotes[ind].textid; + } + + if (YellId) + DoScriptText(YellId, me); +} + +void hyjalAI::Retreat() +{ + if (pInstance) + { + pInstance->SetData(TYPE_RETREAT,SPECIAL); + + if (Faction == 0) + { + pInstance->SetData(DATA_ALLIANCE_RETREAT, 1); + AddWaypoint(0,JainaWPs[0][0],JainaWPs[0][1],JainaWPs[0][2]); + AddWaypoint(1,JainaWPs[1][0],JainaWPs[1][1],JainaWPs[1][2]); + Start(false, false); + SetDespawnAtEnd(false);//move to center of alliance base + } + if (Faction == 1) + { + pInstance->SetData(DATA_HORDE_RETREAT, 1); + Creature* JainaDummy = me->SummonCreature(JAINA,JainaDummySpawn[0][0],JainaDummySpawn[0][1],JainaDummySpawn[0][2],JainaDummySpawn[0][3],TEMPSUMMON_TIMED_DESPAWN,60000); + if (JainaDummy) + { + JainaDummy->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + CAST_AI(hyjalAI, JainaDummy->AI())->IsDummy = true; + DummyGuid = JainaDummy->GetGUID(); + } + AddWaypoint(0,JainaDummySpawn[1][0],JainaDummySpawn[1][1],JainaDummySpawn[1][2]); + Start(false, false); + SetDespawnAtEnd(false);//move to center of alliance base + } + } + SpawnVeins(); + Overrun = true; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//cant talk after overrun event started +} + +void hyjalAI::SpawnVeins() +{ + if (Faction == 0) + { + if (VeinsSpawned[0])//prevent any buggers + return; + for (uint8 i = 0; i<7; ++i) + { + GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); + if (gem) + VeinGUID[i]=gem->GetGUID(); + } + VeinsSpawned[0] = true; + }else{ + if (VeinsSpawned[1]) + return; + for (uint8 i = 7; i<14; ++i) + { + GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); + if (gem) + VeinGUID[i]=gem->GetGUID(); + } + VeinsSpawned[1] = true; + } +} + +void hyjalAI::DeSpawnVeins() +{ + if (!pInstance) + return; + if (Faction == 1) + { + Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (!pUnit)return; + hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); + if (!ai)return; + for (uint8 i = 0; i<7; ++i) + { + if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) + gem->Delete(); + } + } else if (Faction) + { + Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_THRALL)); + if (!pUnit)return; + hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); + if (!ai)return; + for (uint8 i = 7; i<14; ++i) + { + if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) + gem->Delete(); + } + } +} + +void hyjalAI::UpdateAI(const uint32 diff) +{ + if (IsDummy) + { + if (MassTeleportTimer < diff && DoMassTeleport) + { + DoCast(me, SPELL_MASS_TELEPORT, false); + DoMassTeleport = false; + } else MassTeleportTimer -= diff; + return; + } + if (DoHide) + { + DoHide = false; + switch(me->GetEntry()) + { + case JAINA: + if (pInstance && pInstance->GetData(DATA_ALLIANCE_RETREAT)) + { + me->SetVisibility(VISIBILITY_OFF); + HideNearPos(me->GetPositionX(), me->GetPositionY()); + HideNearPos(5037.76, -1889.71); + for (uint8 i = 0; i < 92; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); + + } + else me->SetVisibility(VISIBILITY_ON); + break; + case THRALL: //thrall + if (pInstance && pInstance->GetData(DATA_HORDE_RETREAT)) + { + me->SetVisibility(VISIBILITY_OFF); + HideNearPos(me->GetPositionX(), me->GetPositionY()); + HideNearPos(5563, -2763.19); + HideNearPos(5542.2, -2629.36); + for (uint8 i = 0; i < 65; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); + + } + else me->SetVisibility(VISIBILITY_ON); + break; + } + } + if (DoRespawn) + { + if (RespawnTimer <= diff) + { + DoRespawn = false; + RespawnNearPos(me->GetPositionX(), me->GetPositionY()); + if (Faction == 0) + { + RespawnNearPos(5037.76, -1889.71); + } else if (Faction == 1) + { + RespawnNearPos(5563, -2763.19); + RespawnNearPos(5542.2, -2629.36); + } + me->SetVisibility(VISIBILITY_ON); + }else{ + RespawnTimer -= diff; + me->SetVisibility(VISIBILITY_OFF); + } + return; + } + if (Overrun) + DoOverrun(Faction, diff); + if (bRetreat) + { + if (RetreatTimer <= diff) + { + IsDummy = true; + bRetreat = false; + HideNearPos(me->GetPositionX(), me->GetPositionY()); + switch(me->GetEntry()) + { + case JAINA://jaina + HideNearPos(5037.76, -1889.71); + break; + case THRALL://thrall + HideNearPos(5563, -2763.19); + HideNearPos(5542.2, -2629.36); + HideNearPos(5603.75, -2853.12); + break; + } + me->SetVisibility(VISIBILITY_OFF); + } else RetreatTimer -= diff; + } + + if (!EventBegun) + return; + + if (Summon) + { + if (pInstance && EnemyCount) + { + EnemyCount = pInstance->GetData(DATA_TRASH); + if (!EnemyCount) + NextWaveTimer = 5000; + } + + if (NextWaveTimer <= diff) + { + if (Faction == 0) + SummonNextWave(AllianceWaves, WaveCount, AllianceBase); + else if (Faction == 1) + SummonNextWave(HordeWaves, WaveCount, HordeBase); + ++WaveCount; + } else NextWaveTimer -= diff; + } + + if (CheckTimer <= diff) + { + for (uint8 i = 0; i < 2; ++i) + { + if (BossGUID[i]) + { + Unit* pUnit = Unit::GetUnit((*me), BossGUID[i]); + if (pUnit && (!pUnit->isAlive())) + { + if (BossGUID[i] == BossGUID[0]) + { + Talk(INCOMING); + FirstBossDead = true; + } + else if (BossGUID[i] == BossGUID[1]) + { + Talk(SUCCESS); + SecondBossDead = true; + } + EventBegun = false; + CheckTimer = 0; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + BossGUID[i] = 0; + if (pInstance) + pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); // Reset world state for enemies to disable it + } + } + } + CheckTimer = 5000; + } else CheckTimer -= diff; + + if (!UpdateVictim()) + return; + + for (uint8 i = 0; i < 3; ++i) + { + if (Spell[i].SpellId) + { + if (SpellTimer[i] <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + Unit *pTarget = NULL; + + switch(Spell[i].TargetType) + { + case TARGETTYPE_SELF: pTarget = me; break; + case TARGETTYPE_RANDOM: pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); break; + case TARGETTYPE_VICTIM: pTarget = me->getVictim(); break; + } + + if (pTarget && pTarget->isAlive()) + { + DoCast(pTarget, Spell[i].SpellId); + SpellTimer[i] = Spell[i].Cooldown; + } + } else SpellTimer[i] -= diff; + } + } + + DoMeleeAttackIfReady(); +} +void hyjalAI::JustDied(Unit* /*killer*/) +{ + if (IsDummy)return; + me->Respawn(); + me->SetVisibility(VISIBILITY_OFF); + DoRespawn = true; + RespawnTimer = 120000; + Talk(DEATH); + Summons.DespawnAll();//despawn all wave's summons + if (pInstance) + {//reset encounter if boss is despawned (ex: thrall is killed, boss despawns, event stucks at inprogress) + if (pInstance->GetData(DATA_RAGEWINTERCHILLEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_ANETHERONEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_KAZROGALEVENT) == IN_PROGRESS) + pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); + if (pInstance->GetData(DATA_AZGALOREVENT) == IN_PROGRESS) + pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); + pInstance->SetData(DATA_RESET_RAIDDAMAGE, NULL);//reset damage on die + } +} +void hyjalAI::HideNearPos(float x, float y) +{ + CellPair pair(Trinity::ComputeCellPair(x, y)); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + // First get all creatures. + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + // Get Creatures + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + (*itr)->SetVisibility(VISIBILITY_OFF); + (*itr)->setFaction(35);//make them friendly so mobs won't attack them + } + } +} +void hyjalAI::RespawnNearPos(float x, float y) +{ + CellPair p(Trinity::ComputeCellPair(x, y)); + Cell cell(p); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + Trinity::RespawnDo u_do; + Trinity::WorldObjectWorker worker(me, u_do); + TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); + cell.Visit(p, obj_worker, *me->GetMap()); +} +void hyjalAI::WaypointReached(uint32 i) +{ + if (i == 1 || (i == 0 && me->GetEntry() == THRALL)) + { + me->MonsterYell(YELL_HURRY,0,0); + WaitForTeleport = true; + TeleportTimer = 20000; + if (me->GetEntry() == JAINA) + DoCast(me, SPELL_MASS_TELEPORT, false); + if (me->GetEntry() == THRALL && DummyGuid) + { + Unit* Dummy = Unit::GetUnit((*me),DummyGuid); + if (Dummy) + { + CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->DoMassTeleport = true; + CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->MassTeleportTimer = 20000; + Dummy->CastSpell(me, SPELL_MASS_TELEPORT, false); + } + } + //do some talking + //all alive guards walk near here + CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + // First get all creatures. + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive() && (*itr) != me && (*itr)->GetEntry() != JAINA) + { + if (!(*itr)->IsWithinDist(me, 60)) + (*itr)->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + float x, y, z; + (*itr)->SetDefaultMovementType(IDLE_MOTION_TYPE); + (*itr)->GetMotionMaster()->Initialize(); + float range = 10; + if (me->GetEntry() == THRALL)range = 20; + me->GetNearPoint(me, x, y, z, range, 0, me->GetAngle((*itr))); + (*itr)->GetMotionMaster()->MovePoint(0, x+irand(-5,5), y+irand(-5,5), me->GetPositionZ()); + } + } + } + } +} +void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) +{ + npc_escortAI::UpdateAI(diff); + if (WaitForTeleport) + { + if (TeleportTimer <= diff) + { + CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); + Cell cell(pair); + cell.data.Part.reserved = ALL_DISTRICT; + cell.SetNoCreate(); + + std::list creatures; + Trinity::AllFriendlyCreaturesInGrid creature_check(me); + Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); + TypeContainerVisitor + , + GridTypeMapContainer> creature_visitor(creature_searcher); + + cell.Visit(pair, creature_visitor, *(me->GetMap())); + + if (!creatures.empty()) + { + for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive()) + { + (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); + (*itr)->setFaction(35);//make them friendly so mobs won't attack them + (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + DoCast(me, SPELL_TELEPORT_VISUAL); + bRetreat = true; + RetreatTimer = 1000; + } + + WaitForTeleport = false; + Teleported = true; + }TeleportTimer -= diff; + } + if (!Teleported) + return; + Overrun = false;//execute once + switch(faction) + { + case 0://alliance + for (uint8 i = 0; i < 92; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); + + for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(GHOUL, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 3; ++i)//summon 3 abominations + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(ABOMINATION, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles + { + Creature* pUnit = me->SummonCreature(GARGOYLE, AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + pUnit->SetHomePosition(AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3]); + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + break; + case 1://horde + for (uint8 i = 0; i < 65; ++i)//summon fires + me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); + + for (uint8 i = 0; i < 26; ++i)//summon infernals + { + Creature* pUnit = me->SummonCreature(GIANT_INFERNAL, InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + pUnit->SetHomePosition(InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3]); + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(GHOUL, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + for (uint8 i = 0; i < 5; ++i)//summon 5 abominations + { + uint8 r = rand()%4; + Creature* pUnit = me->SummonCreature(ABOMINATION, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); + if (pUnit) + { + CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; + CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; + CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; + pUnit->setActive(true); + } + } + break; + } +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h new file mode 100644 index 00000000000..5c75465b7b4 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.h @@ -0,0 +1,248 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef SC_HYJALAI_H +#define SC_HYJALAI_H + +#include "hyjal.h" +#include "ScriptedEscortAI.h" + +// Trash Mobs summoned in waves +#define NECROMANCER 17899//done +#define ABOMINATION 17898//done +#define GHOUL 17895//done +#define BANSHEE 17905//done +#define CRYPT_FIEND 17897//done +#define GARGOYLE 17906//done +#define FROST_WYRM 17907//done +#define GIANT_INFERNAL 17908//done +#define FEL_STALKER 17916//done + +#define JAINA 17772 +#define THRALL 17852 +#define TYRANDE 17948 + +#define ANCIENT_VEIN 185557 +#define FLAMEOBJECT 182592 + +// Bosses summoned after every 8 waves +#define RAGE_WINTERCHILL 17767 +#define ANETHERON 17808 +#define KAZROGAL 17888 +#define AZGALOR 17842 +#define ARCHIMONDE 17968 + +#define SPELL_TELEPORT_VISUAL 41232 +#define SPELL_MASS_TELEPORT 16807 + +//Spells for Jaina +#define SPELL_BRILLIANCE_AURA 31260 // The database must handle this spell via creature_addon(it should, but is removed in evade..) +#define SPELL_BLIZZARD 31266 +#define SPELL_PYROBLAST 31263 +#define SPELL_SUMMON_ELEMENTALS 31264 + +//Thrall spells +#define SPELL_CHAIN_LIGHTNING 31330 +#define SPELL_SUMMON_DIRE_WOLF 31331 + +struct Wave +{ + uint32 Mob[18]; // Stores Creature Entries to be summoned in Waves + uint32 WaveTimer; // The timer before the next wave is summoned + bool IsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that +}; + +static Wave AllianceWaves[]= // Waves that will be summoned in the Alliance Base +{ // Rage Winterchill Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron + {RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, + // Anetheron Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, GHOUL, GHOUL, 0, 0, 0, 0, 120000, false}, + {GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + // All 8 Waves are summoned, summon Anatheron + {ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} +}; + +static Wave HordeWaves[]= // Waves that are summoned in the Horde base +{ // Kaz'Rogal Wave 1-8 + {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, + // All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor + {KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, + // Azgalor Wave 1-8 + {ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, FROST_WYRM, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, + {GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, 0, 0, 0, 0, 180000, false}, + {FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, + {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 180000, false}, + {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, + {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, + // All 8 Waves are summoned, summon Azgalor + {AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} +}; + +enum TargetType // Used in the spell cast system for the AI +{ + TARGETTYPE_SELF = 0, + TARGETTYPE_RANDOM = 1, + TARGETTYPE_VICTIM = 2, +}; + +struct Yells +{ + uint32 id; // Used to determine the type of yell (attack, rally, etc) + int32 textid; // The text id to be yelled +}; + +enum YellId +{ + ATTACKED = 0, // Used when attacked and set in combat + BEGIN = 1, // Used when the event is begun + INCOMING = 2, // Used to warn the raid that another wave phase is coming + RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned + FAILURE = 4, // Used when raid has failed (unsure where to place) + SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase + DEATH = 6, // Used on death +}; + +static Yells JainaQuotes[]= +{ + {ATTACKED, -1534000}, + {ATTACKED, -1534001}, + {INCOMING, -1534002}, + {BEGIN, -1534003}, + {RALLY, -1534004}, + {RALLY, -1534005}, + {FAILURE, -1534006}, + {SUCCESS, -1534007}, + {DEATH, -1534008}, +}; + +static Yells ThrallQuotes[]= +{ + {ATTACKED, -1534009}, + {ATTACKED, -1534010}, + {INCOMING, -1534011}, + {BEGIN, -1534012}, + {RALLY, -1534013}, + {RALLY, -1534014}, + {FAILURE, -1534015}, + {SUCCESS, -1534016}, + {DEATH, -1534017}, +}; + +struct hyjalAI : public npc_escortAI +{ + hyjalAI(Creature *c); + + void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat + + void EnterEvadeMode(); // Send creature back to spawn location and evade. + + void EnterCombat(Unit * /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack + + void UpdateAI(const uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells. + + void JustDied(Unit* /*killer*/); // Called on death, informs the raid that they have failed. + + void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal + { + Faction = _faction; + } + + void Retreat(); // "Teleport" (teleport visual + set invisible) all friendly creatures away from the base. + + void SpawnVeins(); + void DeSpawnVeins(); + void JustSummoned(Creature *summoned); + void SummonedCreatureDespawn(Creature* summoned); + void HideNearPos(float x, float y); + void RespawnNearPos(float x, float y); + void WaypointReached(uint32 i); + void DoOverrun(uint32 faction, const uint32 diff); + void MoveInLineOfSight(Unit *who); + + void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base + + // Summons the next wave, calls SummonCreature + void SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]); + + void StartEvent(Player* player); // Begins the event by gossip click + + uint32 GetInstanceData(uint32 Event); // Gets instance data for this instance, used to check if raid has gotten past a certain point and can access the next phase + + void Talk(uint32 id); // Searches for the appropriate yell and sound and uses it to inform the raid of various things + + public: + ScriptedInstance* pInstance; + + uint64 PlayerGUID; + uint64 BossGUID[2]; + uint64 VeinGUID[14]; + + uint32 NextWaveTimer; + uint32 WaveCount; + uint32 CheckTimer; + uint32 Faction; + uint32 EnemyCount; + uint32 RetreatTimer; + + bool EventBegun; + bool FirstBossDead; + bool SecondBossDead; + bool Summon; + bool bRetreat; + bool Debug; + bool VeinsSpawned[2]; + uint8 InfernalCount; + SummonList Summons; + bool Overrun; + bool Teleported; + bool WaitForTeleport; + uint32 TeleportTimer; + uint32 OverrunCounter; + uint32 OverrunCounter2; + uint32 InfernalPoint; + uint32 RespawnTimer; + bool DoRespawn; + bool DoHide; + bool IsDummy; + uint32 MassTeleportTimer; + bool DoMassTeleport; + uint64 DummyGuid; + + struct Spell + { + uint32 SpellId; + uint32 Cooldown; + uint32 TargetType; + }Spell[3]; + + private: + uint32 SpellTimer[3]; + //std::list CreatureList; +}; +#endif + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp new file mode 100644 index 00000000000..c4cf9ede397 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -0,0 +1,1440 @@ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" +#include "hyjalAI.h" + +#define SPELL_METEOR 33814 //infernal visual +#define SPELL_IMMOLATION 37059 +#define SPELL_FLAME_BUFFET 31724 +#define NPC_TRIGGER 21987 //World Trigger (Tiny) +#define MODEL_INVIS 11686 //invisible model + +float HordeWPs[8][3]=//basic waypoints from spawn to leader +{ + {5492.91, -2404.61, 1462.63}, + {5531.76, -2460.87, 1469.55}, + {5554.58, -2514.66, 1476.12}, + {5554.16, -2567.23, 1479.90}, + {5540.67, -2625.99, 1480.89}, + {5508.16, -2659.20, 1480.15},//random rush starts from here + {5489.62, -2704.05, 1482.18}, + {5457.04, -2726.26, 1485.10} +}; +float AllianceWPs[8][3]=//basic waypoints from spawn to leader +{ + {4896.08, -1576.35, 1333.65}, + {4898.68, -1615.02, 1329.48}, + {4907.12, -1667.08, 1321.00}, + {4963.18, -1699.35, 1340.51}, + {4989.16, -1716.67, 1335.74},//first WP in the base, after the gate + {5026.27, -1736.89, 1323.02}, + {5037.77, -1770.56, 1324.36}, + {5067.23, -1789.95, 1321.17} +}; + +float FrostWyrmWPs[3][3]=//waypoints for the frost wyrms in horde base +{ + {5580.82, -2628.83, 1528.28}, + {5550.90, -2667.16, 1505.45}, + {5459.64, -2725.91, 1484.83} +}; + +float GargoyleWPs[3][3]=//waypoints for the gargoyles in horde base +{ + {5533.66, -2634.32, 1495.33}, + {5517.88, -2712.05, 1490.54}, + {5459.64, -2725.91, 1484.83} +}; + +float FlyPathWPs[3][3]=//waypoints for the gargoyls and frost wyrms in horde base in wave 1/3 +{ + {5531.96, -2772.83, 1516.68}, + {5498.32, -2734.84, 1497.01}, + {5456.67, -2725.48, 1493.08} +}; + +float AllianceOverrunWP[55][3]=//waypoints in the alliance base used in the end in the cleaning wave +{ + {4976.37,-1708.02,1339.43},//0spawn + {4994.83,-1725.52,1333.25},//1 start + {4982.92,-1753.7,1330.69},//2 end + {4996.75,-1721.47,1332.95},//3 start + {5015.74,-1755.05,1322.49},//4 + {4998.68,-1773.44,1329.59},//5 + {4994.83,-1725.52,1333.25},//6 start + {5022.8,-1735.46,1323.53},//7 + {5052.15,-1729.02,1320.88},//8 + {5082.43,-1726.29,1327.87},//9 + {4994.83,-1725.52,1333.25},//10 start + {5018.92,-1751.14,1322.19},//11 + {5040.09,-1792.09,1322.1},//12 + {4994.83,-1725.52,1333.25},//13 start + {5023.47,-1748.1,1322.51},//14 + {5013.43,-1842.39,1322.07},//15 + {4994.83,-1725.52,1333.25},//16 start + {5020.8,-1756.86,1322.2},//17 + {5019.53,-1824.6,1321.96},//18 + {5043.42,-1853.75,1324.52},//19 + {5053.02,-1864.13,1330.36},//20 + {5062.49,-1852.47,1330.49},//21 + {5015.27, -1738.77, 1324.83},//35//start 22 + {5027.97, -1775.25, 1321.87},//34 23 + {5015.94, -1821.24, 1321.86},//33 24 + {4983.25, -1857.4, 1320.48},//32 25 + {4981.51, -1883.7, 1322.34},//31 26 + {5002.33, -1893.98, 1325.88},//30 27 + {5049.32, -1886.54, 1331.69},//29 28 + {5089.68, -1846.88, 1328.99},//28 29 + {5127.90, -1825.14, 1335.58},//27 30 + {5163.27, -1789.08, 1337.04},//26 31 + {5138.97, -1755.88, 1334.57},//25 32 + {5096.63, -1742.22, 1329.61},//24 33 + {5065.81, -1729.43, 1325.66},//23 34 + {5049.32, -1726.31, 1320.64},//22 start + {5081.07, -1902.10, 1346.36},//36 abo start + {5107.65, -1912.03, 1356.49},//37 + {5132.83, -1927.07, 1362.42},//38 + {5147.78, -1954.41, 1365.98},//39 + {5164.96, -1966.48, 1367.04},//40 + {5189.04, -1961.06, 1367.90},//41 + {5212.27, -1975.30, 1365.58},//42 + {5221.82, -1994.18, 1364.97},//43 end1 + {5202.23, -1994.94, 1367.59},//44 end2 + {5279.94, -2049.68, 1311.38},//45 garg1 + {5289.15, -2219.06, 1291.12},//46 garg2 + {5202.07, -2136.10, 1305.07},//47 garg3 + {5071.52, -2425.63, 1454.48},//48 garg4 + {5120.65, -2467.92, 1463.93},//49 garg5 + {5283.04, -2043.26, 1300.11},//50 garg target1 + {5313.22, -2207.60, 1290.06},//51 garg target2 + {5180.41, -2121.87, 1292.62},//52 garg target3 + {5088.68, -2432.04, 1441.73},//53 garg target4 + {5111.26, -2454.73, 1449.63}//54 garg target5 + +}; + +float HordeOverrunWP[21][3]=//waypoints in the horde base used in the end in the cleaning wave +{ + {5490.72,-2702.94,1482.14},//0 start + {5469.77,-2741.34,1486.95}, + {5439.47,-2771.02,1494.59}, + {5408.85,-2811.92,1505.68}, + {5423.87,-2857.80,1515.55}, + {5428.19,-2898.15,1524.61}, + {5394.59,-2930.05,1528.23}, + {5351.11,-2935.80,1532.24}, + {5312.37,-2959.06,1536.21}, + {5264.93,-2989.80,1545.70}, + {5256.63,-3056.16,1559.24}, + {5267.32,-3119.55,1575.36}, + {5305.61,-3139.88,1586.38}, + {5330.56,-3135.37,1588.58}, + {5365.87,-3139.78,1583.96}, + {5389.39,-3163.57,1582.57},//15 end + {5500.86,-2669.89,1481.04},//16 start + {5472.08,-2715.14,1483.55}, + {5450.11,-2721.47,1485.61}, + {5433.25,-2712.93,1493.02},//19 end 1 + {5429.91,-2718.44,1493.42}//20 end 2 +}; + +hyjal_trashAI::hyjal_trashAI(Creature *c) : npc_escortAI(c) +{ + pInstance = c->GetInstanceData(); + IsEvent = false; + Delay = 0; + LastOverronPos = 0; + IsOverrun = false; + OverrunType = 0; + SetupOverrun = false; + faction = 0; + useFlyPath = false; + damageTaken = 0; + Reset(); +} + +void hyjal_trashAI::DamageTaken(Unit *done_by, uint32 &damage) +{ + if (done_by->GetTypeId() == TYPEID_PLAYER || (done_by->GetTypeId() == TYPEID_UNIT && CAST_CRE(done_by)->isPet())) + { + damageTaken += damage; + if (pInstance) + pInstance->SetData(DATA_RAIDDAMAGE,damage);//store raid's damage + } +} + +void hyjal_trashAI::UpdateAI(const uint32 /*diff*/) +{ + if (IsOverrun && !SetupOverrun) + { + SetupOverrun = true; + if (faction == 0) + { + if (me->GetEntry() == GARGOYLE) + { + DummyTarget[0] = AllianceOverrunWP[50+OverrunType][0]; //+OverrunType 0 - 4 + DummyTarget[1] = AllianceOverrunWP[50+OverrunType][1]; + DummyTarget[2] = AllianceOverrunWP[50+OverrunType][2]; + } + if (me->GetEntry() == ABOMINATION) + { + for (uint8 i = 0; i < 4; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); + AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); + AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); + AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); + AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); + AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); + AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); + + AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); + AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); + AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); + AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); + AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); + AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); + AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); + AddWaypoint(18, AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2]); + me->SetHomePosition(AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 18; + Start(true, true); + break; + case 1: + AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); + AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); + AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); + AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); + AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); + AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); + AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); + + AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); + AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); + AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); + AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); + AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); + AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); + AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); + AddWaypoint(18, AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2]); + me->SetHomePosition(AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 18; + Start(true, true); + break; + default: + for (uint8 i = 22; i < 36; ++i) + AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); + + SetDespawnAtEnd(true); + LastOverronPos = 17; + Start(true, true); + break; + } + } + if (me->GetEntry() == GHOUL) + { + for (uint8 i = 0; i < 4; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(4, AllianceOverrunWP[1][0]+irand(-3,3), AllianceOverrunWP[1][1]+irand(-3,3), AllianceOverrunWP[1][2]); + AddWaypoint(5, AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2]); + me->SetHomePosition(AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 5; + Start(true, true); + break; + case 1: + AddWaypoint(4, AllianceOverrunWP[3][0]+irand(-3,3), AllianceOverrunWP[3][1]+irand(-3,3), AllianceOverrunWP[3][2]); + AddWaypoint(5, AllianceOverrunWP[4][0]+irand(-3,3), AllianceOverrunWP[4][1]+irand(-3,3), AllianceOverrunWP[4][2]); + AddWaypoint(6, AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2]); + me->SetHomePosition(AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 2: + AddWaypoint(4, AllianceOverrunWP[6][0]+irand(-3,3), AllianceOverrunWP[6][1]+irand(-3,3), AllianceOverrunWP[6][2]); + AddWaypoint(5, AllianceOverrunWP[7][0]+irand(-3,3), AllianceOverrunWP[7][1]+irand(-3,3), AllianceOverrunWP[7][2]); + AddWaypoint(6, AllianceOverrunWP[8][0]+irand(-3,3), AllianceOverrunWP[8][1]+irand(-3,3), AllianceOverrunWP[8][2]); + AddWaypoint(7, AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2]); + me->SetHomePosition(AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 7; + Start(true, true); + break; + case 3: + AddWaypoint(4, AllianceOverrunWP[10][0]+irand(-3,3), AllianceOverrunWP[10][1]+irand(-3,3), AllianceOverrunWP[10][2]); + AddWaypoint(5, AllianceOverrunWP[11][0]+irand(-3,3), AllianceOverrunWP[11][1]+irand(-3,3), AllianceOverrunWP[11][2]); + AddWaypoint(6, AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2]); + me->SetHomePosition(AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 4: + AddWaypoint(4, AllianceOverrunWP[13][0]+irand(-3,3), AllianceOverrunWP[13][1]+irand(-3,3), AllianceOverrunWP[13][2]); + AddWaypoint(5, AllianceOverrunWP[14][0]+irand(-3,3), AllianceOverrunWP[14][1]+irand(-3,3), AllianceOverrunWP[14][2]); + AddWaypoint(6, AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2]); + me->SetHomePosition(AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 6; + Start(true, true); + break; + case 5: + AddWaypoint(4, AllianceOverrunWP[16][0]+irand(-3,3), AllianceOverrunWP[16][1]+irand(-3,3), AllianceOverrunWP[16][2]); + AddWaypoint(5, AllianceOverrunWP[17][0]+irand(-3,3), AllianceOverrunWP[17][1]+irand(-3,3), AllianceOverrunWP[17][2]); + AddWaypoint(6, AllianceOverrunWP[18][0]+irand(-3,3), AllianceOverrunWP[18][1]+irand(-3,3), AllianceOverrunWP[18][2]); + AddWaypoint(7, AllianceOverrunWP[19][0]+irand(-3,3), AllianceOverrunWP[19][1]+irand(-3,3), AllianceOverrunWP[19][2]); + AddWaypoint(8, AllianceOverrunWP[20][0]+irand(-3,3), AllianceOverrunWP[20][1]+irand(-3,3), AllianceOverrunWP[20][2]); + AddWaypoint(9, AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2]); + me->SetHomePosition(AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 9; + Start(true, true); + break; + default: + for (uint8 i = 22; i < 36; ++i) + AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 17; + Start(true, true); + break; + } + } + } + if (faction == 1) + { + if (me->GetEntry() == GHOUL) + { + for (uint8 i = 0; i < 6; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + switch(OverrunType) + { + case 0: + AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); + AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); + AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); + AddWaypoint(8, HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2]); + me->SetHomePosition(HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 8; + Start(true, true); + break; + case 1: + AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); + AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); + AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); + AddWaypoint(8, HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2]); + me->SetHomePosition(HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2],0); + SetDespawnAtEnd(false); + LastOverronPos = 8; + Start(true, true); + break; + default: + for (uint8 i = 0; i < 16; ++i) + AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 21; + Start(true, true); + break; + } + } + if (me->GetEntry() == ABOMINATION) + { + for (uint8 i = 0; i < 6; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-10,10), HordeWPs[i][1]+irand(-10,10), HordeWPs[i][2]); + for (uint8 i = 0; i < 16; ++i) + AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); + SetDespawnAtEnd(true); + LastOverronPos = 21; + Start(true, true); + } + } + } +} + +void hyjal_trashAI::JustDied(Unit * /*victim*/) +{ + if (!pInstance) + return; + if (IsEvent && !me->isWorldBoss()) + pInstance->SetData(DATA_TRASH, 0);//signal trash is dead + + if ((pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE && !me->isWorldBoss()) || (damageTaken < me->GetMaxHealth()/4 && me->isWorldBoss())) + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);//no loot +} + +struct mob_giant_infernalAI : public hyjal_trashAI +{ + mob_giant_infernalAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + meteor = false;//call once! + CanMove = false; + Delay = rand()%30000; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(MODEL_INVIS); + pGo = false; + pos = 0; + Reset(); + } + + bool meteor; + bool CanMove; + bool WpEnabled; + bool pGo; + uint32 pos; + uint32 spawnTimer; + uint32 FlameBuffetTimer; + bool imol; + + void Reset() + { + spawnTimer = 2000; + FlameBuffetTimer= 2000; + imol = false; + } + + void EnterCombat(Unit* /*who*/) {} + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 0 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (Delay <= diff) + { + Delay=0; + }else{ + Delay-=diff; + return; + } + if (!meteor) + { + float x,y,z; + me->GetPosition(x,y,z); + Creature* trigger = me->SummonCreature(NPC_TRIGGER,x+8,y+8,z+25+rand()%10,me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,1000); + if (trigger) + { + trigger->SetVisibility(VISIBILITY_OFF); + trigger->setFaction(me->getFaction()); + trigger->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + trigger->CastSpell(me,SPELL_METEOR,true); + } + me->GetMotionMaster()->Clear(); + meteor = true; + } else if (!CanMove){ + if (spawnTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); + CanMove = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && !pInstance->GetData(DATA_HORDE_RETREAT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } else if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && pInstance->GetData(DATA_HORDE_RETREAT)){ + //do overrun + } + } + } else spawnTimer -= diff; + } + if (!CanMove)return; + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + AddWaypoint(0, HordeWPs[7][0]+irand(-3,3), HordeWPs[7][1]+irand(-3,3), HordeWPs[7][2]);//HordeWPs[7] infront of thrall + Start(true, true); + SetDespawnAtEnd(false); + } + } + } + + if (!UpdateVictim()) + return; + if (!imol) + { + DoCast(me, SPELL_IMMOLATION); + imol=true; + } + if (FlameBuffetTimer <= diff) + { + DoCast(me->getVictim(), SPELL_FLAME_BUFFET, true); + FlameBuffetTimer = 7000; + } else FlameBuffetTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_giant_infernal(Creature* pCreature) +{ + return new mob_giant_infernalAI(pCreature); +} + +#define SPELL_DISEASE_CLOUD 31607 +#define SPELL_KNOCKDOWN 31610 + +struct mob_abominationAI : public hyjal_trashAI +{ + mob_abominationAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 KnockDownTimer; + uint32 pos; + void Reset() + { + KnockDownTimer = 10000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + if (i == LastOverronPos && IsOverrun) + { + if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) + { + me->setDeathState(DEAD); + me->RemoveCorpse(); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!me->HasAura(SPELL_DISEASE_CLOUD)) + DoCast(me, SPELL_DISEASE_CLOUD); + if (!UpdateVictim()) + return; + if (KnockDownTimer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + KnockDownTimer = 15000+rand()%10000; + } else KnockDownTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_abomination(Creature* pCreature) +{ + return new mob_abominationAI(pCreature); +} + +#define SPELL_FRENZY 31540 + +struct mob_ghoulAI : public hyjal_trashAI +{ + mob_ghoulAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 FrenzyTimer; + uint32 pos; + uint32 MoveTimer; + bool RandomMove; + void Reset() + { + FrenzyTimer = 5000+rand()%5000; + MoveTimer = 2000; + RandomMove = false; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + if (i == LastOverronPos && IsOverrun) + { + me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); + if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) + { + me->setDeathState(DEAD); + me->RemoveCorpse(); + } + + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (FrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + FrenzyTimer = 15000+rand()%15000; + } else FrenzyTimer -= diff; + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_ghoul(Creature* pCreature) +{ + return new mob_ghoulAI(pCreature); +} + +#define SPELL_RAISE_DEAD_1 31617 +#define SPELL_RAISE_DEAD_2 31624 +#define SPELL_RAISE_DEAD_3 31625 +#define SPELL_SHADOW_BOLT 31627 + +struct mob_necromancerAI : public hyjal_trashAI +{ + mob_necromancerAI(Creature* c) : hyjal_trashAI(c), summons(me) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + SummonList summons; + bool pGo; + uint32 ShadowBoltTimer; + uint32 pos; + void Reset() + { + ShadowBoltTimer = 1000+rand()%5000; + summons.DespawnAll(); + } + + void JustSummoned(Creature* summon) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true); + if (pTarget && summon) + summon->Attack(pTarget,false); + summons.Summon(summon); + } + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + switch (urand(0,2)) + { + case 0: + DoSpawnCreature(17902,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + DoSpawnCreature(17902,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + case 1: + DoSpawnCreature(17903,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + DoSpawnCreature(17903,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + case 2: + DoSpawnCreature(RAND(17902,17903),3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); + break; + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(true, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(true, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (ShadowBoltTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + ShadowBoltTimer = 20000+rand()%10000; + } else ShadowBoltTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_necromancer(Creature* pCreature) +{ + return new mob_necromancerAI(pCreature); +} + +#define SPELL_BANSHEE_CURSE 31651 +#define SPELL_BANSHEE_WAIL 38183 +#define SPELL_ANTI_MAGIC_SHELL 31662 + +struct mob_bansheeAI : public hyjal_trashAI +{ + mob_bansheeAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 CourseTimer; + uint32 WailTimer; + uint32 ShellTimer; + uint32 pos; + void Reset() + { + CourseTimer = 20000+rand()%5000; + WailTimer = 15000+rand()%5000; + ShellTimer = 50000+rand()%10000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (CourseTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BANSHEE_CURSE); + CourseTimer = 20000+rand()%5000; + } else CourseTimer -= diff; + if (WailTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BANSHEE_WAIL); + WailTimer = 15000+rand()%5000; + } else WailTimer -= diff; + if (ShellTimer <= diff) + { + DoCast(me, SPELL_ANTI_MAGIC_SHELL); + ShellTimer = 50000+rand()%10000; + } else ShellTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_banshee(Creature* pCreature) +{ + return new mob_bansheeAI(pCreature); +} + +#define SPELL_WEB 28991 + +struct mob_crypt_fiendAI : public hyjal_trashAI +{ + mob_crypt_fiendAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 WebTimer; + uint32 pos; + void Reset() + { + WebTimer = 20000+rand()%5000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + + } + } + } + if (!UpdateVictim()) + return; + if (WebTimer <= diff) + { + DoCast(me->getVictim(), SPELL_WEB); + WebTimer = 20000+rand()%5000; + } else WebTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_crypt_fiend(Creature* pCreature) +{ + return new mob_crypt_fiendAI(pCreature); +} + +#define SPELL_MANA_BURN 31729 + +struct mob_fel_stalkerAI : public hyjal_trashAI +{ + mob_fel_stalkerAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 ManaBurnTimer; + uint32 pos; + void Reset() + { + ManaBurnTimer = 9000+rand()%5000; + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 7 && pInstance && !IsOverrun) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + }else{ + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); + if (pTarget && pTarget->isAlive()) + me->AddThreat(pTarget,0.0); + } + } + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + npc_escortAI::UpdateAI(diff); + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else//use alliance WPs + { + for (uint8 i = 0; i < 8; ++i) + AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + + } + } + } + if (!UpdateVictim()) + return; + if (ManaBurnTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MANA_BURN); + ManaBurnTimer = 9000+rand()%5000; + } else ManaBurnTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_fel_stalker(Creature* pCreature) +{ + return new mob_fel_stalkerAI(pCreature); +} + +#define SPELL_FROST_BREATH 31688 + +struct mob_frost_wyrmAI : public hyjal_trashAI +{ + mob_frost_wyrmAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + Reset(); + } + + bool pGo; + uint32 FrostBreathTimer; + uint32 pos; + uint32 MoveTimer; + + void Reset() + { + FrostBreathTimer = 5000; + MoveTimer = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 2 && pInstance && !IsOverrun) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + { + me->AddThreat(pTarget,0.0); + DoCast(pTarget, SPELL_FROST_BREATH, true); + } + } + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance && IsEvent) + pInstance->SetData(DATA_TRASH, 0);//signal trash is dead + + float x,y,z; + me->GetPosition(x,y,z); + z = me->GetMap()->GetHeight(x, y, z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + me->GetMap()->CreatureRelocation(me, x,y,z,0); + } + + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + { + CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); + npc_escortAI::UpdateAI(diff); + } + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (!useFlyPath) + { + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FrostWyrmWPs[i][0], FrostWyrmWPs[i][1], FrostWyrmWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else{//fly path FlyPathWPs + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (!UpdateVictim()) + return; + if (!me->IsWithinDist(me->getVictim(), 25)){ + if (MoveTimer <= diff) + { + me->GetMotionMaster()->MoveChase(me->getVictim()); + MoveTimer = 2000; + } else MoveTimer-=diff; + } + + if (FrostBreathTimer <= diff) + { + if (!me->IsWithinDist(me->getVictim(), 25)) + { + DoCast(me->getVictim(), SPELL_FROST_BREATH); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + FrostBreathTimer = 4000; + } + } else FrostBreathTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_frost_wyrm(Creature* pCreature) +{ + return new mob_frost_wyrmAI(pCreature); +} + +#define SPELL_GARGOYLE_STRIKE 31664 + +struct mob_gargoyleAI : public hyjal_trashAI +{ + mob_gargoyleAI(Creature* c) : hyjal_trashAI(c) + { + pInstance = c->GetInstanceData(); + pGo = false; + pos = 0; + DummyTarget[0] = 0;DummyTarget[1] = 0;DummyTarget[2] = 0; + Reset(); + } + + bool pGo; + uint32 StrikeTimer; + uint32 pos; + uint32 MoveTimer; + float Zpos; + bool forcemove; + + void Reset() + { + forcemove = true; + Zpos = 10.0; + StrikeTimer = 2000+rand()%5000; + MoveTimer = 0; + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + } + + void WaypointReached(uint32 i) + { + pos = i; + if (i == 2 && pInstance && !IsOverrun) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); + if (pTarget && pTarget->isAlive()) + { + me->AddThreat(pTarget,0.0); + DoCast(pTarget, SPELL_GARGOYLE_STRIKE, true); + } + } + } + + void JustDied(Unit *victim) + { + float x,y,z; + me->GetPosition(x,y,z); + z = me->GetMap()->GetHeight(x, y, z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + me->GetMap()->CreatureRelocation(me, x,y,z,0); + hyjal_trashAI::JustDied(victim); + } + + void UpdateAI(const uint32 diff) + { + hyjal_trashAI::UpdateAI(diff); + if (IsEvent || IsOverrun) + { + CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); + npc_escortAI::UpdateAI(diff); + } + if (IsEvent) + { + if (!pGo) + { + pGo = true; + if (pInstance) + { + if (!useFlyPath) + { + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, GargoyleWPs[i][0]+irand(-10,10), GargoyleWPs[i][1]+irand(-10,10), GargoyleWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + }else{//fly path FlyPathWPs + for (uint8 i = 0; i < 3; ++i) + AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); + Start(false, true); + SetDespawnAtEnd(false); + } + } + } + } + if (IsOverrun && !UpdateVictim()) + { + if (faction == 0)//alliance + { + if (StrikeTimer <= diff) + { + me->CastSpell(DummyTarget[0],DummyTarget[1],DummyTarget[2],SPELL_GARGOYLE_STRIKE,false); + StrikeTimer = 2000+rand()%1000; + } else StrikeTimer -= diff; + } + } + if (!UpdateVictim()) + return; + if (!me->IsWithinDist(me->getVictim(), 20) || forcemove) + { + forcemove = false; + if (forcemove) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + me->Attack(pTarget,false); + } + if (MoveTimer <= diff) + { + float x,y,z; + me->getVictim()->GetPosition(x,y,z); + me->GetMotionMaster()->MovePoint(0,x,y,z+Zpos); + Zpos-=1.0; + if (Zpos <= 0)Zpos=0; + MoveTimer = 2000; + } else MoveTimer-=diff; + } + if (StrikeTimer <= diff) + { + if (me->IsWithinDist(me->getVictim(), 20)) + { + DoCast(me->getVictim(), SPELL_GARGOYLE_STRIKE); + me->StopMoving(); + me->GetMotionMaster()->Clear(); + StrikeTimer = 2000+rand()%1000; + } else StrikeTimer=0; + } else StrikeTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_gargoyle(Creature* pCreature) +{ + return new mob_gargoyleAI(pCreature); +} + +#define SPELL_EXPLODING_SHOT 7896 + +struct alliance_riflemanAI : public Scripted_NoMovementAI +{ + alliance_riflemanAI(Creature *c) : Scripted_NoMovementAI(c) + { + Reset(); + } + + uint32 ExplodeTimer; + + void JustDied(Unit* /*who*/) + { + } + + void Reset() + { + ExplodeTimer = 5000+rand()%5000; + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && me->IsHostileTo(who)) + { + //float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, 30)) + AttackStart(who); + } + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Check if we have a target + if (!UpdateVictim()) + return; + if (ExplodeTimer <= diff) + { + if (!me->IsWithinDistInMap(me->getVictim(), 30)) + { + EnterEvadeMode(); + return; + } + int dmg = 500+rand()%700; + me->CastCustomSpell(me->getVictim(), SPELL_EXPLODING_SHOT, &dmg, 0, 0, false); + ExplodeTimer = 5000+rand()%5000; + } else ExplodeTimer -= diff; + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_alliance_rifleman(Creature* pCreature) +{ + return new alliance_riflemanAI(pCreature); +} + +void AddSC_hyjal_trash() +{ + Script *newscript = new Script; + newscript->Name = "mob_giant_infernal"; + newscript->GetAI = &GetAI_mob_giant_infernal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_abomination"; + newscript->GetAI = &GetAI_mob_abomination; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ghoul"; + newscript->GetAI = &GetAI_mob_ghoul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_necromancer"; + newscript->GetAI = &GetAI_mob_necromancer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_banshee"; + newscript->GetAI = &GetAI_mob_banshee; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crypt_fiend"; + newscript->GetAI = &GetAI_mob_crypt_fiend; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_stalker"; + newscript->GetAI = &GetAI_mob_fel_stalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_wyrm"; + newscript->GetAI = &GetAI_mob_frost_wyrm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_gargoyle"; + newscript->GetAI = &GetAI_mob_gargoyle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "alliance_rifleman"; + newscript->GetAI = &GetAI_alliance_rifleman; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h new file mode 100644 index 00000000000..21ee4bc06cc --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.h @@ -0,0 +1,35 @@ + +#ifndef SC_HYJAL_TRASH_AI_H +#define SC_HYJAL_TRASH_AI_H + +#include "hyjal.h" +#include "ScriptedEscortAI.h" + +#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies + +struct hyjal_trashAI : public npc_escortAI +{ + hyjal_trashAI(Creature *c); + + void UpdateAI(const uint32 diff); + + void JustDied(Unit* /*killer*/); + + void DamageTaken(Unit *done_by, uint32 &damage); + + public: + ScriptedInstance* pInstance; + bool IsEvent; + uint32 Delay; + uint32 LastOverronPos; + bool IsOverrun; + bool SetupOverrun; + uint32 OverrunType; + uint8 faction; + bool useFlyPath; + uint32 damageTaken; + float DummyTarget[3]; + + //private: +}; +#endif diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp new file mode 100644 index 00000000000..e89d518c5bc --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/instance_hyjal.cpp @@ -0,0 +1,324 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Mount_Hyjal +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts +SDCategory: Caverns of Time, Mount Hyjal +EndScriptData */ + +#include "ScriptedPch.h" +#include "hyjal.h" +#include "hyjal_trash.h" + +enum eEnums +{ + MAX_ENCOUNTER = 5, + + GO_ANCIENT_GEM = 185557 +}; +/* Battle of Mount Hyjal encounters: +0 - Rage Winterchill event +1 - Anetheron event +2 - Kaz'rogal event +3 - Azgalor event +4 - Archimonde event +*/ + +struct instance_mount_hyjal : public ScriptedInstance +{ + instance_mount_hyjal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + std::list m_uiAncientGemGUID; + + uint64 RageWinterchill; + uint64 Anetheron; + uint64 Kazrogal; + uint64 Azgalor; + uint64 Archimonde; + uint64 JainaProudmoore; + uint64 Thrall; + uint64 TyrandeWhisperwind; + uint64 HordeGate; + uint64 ElfGate; + + uint32 Trash; + + uint32 hordeRetreat; + uint32 allianceRetreat; + bool ArchiYell; + + uint32 RaidDamage; + + #define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more." + #define YELL_EFFORTS_NAME "Archimonde" + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiAncientGemGUID.clear(); + + RageWinterchill = 0; + Anetheron = 0; + Kazrogal = 0; + Azgalor = 0; + Archimonde = 0; + JainaProudmoore = 0; + Thrall = 0; + TyrandeWhisperwind = 0; + HordeGate = 0; + ElfGate = 0; + ArchiYell = false; + RaidDamage = 0; + + Trash = 0; + + hordeRetreat = 0; + allianceRetreat = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 182060: + HordeGate = pGo->GetGUID(); + if (allianceRetreat) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + case 182061: + ElfGate = pGo->GetGUID(); + if (hordeRetreat) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + case GO_ANCIENT_GEM: + m_uiAncientGemGUID.push_back(pGo->GetGUID()); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17767: RageWinterchill = pCreature->GetGUID(); break; + case 17808: Anetheron = pCreature->GetGUID(); break; + case 17888: Kazrogal = pCreature->GetGUID(); break; + case 17842: Azgalor = pCreature->GetGUID(); break; + case 17968: Archimonde = pCreature->GetGUID(); break; + case 17772: JainaProudmoore = pCreature->GetGUID(); break; + case 17852: Thrall = pCreature->GetGUID(); break; + case 17948: TyrandeWhisperwind = pCreature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_RAGEWINTERCHILL: return RageWinterchill; + case DATA_ANETHERON: return Anetheron; + case DATA_KAZROGAL: return Kazrogal; + case DATA_AZGALOR: return Azgalor; + case DATA_ARCHIMONDE: return Archimonde; + case DATA_JAINAPROUDMOORE: return JainaProudmoore; + case DATA_THRALL: return Thrall; + case DATA_TYRANDEWHISPERWIND: return TyrandeWhisperwind; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_RAGEWINTERCHILLEVENT: m_auiEncounter[0] = data; break; + case DATA_ANETHERONEVENT: + m_auiEncounter[1] = data; + break; + case DATA_KAZROGALEVENT: m_auiEncounter[2] = data; break; + case DATA_AZGALOREVENT: + { + m_auiEncounter[3] = data; + if (data == DONE) + { + if (ArchiYell)break; + ArchiYell = true; + + Creature* pCreature = instance->GetCreature(Azgalor); + if (pCreature) + { + Creature* pUnit = pCreature->SummonCreature(21987,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,10000); + + Map* pMap = pCreature->GetMap(); + if (pMap->IsDungeon() && pUnit) + { + pUnit->SetVisibility(VISIBILITY_OFF); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()) + { + WorldPacket data(SMSG_MESSAGECHAT, 200); + pUnit->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,YELL_EFFORTS,0,YELL_EFFORTS_NAME,i->getSource()->GetGUID()); + i->getSource()->GetSession()->SendPacket(&data); + + WorldPacket data2(SMSG_PLAY_SOUND, 4); + data2 << 10986; + i->getSource()->GetSession()->SendPacket(&data2); + } + } + } + } + } + } + break; + case DATA_ARCHIMONDEEVENT: m_auiEncounter[4] = data; break; + case DATA_RESET_TRASH_COUNT: Trash = 0; break; + + case DATA_TRASH: + if (data) Trash = data; + else Trash--; + DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash); + break; + case TYPE_RETREAT: + if (data == SPECIAL) + { + if (!m_uiAncientGemGUID.empty()) + { + for (std::list::const_iterator itr = m_uiAncientGemGUID.begin(); itr != m_uiAncientGemGUID.end(); ++itr) + { + //don't know how long it expected + DoRespawnGameObject(*itr,DAY); + } + } + } + break; + case DATA_ALLIANCE_RETREAT: + allianceRetreat = data; + HandleGameObject(HordeGate, true); + SaveToDB(); + break; + case DATA_HORDE_RETREAT: + hordeRetreat = data; + HandleGameObject(ElfGate, true); + SaveToDB(); + break; + case DATA_RAIDDAMAGE: + RaidDamage += data; + if (RaidDamage >= MINRAIDDAMAGE) + RaidDamage = MINRAIDDAMAGE; + break; + case DATA_RESET_RAIDDAMAGE: + RaidDamage = 0; + break; + } + + debug_log("TSCR: Instance Hyjal: Instance data updated for event %u (Data=%u)",type,data); + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] + << " " << allianceRetreat << " " << hordeRetreat + << " " << RaidDamage; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_RAGEWINTERCHILLEVENT: return m_auiEncounter[0]; + case DATA_ANETHERONEVENT: return m_auiEncounter[1]; + case DATA_KAZROGALEVENT: return m_auiEncounter[2]; + case DATA_AZGALOREVENT: return m_auiEncounter[3]; + case DATA_ARCHIMONDEEVENT: return m_auiEncounter[4]; + case DATA_TRASH: return Trash; + case DATA_ALLIANCE_RETREAT: return allianceRetreat; + case DATA_HORDE_RETREAT: return hordeRetreat; + case DATA_RAIDDAMAGE: return RaidDamage; + } + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4] >> allianceRetreat >> hordeRetreat >> RaidDamage; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_mount_hyjal(Map* pMap) +{ + return new instance_mount_hyjal(pMap); +} + +void AddSC_instance_mount_hyjal() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_hyjal"; + newscript->GetInstanceData = &GetInstanceData_instance_mount_hyjal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_epoch.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_epoch.cpp new file mode 100644 index 00000000000..287d3cf8e9b --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_epoch.cpp @@ -0,0 +1,156 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + + +/* Script Data Start +SDName: Boss epoch +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro, consecutive attacks to a random target durin time wrap, adjust timers +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CURSE_OF_EXERTION = 52772, + SPELL_TIME_WARP = 52766, //Time slows down, reducing attack, casting and movement speed by 70% for 6 sec. + SPELL_TIME_STOP = 58848, //Stops time in a 50 yard sphere for 2 sec. + SPELL_WOUNDING_STRIKE = 52771, //Used only on the tank + H_SPELL_WOUNDING_STRIKE = 58830 +}; + +enum Yells +{ + SAY_INTRO = -1595000, //"Prince Arthas Menethil, on this day, a powerful darkness has taken hold of your soul. The death you are destined to visit upon others will this day be your own." + SAY_AGGRO = -1595001, //"We'll see about that, young prince." + SAY_TIME_WARP_1 = -1595002, //"Tick tock, tick tock..." + SAY_TIME_WARP_2 = -1595003, //"Not quick enough!" + SAY_TIME_WARP_3 = -1595004, //"Let's get this over with. " + SAY_SLAY_1 = -1595005, //"There is no future for you." + SAY_SLAY_2 = -1595006, //"This is the hour of our greatest triumph!" + SAY_SLAY_3 = -1595007, //"You were destined to fail. " + SAY_DEATH = -1595008 //"*gurgles*" +}; + +struct boss_epochAI : public ScriptedAI +{ + boss_epochAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint8 uiStep; + + uint32 uiStepTimer; + uint32 uiWoundingStrikeTimer; + uint32 uiTimeWarpTimer; + uint32 uiTimeStopTimer; + uint32 uiCurseOfExertionTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiStep = 1; + uiStepTimer = 26000; + uiCurseOfExertionTimer = 9300; + uiTimeWarpTimer = 25300; + uiTimeStopTimer = 21300; + uiWoundingStrikeTimer = 5300; + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiCurseOfExertionTimer < diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CURSE_OF_EXERTION); + uiCurseOfExertionTimer = 9300; + } else uiCurseOfExertionTimer -= diff; + + if (uiWoundingStrikeTimer < diff) + { + DoCastVictim(SPELL_WOUNDING_STRIKE); + uiWoundingStrikeTimer = 5300; + } else uiWoundingStrikeTimer -= diff; + + if (uiTimeStopTimer < diff) + { + DoCastAOE(SPELL_TIME_STOP); + uiTimeStopTimer = 21300; + } else uiTimeStopTimer -= diff; + + if (uiTimeWarpTimer < diff) + { + DoScriptText(RAND(SAY_TIME_WARP_1,SAY_TIME_WARP_2,SAY_TIME_WARP_3), me); + DoCastAOE(SPELL_TIME_WARP); + uiTimeWarpTimer = 25300; + } else uiTimeWarpTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_EPOCH_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_epoch(Creature* pCreature) +{ + return new boss_epochAI (pCreature); +} + +void AddSC_boss_epoch() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_epoch"; + newscript->GetAI = &GetAI_boss_epoch; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite.cpp new file mode 100644 index 00000000000..12cdf00f2a5 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_infinite.cpp @@ -0,0 +1,88 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CORRUPTING_BLIGHT = 60588, + SPELL_VOID_STRIKE = 60590 +}; + +enum Yells +{ + SAY_AGGRO = -1595045, + SAY_FAIL = -1595046, + SAY_DEATH = -1595047 +}; + + +struct boss_infinite_corruptorAI : public ScriptedAI +{ + boss_infinite_corruptorAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_INFINITE_EVENT, DONE); + } +}; + +CreatureAI* GetAI_boss_infinite_corruptor(Creature* pCreature) +{ + return new boss_infinite_corruptorAI(pCreature); +} + +void AddSC_boss_infinite_corruptor() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_infinite_corruptor"; + newscript->GetAI = &GetAI_boss_infinite_corruptor; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp new file mode 100644 index 00000000000..a39f3289a5a --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_mal_ganis.cpp @@ -0,0 +1,262 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss mal_ganis +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro & outro +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_mal_ganis' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CARRION_SWARM = 52720, //A cresting wave of chaotic magic splashes over enemies in front of the caster, dealing 3230 to 3570 Shadow damage and 380 to 420 Shadow damage every 3 sec. for 15 sec. + H_SPELL_CARRION_SWARM = 58852, + SPELL_MIND_BLAST = 52722, //Inflicts 4163 to 4837 Shadow damage to an enemy. + H_SPELL_MIND_BLAST = 58850, + SPELL_SLEEP = 52721, //Puts an enemy to sleep for up to 10 sec. Any damage caused will awaken the target. + H_SPELL_SLEEP = 58849, + SPELL_VAMPIRIC_TOUCH = 52723 //Heals the caster for half the damage dealt by a melee attack. +}; + +enum Yells +{ + SAY_INTRO_1 = -1595009, + SAY_INTRO_2 = -1595010, + SAY_AGGRO = -1595011, + SAY_KILL_1 = -1595012, + SAY_KILL_2 = -1595013, + SAY_KILL_3 = -1595014, + SAY_SLAY_1 = -1595015, + SAY_SLAY_2 = -1595016, + SAY_SLAY_3 = -1595017, + SAY_SLAY_4 = -1595018, + SAY_SLEEP_1 = -1595019, + SAY_SLEEP_2 = -1595020, + SAY_30HEALTH = -1595021, + SAY_15HEALTH = -1595022, + SAY_ESCAPE_SPEECH_1 = -1595023, + SAY_ESCAPE_SPEECH_2 = -1595024, + SAY_OUTRO = -1595025, +}; + +enum CombatPhases +{ + COMBAT, + OUTRO +}; + +struct boss_mal_ganisAI : public ScriptedAI +{ + boss_mal_ganisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiCarrionSwarmTimer; + uint32 uiMindBlastTimer; + uint32 uiVampiricTouchTimer; + uint32 uiSleepTimer; + + uint8 uiOutroStep; + uint32 uiOutroTimer; + + bool bYelled; + bool bYelled2; + + CombatPhases Phase; + + ScriptedInstance* pInstance; + + void Reset() + { + bYelled = false; + bYelled2 = false; + Phase = COMBAT; + uiCarrionSwarmTimer = 6000; + uiMindBlastTimer = 11000; + uiVampiricTouchTimer = urand(10000,15000); + uiSleepTimer = urand(15000,20000); + uiOutroTimer = 1000; + + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, IN_PROGRESS); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (damage >= me->GetHealth() && done_by != me) + damage = me->GetHealth()-1; + } + + void UpdateAI(const uint32 diff) + { + switch(Phase) + { + case COMBAT: + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!bYelled && HealthBelowPct(30)) + { + DoScriptText(SAY_30HEALTH, me); + bYelled = true; + } + + if (!bYelled2 && HealthBelowPct(15)) + { + DoScriptText(SAY_15HEALTH, me); + bYelled2 = true; + } + + if (HealthBelowPct(1)) + { + //Handle Escape Event: Don't forget to add Player::RewardPlayerAndGroupAtEvent + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); + uiOutroStep = 1; + Phase = OUTRO; + return; + } + + if (Creature* pArthas = me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0)) + if (pArthas->isDead()) + { + EnterEvadeMode(); + me->DisappearAndDie(); + if (pInstance) + pInstance->SetData(DATA_MAL_GANIS_EVENT, FAIL); + } + + if (uiCarrionSwarmTimer < diff) + { + DoCastVictim(SPELL_CARRION_SWARM); + uiCarrionSwarmTimer = 7000; + } else uiCarrionSwarmTimer -= diff; + + if (uiMindBlastTimer < diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_MIND_BLAST); + uiMindBlastTimer = 6000; + } else uiMindBlastTimer -= diff; + + if (uiVampiricTouchTimer < diff) + { + DoCast(me, SPELL_VAMPIRIC_TOUCH); + uiVampiricTouchTimer = 32000; + } else uiVampiricTouchTimer -= diff; + + if (uiSleepTimer < diff) + { + DoScriptText(RAND(SAY_SLEEP_1,SAY_SLEEP_2), me); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SLEEP); + uiSleepTimer = urand(15000,20000); + } else uiSleepTimer -= diff; + + DoMeleeAttackIfReady(); + break; + case OUTRO: + if (uiOutroTimer < diff) + { + switch(uiOutroStep) + { + case 1: + DoScriptText(SAY_ESCAPE_SPEECH_1, me); + me->GetMotionMaster()->MoveTargetedHome(); + ++uiOutroStep; + uiOutroTimer = 8000; + break; + case 2: + me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0); + me->HandleEmoteCommand(29); + DoScriptText(SAY_ESCAPE_SPEECH_2, me); + ++uiOutroStep; + uiOutroTimer = 9000; + break; + case 3: + DoScriptText(SAY_OUTRO, me); + ++uiOutroStep; + uiOutroTimer = 16000; + break; + case 4: + me->HandleEmoteCommand(33); + ++uiOutroStep; + uiOutroTimer = 500; + break; + case 5: + me->SetVisibility(VISIBILITY_OFF); + me->Kill(me); + break; + + } + } else uiOutroTimer -= diff; + break; + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + pInstance->SetData(DATA_MAL_GANIS_EVENT, DONE); + + // give achievement credit to players. criteria use spell 58630 which doesn't exist. + if (pInstance) + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 58630); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } +}; + +CreatureAI* GetAI_boss_mal_ganis(Creature* pCreature) +{ + return new boss_mal_ganisAI (pCreature); +} + +void AddSC_boss_mal_ganis() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_mal_ganis"; + newscript->GetAI = &GetAI_boss_mal_ganis; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp new file mode 100644 index 00000000000..eba9733c745 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_meathook.cpp @@ -0,0 +1,140 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss meathook +SDAuthor: Tartalo +SD%Complete: 100 +SDComment: It may need timer adjustment +SDCategory: +Script Data End */ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CONSTRICTING_CHAINS = 52696, //Encases the targets in chains, dealing 1800 Physical damage every 1 sec. and stunning the target for 5 sec. + H_SPELL_CONSTRICTING_CHAINS = 58823, + SPELL_DISEASE_EXPULSION = 52666, //Meathook belches out a cloud of disease, dealing 1710 to 1890 Nature damage and interrupting the spell casting of nearby enemy targets for 4 sec. + H_SPELL_DISEASE_EXPULSION = 58824, + SPELL_FRENZY = 58841 //Increases the caster's Physical damage by 10% for 30 sec. +}; + +enum Yells +{ + SAY_AGGRO = -1595026, + SAY_SLAY_1 = -1595027, + SAY_SLAY_2 = -1595028, + SAY_SLAY_3 = -1595029, + SAY_SPAWN = -1595030, + SAY_DEATH = -1595031 +}; + +struct boss_meathookAI : public ScriptedAI +{ + boss_meathookAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + DoScriptText(SAY_SPAWN,me); + } + + uint32 uiChainTimer; + uint32 uiDiseaseTimer; + uint32 uiFrenzyTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiChainTimer = urand(12000,17000); //seen on video 13, 17, 15, 12, 16 + uiDiseaseTimer = urand(2000,4000); //approx 3s + uiFrenzyTimer = urand(21000,26000); //made it up + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiDiseaseTimer <= diff) + { + DoCastAOE(SPELL_DISEASE_EXPULSION); + uiDiseaseTimer = urand(1500,4000); + } else uiDiseaseTimer -= diff; + + if (uiFrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + uiFrenzyTimer = urand(21000,26000); + } else uiFrenzyTimer -= diff; + + if (uiChainTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CONSTRICTING_CHAINS); //anyone but the tank + uiChainTimer = urand(2000,4000); + } else uiChainTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MEATHOOK_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_meathook(Creature* pCreature) +{ + return new boss_meathookAI (pCreature); +} + +void AddSC_boss_meathook() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_meathook"; + newscript->GetAI = &GetAI_boss_meathook; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm.cpp new file mode 100644 index 00000000000..da1c8098517 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/boss_salramm.cpp @@ -0,0 +1,170 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* Script Data Start +SDName: Boss salramm +SDAuthor: Tartalo +SD%Complete: 80 +SDComment: TODO: Intro +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_salramm' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +enum Spells +{ + SPELL_CURSE_OF_TWISTED_FLESH = 58845, + SPELL_EXPLODE_GHOUL = 52480, + H_SPELL_EXPLODE_GHOUL = 58825, + SPELL_SHADOW_BOLT = 57725, + H_SPELL_SHADOW_BOLT = 58828, + SPELL_STEAL_FLESH = 52708, + SPELL_SUMMON_GHOULS = 52451 +}; + +enum Yells +{ + SAY_AGGRO = -1595032, + SAY_SPAWN = -1595033, + SAY_SLAY_1 = -1595034, + SAY_SLAY_2 = -1595035, + SAY_SLAY_3 = -1595036, + SAY_DEATH = -1595037, + SAY_EXPLODE_GHOUL_1 = -1595038, + SAY_EXPLODE_GHOUL_2 = -1595039, + SAY_STEAL_FLESH_1 = -1595040, + SAY_STEAL_FLESH_2 = -1595041, + SAY_STEAL_FLESH_3 = -1595042, + SAY_SUMMON_GHOULS_1 = -1595043, + SAY_SUMMON_GHOULS_2 = -1595044 +}; + +struct boss_salrammAI : public ScriptedAI +{ + boss_salrammAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + if (pInstance) + DoScriptText(SAY_SPAWN,me); + } + + uint32 uiCurseFleshTimer; + uint32 uiExplodeGhoulTimer; + uint32 uiShadowBoltTimer; + uint32 uiStealFleshTimer; + uint32 uiSummonGhoulsTimer; + + ScriptedInstance* pInstance; + + void Reset() + { + uiCurseFleshTimer = 30000; //30s DBM + uiExplodeGhoulTimer = urand(25000,28000); //approx 6 sec after summon ghouls + uiShadowBoltTimer = urand(8000,12000); // approx 10s + uiStealFleshTimer = 12345; + uiSummonGhoulsTimer = urand(19000,24000); //on a video approx 24s after aggro + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Curse of twisted flesh timer + if (uiCurseFleshTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CURSE_OF_TWISTED_FLESH); + uiCurseFleshTimer = 37000; + } else uiCurseFleshTimer -= diff; + + //Shadow bolt timer + if (uiShadowBoltTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + uiShadowBoltTimer = urand(8000,12000); + } else uiShadowBoltTimer -= diff; + + //Steal Flesh timer + if (uiStealFleshTimer <= diff) + { + DoScriptText(RAND(SAY_STEAL_FLESH_1,SAY_STEAL_FLESH_2,SAY_STEAL_FLESH_3), me); + if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(random_pTarget, SPELL_STEAL_FLESH); + uiStealFleshTimer = 10000; + } else uiStealFleshTimer -= diff; + + //Summon ghouls timer + if (uiSummonGhoulsTimer <= diff) + { + DoScriptText(RAND(SAY_SUMMON_GHOULS_1,SAY_SUMMON_GHOULS_2), me); + if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(random_pTarget, SPELL_SUMMON_GHOULS); + uiSummonGhoulsTimer = 10000; + } else uiSummonGhoulsTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_SALRAMM_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_salramm(Creature* pCreature) +{ + return new boss_salrammAI (pCreature); +} + +void AddSC_boss_salramm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_salramm"; + newscript->GetAI = &GetAI_boss_salramm; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp new file mode 100644 index 00000000000..faaed2eb6db --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.cpp @@ -0,0 +1,1210 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" +#include "ScriptedEscortAI.h" + +enum Says +{ + //First Act - Uther and Jaina Dialog + SAY_PHASE101 = -1595070, //Arthas + SAY_PHASE102 = -1595071, //Uther + SAY_PHASE103 = -1595072, //Arthas + SAY_PHASE104 = -1595073, //Arthas + SAY_PHASE105 = -1595074, //Uther + SAY_PHASE106 = -1595075, //Arthas + SAY_PHASE107 = -1595076, //Uther + SAY_PHASE108 = -1595077, //Arthas + SAY_PHASE109 = -1595078, //Arthas + SAY_PHASE110 = -1595079, //Uther + SAY_PHASE111 = -1595080, //Arthas + SAY_PHASE112 = -1595081, //Uther + SAY_PHASE113 = -1595082, //Jaina + SAY_PHASE114 = -1595083, //Arthas + SAY_PHASE115 = -1595084, //Uther + SAY_PHASE116 = -1595085, //Arthas + SAY_PHASE117 = -1595086, //Jaina + SAY_PHASE118 = -1595087, //Arthas + //Second Act - City Streets + SAY_PHASE201 = -1595088, //Arthas + SAY_PHASE202 = -1595089, //Cityman + SAY_PHASE203 = -1595090, //Arthas + SAY_PHASE204 = -1595091, //Crazyman + SAY_PHASE205 = -1595092, //Arthas + SAY_PHASE206 = -1595009, //Malganis + SAY_PHASE207 = -1595010, //Malganis + SAY_PHASE208 = -1595093, //Arthas + SAY_PHASE209 = -1595094, //Arthas + SAY_PHASE210 = -1595095, //Arthas + //Third Act - Town Hall + SAY_PHASE301 = -1595096, //Arthas + SAY_PHASE302 = -1595097, //Drakonian + SAY_PHASE303 = -1595098, //Arthas + SAY_PHASE304 = -1595099, //Arthas + SAY_PHASE305 = -1595100, //Drakonian + SAY_PHASE306 = -1595101, //Arthas + SAY_PHASE307 = -1595102, //Arthas + SAY_PHASE308 = -1595103, //Arthas + SAY_PHASE309 = -1595104, //Arthas + SAY_PHASE310 = -1595105, //Arthas + SAY_PHASE311 = -1595106, //Arthas + SAY_PHASE312 = -1595107, //Arthas + SAY_PHASE313 = -1595108, //Arthas + SAY_PHASE314 = -1595000, //Epoch + SAY_PHASE315 = -1595109, //Arthas + //Fourth Act - Fire Corridor + SAY_PHASE401 = -1595110, //Arthas + SAY_PHASE402 = -1595111, //Arthas + SAY_PHASE403 = -1595112, //Arthas + SAY_PHASE404 = -1595113, //Arthas + SAY_PHASE405 = -1595114, //Arthas + SAY_PHASE406 = -1595115, //Arthas + SAY_PHASE407 = -1595116, //Arthas + //Fifth Act - Mal'Ganis Fight + SAY_PHASE501 = -1595117, //Arthas + SAY_PHASE502 = -1595118, //Arthas + SAY_PHASE503 = -1595119, //Arthas + SAY_PHASE504 = -1595120, //Arthas +}; + +enum NPCs +{ + NPC_INFINITE_ADVERSARY = 27742, + NPC_INFINITE_HUNTER = 27743, + NPC_INFINITE_AGENT = 27744, + NPC_TIME_RIFT = 28409, + NPC_ZOMBIE = 27737, + NPC_GHOUL = 28249, + NPC_NECROMANCER = 28200, + NPC_STALKER = 28199, + NPC_FIEND = 27734, + NPC_GOLEM = 28201, + NPC_EGHOUL = 27729, + NPC_CONSTRUCT = 27736, + + NPC_INVIS_TARGET = 20562, + + NPC_KNIGHT_ESCORT = 27745, + NPC_PRIEST_ESCORT = 27747, + NPC_CITY_MAN = 28167, + NPC_CITY_MAN2 = 28169, + NPC_CITY_MAN3 = 31126, + NPC_CITY_MAN4 = 31127, +}; + +enum Spells +{ + SPELL_FEAR = 39176, + SPELL_ARTHAS_AURA = 52442, + SPELL_EXORCISM_N = 52445, + SPELL_EXORCISM_H = 58822, + SPELL_HOLY_LIGHT = 52444, +}; + +enum GossipMenuArthas +{ + GOSSIP_MENU_ARTHAS_1 = 100001, + GOSSIP_MENU_ARTHAS_2 = 100002, + GOSSIP_MENU_ARTHAS_3 = 100003, + GOSSIP_MENU_ARTHAS_4 = 100004, + GOSSIP_MENU_ARTHAS_5 = 100005 +}; + +enum +{ + ENCOUNTER_WAVES_NUMBER = 8, + ENCOUNTER_WAVES_MAX_SPAWNS = 5, + ENCOUNTER_DRACONIAN_NUMBER = 4, + ENCOUNTER_CHRONO_SPAWNS = 19 +}; + +// Locations for necromancers and add to spawn +float WavesLocations[ENCOUNTER_WAVES_NUMBER][ENCOUNTER_WAVES_MAX_SPAWNS][5]= +{ + { + {NPC_ZOMBIE, 2164.698975, 1255.392944, 135.040878, 0.490202}, + {NPC_ZOMBIE, 2183.501465, 1263.079102, 134.859055, 3.169981}, + {NPC_GHOUL, 2177.512939, 1247.313843, 135.846695, 1.696574}, + {NPC_GHOUL, 2171.991943, 1246.615845, 135.745026, 1.696574}, + {0, 0, 0, 0, 0} + }, + { + {NPC_GHOUL, 2254.434326, 1163.427612, 138.055038, 2.077358}, + {NPC_GHOUL, 2254.703613, 1158.867798, 138.212234, 2.345532}, + {NPC_GHOUL, 2257.615723, 1162.310913, 138.091202, 2.077358}, + {NPC_NECROMANCER, 2258.258057, 1157.250732, 138.272873, 2.387766}, + {0, 0, 0, 0, 0} + }, + { + {NPC_STALKER, 2348.120117, 1202.302490, 130.491104, 4.698538}, + {NPC_GHOUL, 2352.863525, 1207.819092, 130.424271, 4.949865}, + {NPC_GHOUL, 2343.593750, 1207.915039, 130.781311, 4.321547}, + {NPC_NECROMANCER, 2348.257324, 1212.202515, 130.670135, 4.450352}, + {0, 0, 0, 0, 0} + }, + { + {NPC_STALKER, 2139.825195, 1356.277100, 132.199615, 5.820131}, + {NPC_GHOUL, 2137.073486, 1362.464844, 132.271637, 5.820131}, + {NPC_GHOUL, 2134.075684, 1354.148071, 131.885864, 5.820131}, + {NPC_NECROMANCER, 2133.302246, 1358.907837, 132.037689, 5.820131}, + {0, 0, 0, 0, 0} + }, + { + {NPC_NECROMANCER, 2264.013428, 1174.055908, 138.093094, 2.860481}, + {NPC_GHOUL, 2264.207764, 1170.892700, 138.034973, 2.860481}, + {NPC_GHOUL, 2266.948975, 1176.898926, 137.976929, 2.860481}, + {NPC_STALKER, 2269.215576, 1170.109253, 137.742691, 2.860481}, + {NPC_FIEND, 2273.106689, 1176.101074, 137.880508, 2.860481} + }, + { + {NPC_GOLEM, 2349.701660, 1188.436646, 130.428864, 3.908642}, + {NPC_GHOUL, 2349.909180, 1194.582642, 130.417816, 3.577001}, + {NPC_EGHOUL, 2354.662598, 1185.692017, 130.552032, 3.577001}, + {NPC_EGHOUL, 2354.716797, 1191.614380, 130.539810, 3.577001}, + {0, 0, 0, 0, 0} + }, + { + {NPC_CONSTRUCT, 2145.212891, 1355.288086, 132.288773, 6.004838}, + {NPC_NECROMANCER, 2137.078613, 1357.612671, 132.173340, 6.004838}, + {NPC_EGHOUL, 2139.402100, 1352.541626, 132.127518, 5.812850}, + {NPC_EGHOUL, 2142.408447, 1360.760620, 132.321564, 5.812850}, + {0, 0, 0, 0, 0} + }, + { + {NPC_GHOUL, 2172.686279, 1259.618164, 134.391754, 1.865499}, + {NPC_FIEND, 2177.649170, 1256.061157, 135.096512, 1.849572}, + {NPC_CONSTRUCT, 2170.782959, 1253.594849, 134.973022, 1.849572}, + {NPC_NECROMANCER, 2175.595703, 1249.041992, 135.603531, 1.849572}, + {0, 0, 0, 0, 0} + } +}; + +// Locations for rifts to spawn and draconians to go +float RiftAndSpawnsLocations[ENCOUNTER_CHRONO_SPAWNS][5]= +{ + {NPC_TIME_RIFT, 2431.790039, 1190.670044, 148.076004, 0.187923}, + {NPC_INFINITE_ADVERSARY, 2433.857910, 1185.612061, 148.075974, 4.566168}, + {NPC_INFINITE_ADVERSARY, 2437.577881, 1188.241089, 148.075974, 0.196999}, + {NPC_INFINITE_AGENT, 2437.165527, 1192.294922, 148.075974, 0.169247}, + {NPC_INFINITE_HUNTER, 2434.989990, 1197.679565, 148.075974, 0.715971}, + {NPC_TIME_RIFT, 2403.954834, 1178.815430, 148.075943, 4.966126}, + {NPC_INFINITE_AGENT, 2403.676758, 1171.495850, 148.075607, 4.902797}, + {NPC_INFINITE_HUNTER, 2407.691162, 1172.162720, 148.075607, 4.963010}, + {NPC_TIME_RIFT, 2414.217041, 1133.446167, 148.076050, 1.706972}, + {NPC_INFINITE_ADVERSARY, 2416.024658, 1139.456177, 148.076431, 1.752129}, + {NPC_INFINITE_HUNTER, 2410.866699, 1139.680542, 148.076431, 1.752129}, + {NPC_TIME_RIFT, 2433.081543, 1099.869751, 148.076157, 1.809509}, + {NPC_INFINITE_ADVERSARY, 2426.947998, 1107.471680, 148.076019, 1.877580}, + {NPC_INFINITE_HUNTER, 2432.944580, 1108.896362, 148.208160, 2.199241}, + {NPC_TIME_RIFT, 2444.077637, 1114.366089, 148.076157, 3.049565}, + {NPC_INFINITE_ADVERSARY, 2438.190674, 1118.368164, 148.076172, 3.139232}, + {NPC_INFINITE_AGENT, 2435.861328, 1113.402954, 148.169327, 2.390271}, + {NPC_TIME_RIFT, 2463.131592, 1115.391724, 152.473129, 3.409651}, + {NPC_EPOCH, 2451.809326, 1112.901245, 149.220459, 3.363617} +}; + +struct npc_arthasAI : public npc_escortAI +{ + npc_arthasAI(Creature *pCreature) : npc_escortAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + + bool bStepping; + uint32 uiStep; + uint32 uiPhaseTimer; + uint32 uiGossipStep; + uint32 uiPlayerFaction; + uint32 uiBossEvent; + uint32 uiWave; + + uint64 uiUtherGUID; + uint64 uiJainaGUID; + uint64 uiCitymenGUID[2]; + uint64 uiWaveGUID[ENCOUNTER_WAVES_MAX_SPAWNS]; + uint64 uiInfiniteDraconianGUID[ENCOUNTER_DRACONIAN_NUMBER]; + uint64 uiStalkerGUID; + + uint64 uiBossGUID; //uiMeathookGUID || uiSalrammGUID + uint64 uiEpochGUID; + uint64 uiMalganisGUID; + uint64 uiInfiniteGUID; + + uint32 uiExorcismTimer; + + void Reset() + { + uiUtherGUID = 0; + uiJainaGUID = 0; + + for (uint8 i = 0; i < 2; ++i) + uiCitymenGUID[i] = 0; + + for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + uiWaveGUID[i] = 0; + + for (uint8 i = 0; i < ENCOUNTER_DRACONIAN_NUMBER; ++i) + uiInfiniteDraconianGUID[i] = 0; + + uiStalkerGUID = 0; + uiBossGUID = 0; + uiEpochGUID = 0; + uiMalganisGUID = 0; + uiInfiniteGUID = 0; + + if (pInstance) { + pInstance->SetData(DATA_ARTHAS_EVENT, NOT_STARTED); + switch(pInstance->GetData(DATA_ARTHAS_EVENT)) + { + case NOT_STARTED: + bStepping = true; + uiStep = 0; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + uiBossEvent = DATA_MEATHOOK_EVENT; + uiGossipStep = 0; + break; + } + uiPhaseTimer = 1000; + uiExorcismTimer = 7300; + uiWave = 0; + } + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_ARTHAS_AURA); + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_ARTHAS_EVENT, FAIL); + } + + void SpawnTimeRift(uint32 timeRiftID, uint64* guidVector) + { + me->SummonCreature((uint32)RiftAndSpawnsLocations[timeRiftID][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_DESPAWN,11000); + + for (uint32 i = timeRiftID+1; i < ENCOUNTER_CHRONO_SPAWNS; ++i) + { + if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_TIME_RIFT) break; + if (Creature* pTemp = me->SummonCreature((uint32)RiftAndSpawnsLocations[i][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + guidVector[i-timeRiftID-1] = pTemp->GetGUID(); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pTemp->SetReactState(REACT_PASSIVE); + pTemp->GetMotionMaster()->MovePoint(0, RiftAndSpawnsLocations[i][1],RiftAndSpawnsLocations[i][2],RiftAndSpawnsLocations[i][3]); + if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_EPOCH) + uiEpochGUID = pTemp->GetGUID(); + } + } + } + + void SpawnWaveGroup(uint32 waveID, uint64* guidVector) + { + for (uint32 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + { + if ((uint32)WavesLocations[waveID][i][0] == 0) break; + if (Creature* pTemp = me->SummonCreature((uint32)WavesLocations[waveID][i][0],WavesLocations[waveID][i][1],WavesLocations[waveID][i][2],WavesLocations[waveID][i][3],WavesLocations[waveID][i][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + guidVector[i] = pTemp->GetGUID(); + } + } + } + + void SetHoldState(bool bOnHold) + { + SetEscortPaused(bOnHold); + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhaseTimer = uiTimer; + ++uiStep; + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 0: + case 1: + case 3: + case 9: + case 10: + case 11: + case 22: + case 23: + case 26: + case 55: + case 56: + SetHoldState(true); + bStepping = true; + break; + case 7: + if (Unit* pCityman0 = me->SummonCreature(NPC_CITY_MAN,2091.977f,1275.021f,140.757f,0.558f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) + uiCitymenGUID[0] = pCityman0->GetGUID(); + if (Unit* pCityman1 = me->SummonCreature(NPC_CITY_MAN2,2093.514f,1275.842f,140.408f,3.801f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) + uiCitymenGUID[1] = pCityman1->GetGUID(); + break; + case 8: + uiGossipStep = 1; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + case 12: + SetRun(true); + DoScriptText(SAY_PHASE210, me); + if (Unit* pDisguised0 = me->SummonCreature(NPC_CITY_MAN3,2398.14f,1207.81f,134.04f,5.155249f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[0] = pDisguised0->GetGUID(); + if (Unit* pDisguised1 = me->SummonCreature(NPC_CITY_MAN4,2403.22f,1205.54f,134.04f,3.311264f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[1] = pDisguised1->GetGUID(); + + if (Unit* pDisguised2 = me->SummonCreature(NPC_CITY_MAN,2400.82f,1201.69f,134.01f,1.534082f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiInfiniteDraconianGUID[2] = pDisguised2->GetGUID(); + pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); + pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[0]); + pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); + } + } + } + break; + case 20: + uiGossipStep = 2; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetRun(false); + SetHoldState(true); + break; + case 21: + DoScriptText(SAY_PHASE301, me); + break; + case 25: + SetRun(false); + SpawnTimeRift(0,&uiInfiniteDraconianGUID[0]); + DoScriptText(SAY_PHASE307,me); + break; + case 29: + SetRun(false); + SpawnTimeRift(5,&uiInfiniteDraconianGUID[0]); + SpawnTimeRift(8,&uiInfiniteDraconianGUID[2]); + DoScriptText(SAY_PHASE309,me); + SetHoldState(true); + bStepping = true; + break; + case 31: + SetRun(false); + SpawnTimeRift(11,&uiInfiniteDraconianGUID[0]); + SpawnTimeRift(14,&uiInfiniteDraconianGUID[2]); + DoScriptText(SAY_PHASE311,me); + SetHoldState(true); + bStepping = true; + break; + case 32: + DoScriptText(SAY_PHASE401,me); + break; + case 34: + DoScriptText(SAY_PHASE402,me); + break; + case 35: + DoScriptText(SAY_PHASE403,me); + break; + case 36: + if (pInstance) + { + GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SHKAF_GATE)); + pGate->SetGoState(GO_STATE_ACTIVE); + } + break; + case 45: + SetRun(true); + SetDespawnAtFar(false); + uiGossipStep = 4; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + case 47: + SetRun(false); + DoScriptText(SAY_PHASE405,me); + break; + case 48: + SetRun(true); + DoScriptText(SAY_PHASE406,me); + break; + case 53: + DoScriptText(SAY_PHASE407,me); + break; + case 54: + uiGossipStep = 5; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetHoldState(true); + break; + } + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + DoMeleeAttackIfReady(); + + if (bStepping) + { + if (uiPhaseTimer <= diff) + { + switch(uiStep) + { + //After reset + case 0: + if (Unit* pJaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f)) + uiJainaGUID = pJaina->GetGUID(); + else if (Unit* pJaina = me->SummonCreature(NPC_JAINA,1895.48f,1292.66f,143.706f,0.023475f,TEMPSUMMON_DEAD_DESPAWN,180000)) + uiJainaGUID = pJaina->GetGUID(); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 0 + case 1: + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + if (Unit* pUther = me->SummonCreature(NPC_UTHER,1794.357f,1272.183f,140.558f,1.37f,TEMPSUMMON_DEAD_DESPAWN,180000)) + { + uiUtherGUID = pUther->GetGUID(); + pUther->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pUther->GetMotionMaster()->MovePoint(0, 1897.018f, 1287.487f, 143.481f); + pUther->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiUtherGUID); + } + JumpToNextStep(17000); + break; + case 2: + DoScriptText(SAY_PHASE101, me); + JumpToNextStep(2000); + break; + case 3: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + { + DoScriptText(SAY_PHASE102, pUther); + } + JumpToNextStep(8000); + break; + case 4: + SetEscortPaused(false); + bStepping = false; + SetRun(false); + DoScriptText(SAY_PHASE103, me); + JumpToNextStep(0); + break; + //After waypoint 1 + case 5: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + pJaina->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + DoScriptText(SAY_PHASE104, me); + JumpToNextStep(10000); + break; + case 6: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE105, pUther); + JumpToNextStep(1000); + break; + case 7: + DoScriptText(SAY_PHASE106, me); + JumpToNextStep(4000); + break; + case 8: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE107, pUther); + JumpToNextStep(6000); + break; + case 9: + DoScriptText(SAY_PHASE108, me); + JumpToNextStep(4000); + break; + case 10: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE109, pUther); + JumpToNextStep(8000); + break; + case 11: + DoScriptText(SAY_PHASE110, me); + JumpToNextStep(4000); + break; + case 12: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE111, pUther); + JumpToNextStep(4000); + break; + case 13: + DoScriptText(SAY_PHASE112, me); + JumpToNextStep(11000); + break; + case 14: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + DoScriptText(SAY_PHASE113, pJaina); + JumpToNextStep(3000); + break; + case 15: + DoScriptText(SAY_PHASE114, me); + JumpToNextStep(9000); + break; + case 16: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + DoScriptText(SAY_PHASE115, pUther); + JumpToNextStep(4000); + break; + case 17: + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + { + pUther->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pUther->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); + } + JumpToNextStep(1000); + break; + case 18: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + { + me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); + pJaina->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pJaina->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); + } + JumpToNextStep(1000); + break; + case 19: + DoScriptText(SAY_PHASE116, me); + JumpToNextStep(1000); + break; + case 20: + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + DoScriptText(SAY_PHASE117, pJaina); + JumpToNextStep(3000); + break; + case 21: + SetEscortPaused(false); + bStepping = false; + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After waypoint 3 + case 22: + DoScriptText(SAY_PHASE118, me); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); + JumpToNextStep(10000); + break; + case 23: + SetEscortPaused(false); + bStepping = false; + SetRun(true); + + if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) + pJaina->DisappearAndDie(); + + if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) + pUther->DisappearAndDie(); + + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After Gossip 1 (waypoint 8) + case 24: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2026.469f,1287.088f,143.596f,1.37f,TEMPSUMMON_TIMED_DESPAWN,14000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + JumpToNextStep(1000); + break; + case 25: + DoScriptText(SAY_PHASE201, me); + JumpToNextStep(12000); + break; + case 26: + SetEscortPaused(false); + bStepping = false; + SetRun(false); + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + JumpToNextStep(0); + break; + //After waypoint 9 + case 27: + me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[0]); + if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) + { + pCityman->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + pCityman->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pCityman->GetMotionMaster()->MovePoint(0, 2088.625f,1279.191f,140.743f); + } + JumpToNextStep(2000); + break; + case 28: + if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) + DoScriptText(SAY_PHASE202, pCityman); + JumpToNextStep(4000); + break; + case 29: + SetEscortPaused(false); + bStepping = false; + DoScriptText(SAY_PHASE203, me); + JumpToNextStep(0); + break; + //After waypoint 10 + case 30: + me->HandleEmoteCommand(37); + JumpToNextStep(1000); + break; + case 31: + SetEscortPaused(false); + bStepping = false; + if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) + { + DoScriptText(SAY_PHASE204, pCityman1); + pCityman1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pCityman0 = Unit::GetCreature(*me, uiCitymenGUID[0])) + pCityman0->Kill(pCityman0); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[1]); + } + JumpToNextStep(0); + break; + //After waypoint 11 + case 32: + me->HandleEmoteCommand(37); + JumpToNextStep(1000); + break; + case 33: + if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) + pCityman1->Kill(pCityman1); + JumpToNextStep(1000); + break; + case 34: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + DoScriptText(SAY_PHASE205, me); + JumpToNextStep(3000); + break; + case 35: + if (Unit* pStalkerM = me->SummonCreature(NPC_INVIS_TARGET,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + uiStalkerGUID = pStalkerM->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + JumpToNextStep(1000); + break; + case 36: + if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) + { + if (Creature* pStalkerM = Unit::GetCreature(*me, uiStalkerGUID)) + pMalganis->CastSpell(pStalkerM,63793,false); + + uiMalganisGUID = pMalganis->GetGUID(); + DoScriptText(SAY_PHASE206, pMalganis); + pMalganis->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + pMalganis->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(11000); + break; + case 37: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + { + if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN, 100.0f)) + pZombie->UpdateEntry(NPC_ZOMBIE, 0); + else if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN2, 100.0f)) + pZombie->UpdateEntry(NPC_ZOMBIE, 0); + else //There's no one else to transform + uiStep++; + } + else + uiStep++; + uiPhaseTimer = 500; + break; + case 38: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + DoScriptText(SAY_PHASE207, pMalganis); + JumpToNextStep(17000); + break; + case 39: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + pMalganis->SetVisibility(VISIBILITY_OFF); + DoScriptText(SAY_PHASE208, me); + JumpToNextStep(7000); + break; + case 40: + if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) + { + uiStalkerGUID = pStalker->GetGUID(); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); + } + DoScriptText(SAY_PHASE209, me); + + uiBossEvent = DATA_MEATHOOK_EVENT; + if (pInstance) + pInstance->SetData(DATA_ARTHAS_EVENT, IN_PROGRESS); + + me->SetReactState(REACT_DEFENSIVE); + SetDespawnAtFar(false); + JumpToNextStep(5000); + break; + case 41: //Summon wave group + case 43: + case 45: + case 47: + case 51: + case 53: + case 55: + case 57: + if (pInstance->GetData(uiBossEvent) != DONE) + { + SpawnWaveGroup(uiWave, uiWaveGUID); + uiWave++; + } + JumpToNextStep(500); + break; + case 42: //Wait group to die + case 44: + case 46: + case 48: + case 52: + case 54: + case 56: + case 58: + if (pInstance->GetData(uiBossEvent) != DONE) + { + uint32 mobCounter = 0; + uint32 deadCounter = 0; + for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) + { + if (uiWaveGUID[i] == 0) + break; + ++mobCounter; + Unit* pTemp = Unit::GetCreature(*me, uiWaveGUID[i]); + if (!pTemp || pTemp->isDead()) + ++deadCounter; + } + + if (mobCounter <= deadCounter) //If group is dead + JumpToNextStep(1000); + else + uiPhaseTimer = 1000; + } + else + JumpToNextStep(500); + break; + case 49: //Summon Boss + case 59: + if (pInstance->GetData(uiBossEvent) != DONE) + { + uint32 uiBossID = 0; + if (uiBossEvent == DATA_MEATHOOK_EVENT) + uiBossID = NPC_MEATHOOK; + else if (uiBossEvent == DATA_SALRAMM_EVENT) + uiBossID = NPC_SALRAMM; + + if (Unit* pBoss = me->SummonCreature(uiBossID,2232.19f,1331.933f,126.662f,3.15f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + uiBossGUID = pBoss->GetGUID(); + pBoss->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + pBoss->GetMotionMaster()->MovePoint(0, 2194.110f,1332.00f,130.00f); + } + } + JumpToNextStep(30000); + break; + case 50: //Wait Boss death + case 60: + if (pInstance) + { + if (pInstance->GetData(uiBossEvent) == DONE) + { + JumpToNextStep(1000); + if (uiBossEvent == DATA_MEATHOOK_EVENT) + uiBossEvent = DATA_SALRAMM_EVENT; + else if (uiBossEvent == DATA_SALRAMM_EVENT) + { + SetHoldState(false); + bStepping = false; + uiBossEvent = DATA_EPOCH_EVENT; + } + } + else if (pInstance->GetData(uiBossEvent) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After Gossip 2 (waypoint 22) + case 61: + me->SetReactState(REACT_AGGRESSIVE); + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) + pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) + pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); + JumpToNextStep(1000); + break; + case 62: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + DoScriptText(SAY_PHASE302, pDisguised0); + JumpToNextStep(7000); + break; + case 63: + DoScriptText(SAY_PHASE303, me); + SetHoldState(false); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 23 + case 64: + me->HandleEmoteCommand(54); + JumpToNextStep(1000); + break; + case 65: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + pDisguised0->HandleEmoteCommand(11); + JumpToNextStep(1000); + break; + case 66: + DoScriptText(SAY_PHASE304,me); + JumpToNextStep(2000); + break; + case 67: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + DoScriptText(SAY_PHASE305,pDisguised0); + JumpToNextStep(1000); + break; + case 68: + if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) + { + pDisguised2->UpdateEntry(NPC_INFINITE_HUNTER, 0); + //Make them unattackable + pDisguised2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised2->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 69: + if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) + { + pDisguised1->UpdateEntry(NPC_INFINITE_AGENT, 0); + //Make them unattackable + pDisguised1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised1->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 70: + if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) + { + pDisguised0->UpdateEntry(NPC_INFINITE_ADVERSARY, 0); + //Make them unattackable + pDisguised0->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pDisguised0->SetReactState(REACT_PASSIVE); + } + JumpToNextStep(2000); + break; + case 71: + //After waypoint 26,29,31 + case 73: + case 75: + case 77: + //Make cratures attackable + for (uint32 i = 0; i< ENCOUNTER_DRACONIAN_NUMBER; ++i) + if (Creature* pTemp = Unit::GetCreature(*me, uiInfiniteDraconianGUID[i])) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pTemp->SetReactState(REACT_AGGRESSIVE); + } + JumpToNextStep(5000); + break; + case 72: + case 74: + case 76: + if (me->isInCombat()) + uiPhaseTimer = 1000; + else + { + if (uiStep == 72) DoScriptText(SAY_PHASE308,me); + if (uiStep == 74) DoScriptText(SAY_PHASE308,me); + if (uiStep == 76) DoScriptText(SAY_PHASE310,me); + SetHoldState(false); + bStepping = false; + SetRun(true); + JumpToNextStep(2000); + } + break; + case 78: + if (me->isInCombat()) + uiPhaseTimer = 1000; + else + { + DoScriptText(SAY_PHASE312,me); + JumpToNextStep(5000); + } + break; + case 79: + DoScriptText(SAY_PHASE313,me); + JumpToNextStep(1000); + break; + case 80: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + { + SpawnTimeRift(17,&uiEpochGUID); + if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) + DoScriptText(SAY_PHASE314,pEpoch); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiEpochGUID); + } + JumpToNextStep(18000); + break; + case 81: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + DoScriptText(SAY_PHASE315, me); + JumpToNextStep(6000); + break; + case 82: + if (pInstance) + if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) + { + if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) + { + //Make Epoch attackable + pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); + pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pEpoch->SetReactState(REACT_AGGRESSIVE); + } + + } + JumpToNextStep(1000); + break; + case 83: + if (pInstance) + { + if (pInstance->GetData(DATA_EPOCH_EVENT) == DONE) + { + uiGossipStep = 3; + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + bStepping = false; + uiBossEvent = DATA_MAL_GANIS_EVENT; + JumpToNextStep(15000); + } + else if (pInstance->GetData(DATA_EPOCH_EVENT) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After Gossip 4 + case 84: + DoScriptText(SAY_PHASE404,me); + SetHoldState(false); + bStepping = false; + break; + //After Gossip 5 + case 85: + DoScriptText(SAY_PHASE501, me); + if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2296.665f,1502.362f,128.362f,4.961f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + uiMalganisGUID = pMalganis->GetGUID(); + pMalganis->SetReactState(REACT_PASSIVE); + } + if (pInstance) + { + GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAL_GANIS_GATE_1)); + pGate->SetGoState(GO_STATE_ACTIVE); + } + SetHoldState(false); + bStepping = false; + JumpToNextStep(0); + break; + //After waypoint 55 + case 86: + DoScriptText(SAY_PHASE502, me); + JumpToNextStep(6000); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); + break; + case 87: + if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) + { + pMalganis->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_6 | UNIT_FLAG_UNK_9 | UNIT_FLAG_UNK_15); + pMalganis->SetReactState(REACT_AGGRESSIVE); + } + JumpToNextStep(1000); + break; + case 88: + if (pInstance) + { + if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == DONE) + { + SetHoldState(false); + JumpToNextStep(1000); + } + else if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == FAIL) + npc_escortAI::EnterEvadeMode(); + else + uiPhaseTimer = 10000; + } + break; + //After waypoint 56 + case 89: + SetRun(true); + me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); + DoScriptText(SAY_PHASE503, me); + JumpToNextStep(7000); + break; + case 90: + if (pInstance) + { + pInstance->SetData(DATA_ARTHAS_EVENT, DONE); //Rewards: Achiev & Chest ;D + me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance->GetData64(DATA_MAL_GANIS_GATE_2)); //Look behind + } + DoScriptText(SAY_PHASE504, me); + bStepping = false; + break; + } + } else uiPhaseTimer -= diff; + } + + //Battling skills + if (!me->getVictim()) + return; + + if (uiExorcismTimer < diff) + { + if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(target, SPELL_EXORCISM_N); + uiExorcismTimer = 7300; + } else uiExorcismTimer -= diff; + + if (HealthBelowPct(40)) + DoCast(me, SPELL_HOLY_LIGHT); + } +}; + +CreatureAI* GetAI_npc_arthas(Creature* pCreature) +{ + return new npc_arthasAI(pCreature); +} + +#define GOSSIP_ITEM_ARTHAS_0 "I'm ready to start Culling of Stratholme." +#define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready." +#define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness." +#define GOSSIP_ITEM_ARTHAS_3 "I'm ready." +#define GOSSIP_ITEM_ARTHAS_4 "For Lordaeron!" +#define GOSSIP_ITEM_ARTHAS_5 "I'm ready to battle the dreadlord, sire." + +bool GossipHello_npc_arthas(Player* pPlayer, Creature* pCreature) +{ + npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); + + if (pAI && pAI->bStepping == false) + { + switch (pAI->uiGossipStep) + { + case 0: //This one is a workaround since the very beggining of the script is wrong. + if (pPlayer->GetQuestStatus(13149) != QUEST_STATUS_COMPLETE) + return false; + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); + break; + case 1: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_1, pCreature->GetGUID()); + break; + case 2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_2, pCreature->GetGUID()); + break; + case 3: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_3, pCreature->GetGUID()); + break; + case 4: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_4, pCreature->GetGUID()); + break; + case 5: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_5, pCreature->GetGUID()); + break; + default: + return false; + } + } + return true; +} + + +bool GossipSelect_npc_arthas(Player *pPlayer, Creature *pCreature, uint32 /*sender*/, uint32 action) +{ + npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); + + if (!pAI) + return false; + + switch (action) + { + case GOSSIP_ACTION_INFO_DEF: + pAI->Start(true,true,pPlayer->GetGUID(),0,false,false); + pAI->SetDespawnAtEnd(false); + pAI->bStepping = false; + pAI->uiStep = 1; + break; + case GOSSIP_ACTION_INFO_DEF+1: + pAI->bStepping = true; + pAI->uiStep = 24; + break; + case GOSSIP_ACTION_INFO_DEF+2: + pAI->SetHoldState(false); + pAI->bStepping = false; + pAI->uiStep = 61; + break; + case GOSSIP_ACTION_INFO_DEF+3: + pAI->SetHoldState(false); + break; + case GOSSIP_ACTION_INFO_DEF+4: + pAI->bStepping = true; + pAI->uiStep = 84; + break; + case GOSSIP_ACTION_INFO_DEF+5: + pAI->bStepping = true; + pAI->uiStep = 85; + break; + } + pPlayer->CLOSE_GOSSIP_MENU(); + pAI->SetDespawnAtFar(true); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + return true; +} + +void AddSC_culling_of_stratholme() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_arthas"; + newscript->GetAI = &GetAI_npc_arthas; + newscript->pGossipHello = &GossipHello_npc_arthas; + newscript->pGossipSelect = &GossipSelect_npc_arthas; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h new file mode 100644 index 00000000000..4278ad46500 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/culling_of_stratholme.h @@ -0,0 +1,68 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef DEF_CULLING_OF_STRATHOLME_H +#define DEF_CULLING_OF_STRATHOLME_H + +enum Data +{ + DATA_MEATHOOK_EVENT, + DATA_SALRAMM_EVENT, + DATA_EPOCH_EVENT, + DATA_MAL_GANIS_EVENT, + DATA_INFINITE_EVENT, + DATA_ARTHAS_EVENT +}; + +enum Data64 +{ + DATA_ARTHAS, + DATA_MEATHOOK, + DATA_SALRAMM, + DATA_EPOCH, + DATA_MAL_GANIS, + DATA_INFINITE, + DATA_SHKAF_GATE, + DATA_MAL_GANIS_GATE_1, + DATA_MAL_GANIS_GATE_2, + DATA_EXIT_GATE, + DATA_MAL_GANIS_CHEST +}; + +enum Creatures +{ + NPC_MEATHOOK = 26529, + NPC_SALRAMM = 26530, + NPC_EPOCH = 26532, + NPC_MAL_GANIS = 26533, + NPC_INFINITE = 32273, + NPC_ARTHAS = 26499, + NPC_JAINA = 26497, + NPC_UTHER = 26528 +}; + +enum GameObjects +{ + GO_SHKAF_GATE = 188686, + GO_MALGANIS_GATE_1 = 187711, + GO_MALGANIS_GATE_2 = 187723, + GO_EXIT_GATE = 191788, + GO_MALGANIS_CHEST_N = 190663, + GO_MALGANIS_CHEST_H = 193597 +}; +#endif diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp new file mode 100644 index 00000000000..73742a1e748 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/CullingOfStratholme/instance_culling_of_stratholme.cpp @@ -0,0 +1,244 @@ +/* +* Copyright (C) 2008-2010 Trinity +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "culling_of_stratholme.h" + +#define MAX_ENCOUNTER 5 + +/* Culling of Stratholme encounters: +0 - Meathook +1 - Salramm the Fleshcrafter +2 - Chrono-Lord Epoch +3 - Mal'Ganis +4 - Infinite Corruptor (Heroic only) +*/ + +struct instance_culling_of_stratholme : public ScriptedInstance +{ + instance_culling_of_stratholme(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiArthas; + uint64 uiMeathook; + uint64 uiSalramm; + uint64 uiEpoch; + uint64 uiMalGanis; + uint64 uiInfinite; + + uint64 uiShkafGate; + uint64 uiMalGanisGate1; + uint64 uiMalGanisGate2; + uint64 uiExitGate; + uint64 uiMalGanisChest; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_ARTHAS: + uiArthas = pCreature->GetGUID(); + break; + case NPC_MEATHOOK: + uiMeathook = pCreature->GetGUID(); + break; + case NPC_SALRAMM: + uiSalramm = pCreature->GetGUID(); + break; + case NPC_EPOCH: + uiEpoch = pCreature->GetGUID(); + break; + case NPC_MAL_GANIS: + uiMalGanis = pCreature->GetGUID(); + break; + case NPC_INFINITE: + uiInfinite = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_SHKAF_GATE: + uiShkafGate = pGo->GetGUID(); + break; + case GO_MALGANIS_GATE_1: + uiMalGanisGate1 = pGo->GetGUID(); + break; + case GO_MALGANIS_GATE_2: + uiMalGanisGate2 = pGo->GetGUID(); + break; + case GO_EXIT_GATE: + uiExitGate = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + HandleGameObject(uiExitGate,true); + break; + case GO_MALGANIS_CHEST_N: + case GO_MALGANIS_CHEST_H: + uiMalGanisChest = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MEATHOOK_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_SALRAMM_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_EPOCH_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_MAL_GANIS_EVENT: + m_auiEncounter[3] = data; + + switch(m_auiEncounter[3]) + { + case NOT_STARTED: + HandleGameObject(uiMalGanisGate2,true); + break; + case IN_PROGRESS: + HandleGameObject(uiMalGanisGate2,false); + break; + case DONE: + HandleGameObject(uiExitGate, true); + if (GameObject *pGo = instance->GetGameObject(uiMalGanisChest)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + } + break; + case DATA_INFINITE_EVENT: + m_auiEncounter[4] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_MEATHOOK_EVENT: return m_auiEncounter[0]; + case DATA_SALRAMM_EVENT: return m_auiEncounter[1]; + case DATA_EPOCH_EVENT: return m_auiEncounter[2]; + case DATA_MAL_GANIS_EVENT: return m_auiEncounter[3]; + case DATA_INFINITE_EVENT: return m_auiEncounter[4]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_ARTHAS: return uiArthas; + case DATA_MEATHOOK: return uiMeathook; + case DATA_SALRAMM: return uiSalramm; + case DATA_EPOCH: return uiEpoch; + case DATA_MAL_GANIS: return uiMalGanis; + case DATA_INFINITE: return uiInfinite; + case DATA_SHKAF_GATE: return uiShkafGate; + case DATA_MAL_GANIS_GATE_1: return uiMalGanisGate1; + case DATA_MAL_GANIS_GATE_2: return uiMalGanisGate2; + case DATA_EXIT_GATE: return uiExitGate; + case DATA_MAL_GANIS_CHEST: return uiMalGanisChest; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "C S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; + + if (dataHead1 == 'C' && dataHead2 == 'S') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + m_auiEncounter[4] = data4; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap) +{ + return new instance_culling_of_stratholme(pMap); +} + +void AddSC_instance_culling_of_stratholme() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_culling_of_stratholme"; + newscript->GetInstanceData = &GetInstanceData_instance_culling_of_stratholme; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_aeonus.cpp new file mode 100644 index 00000000000..49cf7cd4433 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_aeonus.cpp @@ -0,0 +1,145 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Aeonus +SD%Complete: 80 +SDComment: Some spells not implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269012, + SAY_AGGRO = -1269013, + SAY_BANISH = -1269014, + SAY_SLAY1 = -1269015, + SAY_SLAY2 = -1269016, + SAY_DEATH = -1269017, + EMOTE_FRENZY = -1269018, + + SPELL_CLEAVE = 40504, + SPELL_TIME_STOP = 31422, + SPELL_ENRAGE = 37605, + SPELL_SAND_BREATH = 31473, + H_SPELL_SAND_BREATH = 39049 +}; + +struct boss_aeonusAI : public ScriptedAI +{ + boss_aeonusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SandBreath_Timer; + uint32 TimeStop_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + SandBreath_Timer = 15000+rand()%15000; + TimeStop_Timer = 10000+rand()%5000; + Frenzy_Timer = 30000+rand()%15000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(TYPE_RIFT,DONE); + pInstance->SetData(TYPE_MEDIVH,DONE);//FIXME: later should be removed + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sand Breath + if (SandBreath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SAND_BREATH); + SandBreath_Timer = 15000+rand()%10000; + } else SandBreath_Timer -= diff; + + //Time Stop + if (TimeStop_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIME_STOP); + TimeStop_Timer = 20000+rand()%15000; + } else TimeStop_Timer -= diff; + + //Frenzy + if (Frenzy_Timer <= diff) + { + DoScriptText(EMOTE_FRENZY, me); + DoCast(me, SPELL_ENRAGE); + Frenzy_Timer = 20000+rand()%15000; + } else Frenzy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_aeonus(Creature* pCreature) +{ + return new boss_aeonusAI (pCreature); +} + +void AddSC_boss_aeonus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_aeonus"; + newscript->GetAI = &GetAI_boss_aeonus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_chrono_lord_deja.cpp new file mode 100644 index 00000000000..1f2b4a80612 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_chrono_lord_deja.cpp @@ -0,0 +1,154 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Chrono_Lord_Deja +SD%Complete: 65 +SDComment: All abilities not implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269006, + SAY_AGGRO = -1269007, + SAY_BANISH = -1269008, + SAY_SLAY1 = -1269009, + SAY_SLAY2 = -1269010, + SAY_DEATH = -1269011, + + SPELL_ARCANE_BLAST = 31457, + H_SPELL_ARCANE_BLAST = 38538, + SPELL_ARCANE_DISCHARGE = 31472, + H_SPELL_ARCANE_DISCHARGE = 38539, + SPELL_TIME_LAPSE = 31467, + SPELL_ATTRACTION = 38540 //Not Implemented (Heroic mode) +}; + +struct boss_chrono_lord_dejaAI : public ScriptedAI +{ + boss_chrono_lord_dejaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 ArcaneBlast_Timer; + uint32 TimeLapse_Timer; + uint32 Attraction_Timer; + uint32 ArcaneDischarge_Timer; + + void Reset() + { + ArcaneBlast_Timer = 18000+rand()%5000; + TimeLapse_Timer = 10000+rand()%5000; + ArcaneDischarge_Timer = 20000+rand()%10000; + Attraction_Timer = 25000+rand()%10000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Arcane Blast + if (ArcaneBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BLAST); + ArcaneBlast_Timer = 15000+rand()%10000; + } else ArcaneBlast_Timer -= diff; + + //Arcane Discharge + if (ArcaneDischarge_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + DoCast(pTarget, SPELL_ARCANE_DISCHARGE); + ArcaneDischarge_Timer = 20000+rand()%10000; + } else ArcaneDischarge_Timer -= diff; + + //Time Lapse + if (TimeLapse_Timer <= diff) + { + DoScriptText(SAY_BANISH, me); + DoCast(me, SPELL_TIME_LAPSE); + TimeLapse_Timer = 15000+rand()%10000; + } else TimeLapse_Timer -= diff; + + if (IsHeroic()) + { + if (Attraction_Timer <= diff) + { + DoCast(me, SPELL_ATTRACTION); + Attraction_Timer = 25000+rand()%10000; + } else Attraction_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_chrono_lord_deja(Creature* pCreature) +{ + return new boss_chrono_lord_dejaAI (pCreature); +} + +void AddSC_boss_chrono_lord_deja() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_chrono_lord_deja"; + newscript->GetAI = &GetAI_boss_chrono_lord_deja; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_temporus.cpp new file mode 100644 index 00000000000..04b4b020ead --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/boss_temporus.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Temporus +SD%Complete: 75 +SDComment: More abilities need to be implemented +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +enum eEnums +{ + SAY_ENTER = -1269000, + SAY_AGGRO = -1269001, + SAY_BANISH = -1269002, + SAY_SLAY1 = -1269003, + SAY_SLAY2 = -1269004, + SAY_DEATH = -1269005, + + SPELL_HASTE = 31458, + SPELL_MORTAL_WOUND = 31464, + SPELL_WING_BUFFET = 31475, + H_SPELL_WING_BUFFET = 38593, + SPELL_REFLECT = 38592 //Not Implemented (Heroic mod) +}; + +struct boss_temporusAI : public ScriptedAI +{ + boss_temporusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Haste_Timer; + uint32 SpellReflection_Timer; + uint32 MortalWound_Timer; + uint32 WingBuffet_Timer; + + void Reset() + { + Haste_Timer = 15000+rand()%8000; + SpellReflection_Timer = 30000; + MortalWound_Timer = 8000; + WingBuffet_Timer = 25000+rand()%10000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } + + void MoveInLineOfSight(Unit *who) + { + //Despawn Time Keeper + if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) + { + if (me->IsWithinDistInMap(who,20.0f)) + { + DoScriptText(SAY_BANISH, me); + + me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Attack Haste + if (Haste_Timer <= diff) + { + DoCast(me, SPELL_HASTE); + Haste_Timer = 20000+rand()%5000; + } else Haste_Timer -= diff; + + //MortalWound_Timer + if (MortalWound_Timer <= diff) + { + DoCast(me, SPELL_MORTAL_WOUND); + MortalWound_Timer = 10000+rand()%10000; + } else MortalWound_Timer -= diff; + + //Wing ruffet + if (WingBuffet_Timer <= diff) + { + DoCast(me, SPELL_WING_BUFFET); + WingBuffet_Timer = 20000+rand()%10000; + } else WingBuffet_Timer -= diff; + + if (IsHeroic()) + { + if (SpellReflection_Timer <= diff) + { + DoCast(me, SPELL_REFLECT); + SpellReflection_Timer = 25000+rand()%10000; + } else SpellReflection_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_temporus(Creature* pCreature) +{ + return new boss_temporusAI (pCreature); +} + +void AddSC_boss_temporus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_temporus"; + newscript->GetAI = &GetAI_boss_temporus; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.cpp new file mode 100644 index 00000000000..b0432a9b57c --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.cpp @@ -0,0 +1,404 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Dark_Portal +SD%Complete: 30 +SDComment: Misc NPC's and mobs for instance. Most here far from complete. +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +/* ContentData +npc_medivh_bm +npc_time_rift +npc_saat +EndContentData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +#define SAY_ENTER -1269020 //where does this belong? +#define SAY_INTRO -1269021 +#define SAY_WEAK75 -1269022 +#define SAY_WEAK50 -1269023 +#define SAY_WEAK25 -1269024 +#define SAY_DEATH -1269025 +#define SAY_WIN -1269026 +#define SAY_ORCS_ENTER -1269027 +#define SAY_ORCS_ANSWER -1269028 + +#define SPELL_CHANNEL 31556 +#define SPELL_PORTAL_RUNE 32570 //aura(portal on ground effect) + +#define SPELL_BLACK_CRYSTAL 32563 //aura +#define SPELL_PORTAL_CRYSTAL 32564 //summon + +#define SPELL_BANISH_PURPLE 32566 //aura +#define SPELL_BANISH_GREEN 32567 //aura + +#define SPELL_CORRUPT 31326 +#define SPELL_CORRUPT_AEONUS 37853 + +#define C_COUNCIL_ENFORCER 17023 + +struct npc_medivh_bmAI : public ScriptedAI +{ + npc_medivh_bmAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SpellCorrupt_Timer; + uint32 Check_Timer; + + bool Life75; + bool Life50; + bool Life25; + + void Reset() + { + SpellCorrupt_Timer = 0; + + if (!pInstance) + return; + + if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) + DoCast(me, SPELL_CHANNEL, true); + else if (me->HasAura(SPELL_CHANNEL)) + me->RemoveAura(SPELL_CHANNEL); + + DoCast(me, SPELL_PORTAL_RUNE, true); + } + + void MoveInLineOfSight(Unit *who) + { + if (!pInstance) + return; + + if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 10.0f)) + { + if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS || pInstance->GetData(TYPE_MEDIVH) == DONE) + return; + + DoScriptText(SAY_INTRO, me); + pInstance->SetData(TYPE_MEDIVH,IN_PROGRESS); + DoCast(me, SPELL_CHANNEL, false); + Check_Timer = 5000; + } + else if (who->GetTypeId() == TYPEID_UNIT && me->IsWithinDistInMap(who, 15.0f)) + { + if (pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) + return; + + uint32 entry = who->GetEntry(); + if (entry == C_ASSAS || entry == C_WHELP || entry == C_CHRON || entry == C_EXECU || entry == C_VANQU) + { + who->StopMoving(); + who->CastSpell(me,SPELL_CORRUPT,false); + } + else if (entry == C_AEONUS) + { + who->StopMoving(); + who->CastSpell(me,SPELL_CORRUPT_AEONUS,false); + } + } + } + + void AttackStart(Unit * /*who*/) + { + //if (pInstance && pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) + //return; + + //ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) {} + + void SpellHit(Unit* /*caster*/, const SpellEntry* spell) + { + if (SpellCorrupt_Timer) + return; + + if (spell->Id == SPELL_CORRUPT_AEONUS) + SpellCorrupt_Timer = 1000; + + if (spell->Id == SPELL_CORRUPT) + SpellCorrupt_Timer = 3000; + } + + void JustDied(Unit* Killer) + { + if (Killer->GetEntry() == me->GetEntry()) + return; + + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (SpellCorrupt_Timer) + { + if (SpellCorrupt_Timer <= diff) + { + pInstance->SetData(TYPE_MEDIVH,SPECIAL); + + if (me->HasAura(SPELL_CORRUPT_AEONUS)) + SpellCorrupt_Timer = 1000; + else if (me->HasAura(SPELL_CORRUPT)) + SpellCorrupt_Timer = 3000; + else + SpellCorrupt_Timer = 0; + } else SpellCorrupt_Timer -= diff; + } + + if (Check_Timer) + { + if (Check_Timer <= diff) + { + uint32 pct = pInstance->GetData(DATA_SHIELD); + + Check_Timer = 5000; + + if (Life25 && pct <= 25) + { + DoScriptText(SAY_WEAK25, me); + Life25 = false; + } + else if (Life50 && pct <= 50) + { + DoScriptText(SAY_WEAK50, me); + Life50 = false; + } + else if (Life75 && pct <= 75) + { + DoScriptText(SAY_WEAK75, me); + Life75 = false; + } + + //if we reach this it means event was running but at some point reset. + if (pInstance->GetData(TYPE_MEDIVH) == NOT_STARTED) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + me->RemoveCorpse(); + me->Respawn(); + return; + } + + if (pInstance->GetData(TYPE_RIFT) == DONE) + { + DoScriptText(SAY_WIN, me); + Check_Timer = 0; + + if (me->HasAura(SPELL_CHANNEL)) + me->RemoveAura(SPELL_CHANNEL); + + //TODO: start the post-event here + pInstance->SetData(TYPE_MEDIVH,DONE); + } + } else Check_Timer -= diff; + } + + //if (!UpdateVictim()) + //return; + + //DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_medivh_bm(Creature* pCreature) +{ + return new npc_medivh_bmAI (pCreature); +} + +struct Wave +{ + uint32 PortalMob[4]; //spawns for portal waves (in order) +}; + +static Wave PortalWaves[]= +{ + {C_ASSAS, C_WHELP, C_CHRON, 0}, + {C_EXECU, C_CHRON, C_WHELP, C_ASSAS}, + {C_EXECU, C_VANQU, C_CHRON, C_ASSAS} +}; + +struct npc_time_riftAI : public ScriptedAI +{ + npc_time_riftAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 TimeRiftWave_Timer; + uint8 mRiftWaveCount; + uint8 mPortalCount; + uint8 mWaveId; + + void Reset() + { + + TimeRiftWave_Timer = 15000; + mRiftWaveCount = 0; + + if (!pInstance) + return; + + mPortalCount = pInstance->GetData(DATA_PORTAL_COUNT); + + if (mPortalCount < 6) + mWaveId = 0; + else if (mPortalCount > 12) + mWaveId = 2; + else mWaveId = 1; + + } + void EnterCombat(Unit * /*who*/) {} + + void DoSummonAtRift(uint32 creature_entry) + { + if (!creature_entry) + return; + + if (pInstance && pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) + { + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + return; + } + + Position pos; + me->GetRandomNearPosition(pos, 10.0f); + + //normalize Z-level if we can, if rift is not at ground level. + pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + + if (Unit *Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) + if (Unit *temp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_MEDIVH) : 0)) + Summon->AddThreat(temp,0.0f); + } + + void DoSelectSummon() + { + uint32 entry = 0; + + if ((mRiftWaveCount > 2 && mWaveId < 1) || mRiftWaveCount > 3) + mRiftWaveCount = 0; + + entry = PortalWaves[mWaveId].PortalMob[mRiftWaveCount]; + debug_log("TSCR: npc_time_rift: summoning wave Creature (Wave %u, Entry %u).",mRiftWaveCount,entry); + + ++mRiftWaveCount; + + if (entry == C_WHELP) + { + for (uint8 i = 0; i < 3; ++i) + DoSummonAtRift(entry); + } else DoSummonAtRift(entry); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (TimeRiftWave_Timer <= diff) + { + DoSelectSummon(); + TimeRiftWave_Timer = 15000; + } else TimeRiftWave_Timer -= diff; + + if (me->IsNonMeleeSpellCasted(false)) + return; + + debug_log("TSCR: npc_time_rift: not casting anylonger, i need to die."); + me->setDeathState(JUST_DIED); + + if (pInstance->GetData(TYPE_RIFT) == IN_PROGRESS) + pInstance->SetData(TYPE_RIFT,SPECIAL); + } +}; + +CreatureAI* GetAI_npc_time_rift(Creature* pCreature) +{ + return new npc_time_riftAI (pCreature); +} + +#define SAY_SAAT_WELCOME -1269019 + +#define GOSSIP_ITEM_OBTAIN "[PH] Obtain Chrono-Beacon" +#define SPELL_CHRONO_BEACON 34975 +#define ITEM_CHRONO_BEACON 24289 + +bool GossipHello_npc_saat(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(10000, pCreature->GetGUID()); + return true; + } + else if (pPlayer->GetQuestRewardStatus(QUEST_OPENING_PORTAL) && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(10001, pCreature->GetGUID()); + return true; + } + + pPlayer->SEND_GOSSIP_MENU(10002, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_saat(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->CastSpell(pPlayer,SPELL_CHRONO_BEACON,false); + } + return true; +} + +void AddSC_dark_portal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_medivh_bm"; + newscript->GetAI = &GetAI_npc_medivh_bm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_time_rift"; + newscript->GetAI = &GetAI_npc_time_rift; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_saat"; + newscript->pGossipHello = &GossipHello_npc_saat; + newscript->pGossipSelect = &GossipSelect_npc_saat; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.h b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.h new file mode 100644 index 00000000000..7bfd8c917d7 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/dark_portal.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_DARKPORTAL_H +#define DEF_DARKPORTAL_H + +#define TYPE_MEDIVH 1 +#define TYPE_RIFT 2 + +#define DATA_MEDIVH 10 +#define DATA_PORTAL_COUNT 11 +#define DATA_SHIELD 12 + +#define WORLD_STATE_BM 2541 +#define WORLD_STATE_BM_SHIELD 2540 +#define WORLD_STATE_BM_RIFT 2784 + +#define QUEST_OPENING_PORTAL 10297 +#define QUEST_MASTER_TOUCH 9836 + +#define C_TIME_KEEPER 17918 +#define C_RKEEP 21104 +#define C_RLORD 17839 +#define C_DEJA 17879 +#define C_TEMPO 17880 +#define C_AEONUS 17881 +#define C_ASSAS 17835 +#define C_WHELP 21818 +#define C_CHRON 17892 +#define C_EXECU 18994 +#define C_VANQU 18995 + +#endif + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp new file mode 100644 index 00000000000..d1280230808 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/DarkPortal/instance_dark_portal.cpp @@ -0,0 +1,346 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Instance_Dark_Portal +SD%Complete: 50 +SDComment: Quest support: 9836, 10297. Currently in progress. +SDCategory: Caverns of Time, The Dark Portal +EndScriptData */ + +#include "ScriptedPch.h" +#include "dark_portal.h" + +#define MAX_ENCOUNTER 2 + +#define C_MEDIVH 15608 +#define C_TIME_RIFT 17838 + +#define SPELL_RIFT_CHANNEL 31387 + +#define RIFT_BOSS 1 + +inline uint32 RandRiftBoss() { return ((rand()%2) ? C_RKEEP : C_RLORD); } + +float PortalLocation[4][4]= +{ + {-2041.06, 7042.08, 29.99, 1.30}, + {-1968.18, 7042.11, 21.93, 2.12}, + {-1885.82, 7107.36, 22.32, 3.07}, + {-1928.11, 7175.95, 22.11, 3.44} +}; + +struct Wave +{ + uint32 PortalBoss; //protector of current portal + uint32 NextPortalTime; //time to next portal, or 0 if portal boss need to be killed +}; + +static Wave RiftWaves[]= +{ + {RIFT_BOSS, 0}, + {C_DEJA, 0}, + {RIFT_BOSS, 120000}, + {C_TEMPO, 140000}, + {RIFT_BOSS, 120000}, + {C_AEONUS, 0} +}; + +struct instance_dark_portal : public ScriptedInstance +{ + instance_dark_portal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint32 mRiftPortalCount; + uint32 mShieldPercent; + uint8 mRiftWaveCount; + uint8 mRiftWaveId; + + uint32 NextPortal_Timer; + + uint64 MedivhGUID; + uint8 CurrentRiftId; + + void Initialize() + { + MedivhGUID = 0; + Clear(); + } + + void Clear() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + mRiftPortalCount = 0; + mShieldPercent = 100; + mRiftWaveCount = 0; + mRiftWaveId = 0; + + CurrentRiftId = 0; + + NextPortal_Timer = 0; + } + + void InitWorldState(bool Enable = true) + { + DoUpdateWorldState(WORLD_STATE_BM,Enable ? 1 : 0); + DoUpdateWorldState(WORLD_STATE_BM_SHIELD, 100); + DoUpdateWorldState(WORLD_STATE_BM_RIFT, 0); + } + + bool IsEncounterInProgress() + { + if (GetData(TYPE_MEDIVH) == IN_PROGRESS) + return true; + + return false; + } + + void OnPlayerEnter(Player* pPlayer) + { + if (GetData(TYPE_MEDIVH) == IN_PROGRESS) + return; + + pPlayer->SendUpdateWorldState(WORLD_STATE_BM,0); + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == C_MEDIVH) + MedivhGUID = pCreature->GetGUID(); + } + + //what other conditions to check? + bool CanProgressEvent() + { + if (instance->GetPlayers().isEmpty()) + return false; + + return true; + } + + uint8 GetRiftWaveId() + { + switch(mRiftPortalCount) + { + case 6: + mRiftWaveId = 2; + return 1; + case 12: + mRiftWaveId = 4; + return 3; + case 18: + return 5; + default: + return mRiftWaveId; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_MEDIVH: + if (data == SPECIAL && m_auiEncounter[0] == IN_PROGRESS) + { + --mShieldPercent; + + DoUpdateWorldState(WORLD_STATE_BM_SHIELD, mShieldPercent); + + if (!mShieldPercent) + { + if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) + { + if (pMedivh->isAlive()) + { + pMedivh->DealDamage(pMedivh, pMedivh->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_auiEncounter[0] = FAIL; + m_auiEncounter[1] = NOT_STARTED; + } + } + } + } + else + { + if (data == IN_PROGRESS) + { + debug_log("TSCR: Instance Dark Portal: Starting event."); + InitWorldState(); + m_auiEncounter[1] = IN_PROGRESS; + NextPortal_Timer = 15000; + } + + if (data == DONE) + { + //this may be completed further out in the post-event + debug_log("TSCR: Instance Dark Portal: Event completed."); + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL); + + if (pPlayer->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE) + pPlayer->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH); + } + } + } + } + + m_auiEncounter[0] = data; + } + break; + case TYPE_RIFT: + if (data == SPECIAL) + { + if (mRiftPortalCount < 7) + NextPortal_Timer = 5000; + } + else + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_MEDIVH: + return m_auiEncounter[0]; + case TYPE_RIFT: + return m_auiEncounter[1]; + case DATA_PORTAL_COUNT: + return mRiftPortalCount; + case DATA_SHIELD: + return mShieldPercent; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + if (data == DATA_MEDIVH) + return MedivhGUID; + + return 0; + } + + Creature* SummonedPortalBoss(Creature* me) + { + uint32 entry = RiftWaves[GetRiftWaveId()].PortalBoss; + + if (entry == RIFT_BOSS) + entry = RandRiftBoss(); + + debug_log("TSCR: Instance Dark Portal: Summoning rift boss entry %u.",entry); + + Position pos; + me->GetRandomNearPosition(pos, 10.0f); + + //normalize Z-level if we can, if rift is not at ground level. + pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); + + if (Creature *summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) + return summon; + + debug_log("TSCR: Instance Dark Portal: What just happened there? No boss, no loot, no fun..."); + return NULL; + } + + void DoSpawnPortal() + { + if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) + { + uint8 tmp = urand(0,2); + + if (tmp >= CurrentRiftId) + ++tmp; + + debug_log("TSCR: Instance Dark Portal: Creating Time Rift at locationId %i (old locationId was %u).",tmp,CurrentRiftId); + + CurrentRiftId = tmp; + + Creature *pTemp = pMedivh->SummonCreature(C_TIME_RIFT, + PortalLocation[tmp][0],PortalLocation[tmp][1],PortalLocation[tmp][2],PortalLocation[tmp][3], + TEMPSUMMON_CORPSE_DESPAWN,0); + if (pTemp) + { + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + if (Creature *pBoss = SummonedPortalBoss(pTemp)) + { + if (pBoss->GetEntry() == C_AEONUS) + pBoss->AddThreat(pMedivh,0.0f); + else + { + pBoss->AddThreat(pTemp,0.0f); + pTemp->CastSpell(pBoss,SPELL_RIFT_CHANNEL,false); + } + } + } + } + } + + void Update(uint32 diff) + { + if (m_auiEncounter[1] != IN_PROGRESS) + return; + + //add delay timer? + if (!CanProgressEvent()) + { + Clear(); + return; + } + + if (NextPortal_Timer) + { + if (NextPortal_Timer <= diff) + { + ++mRiftPortalCount; + + DoUpdateWorldState(WORLD_STATE_BM_RIFT, mRiftPortalCount); + + DoSpawnPortal(); + NextPortal_Timer = RiftWaves[GetRiftWaveId()].NextPortalTime; + } else NextPortal_Timer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_dark_portal(Map* pMap) +{ + return new instance_dark_portal(pMap); +} + +void AddSC_instance_dark_portal() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_dark_portal"; + newscript->GetInstanceData = &GetInstanceData_instance_dark_portal; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp new file mode 100644 index 00000000000..91c9e274b83 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_captain_skarloc.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Captain_Skarloc +SD%Complete: 75 +SDComment: Missing adds, missing waypoints to move up to Thrall once spawned + speech before enter combat. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define SAY_ENTER -1560000 +#define SAY_TAUNT1 -1560001 +#define SAY_TAUNT2 -1560002 +#define SAY_SLAY1 -1560003 +#define SAY_SLAY2 -1560004 +#define SAY_DEATH -1560005 + +#define SPELL_HOLY_LIGHT 29427 +#define SPELL_CLEANSE 29380 +#define SPELL_HAMMER_OF_JUSTICE 13005 +#define SPELL_HOLY_SHIELD 31904 +#define SPELL_DEVOTION_AURA 8258 +#define SPELL_CONSECRATION 38385 + +struct boss_captain_skarlocAI : public ScriptedAI +{ + boss_captain_skarlocAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Holy_Light_Timer; + uint32 Cleanse_Timer; + uint32 HammerOfJustice_Timer; + uint32 HolyShield_Timer; + uint32 DevotionAura_Timer; + uint32 Consecration_Timer; + + void Reset() + { + Holy_Light_Timer = 20000 + rand()%10000; + Cleanse_Timer = 10000; + HammerOfJustice_Timer = 20000 + rand()%15000; + HolyShield_Timer = 240000; + DevotionAura_Timer = 3000; + Consecration_Timer = 8000; + } + + void EnterCombat(Unit * /*who*/) + { + //This is not correct. Should taunt Thrall before engage in combat + DoScriptText(SAY_TAUNT1, me); + DoScriptText(SAY_TAUNT2, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + pInstance->SetData(TYPE_THRALL_PART1, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Holy_Light + if (Holy_Light_Timer <= diff) + { + DoCast(me, SPELL_HOLY_LIGHT); + Holy_Light_Timer = 30000; + } else Holy_Light_Timer -= diff; + + //Cleanse + if (Cleanse_Timer <= diff) + { + DoCast(me, SPELL_CLEANSE); + Cleanse_Timer = 10000; + } else Cleanse_Timer -= diff; + + //Hammer of Justice + if (HammerOfJustice_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); + HammerOfJustice_Timer = 60000; + } else HammerOfJustice_Timer -= diff; + + //Holy Shield + if (HolyShield_Timer <= diff) + { + DoCast(me, SPELL_HOLY_SHIELD); + HolyShield_Timer = 240000; + } else HolyShield_Timer -= diff; + + //Devotion_Aura + if (DevotionAura_Timer <= diff) + { + DoCast(me, SPELL_DEVOTION_AURA); + DevotionAura_Timer = 45000 + rand()%10000; + } else DevotionAura_Timer -= diff; + + //Consecration + if (Consecration_Timer <= diff) + { + //DoCast(me->getVictim(), SPELL_CONSECRATION); + Consecration_Timer = 5000 + rand()%5000; + } else Consecration_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_captain_skarloc(Creature* pCreature) +{ + return new boss_captain_skarlocAI (pCreature); +} + +void AddSC_boss_captain_skarloc() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_captain_skarloc"; + newscript->GetAI = &GetAI_boss_captain_skarloc; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp new file mode 100644 index 00000000000..2c2ad96ddb7 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_epoch_hunter.cpp @@ -0,0 +1,138 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Epoch_Hunter +SD%Complete: 60 +SDComment: Missing spawns pre-event, missing speech to be coordinated with rest of escort event. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define SAY_ENTER1 -1560013 +#define SAY_ENTER2 -1560014 +#define SAY_ENTER3 -1560015 +#define SAY_AGGRO1 -1560016 +#define SAY_AGGRO2 -1560017 +#define SAY_SLAY1 -1560018 +#define SAY_SLAY2 -1560019 +#define SAY_BREATH1 -1560020 +#define SAY_BREATH2 -1560021 +#define SAY_DEATH -1560022 + +#define SPELL_SAND_BREATH 31914 +#define SPELL_IMPENDING_DEATH 31916 +#define SPELL_MAGIC_DISRUPTION_AURA 33834 +#define SPELL_WING_BUFFET 31475 + +struct boss_epoch_hunterAI : public ScriptedAI +{ + boss_epoch_hunterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 SandBreath_Timer; + uint32 ImpendingDeath_Timer; + uint32 WingBuffet_Timer; + uint32 Mda_Timer; + + void Reset() + { + SandBreath_Timer = 8000 + rand()%8000; + ImpendingDeath_Timer = 25000 + rand()%5000; + WingBuffet_Timer = 35000; + Mda_Timer = 40000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2), me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + pInstance->SetData(TYPE_THRALL_PART4, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Sand Breath + if (SandBreath_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me->getVictim(), SPELL_SAND_BREATH); + + DoScriptText(RAND(SAY_BREATH1,SAY_BREATH2), me); + + SandBreath_Timer = 10000 + rand()%10000; + } else SandBreath_Timer -= diff; + + if (ImpendingDeath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_IMPENDING_DEATH); + ImpendingDeath_Timer = 25000+rand()%5000; + } else ImpendingDeath_Timer -= diff; + + if (WingBuffet_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_WING_BUFFET); + WingBuffet_Timer = 25000+rand()%10000; + } else WingBuffet_Timer -= diff; + + if (Mda_Timer <= diff) + { + DoCast(me, SPELL_MAGIC_DISRUPTION_AURA); + Mda_Timer = 15000; + } else Mda_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_epoch_hunter(Creature* pCreature) +{ + return new boss_epoch_hunterAI (pCreature); +} + +void AddSC_boss_epoch_hunter() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_epoch_hunter"; + newscript->GetAI = &GetAI_boss_epoch_hunter; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp new file mode 100644 index 00000000000..dae0f5390b1 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/boss_leutenant_drake.cpp @@ -0,0 +1,190 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Luetenant_Drake +SD%Complete: 70 +SDComment: Missing proper code for patrolling area after being spawned. Script for GO (barrels) quest 10283 +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" +#include "ScriptedEscortAI.h" + +/*###### +## go_barrel_old_hillsbrad +######*/ + +bool GOHello_go_barrel_old_hillsbrad(Player* /*pPlayer*/, GameObject* pGO) +{ + if (ScriptedInstance* pInstance = pGO->GetInstanceData()) + { + if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE) + return false; + + pInstance->SetData(TYPE_BARREL_DIVERSION, IN_PROGRESS); + } + + return false; +} + +/*###### +## boss_lieutenant_drake +######*/ + +#define SAY_ENTER -1560006 +#define SAY_AGGRO -1560007 +#define SAY_SLAY1 -1560008 +#define SAY_SLAY2 -1560009 +#define SAY_MORTAL -1560010 +#define SAY_SHOUT -1560011 +#define SAY_DEATH -1560012 + +#define SPELL_WHIRLWIND 31909 +#define SPELL_HAMSTRING 9080 +#define SPELL_MORTAL_STRIKE 31911 +#define SPELL_FRIGHTENING_SHOUT 33789 + +struct Location +{ + uint32 wpId; + float x; + float y; + float z; +}; + +static Location DrakeWP[]= +{ + {0, 2125.84, 88.2535, 54.8830}, + {1, 2111.01, 93.8022, 52.6356}, + {2, 2106.70, 114.753, 53.1965}, + {3, 2107.76, 138.746, 52.5109}, + {4, 2114.83, 160.142, 52.4738}, + {5, 2125.24, 178.909, 52.7283}, + {6, 2151.02, 208.901, 53.1551}, + {7, 2177.00, 233.069, 52.4409}, + {8, 2190.71, 227.831, 53.2742}, + {9, 2178.14, 214.219, 53.0779}, + {10, 2154.99, 202.795, 52.6446}, + {11, 2132.00, 191.834, 52.5709}, + {12, 2117.59, 166.708, 52.7686}, + {13, 2093.61, 139.441, 52.7616}, + {14, 2086.29, 104.950, 52.9246}, + {15, 2094.23, 81.2788, 52.6946}, + {16, 2108.70, 85.3075, 53.3294}, + {17, 2125.50, 88.9481, 54.7953}, + {18, 2128.20, 70.9763, 64.4221} +}; + +struct boss_lieutenant_drakeAI : public ScriptedAI +{ + boss_lieutenant_drakeAI(Creature *c) : ScriptedAI(c) {} + + bool CanPatrol; + uint32 wpId; + + uint32 Whirlwind_Timer; + uint32 Fear_Timer; + uint32 MortalStrike_Timer; + uint32 ExplodingShout_Timer; + + void Reset() + { + CanPatrol = true; + wpId = 0; + + Whirlwind_Timer = 20000; + Fear_Timer = 30000; + MortalStrike_Timer = 45000; + ExplodingShout_Timer = 25000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + //TODO: make this work + if (CanPatrol && wpId == 0) + { + me->GetMotionMaster()->MovePoint(DrakeWP[0].wpId, DrakeWP[0].x, DrakeWP[0].y, DrakeWP[0].z); + ++wpId; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Whirlwind + if (Whirlwind_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WHIRLWIND); + Whirlwind_Timer = 20000+rand()%5000; + } else Whirlwind_Timer -= diff; + + //Fear + if (Fear_Timer <= diff) + { + DoScriptText(SAY_SHOUT, me); + DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); + Fear_Timer = 25000+rand()%10000; + } else Fear_Timer -= diff; + + //Mortal Strike + if (MortalStrike_Timer <= diff) + { + DoScriptText(SAY_MORTAL, me); + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + MortalStrike_Timer = 20000+rand()%10000; + } else MortalStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_lieutenant_drake(Creature* pCreature) +{ + return new boss_lieutenant_drakeAI (pCreature); +} + +void AddSC_boss_lieutenant_drake() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_barrel_old_hillsbrad"; + newscript->pGOHello = &GOHello_go_barrel_old_hillsbrad; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lieutenant_drake"; + newscript->GetAI = &GetAI_boss_lieutenant_drake; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp new file mode 100644 index 00000000000..fa0b7c14595 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/instance_old_hillsbrad.cpp @@ -0,0 +1,238 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Old_Hillsbrad +SD%Complete: 75 +SDComment: If thrall escort fail, all parts will reset. In future, save sub-parts and continue from last known. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +#include "ScriptedPch.h" +#include "old_hillsbrad.h" + +#define MAX_ENCOUNTER 6 + +#define THRALL_ENTRY 17876 +#define TARETHA_ENTRY 18887 +#define EPOCH_ENTRY 18096 + +#define DRAKE_ENTRY 17848 + +#define QUEST_ENTRY_DIVERSION 10283 +#define LODGE_QUEST_TRIGGER 20155 + +struct instance_old_hillsbrad : public ScriptedInstance +{ + instance_old_hillsbrad(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 mBarrelCount; + uint32 mThrallEventCount; + + uint64 ThrallGUID; + uint64 TarethaGUID; + uint64 EpochGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + mBarrelCount = 0; + mThrallEventCount = 0; + ThrallGUID = 0; + TarethaGUID = 0; + EpochGUID = 0; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Old Hillsbrad: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void UpdateQuestCredit() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->KilledMonsterCredit(LODGE_QUEST_TRIGGER,0); + } + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case THRALL_ENTRY: + ThrallGUID = pCreature->GetGUID(); + break; + case TARETHA_ENTRY: + TarethaGUID = pCreature->GetGUID(); + break; + case EPOCH_ENTRY: + EpochGUID = pCreature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + Player* pPlayer = GetPlayerInMap(); + + if (!pPlayer) + { + debug_log("TSCR: Instance Old Hillsbrad: SetData (Type: %u Data %u) cannot find any player.", type, data); + return; + } + + switch(type) + { + case TYPE_BARREL_DIVERSION: + { + if (data == IN_PROGRESS) + { + if (mBarrelCount >= 5) + return; + + ++mBarrelCount; + DoUpdateWorldState(WORLD_STATE_OH, mBarrelCount); + + debug_log("TSCR: Instance Old Hillsbrad: go_barrel_old_hillsbrad count %u",mBarrelCount); + + m_auiEncounter[0] = IN_PROGRESS; + + if (mBarrelCount == 5) + { + UpdateQuestCredit(); + pPlayer->SummonCreature(DRAKE_ENTRY, 2128.43, 71.01, 64.42, 1.74, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000); + m_auiEncounter[0] = DONE; + } + } + break; + } + case TYPE_THRALL_EVENT: + { + if (data == FAIL) + { + if (mThrallEventCount <= 20) + { + ++mThrallEventCount; + m_auiEncounter[1] = NOT_STARTED; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); + m_auiEncounter[2] = NOT_STARTED; + m_auiEncounter[3] = NOT_STARTED; + m_auiEncounter[4] = NOT_STARTED; + m_auiEncounter[5] = NOT_STARTED; + } + else if (mThrallEventCount > 20) + { + m_auiEncounter[1] = data; + m_auiEncounter[2] = data; + m_auiEncounter[3] = data; + m_auiEncounter[4] = data; + m_auiEncounter[5] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); + } + } + else + m_auiEncounter[1] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall escort event adjusted to data %u.",data); + break; + } + case TYPE_THRALL_PART1: + m_auiEncounter[2] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part I adjusted to data %u.",data); + break; + case TYPE_THRALL_PART2: + m_auiEncounter[3] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part II adjusted to data %u.",data); + break; + case TYPE_THRALL_PART3: + m_auiEncounter[4] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part III adjusted to data %u.",data); + break; + case TYPE_THRALL_PART4: + m_auiEncounter[5] = data; + debug_log("TSCR: Instance Old Hillsbrad: Thrall event part IV adjusted to data %u.",data); + break; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_BARREL_DIVERSION: + return m_auiEncounter[0]; + case TYPE_THRALL_EVENT: + return m_auiEncounter[1]; + case TYPE_THRALL_PART1: + return m_auiEncounter[2]; + case TYPE_THRALL_PART2: + return m_auiEncounter[3]; + case TYPE_THRALL_PART3: + return m_auiEncounter[4]; + case TYPE_THRALL_PART4: + return m_auiEncounter[5]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THRALL: + return ThrallGUID; + case DATA_TARETHA: + return TarethaGUID; + case DATA_EPOCH: + return EpochGUID; + } + return 0; + } +}; +InstanceData* GetInstanceData_instance_old_hillsbrad(Map* pMap) +{ + return new instance_old_hillsbrad(pMap); +} + +void AddSC_instance_old_hillsbrad() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_old_hillsbrad"; + newscript->GetInstanceData = &GetInstanceData_instance_old_hillsbrad; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp new file mode 100644 index 00000000000..08c63954db5 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp @@ -0,0 +1,658 @@ + /* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Old_Hillsbrad +SD%Complete: 40 +SDComment: Quest support: 10283, 10284. All friendly NPC's. Thrall waypoints fairly complete, missing many details, but possible to complete escort. +SDCategory: Caverns of Time, Old Hillsbrad Foothills +EndScriptData */ + +/* ContentData +npc_erozion +npc_thrall_old_hillsbrad +npc_taretha +EndContentData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "old_hillsbrad.h" + +#define QUEST_ENTRY_HILLSBRAD 10282 +#define QUEST_ENTRY_DIVERSION 10283 +#define QUEST_ENTRY_ESCAPE 10284 +#define QUEST_ENTRY_RETURN 10285 +#define ITEM_ENTRY_BOMBS 25853 + +#define GOSSIP_HELLO_EROZION1 "I need a pack of Incendiary Bombs." +#define GOSSIP_HELLO_EROZION2 "[PH] Teleport please, i'm tired." + +/*###### +## npc_erozion +######*/ + +bool GossipHello_npc_erozion(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance && pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE && !pPlayer->HasItemCount(ITEM_ENTRY_BOMBS,1)) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + if (!pPlayer->GetQuestRewardStatus(QUEST_ENTRY_RETURN) && pPlayer->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(9778, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_erozion(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_ENTRY_BOMBS, 1); + if (msg == EQUIP_ERR_OK) + { + pPlayer->StoreNewItem(dest, ITEM_ENTRY_BOMBS, true); + } + pPlayer->SEND_GOSSIP_MENU(9515, pCreature->GetGUID()); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + } + return true; +} + +/*###### +## npc_thrall_old_hillsbrad +######*/ + +//Thrall texts +#define SAY_TH_START_EVENT_PART1 -1560023 +#define SAY_TH_ARMORY -1560024 +#define SAY_TH_SKARLOC_MEET -1560025 +#define SAY_TH_SKARLOC_TAUNT -1560026 +#define SAY_TH_START_EVENT_PART2 -1560027 +#define SAY_TH_MOUNTS_UP -1560028 +#define SAY_TH_CHURCH_END -1560029 +#define SAY_TH_MEET_TARETHA -1560030 +#define SAY_TH_EPOCH_WONDER -1560031 +#define SAY_TH_EPOCH_KILL_TARETHA -1560032 +#define SAY_TH_EVENT_COMPLETE -1560033 + +#define SAY_TH_RANDOM_LOW_HP1 -1560034 +#define SAY_TH_RANDOM_LOW_HP2 -1560035 + +#define SAY_TH_RANDOM_DIE1 -1560036 +#define SAY_TH_RANDOM_DIE2 -1560037 + +#define SAY_TH_RANDOM_AGGRO1 -1560038 +#define SAY_TH_RANDOM_AGGRO2 -1560039 +#define SAY_TH_RANDOM_AGGRO3 -1560040 +#define SAY_TH_RANDOM_AGGRO4 -1560041 + +#define SAY_TH_RANDOM_KILL1 -1560042 +#define SAY_TH_RANDOM_KILL2 -1560043 +#define SAY_TH_RANDOM_KILL3 -1560044 + +#define SAY_TH_LEAVE_COMBAT1 -1560045 +#define SAY_TH_LEAVE_COMBAT2 -1560046 +#define SAY_TH_LEAVE_COMBAT3 -1560047 + +//Taretha texts +#define SAY_TA_FREE -1560048 +#define SAY_TA_ESCAPED -1560049 + +//Misc for Thrall +#define SPELL_STRIKE 14516 +#define SPELL_SHIELD_BLOCK 12169 +#define SPELL_SUMMON_EROZION_IMAGE 33954 //if thrall dies during escort? + +#define SPEED_WALK (0.5f) +#define SPEED_RUN (1.0f) +#define SPEED_MOUNT (1.6f) + +#define THRALL_WEAPON_MODEL 22106 +#define THRALL_WEAPON_INFO 218169346 +#define THRALL_SHIELD_MODEL 18662 +#define THRALL_SHIELD_INFO 234948100 +#define THRALL_MODEL_UNEQUIPPED 17292 +#define THRALL_MODEL_EQUIPPED 18165 + +//Misc Creature entries +#define ENTRY_ARMORER 18764 +#define ENTRY_SCARLOC 17862 + +#define MOB_ENTRY_RIFLE 17820 +#define MOB_ENTRY_WARDEN 17833 +#define MOB_ENTRY_VETERAN 17860 +#define MOB_ENTRY_WATCHMAN 17814 +#define MOB_ENTRY_SENTRY 17815 + +#define MOB_ENTRY_BARN_GUARDSMAN 18092 +#define MOB_ENTRY_BARN_PROTECTOR 18093 +#define MOB_ENTRY_BARN_LOOKOUT 18094 + +#define MOB_ENTRY_CHURCH_GUARDSMAN 23175 +#define MOB_ENTRY_CHURCH_PROTECTOR 23179 +#define MOB_ENTRY_CHURCH_LOOKOUT 23177 + +#define MOB_ENTRY_INN_GUARDSMAN 23176 +#define MOB_ENTRY_INN_PROTECTOR 23180 +#define MOB_ENTRY_INN_LOOKOUT 23178 + +#define SKARLOC_MOUNT 18798 +#define SKARLOC_MOUNT_MODEL 18223 +#define EROZION_ENTRY 18723 +#define ENTRY_EPOCH 18096 + +//gossip items +#define GOSSIP_ID_START 9568 +#define GOSSIP_ID_SKARLOC1 9614 //I'm glad Taretha is alive. We now must find a way to free her... +#define GOSSIP_ITEM_SKARLOC1 "Taretha cannot see you, Thrall." +#define GOSSIP_ID_SKARLOC2 9579 //What do you mean by this? Is Taretha in danger? +#define GOSSIP_ITEM_SKARLOC2 "The situation is rather complicated, Thrall. It would be best for you to head into the mountains now, before more of Blackmoore's men show up. We'll make sure Taretha is safe." +#define GOSSIP_ID_SKARLOC3 9580 + +#define GOSSIP_ID_TARREN 9597 //tarren mill is beyond these trees +#define GOSSIP_ITEM_TARREN "We're ready, Thrall." + +#define GOSSIP_ID_COMPLETE 9578 //Thank you friends, I owe my freedom to you. Where is Taretha? I hoped to see her + +#define GOSSIP_ITEM_WALKING "[PH] Start walking." + +struct npc_thrall_old_hillsbradAI : public npc_escortAI +{ + npc_thrall_old_hillsbradAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + HadMount = false; + me->setActive(true); + } + + ScriptedInstance *pInstance; + + uint64 TarethaGUID; + + bool LowHp; + bool HadMount; + + void WaypointReached(uint32 i) + { + if (!pInstance) + return; + + switch(i) + { + case 8: + SetRun(false); + me->SummonCreature(18764,2181.87,112.46,89.45,0.26,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 9: + DoScriptText(SAY_TH_ARMORY, me); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_MODEL); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_MODEL); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); + //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); + break; + case 10: + me->SetDisplayId(THRALL_MODEL_EQUIPPED); + break; + case 11: + SetRun(); + break; + case 15: + me->SummonCreature(MOB_ENTRY_RIFLE,2200.28,137.37,87.93,5.07,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2197.44,131.83,87.93,0.78,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2203.62,135.40,87.93,3.70,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2200.75,130.13,87.93,1.48,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 21: + me->SummonCreature(MOB_ENTRY_RIFLE,2135.80,154.01,67.45,4.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2144.36,151.87,67.74,4.46,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2142.12,154.41,67.12,4.56,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2138.08,155.38,67.24,4.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 25: + me->SummonCreature(MOB_ENTRY_RIFLE,2102.98,192.17,65.24,6.02,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WARDEN,2108.48,198.75,65.18,5.15,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2106.11,197.29,65.18,5.63,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_VETERAN,2104.18,194.82,65.18,5.75,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 29: + DoScriptText(SAY_TH_SKARLOC_MEET, me); + me->SummonCreature(ENTRY_SCARLOC,2036.48,271.22,63.43,5.27,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + //temporary,skarloc should rather be triggered to walk up to thrall + break; + case 30: + SetEscortPaused(true); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetRun(false); + break; + case 31: + DoScriptText(SAY_TH_MOUNTS_UP, me); + DoMount(); + SetRun(); + break; + case 37: + //possibly regular patrollers? If so, remove this and let database handle them + me->SummonCreature(MOB_ENTRY_WATCHMAN,2124.26,522.16,56.87,3.99,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_WATCHMAN,2121.69,525.37,57.11,4.01,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_SENTRY,2124.65,524.55,56.63,3.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 59: + me->SummonCreature(SKARLOC_MOUNT,2488.64,625.77,58.26,4.71,TEMPSUMMON_TIMED_DESPAWN,10000); + DoUnmount(); + HadMount = false; + SetRun(false); + break; + case 60: + me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + //make horsie run off + SetEscortPaused(true); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(TYPE_THRALL_PART2, DONE); + SetRun(); + break; + case 64: + SetRun(false); + break; + case 68: + me->SummonCreature(MOB_ENTRY_BARN_PROTECTOR,2500.22,692.60,55.50,2.84,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_LOOKOUT,2500.13,696.55,55.51,3.38,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.55,693.64,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.94,695.81,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 71: + SetRun(); + break; + case 81: + SetRun(false); + break; + case 83: + me->SummonCreature(MOB_ENTRY_CHURCH_PROTECTOR,2627.33,646.82,56.03,4.28,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_LOOKOUT,2624.14,648.03,56.03,4.50,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2625.32,649.60,56.03,4.38,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2627.22,649.00,56.03,4.34,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); + break; + case 84: + DoScriptText(SAY_TH_CHURCH_END, me); + SetRun(); + break; + case 91: + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + SetRun(false); + break; + case 93: + me->SummonCreature(MOB_ENTRY_INN_PROTECTOR,2652.71,660.31,61.93,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_LOOKOUT,2648.96,662.59,61.93,0.79,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2657.36,662.34,61.93,2.68,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2656.39,659.77,61.93,2.61,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); + break; + case 94: + if (uint64 TarethaGUID = pInstance->GetData64(DATA_TARETHA)) + { + if (Unit* Taretha = Unit::GetUnit((*me), TarethaGUID)) + DoScriptText(SAY_TA_ESCAPED, Taretha, me); + } + break; + case 95: + DoScriptText(SAY_TH_MEET_TARETHA, me); + pInstance->SetData(TYPE_THRALL_PART3,DONE); + SetEscortPaused(true); + break; + case 96: + DoScriptText(SAY_TH_EPOCH_WONDER, me); + break; + case 97: + DoScriptText(SAY_TH_EPOCH_KILL_TARETHA, me); + SetRun(); + break; + case 98: + //trigger epoch Yell("Thrall! Come outside and face your fate! ....") + //from here, thrall should not never be allowed to move to point 106 which he currently does. + break; + + case 106: + { + //trigger taretha to run down outside + if (Creature* Taretha = pInstance->instance->GetCreature(pInstance->GetData64(DATA_TARETHA))) + { + if (Player* pPlayer = GetPlayerForEscort()) + CAST_AI(npc_escortAI, (Taretha->AI()))->Start(false, true, pPlayer->GetGUID()); + } + + //kill credit Creature for quest + Map* pMap = me->GetMap(); + Map::PlayerList const& players = pMap->GetPlayers(); + if (!players.isEmpty() && pMap->IsDungeon()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->KilledMonsterCredit(20156,me->GetGUID()); + } + } + + //alot will happen here, thrall and taretha talk, erozion appear at spot to explain + me->SummonCreature(EROZION_ENTRY,2646.47,680.416,55.38,4.16,TEMPSUMMON_TIMED_DESPAWN,120000); + } + break; + case 108: + //last waypoint, just set Thrall invisible, respawn is turned off + me->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void Reset() + { + LowHp = false; + + if (HadMount) + DoMount(); + + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + DoUnmount(); + HadMount = false; + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + me->SetDisplayId(THRALL_MODEL_UNEQUIPPED); + } + if (HasEscortState(STATE_ESCORT_ESCORTING)) + { + DoScriptText(RAND(SAY_TH_LEAVE_COMBAT1,SAY_TH_LEAVE_COMBAT2,SAY_TH_LEAVE_COMBAT3), me); + } + } + void StartWP() + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetEscortPaused(false); + } + void DoMount() + { + me->Mount(SKARLOC_MOUNT_MODEL); + me->SetSpeed(MOVE_RUN,SPEED_MOUNT); + } + void DoUnmount() + { + me->Unmount(); + me->SetSpeed(MOVE_RUN,SPEED_RUN); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(RAND(SAY_TH_RANDOM_AGGRO1,SAY_TH_RANDOM_AGGRO2,SAY_TH_RANDOM_AGGRO3,SAY_TH_RANDOM_AGGRO4), me); + if (me->IsMounted()) + { + DoUnmount(); + HadMount = true; + } + } + + void JustSummoned(Creature* summoned) + { + switch(summoned->GetEntry()) + { + //TODO: make Scarloc start into event instead, and not start attack directly + case MOB_ENTRY_BARN_GUARDSMAN: + case MOB_ENTRY_BARN_PROTECTOR: + case MOB_ENTRY_BARN_LOOKOUT: + case SKARLOC_MOUNT: + case EROZION_ENTRY: + break; + default: + summoned->AI()->AttackStart(me); + break; + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_TH_RANDOM_KILL1,SAY_TH_RANDOM_KILL2,SAY_TH_RANDOM_KILL3), me); + } + void JustDied(Unit *slayer) + { + if (pInstance) + pInstance->SetData(TYPE_THRALL_EVENT,FAIL); + + // Don't do a yell if he kills self (if player goes too far or at the end). + if (slayer == me) + return; + + DoScriptText(RAND(SAY_TH_RANDOM_DIE1,SAY_TH_RANDOM_DIE2), me); + } + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + //TODO: add his abilities'n-crap here + if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) + { + DoScriptText(RAND(SAY_TH_RANDOM_LOW_HP1,SAY_TH_RANDOM_LOW_HP2), me); + LowHp = true; + } + } +}; + +CreatureAI* GetAI_npc_thrall_old_hillsbrad(Creature* pCreature) +{ + return new npc_thrall_old_hillsbradAI(pCreature); +} + +bool GossipHello_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + { + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + pPlayer->SendPreparedQuest(pCreature->GetGUID()); + } + + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance) + { + if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE && !pInstance->GetData(TYPE_THRALL_EVENT)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WALKING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START, pCreature->GetGUID()); + } + + if (pInstance->GetData(TYPE_THRALL_PART1) == DONE && !pInstance->GetData(TYPE_THRALL_PART2)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC1, pCreature->GetGUID()); + } + + if (pInstance->GetData(TYPE_THRALL_PART2) == DONE && !pInstance->GetData(TYPE_THRALL_PART3)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TARREN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_TARREN, pCreature->GetGUID()); + } + } + return true; +} + +bool GossipSelect_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pInstance) + { + pInstance->SetData(TYPE_THRALL_EVENT,IN_PROGRESS); + pInstance->SetData(TYPE_THRALL_PART1,IN_PROGRESS); + } + + DoScriptText(SAY_TH_START_EVENT_PART1, pCreature); + + if (npc_escortAI* pEscortAI = CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())) + pEscortAI->Start(true, true, pPlayer->GetGUID()); + + CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(100.0f);//not really needed, because it will not despawn if player is too far + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); + CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); + break; + + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC2, pCreature->GetGUID()); + break; + + case GOSSIP_ACTION_INFO_DEF+20: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC3, pCreature->GetGUID()); + pCreature->SummonCreature(SKARLOC_MOUNT,2038.81,270.26,63.20,5.41,TEMPSUMMON_TIMED_DESPAWN,12000); + if (pInstance) + pInstance->SetData(TYPE_THRALL_PART2,IN_PROGRESS); + + DoScriptText(SAY_TH_START_EVENT_PART2, pCreature); + + CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); + break; + + case GOSSIP_ACTION_INFO_DEF+3: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pInstance) + pInstance->SetData(TYPE_THRALL_PART3,IN_PROGRESS); + CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); + break; + } + return true; +} + +/*###### +## npc_taretha +######*/ + +#define GOSSIP_ID_EPOCH1 9610 //Thank you for helping Thrall escape, friends. Now I only hope +#define GOSSIP_ITEM_EPOCH1 "Strange wizard?" +#define GOSSIP_ID_EPOCH2 9613 //Yes, friends. This man was no wizard of +#define GOSSIP_ITEM_EPOCH2 "We'll get you out. Taretha. Don't worry. I doubt the wizard would wander too far away." + +struct npc_tarethaAI : public npc_escortAI +{ + npc_tarethaAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void WaypointReached(uint32 i) + { + switch(i) + { + case 6: + DoScriptText(SAY_TA_FREE, me); + break; + case 7: + me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); + break; + } + } + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + npc_escortAI::UpdateAI(diff); + } +}; +CreatureAI* GetAI_npc_taretha(Creature* pCreature) +{ + return new npc_tarethaAI(pCreature); +} + +bool GossipHello_npc_taretha(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (pInstance && pInstance->GetData(TYPE_THRALL_PART3) == DONE && pInstance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH1, pCreature->GetGUID()); + } + return true; +} + +bool GossipSelect_npc_taretha(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH2, pCreature->GetGUID()); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) + { + pInstance->SetData(TYPE_THRALL_PART4,IN_PROGRESS); + if (pInstance->GetData64(DATA_EPOCH) == 0) + pCreature->SummonCreature(ENTRY_EPOCH,2639.13,698.55,65.43,4.59,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); + + if (uint64 ThrallGUID = pInstance->GetData64(DATA_THRALL)) + { + Creature* Thrall = (Unit::GetCreature((*pCreature), ThrallGUID)); + if (Thrall) + CAST_AI(npc_thrall_old_hillsbradAI, Thrall->AI())->StartWP(); + } + } + } + return true; +} + +/*###### +## AddSC +######*/ + +void AddSC_old_hillsbrad() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_erozion"; + newscript->pGossipHello = &GossipHello_npc_erozion; + newscript->pGossipSelect = &GossipSelect_npc_erozion; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_thrall_old_hillsbrad"; + newscript->pGossipHello = &GossipHello_npc_thrall_old_hillsbrad; + newscript->pGossipSelect = &GossipSelect_npc_thrall_old_hillsbrad; + newscript->GetAI = &GetAI_npc_thrall_old_hillsbrad; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_taretha"; + newscript->pGossipHello = &GossipHello_npc_taretha; + newscript->pGossipSelect = &GossipSelect_npc_taretha; + newscript->GetAI = &GetAI_npc_taretha; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h new file mode 100644 index 00000000000..5c398cc2647 --- /dev/null +++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.h @@ -0,0 +1,19 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_OLD_HILLSBRAD_H +#define DEF_OLD_HILLSBRAD_H + +#define TYPE_BARREL_DIVERSION 1 +#define TYPE_THRALL_EVENT 2 +#define TYPE_THRALL_PART1 3 +#define TYPE_THRALL_PART2 4 +#define TYPE_THRALL_PART3 5 +#define TYPE_THRALL_PART4 6 +#define DATA_THRALL 7 +#define DATA_TARETHA 8 +#define DATA_EPOCH 9 +#define WORLD_STATE_OH 2436 +#endif + diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp deleted file mode 100644 index 287d3cf8e9b..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_epoch.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - - -/* Script Data Start -SDName: Boss epoch -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro, consecutive attacks to a random target durin time wrap, adjust timers -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CURSE_OF_EXERTION = 52772, - SPELL_TIME_WARP = 52766, //Time slows down, reducing attack, casting and movement speed by 70% for 6 sec. - SPELL_TIME_STOP = 58848, //Stops time in a 50 yard sphere for 2 sec. - SPELL_WOUNDING_STRIKE = 52771, //Used only on the tank - H_SPELL_WOUNDING_STRIKE = 58830 -}; - -enum Yells -{ - SAY_INTRO = -1595000, //"Prince Arthas Menethil, on this day, a powerful darkness has taken hold of your soul. The death you are destined to visit upon others will this day be your own." - SAY_AGGRO = -1595001, //"We'll see about that, young prince." - SAY_TIME_WARP_1 = -1595002, //"Tick tock, tick tock..." - SAY_TIME_WARP_2 = -1595003, //"Not quick enough!" - SAY_TIME_WARP_3 = -1595004, //"Let's get this over with. " - SAY_SLAY_1 = -1595005, //"There is no future for you." - SAY_SLAY_2 = -1595006, //"This is the hour of our greatest triumph!" - SAY_SLAY_3 = -1595007, //"You were destined to fail. " - SAY_DEATH = -1595008 //"*gurgles*" -}; - -struct boss_epochAI : public ScriptedAI -{ - boss_epochAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint8 uiStep; - - uint32 uiStepTimer; - uint32 uiWoundingStrikeTimer; - uint32 uiTimeWarpTimer; - uint32 uiTimeStopTimer; - uint32 uiCurseOfExertionTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiStep = 1; - uiStepTimer = 26000; - uiCurseOfExertionTimer = 9300; - uiTimeWarpTimer = 25300; - uiTimeStopTimer = 21300; - uiWoundingStrikeTimer = 5300; - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiCurseOfExertionTimer < diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CURSE_OF_EXERTION); - uiCurseOfExertionTimer = 9300; - } else uiCurseOfExertionTimer -= diff; - - if (uiWoundingStrikeTimer < diff) - { - DoCastVictim(SPELL_WOUNDING_STRIKE); - uiWoundingStrikeTimer = 5300; - } else uiWoundingStrikeTimer -= diff; - - if (uiTimeStopTimer < diff) - { - DoCastAOE(SPELL_TIME_STOP); - uiTimeStopTimer = 21300; - } else uiTimeStopTimer -= diff; - - if (uiTimeWarpTimer < diff) - { - DoScriptText(RAND(SAY_TIME_WARP_1,SAY_TIME_WARP_2,SAY_TIME_WARP_3), me); - DoCastAOE(SPELL_TIME_WARP); - uiTimeWarpTimer = 25300; - } else uiTimeWarpTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_EPOCH_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_epoch(Creature* pCreature) -{ - return new boss_epochAI (pCreature); -} - -void AddSC_boss_epoch() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_epoch"; - newscript->GetAI = &GetAI_boss_epoch; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp deleted file mode 100644 index 12cdf00f2a5..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_infinite.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CORRUPTING_BLIGHT = 60588, - SPELL_VOID_STRIKE = 60590 -}; - -enum Yells -{ - SAY_AGGRO = -1595045, - SAY_FAIL = -1595046, - SAY_DEATH = -1595047 -}; - - -struct boss_infinite_corruptorAI : public ScriptedAI -{ - boss_infinite_corruptorAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_INFINITE_EVENT, DONE); - } -}; - -CreatureAI* GetAI_boss_infinite_corruptor(Creature* pCreature) -{ - return new boss_infinite_corruptorAI(pCreature); -} - -void AddSC_boss_infinite_corruptor() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_infinite_corruptor"; - newscript->GetAI = &GetAI_boss_infinite_corruptor; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp deleted file mode 100644 index a39f3289a5a..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_mal_ganis.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss mal_ganis -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro & outro -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_mal_ganis' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CARRION_SWARM = 52720, //A cresting wave of chaotic magic splashes over enemies in front of the caster, dealing 3230 to 3570 Shadow damage and 380 to 420 Shadow damage every 3 sec. for 15 sec. - H_SPELL_CARRION_SWARM = 58852, - SPELL_MIND_BLAST = 52722, //Inflicts 4163 to 4837 Shadow damage to an enemy. - H_SPELL_MIND_BLAST = 58850, - SPELL_SLEEP = 52721, //Puts an enemy to sleep for up to 10 sec. Any damage caused will awaken the target. - H_SPELL_SLEEP = 58849, - SPELL_VAMPIRIC_TOUCH = 52723 //Heals the caster for half the damage dealt by a melee attack. -}; - -enum Yells -{ - SAY_INTRO_1 = -1595009, - SAY_INTRO_2 = -1595010, - SAY_AGGRO = -1595011, - SAY_KILL_1 = -1595012, - SAY_KILL_2 = -1595013, - SAY_KILL_3 = -1595014, - SAY_SLAY_1 = -1595015, - SAY_SLAY_2 = -1595016, - SAY_SLAY_3 = -1595017, - SAY_SLAY_4 = -1595018, - SAY_SLEEP_1 = -1595019, - SAY_SLEEP_2 = -1595020, - SAY_30HEALTH = -1595021, - SAY_15HEALTH = -1595022, - SAY_ESCAPE_SPEECH_1 = -1595023, - SAY_ESCAPE_SPEECH_2 = -1595024, - SAY_OUTRO = -1595025, -}; - -enum CombatPhases -{ - COMBAT, - OUTRO -}; - -struct boss_mal_ganisAI : public ScriptedAI -{ - boss_mal_ganisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiCarrionSwarmTimer; - uint32 uiMindBlastTimer; - uint32 uiVampiricTouchTimer; - uint32 uiSleepTimer; - - uint8 uiOutroStep; - uint32 uiOutroTimer; - - bool bYelled; - bool bYelled2; - - CombatPhases Phase; - - ScriptedInstance* pInstance; - - void Reset() - { - bYelled = false; - bYelled2 = false; - Phase = COMBAT; - uiCarrionSwarmTimer = 6000; - uiMindBlastTimer = 11000; - uiVampiricTouchTimer = urand(10000,15000); - uiSleepTimer = urand(15000,20000); - uiOutroTimer = 1000; - - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, IN_PROGRESS); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (damage >= me->GetHealth() && done_by != me) - damage = me->GetHealth()-1; - } - - void UpdateAI(const uint32 diff) - { - switch(Phase) - { - case COMBAT: - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!bYelled && HealthBelowPct(30)) - { - DoScriptText(SAY_30HEALTH, me); - bYelled = true; - } - - if (!bYelled2 && HealthBelowPct(15)) - { - DoScriptText(SAY_15HEALTH, me); - bYelled2 = true; - } - - if (HealthBelowPct(1)) - { - //Handle Escape Event: Don't forget to add Player::RewardPlayerAndGroupAtEvent - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE); - uiOutroStep = 1; - Phase = OUTRO; - return; - } - - if (Creature* pArthas = me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0)) - if (pArthas->isDead()) - { - EnterEvadeMode(); - me->DisappearAndDie(); - if (pInstance) - pInstance->SetData(DATA_MAL_GANIS_EVENT, FAIL); - } - - if (uiCarrionSwarmTimer < diff) - { - DoCastVictim(SPELL_CARRION_SWARM); - uiCarrionSwarmTimer = 7000; - } else uiCarrionSwarmTimer -= diff; - - if (uiMindBlastTimer < diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_MIND_BLAST); - uiMindBlastTimer = 6000; - } else uiMindBlastTimer -= diff; - - if (uiVampiricTouchTimer < diff) - { - DoCast(me, SPELL_VAMPIRIC_TOUCH); - uiVampiricTouchTimer = 32000; - } else uiVampiricTouchTimer -= diff; - - if (uiSleepTimer < diff) - { - DoScriptText(RAND(SAY_SLEEP_1,SAY_SLEEP_2), me); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SLEEP); - uiSleepTimer = urand(15000,20000); - } else uiSleepTimer -= diff; - - DoMeleeAttackIfReady(); - break; - case OUTRO: - if (uiOutroTimer < diff) - { - switch(uiOutroStep) - { - case 1: - DoScriptText(SAY_ESCAPE_SPEECH_1, me); - me->GetMotionMaster()->MoveTargetedHome(); - ++uiOutroStep; - uiOutroTimer = 8000; - break; - case 2: - me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance ? pInstance->GetData64(DATA_ARTHAS) : 0); - me->HandleEmoteCommand(29); - DoScriptText(SAY_ESCAPE_SPEECH_2, me); - ++uiOutroStep; - uiOutroTimer = 9000; - break; - case 3: - DoScriptText(SAY_OUTRO, me); - ++uiOutroStep; - uiOutroTimer = 16000; - break; - case 4: - me->HandleEmoteCommand(33); - ++uiOutroStep; - uiOutroTimer = 500; - break; - case 5: - me->SetVisibility(VISIBILITY_OFF); - me->Kill(me); - break; - - } - } else uiOutroTimer -= diff; - break; - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - pInstance->SetData(DATA_MAL_GANIS_EVENT, DONE); - - // give achievement credit to players. criteria use spell 58630 which doesn't exist. - if (pInstance) - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 58630); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } -}; - -CreatureAI* GetAI_boss_mal_ganis(Creature* pCreature) -{ - return new boss_mal_ganisAI (pCreature); -} - -void AddSC_boss_mal_ganis() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_mal_ganis"; - newscript->GetAI = &GetAI_boss_mal_ganis; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp deleted file mode 100644 index eba9733c745..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_meathook.cpp +++ /dev/null @@ -1,140 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss meathook -SDAuthor: Tartalo -SD%Complete: 100 -SDComment: It may need timer adjustment -SDCategory: -Script Data End */ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CONSTRICTING_CHAINS = 52696, //Encases the targets in chains, dealing 1800 Physical damage every 1 sec. and stunning the target for 5 sec. - H_SPELL_CONSTRICTING_CHAINS = 58823, - SPELL_DISEASE_EXPULSION = 52666, //Meathook belches out a cloud of disease, dealing 1710 to 1890 Nature damage and interrupting the spell casting of nearby enemy targets for 4 sec. - H_SPELL_DISEASE_EXPULSION = 58824, - SPELL_FRENZY = 58841 //Increases the caster's Physical damage by 10% for 30 sec. -}; - -enum Yells -{ - SAY_AGGRO = -1595026, - SAY_SLAY_1 = -1595027, - SAY_SLAY_2 = -1595028, - SAY_SLAY_3 = -1595029, - SAY_SPAWN = -1595030, - SAY_DEATH = -1595031 -}; - -struct boss_meathookAI : public ScriptedAI -{ - boss_meathookAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - DoScriptText(SAY_SPAWN,me); - } - - uint32 uiChainTimer; - uint32 uiDiseaseTimer; - uint32 uiFrenzyTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiChainTimer = urand(12000,17000); //seen on video 13, 17, 15, 12, 16 - uiDiseaseTimer = urand(2000,4000); //approx 3s - uiFrenzyTimer = urand(21000,26000); //made it up - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiDiseaseTimer <= diff) - { - DoCastAOE(SPELL_DISEASE_EXPULSION); - uiDiseaseTimer = urand(1500,4000); - } else uiDiseaseTimer -= diff; - - if (uiFrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - uiFrenzyTimer = urand(21000,26000); - } else uiFrenzyTimer -= diff; - - if (uiChainTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CONSTRICTING_CHAINS); //anyone but the tank - uiChainTimer = urand(2000,4000); - } else uiChainTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MEATHOOK_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_meathook(Creature* pCreature) -{ - return new boss_meathookAI (pCreature); -} - -void AddSC_boss_meathook() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_meathook"; - newscript->GetAI = &GetAI_boss_meathook; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp deleted file mode 100644 index da1c8098517..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/boss_salramm.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* Script Data Start -SDName: Boss salramm -SDAuthor: Tartalo -SD%Complete: 80 -SDComment: TODO: Intro -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_salramm' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -enum Spells -{ - SPELL_CURSE_OF_TWISTED_FLESH = 58845, - SPELL_EXPLODE_GHOUL = 52480, - H_SPELL_EXPLODE_GHOUL = 58825, - SPELL_SHADOW_BOLT = 57725, - H_SPELL_SHADOW_BOLT = 58828, - SPELL_STEAL_FLESH = 52708, - SPELL_SUMMON_GHOULS = 52451 -}; - -enum Yells -{ - SAY_AGGRO = -1595032, - SAY_SPAWN = -1595033, - SAY_SLAY_1 = -1595034, - SAY_SLAY_2 = -1595035, - SAY_SLAY_3 = -1595036, - SAY_DEATH = -1595037, - SAY_EXPLODE_GHOUL_1 = -1595038, - SAY_EXPLODE_GHOUL_2 = -1595039, - SAY_STEAL_FLESH_1 = -1595040, - SAY_STEAL_FLESH_2 = -1595041, - SAY_STEAL_FLESH_3 = -1595042, - SAY_SUMMON_GHOULS_1 = -1595043, - SAY_SUMMON_GHOULS_2 = -1595044 -}; - -struct boss_salrammAI : public ScriptedAI -{ - boss_salrammAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - DoScriptText(SAY_SPAWN,me); - } - - uint32 uiCurseFleshTimer; - uint32 uiExplodeGhoulTimer; - uint32 uiShadowBoltTimer; - uint32 uiStealFleshTimer; - uint32 uiSummonGhoulsTimer; - - ScriptedInstance* pInstance; - - void Reset() - { - uiCurseFleshTimer = 30000; //30s DBM - uiExplodeGhoulTimer = urand(25000,28000); //approx 6 sec after summon ghouls - uiShadowBoltTimer = urand(8000,12000); // approx 10s - uiStealFleshTimer = 12345; - uiSummonGhoulsTimer = urand(19000,24000); //on a video approx 24s after aggro - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Curse of twisted flesh timer - if (uiCurseFleshTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CURSE_OF_TWISTED_FLESH); - uiCurseFleshTimer = 37000; - } else uiCurseFleshTimer -= diff; - - //Shadow bolt timer - if (uiShadowBoltTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - uiShadowBoltTimer = urand(8000,12000); - } else uiShadowBoltTimer -= diff; - - //Steal Flesh timer - if (uiStealFleshTimer <= diff) - { - DoScriptText(RAND(SAY_STEAL_FLESH_1,SAY_STEAL_FLESH_2,SAY_STEAL_FLESH_3), me); - if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(random_pTarget, SPELL_STEAL_FLESH); - uiStealFleshTimer = 10000; - } else uiStealFleshTimer -= diff; - - //Summon ghouls timer - if (uiSummonGhoulsTimer <= diff) - { - DoScriptText(RAND(SAY_SUMMON_GHOULS_1,SAY_SUMMON_GHOULS_2), me); - if (Unit* random_pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(random_pTarget, SPELL_SUMMON_GHOULS); - uiSummonGhoulsTimer = 10000; - } else uiSummonGhoulsTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_SALRAMM_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_salramm(Creature* pCreature) -{ - return new boss_salrammAI (pCreature); -} - -void AddSC_boss_salramm() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_salramm"; - newscript->GetAI = &GetAI_boss_salramm; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp deleted file mode 100644 index faaed2eb6db..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.cpp +++ /dev/null @@ -1,1210 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" -#include "ScriptedEscortAI.h" - -enum Says -{ - //First Act - Uther and Jaina Dialog - SAY_PHASE101 = -1595070, //Arthas - SAY_PHASE102 = -1595071, //Uther - SAY_PHASE103 = -1595072, //Arthas - SAY_PHASE104 = -1595073, //Arthas - SAY_PHASE105 = -1595074, //Uther - SAY_PHASE106 = -1595075, //Arthas - SAY_PHASE107 = -1595076, //Uther - SAY_PHASE108 = -1595077, //Arthas - SAY_PHASE109 = -1595078, //Arthas - SAY_PHASE110 = -1595079, //Uther - SAY_PHASE111 = -1595080, //Arthas - SAY_PHASE112 = -1595081, //Uther - SAY_PHASE113 = -1595082, //Jaina - SAY_PHASE114 = -1595083, //Arthas - SAY_PHASE115 = -1595084, //Uther - SAY_PHASE116 = -1595085, //Arthas - SAY_PHASE117 = -1595086, //Jaina - SAY_PHASE118 = -1595087, //Arthas - //Second Act - City Streets - SAY_PHASE201 = -1595088, //Arthas - SAY_PHASE202 = -1595089, //Cityman - SAY_PHASE203 = -1595090, //Arthas - SAY_PHASE204 = -1595091, //Crazyman - SAY_PHASE205 = -1595092, //Arthas - SAY_PHASE206 = -1595009, //Malganis - SAY_PHASE207 = -1595010, //Malganis - SAY_PHASE208 = -1595093, //Arthas - SAY_PHASE209 = -1595094, //Arthas - SAY_PHASE210 = -1595095, //Arthas - //Third Act - Town Hall - SAY_PHASE301 = -1595096, //Arthas - SAY_PHASE302 = -1595097, //Drakonian - SAY_PHASE303 = -1595098, //Arthas - SAY_PHASE304 = -1595099, //Arthas - SAY_PHASE305 = -1595100, //Drakonian - SAY_PHASE306 = -1595101, //Arthas - SAY_PHASE307 = -1595102, //Arthas - SAY_PHASE308 = -1595103, //Arthas - SAY_PHASE309 = -1595104, //Arthas - SAY_PHASE310 = -1595105, //Arthas - SAY_PHASE311 = -1595106, //Arthas - SAY_PHASE312 = -1595107, //Arthas - SAY_PHASE313 = -1595108, //Arthas - SAY_PHASE314 = -1595000, //Epoch - SAY_PHASE315 = -1595109, //Arthas - //Fourth Act - Fire Corridor - SAY_PHASE401 = -1595110, //Arthas - SAY_PHASE402 = -1595111, //Arthas - SAY_PHASE403 = -1595112, //Arthas - SAY_PHASE404 = -1595113, //Arthas - SAY_PHASE405 = -1595114, //Arthas - SAY_PHASE406 = -1595115, //Arthas - SAY_PHASE407 = -1595116, //Arthas - //Fifth Act - Mal'Ganis Fight - SAY_PHASE501 = -1595117, //Arthas - SAY_PHASE502 = -1595118, //Arthas - SAY_PHASE503 = -1595119, //Arthas - SAY_PHASE504 = -1595120, //Arthas -}; - -enum NPCs -{ - NPC_INFINITE_ADVERSARY = 27742, - NPC_INFINITE_HUNTER = 27743, - NPC_INFINITE_AGENT = 27744, - NPC_TIME_RIFT = 28409, - NPC_ZOMBIE = 27737, - NPC_GHOUL = 28249, - NPC_NECROMANCER = 28200, - NPC_STALKER = 28199, - NPC_FIEND = 27734, - NPC_GOLEM = 28201, - NPC_EGHOUL = 27729, - NPC_CONSTRUCT = 27736, - - NPC_INVIS_TARGET = 20562, - - NPC_KNIGHT_ESCORT = 27745, - NPC_PRIEST_ESCORT = 27747, - NPC_CITY_MAN = 28167, - NPC_CITY_MAN2 = 28169, - NPC_CITY_MAN3 = 31126, - NPC_CITY_MAN4 = 31127, -}; - -enum Spells -{ - SPELL_FEAR = 39176, - SPELL_ARTHAS_AURA = 52442, - SPELL_EXORCISM_N = 52445, - SPELL_EXORCISM_H = 58822, - SPELL_HOLY_LIGHT = 52444, -}; - -enum GossipMenuArthas -{ - GOSSIP_MENU_ARTHAS_1 = 100001, - GOSSIP_MENU_ARTHAS_2 = 100002, - GOSSIP_MENU_ARTHAS_3 = 100003, - GOSSIP_MENU_ARTHAS_4 = 100004, - GOSSIP_MENU_ARTHAS_5 = 100005 -}; - -enum -{ - ENCOUNTER_WAVES_NUMBER = 8, - ENCOUNTER_WAVES_MAX_SPAWNS = 5, - ENCOUNTER_DRACONIAN_NUMBER = 4, - ENCOUNTER_CHRONO_SPAWNS = 19 -}; - -// Locations for necromancers and add to spawn -float WavesLocations[ENCOUNTER_WAVES_NUMBER][ENCOUNTER_WAVES_MAX_SPAWNS][5]= -{ - { - {NPC_ZOMBIE, 2164.698975, 1255.392944, 135.040878, 0.490202}, - {NPC_ZOMBIE, 2183.501465, 1263.079102, 134.859055, 3.169981}, - {NPC_GHOUL, 2177.512939, 1247.313843, 135.846695, 1.696574}, - {NPC_GHOUL, 2171.991943, 1246.615845, 135.745026, 1.696574}, - {0, 0, 0, 0, 0} - }, - { - {NPC_GHOUL, 2254.434326, 1163.427612, 138.055038, 2.077358}, - {NPC_GHOUL, 2254.703613, 1158.867798, 138.212234, 2.345532}, - {NPC_GHOUL, 2257.615723, 1162.310913, 138.091202, 2.077358}, - {NPC_NECROMANCER, 2258.258057, 1157.250732, 138.272873, 2.387766}, - {0, 0, 0, 0, 0} - }, - { - {NPC_STALKER, 2348.120117, 1202.302490, 130.491104, 4.698538}, - {NPC_GHOUL, 2352.863525, 1207.819092, 130.424271, 4.949865}, - {NPC_GHOUL, 2343.593750, 1207.915039, 130.781311, 4.321547}, - {NPC_NECROMANCER, 2348.257324, 1212.202515, 130.670135, 4.450352}, - {0, 0, 0, 0, 0} - }, - { - {NPC_STALKER, 2139.825195, 1356.277100, 132.199615, 5.820131}, - {NPC_GHOUL, 2137.073486, 1362.464844, 132.271637, 5.820131}, - {NPC_GHOUL, 2134.075684, 1354.148071, 131.885864, 5.820131}, - {NPC_NECROMANCER, 2133.302246, 1358.907837, 132.037689, 5.820131}, - {0, 0, 0, 0, 0} - }, - { - {NPC_NECROMANCER, 2264.013428, 1174.055908, 138.093094, 2.860481}, - {NPC_GHOUL, 2264.207764, 1170.892700, 138.034973, 2.860481}, - {NPC_GHOUL, 2266.948975, 1176.898926, 137.976929, 2.860481}, - {NPC_STALKER, 2269.215576, 1170.109253, 137.742691, 2.860481}, - {NPC_FIEND, 2273.106689, 1176.101074, 137.880508, 2.860481} - }, - { - {NPC_GOLEM, 2349.701660, 1188.436646, 130.428864, 3.908642}, - {NPC_GHOUL, 2349.909180, 1194.582642, 130.417816, 3.577001}, - {NPC_EGHOUL, 2354.662598, 1185.692017, 130.552032, 3.577001}, - {NPC_EGHOUL, 2354.716797, 1191.614380, 130.539810, 3.577001}, - {0, 0, 0, 0, 0} - }, - { - {NPC_CONSTRUCT, 2145.212891, 1355.288086, 132.288773, 6.004838}, - {NPC_NECROMANCER, 2137.078613, 1357.612671, 132.173340, 6.004838}, - {NPC_EGHOUL, 2139.402100, 1352.541626, 132.127518, 5.812850}, - {NPC_EGHOUL, 2142.408447, 1360.760620, 132.321564, 5.812850}, - {0, 0, 0, 0, 0} - }, - { - {NPC_GHOUL, 2172.686279, 1259.618164, 134.391754, 1.865499}, - {NPC_FIEND, 2177.649170, 1256.061157, 135.096512, 1.849572}, - {NPC_CONSTRUCT, 2170.782959, 1253.594849, 134.973022, 1.849572}, - {NPC_NECROMANCER, 2175.595703, 1249.041992, 135.603531, 1.849572}, - {0, 0, 0, 0, 0} - } -}; - -// Locations for rifts to spawn and draconians to go -float RiftAndSpawnsLocations[ENCOUNTER_CHRONO_SPAWNS][5]= -{ - {NPC_TIME_RIFT, 2431.790039, 1190.670044, 148.076004, 0.187923}, - {NPC_INFINITE_ADVERSARY, 2433.857910, 1185.612061, 148.075974, 4.566168}, - {NPC_INFINITE_ADVERSARY, 2437.577881, 1188.241089, 148.075974, 0.196999}, - {NPC_INFINITE_AGENT, 2437.165527, 1192.294922, 148.075974, 0.169247}, - {NPC_INFINITE_HUNTER, 2434.989990, 1197.679565, 148.075974, 0.715971}, - {NPC_TIME_RIFT, 2403.954834, 1178.815430, 148.075943, 4.966126}, - {NPC_INFINITE_AGENT, 2403.676758, 1171.495850, 148.075607, 4.902797}, - {NPC_INFINITE_HUNTER, 2407.691162, 1172.162720, 148.075607, 4.963010}, - {NPC_TIME_RIFT, 2414.217041, 1133.446167, 148.076050, 1.706972}, - {NPC_INFINITE_ADVERSARY, 2416.024658, 1139.456177, 148.076431, 1.752129}, - {NPC_INFINITE_HUNTER, 2410.866699, 1139.680542, 148.076431, 1.752129}, - {NPC_TIME_RIFT, 2433.081543, 1099.869751, 148.076157, 1.809509}, - {NPC_INFINITE_ADVERSARY, 2426.947998, 1107.471680, 148.076019, 1.877580}, - {NPC_INFINITE_HUNTER, 2432.944580, 1108.896362, 148.208160, 2.199241}, - {NPC_TIME_RIFT, 2444.077637, 1114.366089, 148.076157, 3.049565}, - {NPC_INFINITE_ADVERSARY, 2438.190674, 1118.368164, 148.076172, 3.139232}, - {NPC_INFINITE_AGENT, 2435.861328, 1113.402954, 148.169327, 2.390271}, - {NPC_TIME_RIFT, 2463.131592, 1115.391724, 152.473129, 3.409651}, - {NPC_EPOCH, 2451.809326, 1112.901245, 149.220459, 3.363617} -}; - -struct npc_arthasAI : public npc_escortAI -{ - npc_arthasAI(Creature *pCreature) : npc_escortAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - Reset(); - } - - ScriptedInstance* pInstance; - - bool bStepping; - uint32 uiStep; - uint32 uiPhaseTimer; - uint32 uiGossipStep; - uint32 uiPlayerFaction; - uint32 uiBossEvent; - uint32 uiWave; - - uint64 uiUtherGUID; - uint64 uiJainaGUID; - uint64 uiCitymenGUID[2]; - uint64 uiWaveGUID[ENCOUNTER_WAVES_MAX_SPAWNS]; - uint64 uiInfiniteDraconianGUID[ENCOUNTER_DRACONIAN_NUMBER]; - uint64 uiStalkerGUID; - - uint64 uiBossGUID; //uiMeathookGUID || uiSalrammGUID - uint64 uiEpochGUID; - uint64 uiMalganisGUID; - uint64 uiInfiniteGUID; - - uint32 uiExorcismTimer; - - void Reset() - { - uiUtherGUID = 0; - uiJainaGUID = 0; - - for (uint8 i = 0; i < 2; ++i) - uiCitymenGUID[i] = 0; - - for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - uiWaveGUID[i] = 0; - - for (uint8 i = 0; i < ENCOUNTER_DRACONIAN_NUMBER; ++i) - uiInfiniteDraconianGUID[i] = 0; - - uiStalkerGUID = 0; - uiBossGUID = 0; - uiEpochGUID = 0; - uiMalganisGUID = 0; - uiInfiniteGUID = 0; - - if (pInstance) { - pInstance->SetData(DATA_ARTHAS_EVENT, NOT_STARTED); - switch(pInstance->GetData(DATA_ARTHAS_EVENT)) - { - case NOT_STARTED: - bStepping = true; - uiStep = 0; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - uiBossEvent = DATA_MEATHOOK_EVENT; - uiGossipStep = 0; - break; - } - uiPhaseTimer = 1000; - uiExorcismTimer = 7300; - uiWave = 0; - } - } - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_ARTHAS_AURA); - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_ARTHAS_EVENT, FAIL); - } - - void SpawnTimeRift(uint32 timeRiftID, uint64* guidVector) - { - me->SummonCreature((uint32)RiftAndSpawnsLocations[timeRiftID][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_DESPAWN,11000); - - for (uint32 i = timeRiftID+1; i < ENCOUNTER_CHRONO_SPAWNS; ++i) - { - if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_TIME_RIFT) break; - if (Creature* pTemp = me->SummonCreature((uint32)RiftAndSpawnsLocations[i][0],RiftAndSpawnsLocations[timeRiftID][1],RiftAndSpawnsLocations[timeRiftID][2],RiftAndSpawnsLocations[timeRiftID][3],RiftAndSpawnsLocations[timeRiftID][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - guidVector[i-timeRiftID-1] = pTemp->GetGUID(); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pTemp->SetReactState(REACT_PASSIVE); - pTemp->GetMotionMaster()->MovePoint(0, RiftAndSpawnsLocations[i][1],RiftAndSpawnsLocations[i][2],RiftAndSpawnsLocations[i][3]); - if ((uint32)RiftAndSpawnsLocations[i][0] == NPC_EPOCH) - uiEpochGUID = pTemp->GetGUID(); - } - } - } - - void SpawnWaveGroup(uint32 waveID, uint64* guidVector) - { - for (uint32 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - { - if ((uint32)WavesLocations[waveID][i][0] == 0) break; - if (Creature* pTemp = me->SummonCreature((uint32)WavesLocations[waveID][i][0],WavesLocations[waveID][i][1],WavesLocations[waveID][i][2],WavesLocations[waveID][i][3],WavesLocations[waveID][i][4],TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - guidVector[i] = pTemp->GetGUID(); - } - } - } - - void SetHoldState(bool bOnHold) - { - SetEscortPaused(bOnHold); - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhaseTimer = uiTimer; - ++uiStep; - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 0: - case 1: - case 3: - case 9: - case 10: - case 11: - case 22: - case 23: - case 26: - case 55: - case 56: - SetHoldState(true); - bStepping = true; - break; - case 7: - if (Unit* pCityman0 = me->SummonCreature(NPC_CITY_MAN,2091.977f,1275.021f,140.757f,0.558f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) - uiCitymenGUID[0] = pCityman0->GetGUID(); - if (Unit* pCityman1 = me->SummonCreature(NPC_CITY_MAN2,2093.514f,1275.842f,140.408f,3.801f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000)) - uiCitymenGUID[1] = pCityman1->GetGUID(); - break; - case 8: - uiGossipStep = 1; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - case 12: - SetRun(true); - DoScriptText(SAY_PHASE210, me); - if (Unit* pDisguised0 = me->SummonCreature(NPC_CITY_MAN3,2398.14f,1207.81f,134.04f,5.155249f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[0] = pDisguised0->GetGUID(); - if (Unit* pDisguised1 = me->SummonCreature(NPC_CITY_MAN4,2403.22f,1205.54f,134.04f,3.311264f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[1] = pDisguised1->GetGUID(); - - if (Unit* pDisguised2 = me->SummonCreature(NPC_CITY_MAN,2400.82f,1201.69f,134.01f,1.534082f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiInfiniteDraconianGUID[2] = pDisguised2->GetGUID(); - pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); - pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[0]); - pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, uiInfiniteDraconianGUID[1]); - } - } - } - break; - case 20: - uiGossipStep = 2; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetRun(false); - SetHoldState(true); - break; - case 21: - DoScriptText(SAY_PHASE301, me); - break; - case 25: - SetRun(false); - SpawnTimeRift(0,&uiInfiniteDraconianGUID[0]); - DoScriptText(SAY_PHASE307,me); - break; - case 29: - SetRun(false); - SpawnTimeRift(5,&uiInfiniteDraconianGUID[0]); - SpawnTimeRift(8,&uiInfiniteDraconianGUID[2]); - DoScriptText(SAY_PHASE309,me); - SetHoldState(true); - bStepping = true; - break; - case 31: - SetRun(false); - SpawnTimeRift(11,&uiInfiniteDraconianGUID[0]); - SpawnTimeRift(14,&uiInfiniteDraconianGUID[2]); - DoScriptText(SAY_PHASE311,me); - SetHoldState(true); - bStepping = true; - break; - case 32: - DoScriptText(SAY_PHASE401,me); - break; - case 34: - DoScriptText(SAY_PHASE402,me); - break; - case 35: - DoScriptText(SAY_PHASE403,me); - break; - case 36: - if (pInstance) - { - GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SHKAF_GATE)); - pGate->SetGoState(GO_STATE_ACTIVE); - } - break; - case 45: - SetRun(true); - SetDespawnAtFar(false); - uiGossipStep = 4; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - case 47: - SetRun(false); - DoScriptText(SAY_PHASE405,me); - break; - case 48: - SetRun(true); - DoScriptText(SAY_PHASE406,me); - break; - case 53: - DoScriptText(SAY_PHASE407,me); - break; - case 54: - uiGossipStep = 5; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetHoldState(true); - break; - } - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - DoMeleeAttackIfReady(); - - if (bStepping) - { - if (uiPhaseTimer <= diff) - { - switch(uiStep) - { - //After reset - case 0: - if (Unit* pJaina = GetClosestCreatureWithEntry(me, NPC_JAINA, 50.0f)) - uiJainaGUID = pJaina->GetGUID(); - else if (Unit* pJaina = me->SummonCreature(NPC_JAINA,1895.48f,1292.66f,143.706f,0.023475f,TEMPSUMMON_DEAD_DESPAWN,180000)) - uiJainaGUID = pJaina->GetGUID(); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 0 - case 1: - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - if (Unit* pUther = me->SummonCreature(NPC_UTHER,1794.357f,1272.183f,140.558f,1.37f,TEMPSUMMON_DEAD_DESPAWN,180000)) - { - uiUtherGUID = pUther->GetGUID(); - pUther->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pUther->GetMotionMaster()->MovePoint(0, 1897.018f, 1287.487f, 143.481f); - pUther->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiUtherGUID); - } - JumpToNextStep(17000); - break; - case 2: - DoScriptText(SAY_PHASE101, me); - JumpToNextStep(2000); - break; - case 3: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - { - DoScriptText(SAY_PHASE102, pUther); - } - JumpToNextStep(8000); - break; - case 4: - SetEscortPaused(false); - bStepping = false; - SetRun(false); - DoScriptText(SAY_PHASE103, me); - JumpToNextStep(0); - break; - //After waypoint 1 - case 5: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - pJaina->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - DoScriptText(SAY_PHASE104, me); - JumpToNextStep(10000); - break; - case 6: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE105, pUther); - JumpToNextStep(1000); - break; - case 7: - DoScriptText(SAY_PHASE106, me); - JumpToNextStep(4000); - break; - case 8: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE107, pUther); - JumpToNextStep(6000); - break; - case 9: - DoScriptText(SAY_PHASE108, me); - JumpToNextStep(4000); - break; - case 10: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE109, pUther); - JumpToNextStep(8000); - break; - case 11: - DoScriptText(SAY_PHASE110, me); - JumpToNextStep(4000); - break; - case 12: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE111, pUther); - JumpToNextStep(4000); - break; - case 13: - DoScriptText(SAY_PHASE112, me); - JumpToNextStep(11000); - break; - case 14: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - DoScriptText(SAY_PHASE113, pJaina); - JumpToNextStep(3000); - break; - case 15: - DoScriptText(SAY_PHASE114, me); - JumpToNextStep(9000); - break; - case 16: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - DoScriptText(SAY_PHASE115, pUther); - JumpToNextStep(4000); - break; - case 17: - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - { - pUther->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pUther->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); - } - JumpToNextStep(1000); - break; - case 18: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - { - me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); - pJaina->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pJaina->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); - } - JumpToNextStep(1000); - break; - case 19: - DoScriptText(SAY_PHASE116, me); - JumpToNextStep(1000); - break; - case 20: - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - DoScriptText(SAY_PHASE117, pJaina); - JumpToNextStep(3000); - break; - case 21: - SetEscortPaused(false); - bStepping = false; - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After waypoint 3 - case 22: - DoScriptText(SAY_PHASE118, me); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiJainaGUID); - JumpToNextStep(10000); - break; - case 23: - SetEscortPaused(false); - bStepping = false; - SetRun(true); - - if (Creature* pJaina = Unit::GetCreature(*me, uiJainaGUID)) - pJaina->DisappearAndDie(); - - if (Creature* pUther = Unit::GetCreature(*me, uiUtherGUID)) - pUther->DisappearAndDie(); - - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After Gossip 1 (waypoint 8) - case 24: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2026.469f,1287.088f,143.596f,1.37f,TEMPSUMMON_TIMED_DESPAWN,14000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - JumpToNextStep(1000); - break; - case 25: - DoScriptText(SAY_PHASE201, me); - JumpToNextStep(12000); - break; - case 26: - SetEscortPaused(false); - bStepping = false; - SetRun(false); - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - JumpToNextStep(0); - break; - //After waypoint 9 - case 27: - me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[0]); - if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) - { - pCityman->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - pCityman->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pCityman->GetMotionMaster()->MovePoint(0, 2088.625f,1279.191f,140.743f); - } - JumpToNextStep(2000); - break; - case 28: - if (Creature* pCityman = Unit::GetCreature(*me, uiCitymenGUID[0])) - DoScriptText(SAY_PHASE202, pCityman); - JumpToNextStep(4000); - break; - case 29: - SetEscortPaused(false); - bStepping = false; - DoScriptText(SAY_PHASE203, me); - JumpToNextStep(0); - break; - //After waypoint 10 - case 30: - me->HandleEmoteCommand(37); - JumpToNextStep(1000); - break; - case 31: - SetEscortPaused(false); - bStepping = false; - if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) - { - DoScriptText(SAY_PHASE204, pCityman1); - pCityman1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pCityman0 = Unit::GetCreature(*me, uiCitymenGUID[0])) - pCityman0->Kill(pCityman0); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiCitymenGUID[1]); - } - JumpToNextStep(0); - break; - //After waypoint 11 - case 32: - me->HandleEmoteCommand(37); - JumpToNextStep(1000); - break; - case 33: - if (Creature* pCityman1 = Unit::GetCreature(*me, uiCitymenGUID[1])) - pCityman1->Kill(pCityman1); - JumpToNextStep(1000); - break; - case 34: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - DoScriptText(SAY_PHASE205, me); - JumpToNextStep(3000); - break; - case 35: - if (Unit* pStalkerM = me->SummonCreature(NPC_INVIS_TARGET,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) - { - uiStalkerGUID = pStalkerM->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - JumpToNextStep(1000); - break; - case 36: - if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) - { - if (Creature* pStalkerM = Unit::GetCreature(*me, uiStalkerGUID)) - pMalganis->CastSpell(pStalkerM,63793,false); - - uiMalganisGUID = pMalganis->GetGUID(); - DoScriptText(SAY_PHASE206, pMalganis); - pMalganis->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - pMalganis->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(11000); - break; - case 37: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - { - if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN, 100.0f)) - pZombie->UpdateEntry(NPC_ZOMBIE, 0); - else if (Creature* pZombie = GetClosestCreatureWithEntry(pMalganis, NPC_CITY_MAN2, 100.0f)) - pZombie->UpdateEntry(NPC_ZOMBIE, 0); - else //There's no one else to transform - uiStep++; - } - else - uiStep++; - uiPhaseTimer = 500; - break; - case 38: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - DoScriptText(SAY_PHASE207, pMalganis); - JumpToNextStep(17000); - break; - case 39: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - pMalganis->SetVisibility(VISIBILITY_OFF); - DoScriptText(SAY_PHASE208, me); - JumpToNextStep(7000); - break; - case 40: - if (Unit* pStalker = me->SummonCreature(NPC_INVIS_TARGET,2081.447f,1287.770f,141.3241f,1.37f,TEMPSUMMON_TIMED_DESPAWN,10000)) - { - uiStalkerGUID = pStalker->GetGUID(); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiStalkerGUID); - } - DoScriptText(SAY_PHASE209, me); - - uiBossEvent = DATA_MEATHOOK_EVENT; - if (pInstance) - pInstance->SetData(DATA_ARTHAS_EVENT, IN_PROGRESS); - - me->SetReactState(REACT_DEFENSIVE); - SetDespawnAtFar(false); - JumpToNextStep(5000); - break; - case 41: //Summon wave group - case 43: - case 45: - case 47: - case 51: - case 53: - case 55: - case 57: - if (pInstance->GetData(uiBossEvent) != DONE) - { - SpawnWaveGroup(uiWave, uiWaveGUID); - uiWave++; - } - JumpToNextStep(500); - break; - case 42: //Wait group to die - case 44: - case 46: - case 48: - case 52: - case 54: - case 56: - case 58: - if (pInstance->GetData(uiBossEvent) != DONE) - { - uint32 mobCounter = 0; - uint32 deadCounter = 0; - for (uint8 i = 0; i < ENCOUNTER_WAVES_MAX_SPAWNS; ++i) - { - if (uiWaveGUID[i] == 0) - break; - ++mobCounter; - Unit* pTemp = Unit::GetCreature(*me, uiWaveGUID[i]); - if (!pTemp || pTemp->isDead()) - ++deadCounter; - } - - if (mobCounter <= deadCounter) //If group is dead - JumpToNextStep(1000); - else - uiPhaseTimer = 1000; - } - else - JumpToNextStep(500); - break; - case 49: //Summon Boss - case 59: - if (pInstance->GetData(uiBossEvent) != DONE) - { - uint32 uiBossID = 0; - if (uiBossEvent == DATA_MEATHOOK_EVENT) - uiBossID = NPC_MEATHOOK; - else if (uiBossEvent == DATA_SALRAMM_EVENT) - uiBossID = NPC_SALRAMM; - - if (Unit* pBoss = me->SummonCreature(uiBossID,2232.19f,1331.933f,126.662f,3.15f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - uiBossGUID = pBoss->GetGUID(); - pBoss->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pBoss->GetMotionMaster()->MovePoint(0, 2194.110f,1332.00f,130.00f); - } - } - JumpToNextStep(30000); - break; - case 50: //Wait Boss death - case 60: - if (pInstance) - { - if (pInstance->GetData(uiBossEvent) == DONE) - { - JumpToNextStep(1000); - if (uiBossEvent == DATA_MEATHOOK_EVENT) - uiBossEvent = DATA_SALRAMM_EVENT; - else if (uiBossEvent == DATA_SALRAMM_EVENT) - { - SetHoldState(false); - bStepping = false; - uiBossEvent = DATA_EPOCH_EVENT; - } - } - else if (pInstance->GetData(uiBossEvent) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After Gossip 2 (waypoint 22) - case 61: - me->SetReactState(REACT_AGGRESSIVE); - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - pDisguised0->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) - pDisguised1->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) - pDisguised2->SetUInt64Value(UNIT_FIELD_TARGET, me->GetGUID()); - JumpToNextStep(1000); - break; - case 62: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - DoScriptText(SAY_PHASE302, pDisguised0); - JumpToNextStep(7000); - break; - case 63: - DoScriptText(SAY_PHASE303, me); - SetHoldState(false); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 23 - case 64: - me->HandleEmoteCommand(54); - JumpToNextStep(1000); - break; - case 65: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - pDisguised0->HandleEmoteCommand(11); - JumpToNextStep(1000); - break; - case 66: - DoScriptText(SAY_PHASE304,me); - JumpToNextStep(2000); - break; - case 67: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - DoScriptText(SAY_PHASE305,pDisguised0); - JumpToNextStep(1000); - break; - case 68: - if (Creature* pDisguised2 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[2])) - { - pDisguised2->UpdateEntry(NPC_INFINITE_HUNTER, 0); - //Make them unattackable - pDisguised2->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised2->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 69: - if (Creature* pDisguised1 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[1])) - { - pDisguised1->UpdateEntry(NPC_INFINITE_AGENT, 0); - //Make them unattackable - pDisguised1->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised1->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 70: - if (Creature* pDisguised0 = Unit::GetCreature(*me, uiInfiniteDraconianGUID[0])) - { - pDisguised0->UpdateEntry(NPC_INFINITE_ADVERSARY, 0); - //Make them unattackable - pDisguised0->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pDisguised0->SetReactState(REACT_PASSIVE); - } - JumpToNextStep(2000); - break; - case 71: - //After waypoint 26,29,31 - case 73: - case 75: - case 77: - //Make cratures attackable - for (uint32 i = 0; i< ENCOUNTER_DRACONIAN_NUMBER; ++i) - if (Creature* pTemp = Unit::GetCreature(*me, uiInfiniteDraconianGUID[i])) - { - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pTemp->SetReactState(REACT_AGGRESSIVE); - } - JumpToNextStep(5000); - break; - case 72: - case 74: - case 76: - if (me->isInCombat()) - uiPhaseTimer = 1000; - else - { - if (uiStep == 72) DoScriptText(SAY_PHASE308,me); - if (uiStep == 74) DoScriptText(SAY_PHASE308,me); - if (uiStep == 76) DoScriptText(SAY_PHASE310,me); - SetHoldState(false); - bStepping = false; - SetRun(true); - JumpToNextStep(2000); - } - break; - case 78: - if (me->isInCombat()) - uiPhaseTimer = 1000; - else - { - DoScriptText(SAY_PHASE312,me); - JumpToNextStep(5000); - } - break; - case 79: - DoScriptText(SAY_PHASE313,me); - JumpToNextStep(1000); - break; - case 80: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - { - SpawnTimeRift(17,&uiEpochGUID); - if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) - DoScriptText(SAY_PHASE314,pEpoch); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiEpochGUID); - } - JumpToNextStep(18000); - break; - case 81: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - DoScriptText(SAY_PHASE315, me); - JumpToNextStep(6000); - break; - case 82: - if (pInstance) - if (pInstance->GetData(DATA_EPOCH_EVENT) != DONE) - { - if (Creature* pEpoch = Unit::GetCreature(*me, uiEpochGUID)) - { - //Make Epoch attackable - pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_9); - pEpoch->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pEpoch->SetReactState(REACT_AGGRESSIVE); - } - - } - JumpToNextStep(1000); - break; - case 83: - if (pInstance) - { - if (pInstance->GetData(DATA_EPOCH_EVENT) == DONE) - { - uiGossipStep = 3; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - bStepping = false; - uiBossEvent = DATA_MAL_GANIS_EVENT; - JumpToNextStep(15000); - } - else if (pInstance->GetData(DATA_EPOCH_EVENT) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After Gossip 4 - case 84: - DoScriptText(SAY_PHASE404,me); - SetHoldState(false); - bStepping = false; - break; - //After Gossip 5 - case 85: - DoScriptText(SAY_PHASE501, me); - if (Creature* pMalganis = me->SummonCreature(NPC_MAL_GANIS,2296.665f,1502.362f,128.362f,4.961f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) - { - uiMalganisGUID = pMalganis->GetGUID(); - pMalganis->SetReactState(REACT_PASSIVE); - } - if (pInstance) - { - GameObject* pGate = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAL_GANIS_GATE_1)); - pGate->SetGoState(GO_STATE_ACTIVE); - } - SetHoldState(false); - bStepping = false; - JumpToNextStep(0); - break; - //After waypoint 55 - case 86: - DoScriptText(SAY_PHASE502, me); - JumpToNextStep(6000); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); - break; - case 87: - if (Creature* pMalganis = Unit::GetCreature(*me, uiMalganisGUID)) - { - pMalganis->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE | UNIT_FLAG_UNK_6 | UNIT_FLAG_UNK_9 | UNIT_FLAG_UNK_15); - pMalganis->SetReactState(REACT_AGGRESSIVE); - } - JumpToNextStep(1000); - break; - case 88: - if (pInstance) - { - if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == DONE) - { - SetHoldState(false); - JumpToNextStep(1000); - } - else if (pInstance->GetData(DATA_MAL_GANIS_EVENT) == FAIL) - npc_escortAI::EnterEvadeMode(); - else - uiPhaseTimer = 10000; - } - break; - //After waypoint 56 - case 89: - SetRun(true); - me->SetUInt64Value(UNIT_FIELD_TARGET, uiMalganisGUID); - DoScriptText(SAY_PHASE503, me); - JumpToNextStep(7000); - break; - case 90: - if (pInstance) - { - pInstance->SetData(DATA_ARTHAS_EVENT, DONE); //Rewards: Achiev & Chest ;D - me->SetUInt64Value(UNIT_FIELD_TARGET, pInstance->GetData64(DATA_MAL_GANIS_GATE_2)); //Look behind - } - DoScriptText(SAY_PHASE504, me); - bStepping = false; - break; - } - } else uiPhaseTimer -= diff; - } - - //Battling skills - if (!me->getVictim()) - return; - - if (uiExorcismTimer < diff) - { - if (Unit* target = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(target, SPELL_EXORCISM_N); - uiExorcismTimer = 7300; - } else uiExorcismTimer -= diff; - - if (HealthBelowPct(40)) - DoCast(me, SPELL_HOLY_LIGHT); - } -}; - -CreatureAI* GetAI_npc_arthas(Creature* pCreature) -{ - return new npc_arthasAI(pCreature); -} - -#define GOSSIP_ITEM_ARTHAS_0 "I'm ready to start Culling of Stratholme." -#define GOSSIP_ITEM_ARTHAS_1 "Yes, my Prince. We're ready." -#define GOSSIP_ITEM_ARTHAS_2 "We're only doing what is best for Loarderon your Highness." -#define GOSSIP_ITEM_ARTHAS_3 "I'm ready." -#define GOSSIP_ITEM_ARTHAS_4 "For Lordaeron!" -#define GOSSIP_ITEM_ARTHAS_5 "I'm ready to battle the dreadlord, sire." - -bool GossipHello_npc_arthas(Player* pPlayer, Creature* pCreature) -{ - npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); - - if (pAI && pAI->bStepping == false) - { - switch (pAI->uiGossipStep) - { - case 0: //This one is a workaround since the very beggining of the script is wrong. - if (pPlayer->GetQuestStatus(13149) != QUEST_STATUS_COMPLETE) - return false; - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_0, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - break; - case 1: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_1, pCreature->GetGUID()); - break; - case 2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_2, pCreature->GetGUID()); - break; - case 3: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_3, pCreature->GetGUID()); - break; - case 4: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_4, pCreature->GetGUID()); - break; - case 5: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_5, pCreature->GetGUID()); - break; - default: - return false; - } - } - return true; -} - - -bool GossipSelect_npc_arthas(Player *pPlayer, Creature *pCreature, uint32 /*sender*/, uint32 action) -{ - npc_arthasAI* pAI = CAST_AI(npc_arthasAI,pCreature->AI()); - - if (!pAI) - return false; - - switch (action) - { - case GOSSIP_ACTION_INFO_DEF: - pAI->Start(true,true,pPlayer->GetGUID(),0,false,false); - pAI->SetDespawnAtEnd(false); - pAI->bStepping = false; - pAI->uiStep = 1; - break; - case GOSSIP_ACTION_INFO_DEF+1: - pAI->bStepping = true; - pAI->uiStep = 24; - break; - case GOSSIP_ACTION_INFO_DEF+2: - pAI->SetHoldState(false); - pAI->bStepping = false; - pAI->uiStep = 61; - break; - case GOSSIP_ACTION_INFO_DEF+3: - pAI->SetHoldState(false); - break; - case GOSSIP_ACTION_INFO_DEF+4: - pAI->bStepping = true; - pAI->uiStep = 84; - break; - case GOSSIP_ACTION_INFO_DEF+5: - pAI->bStepping = true; - pAI->uiStep = 85; - break; - } - pPlayer->CLOSE_GOSSIP_MENU(); - pAI->SetDespawnAtFar(true); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - return true; -} - -void AddSC_culling_of_stratholme() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_arthas"; - newscript->GetAI = &GetAI_npc_arthas; - newscript->pGossipHello = &GossipHello_npc_arthas; - newscript->pGossipSelect = &GossipSelect_npc_arthas; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h deleted file mode 100644 index 4278ad46500..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/culling_of_stratholme.h +++ /dev/null @@ -1,68 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef DEF_CULLING_OF_STRATHOLME_H -#define DEF_CULLING_OF_STRATHOLME_H - -enum Data -{ - DATA_MEATHOOK_EVENT, - DATA_SALRAMM_EVENT, - DATA_EPOCH_EVENT, - DATA_MAL_GANIS_EVENT, - DATA_INFINITE_EVENT, - DATA_ARTHAS_EVENT -}; - -enum Data64 -{ - DATA_ARTHAS, - DATA_MEATHOOK, - DATA_SALRAMM, - DATA_EPOCH, - DATA_MAL_GANIS, - DATA_INFINITE, - DATA_SHKAF_GATE, - DATA_MAL_GANIS_GATE_1, - DATA_MAL_GANIS_GATE_2, - DATA_EXIT_GATE, - DATA_MAL_GANIS_CHEST -}; - -enum Creatures -{ - NPC_MEATHOOK = 26529, - NPC_SALRAMM = 26530, - NPC_EPOCH = 26532, - NPC_MAL_GANIS = 26533, - NPC_INFINITE = 32273, - NPC_ARTHAS = 26499, - NPC_JAINA = 26497, - NPC_UTHER = 26528 -}; - -enum GameObjects -{ - GO_SHKAF_GATE = 188686, - GO_MALGANIS_GATE_1 = 187711, - GO_MALGANIS_GATE_2 = 187723, - GO_EXIT_GATE = 191788, - GO_MALGANIS_CHEST_N = 190663, - GO_MALGANIS_CHEST_H = 193597 -}; -#endif diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp deleted file mode 100644 index 73742a1e748..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/culling_of_stratholme/instance_culling_of_stratholme.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/* -* Copyright (C) 2008-2010 Trinity -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "culling_of_stratholme.h" - -#define MAX_ENCOUNTER 5 - -/* Culling of Stratholme encounters: -0 - Meathook -1 - Salramm the Fleshcrafter -2 - Chrono-Lord Epoch -3 - Mal'Ganis -4 - Infinite Corruptor (Heroic only) -*/ - -struct instance_culling_of_stratholme : public ScriptedInstance -{ - instance_culling_of_stratholme(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiArthas; - uint64 uiMeathook; - uint64 uiSalramm; - uint64 uiEpoch; - uint64 uiMalGanis; - uint64 uiInfinite; - - uint64 uiShkafGate; - uint64 uiMalGanisGate1; - uint64 uiMalGanisGate2; - uint64 uiExitGate; - uint64 uiMalGanisChest; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_ARTHAS: - uiArthas = pCreature->GetGUID(); - break; - case NPC_MEATHOOK: - uiMeathook = pCreature->GetGUID(); - break; - case NPC_SALRAMM: - uiSalramm = pCreature->GetGUID(); - break; - case NPC_EPOCH: - uiEpoch = pCreature->GetGUID(); - break; - case NPC_MAL_GANIS: - uiMalGanis = pCreature->GetGUID(); - break; - case NPC_INFINITE: - uiInfinite = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_SHKAF_GATE: - uiShkafGate = pGo->GetGUID(); - break; - case GO_MALGANIS_GATE_1: - uiMalGanisGate1 = pGo->GetGUID(); - break; - case GO_MALGANIS_GATE_2: - uiMalGanisGate2 = pGo->GetGUID(); - break; - case GO_EXIT_GATE: - uiExitGate = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - HandleGameObject(uiExitGate,true); - break; - case GO_MALGANIS_CHEST_N: - case GO_MALGANIS_CHEST_H: - uiMalGanisChest = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MEATHOOK_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_SALRAMM_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_EPOCH_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_MAL_GANIS_EVENT: - m_auiEncounter[3] = data; - - switch(m_auiEncounter[3]) - { - case NOT_STARTED: - HandleGameObject(uiMalGanisGate2,true); - break; - case IN_PROGRESS: - HandleGameObject(uiMalGanisGate2,false); - break; - case DONE: - HandleGameObject(uiExitGate, true); - if (GameObject *pGo = instance->GetGameObject(uiMalGanisChest)) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - } - break; - case DATA_INFINITE_EVENT: - m_auiEncounter[4] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_MEATHOOK_EVENT: return m_auiEncounter[0]; - case DATA_SALRAMM_EVENT: return m_auiEncounter[1]; - case DATA_EPOCH_EVENT: return m_auiEncounter[2]; - case DATA_MAL_GANIS_EVENT: return m_auiEncounter[3]; - case DATA_INFINITE_EVENT: return m_auiEncounter[4]; - } - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_ARTHAS: return uiArthas; - case DATA_MEATHOOK: return uiMeathook; - case DATA_SALRAMM: return uiSalramm; - case DATA_EPOCH: return uiEpoch; - case DATA_MAL_GANIS: return uiMalGanis; - case DATA_INFINITE: return uiInfinite; - case DATA_SHKAF_GATE: return uiShkafGate; - case DATA_MAL_GANIS_GATE_1: return uiMalGanisGate1; - case DATA_MAL_GANIS_GATE_2: return uiMalGanisGate2; - case DATA_EXIT_GATE: return uiExitGate; - case DATA_MAL_GANIS_CHEST: return uiMalGanisChest; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "C S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4; - - if (dataHead1 == 'C' && dataHead2 == 'S') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - m_auiEncounter[4] = data4; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap) -{ - return new instance_culling_of_stratholme(pMap); -} - -void AddSC_instance_culling_of_stratholme() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_culling_of_stratholme"; - newscript->GetInstanceData = &GetInstanceData_instance_culling_of_stratholme; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp deleted file mode 100644 index 49cf7cd4433..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_aeonus.cpp +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Aeonus -SD%Complete: 80 -SDComment: Some spells not implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269012, - SAY_AGGRO = -1269013, - SAY_BANISH = -1269014, - SAY_SLAY1 = -1269015, - SAY_SLAY2 = -1269016, - SAY_DEATH = -1269017, - EMOTE_FRENZY = -1269018, - - SPELL_CLEAVE = 40504, - SPELL_TIME_STOP = 31422, - SPELL_ENRAGE = 37605, - SPELL_SAND_BREATH = 31473, - H_SPELL_SAND_BREATH = 39049 -}; - -struct boss_aeonusAI : public ScriptedAI -{ - boss_aeonusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SandBreath_Timer; - uint32 TimeStop_Timer; - uint32 Frenzy_Timer; - - void Reset() - { - SandBreath_Timer = 15000+rand()%15000; - TimeStop_Timer = 10000+rand()%5000; - Frenzy_Timer = 30000+rand()%15000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(TYPE_RIFT,DONE); - pInstance->SetData(TYPE_MEDIVH,DONE);//FIXME: later should be removed - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sand Breath - if (SandBreath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SAND_BREATH); - SandBreath_Timer = 15000+rand()%10000; - } else SandBreath_Timer -= diff; - - //Time Stop - if (TimeStop_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIME_STOP); - TimeStop_Timer = 20000+rand()%15000; - } else TimeStop_Timer -= diff; - - //Frenzy - if (Frenzy_Timer <= diff) - { - DoScriptText(EMOTE_FRENZY, me); - DoCast(me, SPELL_ENRAGE); - Frenzy_Timer = 20000+rand()%15000; - } else Frenzy_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_aeonus(Creature* pCreature) -{ - return new boss_aeonusAI (pCreature); -} - -void AddSC_boss_aeonus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_aeonus"; - newscript->GetAI = &GetAI_boss_aeonus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp deleted file mode 100644 index 1f2b4a80612..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_chrono_lord_deja.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Chrono_Lord_Deja -SD%Complete: 65 -SDComment: All abilities not implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269006, - SAY_AGGRO = -1269007, - SAY_BANISH = -1269008, - SAY_SLAY1 = -1269009, - SAY_SLAY2 = -1269010, - SAY_DEATH = -1269011, - - SPELL_ARCANE_BLAST = 31457, - H_SPELL_ARCANE_BLAST = 38538, - SPELL_ARCANE_DISCHARGE = 31472, - H_SPELL_ARCANE_DISCHARGE = 38539, - SPELL_TIME_LAPSE = 31467, - SPELL_ATTRACTION = 38540 //Not Implemented (Heroic mode) -}; - -struct boss_chrono_lord_dejaAI : public ScriptedAI -{ - boss_chrono_lord_dejaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 ArcaneBlast_Timer; - uint32 TimeLapse_Timer; - uint32 Attraction_Timer; - uint32 ArcaneDischarge_Timer; - - void Reset() - { - ArcaneBlast_Timer = 18000+rand()%5000; - TimeLapse_Timer = 10000+rand()%5000; - ArcaneDischarge_Timer = 20000+rand()%10000; - Attraction_Timer = 25000+rand()%10000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Arcane Blast - if (ArcaneBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BLAST); - ArcaneBlast_Timer = 15000+rand()%10000; - } else ArcaneBlast_Timer -= diff; - - //Arcane Discharge - if (ArcaneDischarge_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - DoCast(pTarget, SPELL_ARCANE_DISCHARGE); - ArcaneDischarge_Timer = 20000+rand()%10000; - } else ArcaneDischarge_Timer -= diff; - - //Time Lapse - if (TimeLapse_Timer <= diff) - { - DoScriptText(SAY_BANISH, me); - DoCast(me, SPELL_TIME_LAPSE); - TimeLapse_Timer = 15000+rand()%10000; - } else TimeLapse_Timer -= diff; - - if (IsHeroic()) - { - if (Attraction_Timer <= diff) - { - DoCast(me, SPELL_ATTRACTION); - Attraction_Timer = 25000+rand()%10000; - } else Attraction_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_chrono_lord_deja(Creature* pCreature) -{ - return new boss_chrono_lord_dejaAI (pCreature); -} - -void AddSC_boss_chrono_lord_deja() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_chrono_lord_deja"; - newscript->GetAI = &GetAI_boss_chrono_lord_deja; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp deleted file mode 100644 index 04b4b020ead..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/boss_temporus.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Temporus -SD%Complete: 75 -SDComment: More abilities need to be implemented -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -enum eEnums -{ - SAY_ENTER = -1269000, - SAY_AGGRO = -1269001, - SAY_BANISH = -1269002, - SAY_SLAY1 = -1269003, - SAY_SLAY2 = -1269004, - SAY_DEATH = -1269005, - - SPELL_HASTE = 31458, - SPELL_MORTAL_WOUND = 31464, - SPELL_WING_BUFFET = 31475, - H_SPELL_WING_BUFFET = 38593, - SPELL_REFLECT = 38592 //Not Implemented (Heroic mod) -}; - -struct boss_temporusAI : public ScriptedAI -{ - boss_temporusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Haste_Timer; - uint32 SpellReflection_Timer; - uint32 MortalWound_Timer; - uint32 WingBuffet_Timer; - - void Reset() - { - Haste_Timer = 15000+rand()%8000; - SpellReflection_Timer = 30000; - MortalWound_Timer = 8000; - WingBuffet_Timer = 25000+rand()%10000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } - - void MoveInLineOfSight(Unit *who) - { - //Despawn Time Keeper - if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == C_TIME_KEEPER) - { - if (me->IsWithinDistInMap(who,20.0f)) - { - DoScriptText(SAY_BANISH, me); - - me->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Attack Haste - if (Haste_Timer <= diff) - { - DoCast(me, SPELL_HASTE); - Haste_Timer = 20000+rand()%5000; - } else Haste_Timer -= diff; - - //MortalWound_Timer - if (MortalWound_Timer <= diff) - { - DoCast(me, SPELL_MORTAL_WOUND); - MortalWound_Timer = 10000+rand()%10000; - } else MortalWound_Timer -= diff; - - //Wing ruffet - if (WingBuffet_Timer <= diff) - { - DoCast(me, SPELL_WING_BUFFET); - WingBuffet_Timer = 20000+rand()%10000; - } else WingBuffet_Timer -= diff; - - if (IsHeroic()) - { - if (SpellReflection_Timer <= diff) - { - DoCast(me, SPELL_REFLECT); - SpellReflection_Timer = 25000+rand()%10000; - } else SpellReflection_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_temporus(Creature* pCreature) -{ - return new boss_temporusAI (pCreature); -} - -void AddSC_boss_temporus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_temporus"; - newscript->GetAI = &GetAI_boss_temporus; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp deleted file mode 100644 index b0432a9b57c..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Dark_Portal -SD%Complete: 30 -SDComment: Misc NPC's and mobs for instance. Most here far from complete. -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -/* ContentData -npc_medivh_bm -npc_time_rift -npc_saat -EndContentData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -#define SAY_ENTER -1269020 //where does this belong? -#define SAY_INTRO -1269021 -#define SAY_WEAK75 -1269022 -#define SAY_WEAK50 -1269023 -#define SAY_WEAK25 -1269024 -#define SAY_DEATH -1269025 -#define SAY_WIN -1269026 -#define SAY_ORCS_ENTER -1269027 -#define SAY_ORCS_ANSWER -1269028 - -#define SPELL_CHANNEL 31556 -#define SPELL_PORTAL_RUNE 32570 //aura(portal on ground effect) - -#define SPELL_BLACK_CRYSTAL 32563 //aura -#define SPELL_PORTAL_CRYSTAL 32564 //summon - -#define SPELL_BANISH_PURPLE 32566 //aura -#define SPELL_BANISH_GREEN 32567 //aura - -#define SPELL_CORRUPT 31326 -#define SPELL_CORRUPT_AEONUS 37853 - -#define C_COUNCIL_ENFORCER 17023 - -struct npc_medivh_bmAI : public ScriptedAI -{ - npc_medivh_bmAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SpellCorrupt_Timer; - uint32 Check_Timer; - - bool Life75; - bool Life50; - bool Life25; - - void Reset() - { - SpellCorrupt_Timer = 0; - - if (!pInstance) - return; - - if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) - DoCast(me, SPELL_CHANNEL, true); - else if (me->HasAura(SPELL_CHANNEL)) - me->RemoveAura(SPELL_CHANNEL); - - DoCast(me, SPELL_PORTAL_RUNE, true); - } - - void MoveInLineOfSight(Unit *who) - { - if (!pInstance) - return; - - if (who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 10.0f)) - { - if (pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS || pInstance->GetData(TYPE_MEDIVH) == DONE) - return; - - DoScriptText(SAY_INTRO, me); - pInstance->SetData(TYPE_MEDIVH,IN_PROGRESS); - DoCast(me, SPELL_CHANNEL, false); - Check_Timer = 5000; - } - else if (who->GetTypeId() == TYPEID_UNIT && me->IsWithinDistInMap(who, 15.0f)) - { - if (pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) - return; - - uint32 entry = who->GetEntry(); - if (entry == C_ASSAS || entry == C_WHELP || entry == C_CHRON || entry == C_EXECU || entry == C_VANQU) - { - who->StopMoving(); - who->CastSpell(me,SPELL_CORRUPT,false); - } - else if (entry == C_AEONUS) - { - who->StopMoving(); - who->CastSpell(me,SPELL_CORRUPT_AEONUS,false); - } - } - } - - void AttackStart(Unit * /*who*/) - { - //if (pInstance && pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS) - //return; - - //ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit * /*who*/) {} - - void SpellHit(Unit* /*caster*/, const SpellEntry* spell) - { - if (SpellCorrupt_Timer) - return; - - if (spell->Id == SPELL_CORRUPT_AEONUS) - SpellCorrupt_Timer = 1000; - - if (spell->Id == SPELL_CORRUPT) - SpellCorrupt_Timer = 3000; - } - - void JustDied(Unit* Killer) - { - if (Killer->GetEntry() == me->GetEntry()) - return; - - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (SpellCorrupt_Timer) - { - if (SpellCorrupt_Timer <= diff) - { - pInstance->SetData(TYPE_MEDIVH,SPECIAL); - - if (me->HasAura(SPELL_CORRUPT_AEONUS)) - SpellCorrupt_Timer = 1000; - else if (me->HasAura(SPELL_CORRUPT)) - SpellCorrupt_Timer = 3000; - else - SpellCorrupt_Timer = 0; - } else SpellCorrupt_Timer -= diff; - } - - if (Check_Timer) - { - if (Check_Timer <= diff) - { - uint32 pct = pInstance->GetData(DATA_SHIELD); - - Check_Timer = 5000; - - if (Life25 && pct <= 25) - { - DoScriptText(SAY_WEAK25, me); - Life25 = false; - } - else if (Life50 && pct <= 50) - { - DoScriptText(SAY_WEAK50, me); - Life50 = false; - } - else if (Life75 && pct <= 75) - { - DoScriptText(SAY_WEAK75, me); - Life75 = false; - } - - //if we reach this it means event was running but at some point reset. - if (pInstance->GetData(TYPE_MEDIVH) == NOT_STARTED) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - me->RemoveCorpse(); - me->Respawn(); - return; - } - - if (pInstance->GetData(TYPE_RIFT) == DONE) - { - DoScriptText(SAY_WIN, me); - Check_Timer = 0; - - if (me->HasAura(SPELL_CHANNEL)) - me->RemoveAura(SPELL_CHANNEL); - - //TODO: start the post-event here - pInstance->SetData(TYPE_MEDIVH,DONE); - } - } else Check_Timer -= diff; - } - - //if (!UpdateVictim()) - //return; - - //DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_medivh_bm(Creature* pCreature) -{ - return new npc_medivh_bmAI (pCreature); -} - -struct Wave -{ - uint32 PortalMob[4]; //spawns for portal waves (in order) -}; - -static Wave PortalWaves[]= -{ - {C_ASSAS, C_WHELP, C_CHRON, 0}, - {C_EXECU, C_CHRON, C_WHELP, C_ASSAS}, - {C_EXECU, C_VANQU, C_CHRON, C_ASSAS} -}; - -struct npc_time_riftAI : public ScriptedAI -{ - npc_time_riftAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 TimeRiftWave_Timer; - uint8 mRiftWaveCount; - uint8 mPortalCount; - uint8 mWaveId; - - void Reset() - { - - TimeRiftWave_Timer = 15000; - mRiftWaveCount = 0; - - if (!pInstance) - return; - - mPortalCount = pInstance->GetData(DATA_PORTAL_COUNT); - - if (mPortalCount < 6) - mWaveId = 0; - else if (mPortalCount > 12) - mWaveId = 2; - else mWaveId = 1; - - } - void EnterCombat(Unit * /*who*/) {} - - void DoSummonAtRift(uint32 creature_entry) - { - if (!creature_entry) - return; - - if (pInstance && pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS) - { - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - return; - } - - Position pos; - me->GetRandomNearPosition(pos, 10.0f); - - //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); - - if (Unit *Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) - if (Unit *temp = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_MEDIVH) : 0)) - Summon->AddThreat(temp,0.0f); - } - - void DoSelectSummon() - { - uint32 entry = 0; - - if ((mRiftWaveCount > 2 && mWaveId < 1) || mRiftWaveCount > 3) - mRiftWaveCount = 0; - - entry = PortalWaves[mWaveId].PortalMob[mRiftWaveCount]; - debug_log("TSCR: npc_time_rift: summoning wave Creature (Wave %u, Entry %u).",mRiftWaveCount,entry); - - ++mRiftWaveCount; - - if (entry == C_WHELP) - { - for (uint8 i = 0; i < 3; ++i) - DoSummonAtRift(entry); - } else DoSummonAtRift(entry); - } - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (TimeRiftWave_Timer <= diff) - { - DoSelectSummon(); - TimeRiftWave_Timer = 15000; - } else TimeRiftWave_Timer -= diff; - - if (me->IsNonMeleeSpellCasted(false)) - return; - - debug_log("TSCR: npc_time_rift: not casting anylonger, i need to die."); - me->setDeathState(JUST_DIED); - - if (pInstance->GetData(TYPE_RIFT) == IN_PROGRESS) - pInstance->SetData(TYPE_RIFT,SPECIAL); - } -}; - -CreatureAI* GetAI_npc_time_rift(Creature* pCreature) -{ - return new npc_time_riftAI (pCreature); -} - -#define SAY_SAAT_WELCOME -1269019 - -#define GOSSIP_ITEM_OBTAIN "[PH] Obtain Chrono-Beacon" -#define SPELL_CHRONO_BEACON 34975 -#define ITEM_CHRONO_BEACON 24289 - -bool GossipHello_npc_saat(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(10000, pCreature->GetGUID()); - return true; - } - else if (pPlayer->GetQuestRewardStatus(QUEST_OPENING_PORTAL) && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_OBTAIN,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(10001, pCreature->GetGUID()); - return true; - } - - pPlayer->SEND_GOSSIP_MENU(10002, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_saat(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - pCreature->CastSpell(pPlayer,SPELL_CHRONO_BEACON,false); - } - return true; -} - -void AddSC_dark_portal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_medivh_bm"; - newscript->GetAI = &GetAI_npc_medivh_bm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_time_rift"; - newscript->GetAI = &GetAI_npc_time_rift; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_saat"; - newscript->pGossipHello = &GossipHello_npc_saat; - newscript->pGossipSelect = &GossipSelect_npc_saat; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h deleted file mode 100644 index 7bfd8c917d7..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/dark_portal.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_DARKPORTAL_H -#define DEF_DARKPORTAL_H - -#define TYPE_MEDIVH 1 -#define TYPE_RIFT 2 - -#define DATA_MEDIVH 10 -#define DATA_PORTAL_COUNT 11 -#define DATA_SHIELD 12 - -#define WORLD_STATE_BM 2541 -#define WORLD_STATE_BM_SHIELD 2540 -#define WORLD_STATE_BM_RIFT 2784 - -#define QUEST_OPENING_PORTAL 10297 -#define QUEST_MASTER_TOUCH 9836 - -#define C_TIME_KEEPER 17918 -#define C_RKEEP 21104 -#define C_RLORD 17839 -#define C_DEJA 17879 -#define C_TEMPO 17880 -#define C_AEONUS 17881 -#define C_ASSAS 17835 -#define C_WHELP 21818 -#define C_CHRON 17892 -#define C_EXECU 18994 -#define C_VANQU 18995 - -#endif - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp deleted file mode 100644 index d1280230808..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/dark_portal/instance_dark_portal.cpp +++ /dev/null @@ -1,346 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Instance_Dark_Portal -SD%Complete: 50 -SDComment: Quest support: 9836, 10297. Currently in progress. -SDCategory: Caverns of Time, The Dark Portal -EndScriptData */ - -#include "ScriptedPch.h" -#include "dark_portal.h" - -#define MAX_ENCOUNTER 2 - -#define C_MEDIVH 15608 -#define C_TIME_RIFT 17838 - -#define SPELL_RIFT_CHANNEL 31387 - -#define RIFT_BOSS 1 - -inline uint32 RandRiftBoss() { return ((rand()%2) ? C_RKEEP : C_RLORD); } - -float PortalLocation[4][4]= -{ - {-2041.06, 7042.08, 29.99, 1.30}, - {-1968.18, 7042.11, 21.93, 2.12}, - {-1885.82, 7107.36, 22.32, 3.07}, - {-1928.11, 7175.95, 22.11, 3.44} -}; - -struct Wave -{ - uint32 PortalBoss; //protector of current portal - uint32 NextPortalTime; //time to next portal, or 0 if portal boss need to be killed -}; - -static Wave RiftWaves[]= -{ - {RIFT_BOSS, 0}, - {C_DEJA, 0}, - {RIFT_BOSS, 120000}, - {C_TEMPO, 140000}, - {RIFT_BOSS, 120000}, - {C_AEONUS, 0} -}; - -struct instance_dark_portal : public ScriptedInstance -{ - instance_dark_portal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint32 mRiftPortalCount; - uint32 mShieldPercent; - uint8 mRiftWaveCount; - uint8 mRiftWaveId; - - uint32 NextPortal_Timer; - - uint64 MedivhGUID; - uint8 CurrentRiftId; - - void Initialize() - { - MedivhGUID = 0; - Clear(); - } - - void Clear() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - mRiftPortalCount = 0; - mShieldPercent = 100; - mRiftWaveCount = 0; - mRiftWaveId = 0; - - CurrentRiftId = 0; - - NextPortal_Timer = 0; - } - - void InitWorldState(bool Enable = true) - { - DoUpdateWorldState(WORLD_STATE_BM,Enable ? 1 : 0); - DoUpdateWorldState(WORLD_STATE_BM_SHIELD, 100); - DoUpdateWorldState(WORLD_STATE_BM_RIFT, 0); - } - - bool IsEncounterInProgress() - { - if (GetData(TYPE_MEDIVH) == IN_PROGRESS) - return true; - - return false; - } - - void OnPlayerEnter(Player* pPlayer) - { - if (GetData(TYPE_MEDIVH) == IN_PROGRESS) - return; - - pPlayer->SendUpdateWorldState(WORLD_STATE_BM,0); - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == C_MEDIVH) - MedivhGUID = pCreature->GetGUID(); - } - - //what other conditions to check? - bool CanProgressEvent() - { - if (instance->GetPlayers().isEmpty()) - return false; - - return true; - } - - uint8 GetRiftWaveId() - { - switch(mRiftPortalCount) - { - case 6: - mRiftWaveId = 2; - return 1; - case 12: - mRiftWaveId = 4; - return 3; - case 18: - return 5; - default: - return mRiftWaveId; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_MEDIVH: - if (data == SPECIAL && m_auiEncounter[0] == IN_PROGRESS) - { - --mShieldPercent; - - DoUpdateWorldState(WORLD_STATE_BM_SHIELD, mShieldPercent); - - if (!mShieldPercent) - { - if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) - { - if (pMedivh->isAlive()) - { - pMedivh->DealDamage(pMedivh, pMedivh->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - m_auiEncounter[0] = FAIL; - m_auiEncounter[1] = NOT_STARTED; - } - } - } - } - else - { - if (data == IN_PROGRESS) - { - debug_log("TSCR: Instance Dark Portal: Starting event."); - InitWorldState(); - m_auiEncounter[1] = IN_PROGRESS; - NextPortal_Timer = 15000; - } - - if (data == DONE) - { - //this may be completed further out in the post-event - debug_log("TSCR: Instance Dark Portal: Event completed."); - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - { - if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL); - - if (pPlayer->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE) - pPlayer->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH); - } - } - } - } - - m_auiEncounter[0] = data; - } - break; - case TYPE_RIFT: - if (data == SPECIAL) - { - if (mRiftPortalCount < 7) - NextPortal_Timer = 5000; - } - else - m_auiEncounter[1] = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_MEDIVH: - return m_auiEncounter[0]; - case TYPE_RIFT: - return m_auiEncounter[1]; - case DATA_PORTAL_COUNT: - return mRiftPortalCount; - case DATA_SHIELD: - return mShieldPercent; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - if (data == DATA_MEDIVH) - return MedivhGUID; - - return 0; - } - - Creature* SummonedPortalBoss(Creature* me) - { - uint32 entry = RiftWaves[GetRiftWaveId()].PortalBoss; - - if (entry == RIFT_BOSS) - entry = RandRiftBoss(); - - debug_log("TSCR: Instance Dark Portal: Summoning rift boss entry %u.",entry); - - Position pos; - me->GetRandomNearPosition(pos, 10.0f); - - //normalize Z-level if we can, if rift is not at ground level. - pos.m_positionZ = std::max(me->GetMap()->GetHeight(pos.m_positionX, pos.m_positionY, MAX_HEIGHT), me->GetMap()->GetWaterLevel(pos.m_positionX, pos.m_positionY)); - - if (Creature *summon = me->SummonCreature(entry, pos, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000)) - return summon; - - debug_log("TSCR: Instance Dark Portal: What just happened there? No boss, no loot, no fun..."); - return NULL; - } - - void DoSpawnPortal() - { - if (Creature* pMedivh = instance->GetCreature(MedivhGUID)) - { - uint8 tmp = urand(0,2); - - if (tmp >= CurrentRiftId) - ++tmp; - - debug_log("TSCR: Instance Dark Portal: Creating Time Rift at locationId %i (old locationId was %u).",tmp,CurrentRiftId); - - CurrentRiftId = tmp; - - Creature *pTemp = pMedivh->SummonCreature(C_TIME_RIFT, - PortalLocation[tmp][0],PortalLocation[tmp][1],PortalLocation[tmp][2],PortalLocation[tmp][3], - TEMPSUMMON_CORPSE_DESPAWN,0); - if (pTemp) - { - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - if (Creature *pBoss = SummonedPortalBoss(pTemp)) - { - if (pBoss->GetEntry() == C_AEONUS) - pBoss->AddThreat(pMedivh,0.0f); - else - { - pBoss->AddThreat(pTemp,0.0f); - pTemp->CastSpell(pBoss,SPELL_RIFT_CHANNEL,false); - } - } - } - } - } - - void Update(uint32 diff) - { - if (m_auiEncounter[1] != IN_PROGRESS) - return; - - //add delay timer? - if (!CanProgressEvent()) - { - Clear(); - return; - } - - if (NextPortal_Timer) - { - if (NextPortal_Timer <= diff) - { - ++mRiftPortalCount; - - DoUpdateWorldState(WORLD_STATE_BM_RIFT, mRiftPortalCount); - - DoSpawnPortal(); - NextPortal_Timer = RiftWaves[GetRiftWaveId()].NextPortalTime; - } else NextPortal_Timer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_dark_portal(Map* pMap) -{ - return new instance_dark_portal(pMap); -} - -void AddSC_instance_dark_portal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_dark_portal"; - newscript->GetInstanceData = &GetInstanceData_instance_dark_portal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp deleted file mode 100644 index 14ce4a59b37..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_anetheron.cpp +++ /dev/null @@ -1,309 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_CARRION_SWARM 31306 -#define SPELL_SLEEP 31298 -#define SPELL_VAMPIRIC_AURA 38196 -#define SPELL_INFERNO 31299 - -#define SAY_ONDEATH "The clock... is still... ticking." -#define SOUND_ONDEATH 10982 - -#define SAY_ONSLAY1 "Your hopes are lost!" -#define SAY_ONSLAY2 "Scream for me!" -#define SAY_ONSLAY3 "Pity, no time for a slow death!" -#define SOUND_ONSLAY1 10981 -#define SOUND_ONSLAY2 11038 -#define SOUND_ONSLAY3 11039 - -#define SAY_SWARM1 "The swarm is eager to feed!" -#define SAY_SWARM2 "Pestilence upon you!" -#define SOUND_SWARM1 10979 -#define SOUND_SWARM2 11037 - -#define SAY_SLEEP1 "You look tired..." -#define SAY_SLEEP2 "Sweet dreams..." -#define SOUND_SLEEP1 10978 -#define SOUND_SLEEP2 11545 - -#define SAY_INFERNO1 "Let fire rain from above!" -#define SAY_INFERNO2 "Earth and sky shall burn!" -#define SOUND_INFERNO1 10980 -#define SOUND_INFERNO2 11036 - -#define SAY_ONAGGRO "You are defenders of a doomed world! Flee here, and perhaps you will prolong your pathetic lives!" -#define SOUND_ONAGGRO 10977 - -struct boss_anetheronAI : public hyjal_trashAI -{ - boss_anetheronAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_SLEEP); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) - { - TempSpell->EffectImplicitTargetA[0] = 1; - TempSpell->EffectImplicitTargetB[0] = 0; - } - } - - uint32 SwarmTimer; - uint32 SleepTimer; - uint32 AuraTimer; - uint32 InfernoTimer; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - SwarmTimer = 45000; - SleepTimer = 60000; - AuraTimer = 5000; - InfernoTimer = 45000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, 0); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, 0); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_ANETHERONEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, 0); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 4896.08, -1576.35, 1333.65); - AddWaypoint(1, 4898.68, -1615.02, 1329.48); - AddWaypoint(2, 4907.12, -1667.08, 1321.00); - AddWaypoint(3, 4963.18, -1699.35, 1340.51); - AddWaypoint(4, 4989.16, -1716.67, 1335.74); - AddWaypoint(5, 5026.27, -1736.89, 1323.02); - AddWaypoint(6, 5037.77, -1770.56, 1324.36); - AddWaypoint(7, 5067.23, -1789.95, 1321.17); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (SwarmTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CARRION_SWARM); - - SwarmTimer = urand(45000,60000); - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_SWARM1); - me->MonsterYell(SAY_SWARM1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_SWARM2); - me->MonsterYell(SAY_SWARM2, LANG_UNIVERSAL, 0); - break; - } - } else SwarmTimer -= diff; - - if (SleepTimer <= diff) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - pTarget->CastSpell(pTarget,SPELL_SLEEP,true); - } - SleepTimer = 60000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_SLEEP1); - me->MonsterYell(SAY_SLEEP1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_SLEEP2); - me->MonsterYell(SAY_SLEEP2, LANG_UNIVERSAL, 0); - break; - } - } else SleepTimer -= diff; - if (AuraTimer <= diff) - { - DoCast(me, SPELL_VAMPIRIC_AURA, true); - AuraTimer = urand(10000,20000); - } else AuraTimer -= diff; - if (InfernoTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_INFERNO); - InfernoTimer = 45000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_INFERNO1); - me->MonsterYell(SAY_INFERNO1, LANG_UNIVERSAL, 0); - break; - case 1: - DoPlaySoundToSet(me, SOUND_INFERNO2); - me->MonsterYell(SAY_INFERNO2, LANG_UNIVERSAL, 0); - break; - } - } else InfernoTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_anetheron(Creature* pCreature) -{ - return new boss_anetheronAI (pCreature); -} - -#define SPELL_IMMOLATION 31303 -#define SPELL_INFERNO_EFFECT 31302 - -struct mob_towering_infernalAI : public ScriptedAI -{ - mob_towering_infernalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - AnetheronGUID = pInstance->GetData64(DATA_ANETHERON); - } - - uint32 ImmolationTimer; - uint32 CheckTimer; - uint64 AnetheronGUID; - ScriptedInstance* pInstance; - - void Reset() - { - DoCast(me, SPELL_INFERNO_EFFECT); - ImmolationTimer = 5000; - CheckTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - } - - void JustDied(Unit * /*victim*/) - { - } - - void MoveInLineOfSight(Unit *who) - { - if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) - AttackStart(who); - } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (AnetheronGUID) - { - Creature* boss = Unit::GetCreature((*me),AnetheronGUID); - if (!boss || (boss && boss->isDead())) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (ImmolationTimer <= diff) - { - DoCast(me, SPELL_IMMOLATION); - ImmolationTimer = 5000; - } else ImmolationTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_towering_infernal(Creature* pCreature) -{ - return new mob_towering_infernalAI (pCreature); -} - -void AddSC_boss_anetheron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_anetheron"; - newscript->GetAI = &GetAI_boss_anetheron; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_towering_infernal"; - newscript->GetAI = &GetAI_mob_towering_infernal; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp deleted file mode 100644 index 8e1fa378e07..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_archimonde.cpp +++ /dev/null @@ -1,635 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Archimonde -SD%Complete: 85 -SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented. -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "SpellAuras.h" -#include "hyjal_trash.h" - -//text id -1534018 are the text used when previous events complete. Not part of this script. -#define SAY_AGGRO -1534019 -#define SAY_DOOMFIRE1 -1534020 -#define SAY_DOOMFIRE2 -1534021 -#define SAY_AIR_BURST1 -1534022 -#define SAY_AIR_BURST2 -1534023 -#define SAY_SLAY1 -1534024 -#define SAY_SLAY2 -1534025 -#define SAY_SLAY3 -1534026 -#define SAY_ENRAGE -1534027 -#define SAY_DEATH -1534028 -#define SAY_SOUL_CHARGE1 -1534029 -#define SAY_SOUL_CHARGE2 -1534030 - -#define SPELL_DENOUEMENT_WISP 32124 -#define SPELL_ANCIENT_SPARK 39349 -#define SPELL_PROTECTION_OF_ELUNE 38528 - -#define SPELL_DRAIN_WORLD_TREE 39140 -#define SPELL_DRAIN_WORLD_TREE_2 39141 - -#define SPELL_FINGER_OF_DEATH 31984 -#define SPELL_HAND_OF_DEATH 35354 -#define SPELL_AIR_BURST 32014 -#define SPELL_GRIP_OF_THE_LEGION 31972 -#define SPELL_DOOMFIRE_STRIKE 31903 //summons two creatures -#define SPELL_DOOMFIRE_SPAWN 32074 -#define SPELL_DOOMFIRE 31945 -#define SPELL_SOUL_CHARGE_YELLOW 32045 -#define SPELL_SOUL_CHARGE_GREEN 32051 -#define SPELL_SOUL_CHARGE_RED 32052 -#define SPELL_UNLEASH_SOUL_YELLOW 32054 -#define SPELL_UNLEASH_SOUL_GREEN 32057 -#define SPELL_UNLEASH_SOUL_RED 32053 -#define SPELL_FEAR 31970 - -#define CREATURE_ARCHIMONDE 17968 -#define CREATURE_DOOMFIRE 18095 -#define CREATURE_DOOMFIRE_SPIRIT 18104 -#define CREATURE_ANCIENT_WISP 17946 -#define CREATURE_CHANNEL_TARGET 22418 - -#define NORDRASSIL_X 5503.713 -#define NORDRASSIL_Y -3523.436 -#define NORDRASSIL_Z 1608.781 - -struct mob_ancient_wispAI : public ScriptedAI -{ - mob_ancient_wispAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - ArchimondeGUID = 0; - } - - ScriptedInstance* pInstance; - uint64 ArchimondeGUID; - uint32 CheckTimer; - - void Reset() - { - CheckTimer = 1000; - - if (pInstance) - ArchimondeGUID = pInstance->GetData64(DATA_ARCHIMONDE); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void EnterCombat(Unit* /*who*/) {} - - void DamageTaken(Unit* /*done_by*/, uint32 &damage) { damage = 0; } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (Unit* Archimonde = Unit::GetUnit((*me), ArchimondeGUID)) - { - if ((((Archimonde->GetHealth()*100) / Archimonde->GetMaxHealth()) < 2) || !Archimonde->isAlive()) - DoCast(me, SPELL_DENOUEMENT_WISP); - else - DoCast(Archimonde, SPELL_ANCIENT_SPARK); - } - CheckTimer = 1000; - } else CheckTimer -= diff; - } -}; - -/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will - MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */ -struct mob_doomfireAI : public ScriptedAI -{ - mob_doomfireAI(Creature* c) : ScriptedAI(c) {} - - void Reset() { } - - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit* /*who*/) {} - void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } -}; - -/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or - travels in random directions if pTarget cannot be found. */ -struct mob_doomfire_targettingAI : public ScriptedAI -{ - mob_doomfire_targettingAI(Creature* c) : ScriptedAI(c) {} - - uint64 TargetGUID; - uint32 ChangeTargetTimer; - - void Reset() - { - TargetGUID = 0; - ChangeTargetTimer = 5000; - } - - void MoveInLineOfSight(Unit* who) - { - //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0 - //when UpdateAI needs it, it will be forced to select randomPoint - if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER) - TargetGUID = who->GetGUID(); - } - - void EnterCombat(Unit* /*who*/) {} - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) { damage = 0; } - - void UpdateAI(const uint32 diff) - { - if (ChangeTargetTimer <= diff) - { - if (Unit *temp = Unit::GetUnit(*me,TargetGUID)) - { - me->GetMotionMaster()->MoveFollow(temp,0.0f,0.0f); - TargetGUID = 0; - } - else - { - Position pos; - me->GetRandomNearPosition(pos, 40); - me->GetMotionMaster()->MovePoint(0, pos.m_positionX, pos.m_positionY, pos.m_positionZ); - } - - ChangeTargetTimer = 5000; - } else ChangeTargetTimer -= diff; - } -}; - -/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers. - The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the - hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then - select a random pTarget and cast the spell on them. However, if someone IS in melee range, and this - is NOT the main tank (creature's victim), then we aggro that player and they become the new victim. - For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will - randomly select it's pTarget to follow and then we create the random movement making it unpredictable. */ - -struct boss_archimondeAI : public hyjal_trashAI -{ - boss_archimondeAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 DoomfireSpiritGUID; - uint64 WorldTreeGUID; - - uint32 DrainNordrassilTimer; - uint32 FearTimer; - uint32 AirBurstTimer; - uint32 GripOfTheLegionTimer; - uint32 DoomfireTimer; - uint32 SoulChargeTimer; - uint32 SoulChargeCount; - uint32 MeleeRangeCheckTimer; - uint32 HandOfDeathTimer; - uint32 SummonWispTimer; - uint32 WispCount; - uint32 EnrageTimer; - uint32 CheckDistanceTimer; - - bool Enraged; - bool BelowTenPercent; - bool HasProtected; - bool IsChanneling; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, NOT_STARTED); - - DoomfireSpiritGUID = 0; - damageTaken = 0; - WorldTreeGUID = 0; - - DrainNordrassilTimer = 0; - FearTimer = 42000; - AirBurstTimer = 30000; - GripOfTheLegionTimer = urand(5000,25000); - DoomfireTimer = 20000; - SoulChargeTimer = urand(2000,30000); - SoulChargeCount = 0; - MeleeRangeCheckTimer = 15000; - HandOfDeathTimer = 2000; - WispCount = 0; // When ~30 wisps are summoned, Archimonde dies - EnrageTimer = 600000; // 10 minutes - CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage - SummonWispTimer = 0; - - Enraged = false; - BelowTenPercent = false; - HasProtected = false; - IsChanneling = false; - } - - void EnterCombat(Unit * /*who*/) - { - me->InterruptSpell(CURRENT_CHANNELED_SPELL); - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * victim) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - - if (victim && (victim->GetTypeId() == TYPEID_PLAYER)) - GainSoulCharge(CAST_PLR(victim)); - } - - void GainSoulCharge(Player* victim) - { - switch(victim->getClass()) - { - case CLASS_PRIEST: - case CLASS_PALADIN: - case CLASS_WARLOCK: - victim->CastSpell(me, SPELL_SOUL_CHARGE_RED, true); - break; - case CLASS_MAGE: - case CLASS_ROGUE: - case CLASS_WARRIOR: - victim->CastSpell(me, SPELL_SOUL_CHARGE_YELLOW, true); - break; - case CLASS_DRUID: - case CLASS_SHAMAN: - case CLASS_HUNTER: - victim->CastSpell(me, SPELL_SOUL_CHARGE_GREEN, true); - break; - } - - SoulChargeTimer = urand(2000,30000); - ++SoulChargeCount; - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_ARCHIMONDEEVENT, DONE); - } - - bool CanUseFingerOfDeath() - { - // First we check if our current victim is in melee range or not. - Unit* victim = me->getVictim(); - if (victim && me->IsWithinDistInMap(victim, me->GetAttackDistance(victim))) - return false; - - std::list& m_threatlist = me->getThreatManager().getThreatList(); - if (m_threatlist.empty()) - return false; - - std::list targets; - std::list::const_iterator itr = m_threatlist.begin(); - for (; itr != m_threatlist.end(); ++itr) - { - Unit* pUnit = Unit::GetUnit((*me), (*itr)->getUnitGuid()); - if (pUnit && pUnit->isAlive()) - targets.push_back(pUnit); - } - - if (targets.empty()) - return false; - - targets.sort(Trinity::ObjectDistanceOrderPred(me)); - Unit *pTarget = targets.front(); - if (pTarget) - { - if (!me->IsWithinDistInMap(pTarget, me->GetAttackDistance(pTarget))) - return true; // Cast Finger of Death - else // This target is closest, he is our new tank - me->AddThreat(pTarget, me->getThreatManager().getThreat(me->getVictim())); - } - - return false; - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == CREATURE_ANCIENT_WISP) - summoned->AI()->AttackStart(me); - else - { - summoned->setFaction(me->getFaction()); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - if (summoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT) - { - DoomfireSpiritGUID = summoned->GetGUID(); - } - - if (summoned->GetEntry() == CREATURE_DOOMFIRE) - { - summoned->CastSpell(summoned,SPELL_DOOMFIRE_SPAWN,false); - summoned->CastSpell(summoned,SPELL_DOOMFIRE,true,0,0,me->GetGUID()); - - if (Unit *DoomfireSpirit = Unit::GetUnit(*me, DoomfireSpiritGUID)) - { - summoned->GetMotionMaster()->MoveFollow(DoomfireSpirit,0.0f,0.0f); - DoomfireSpiritGUID = 0; - } - } - } - - //this is code doing close to what the summoning spell would do (spell 31903) - void SummonDoomfire(Unit *pTarget) - { - me->SummonCreature(CREATURE_DOOMFIRE_SPIRIT, - pTarget->GetPositionX()+15.0,pTarget->GetPositionY()+15.0,pTarget->GetPositionZ(),0, - TEMPSUMMON_TIMED_DESPAWN, 27000); - - me->SummonCreature(CREATURE_DOOMFIRE, - pTarget->GetPositionX()-15.0,pTarget->GetPositionY()-15.0,pTarget->GetPositionZ(),0, - TEMPSUMMON_TIMED_DESPAWN, 27000); - } - - void UnleashSoulCharge() - { - me->InterruptNonMeleeSpells(false); - - bool HasCast = false; - uint32 chargeSpell = 0; - uint32 unleashSpell = 0; - - switch (urand(0,2)) - { - case 0: - chargeSpell = SPELL_SOUL_CHARGE_RED; - unleashSpell = SPELL_UNLEASH_SOUL_RED; - break; - case 1: - chargeSpell = SPELL_SOUL_CHARGE_YELLOW; - unleashSpell = SPELL_UNLEASH_SOUL_YELLOW; - break; - case 2: - chargeSpell = SPELL_SOUL_CHARGE_GREEN; - unleashSpell = SPELL_UNLEASH_SOUL_GREEN; - break; - } - - if (me->HasAura(chargeSpell)) - { - me->RemoveAuraFromStack(chargeSpell); - DoCast(me->getVictim(), unleashSpell); - HasCast = true; - SoulChargeCount--; - } - - if (HasCast) - SoulChargeTimer = urand(2000,30000); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - { - if (pInstance) - { - // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished. - if ((pInstance->GetData(DATA_AZGALOREVENT) < DONE) && ((me->GetVisibility() != VISIBILITY_OFF) || (me->getFaction() != 35))) - { - me->SetVisibility(VISIBILITY_OFF); - me->setFaction(35); - } - else if ((pInstance->GetData(DATA_AZGALOREVENT) >= DONE) && ((me->GetVisibility() != VISIBILITY_ON) || (me->getFaction() == 35))) - { - me->setFaction(1720); - me->SetVisibility(VISIBILITY_ON); - } - } - - if (DrainNordrassilTimer <= diff) - { - if (!IsChanneling) - { - Creature *temp = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 1200000); - - if (temp) - WorldTreeGUID = temp->GetGUID(); - - if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Nordrassil->SetDisplayId(11686); - DoCast(Nordrassil, SPELL_DRAIN_WORLD_TREE); - IsChanneling = true; - } - } - - if (Unit *Nordrassil = Unit::GetUnit(*me, WorldTreeGUID)) - { - Nordrassil->CastSpell(me, SPELL_DRAIN_WORLD_TREE_2, true); - DrainNordrassilTimer = 1000; - } - } else DrainNordrassilTimer -= diff; - } - - if (!UpdateVictim()) - return; - - if (((me->GetHealth()*100 / me->GetMaxHealth()) < 10) && !BelowTenPercent && !Enraged) - BelowTenPercent = true; - - if (!Enraged) - { - if (EnrageTimer <= diff) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) > 10) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - DoScriptText(SAY_ENRAGE, me); - } - } else EnrageTimer -= diff; - - if (CheckDistanceTimer <= diff) - { - // To simplify the check, we simply summon a Creature in the location and then check how far we are from the creature - Creature* Check = me->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000); - if (Check) - { - Check->SetVisibility(VISIBILITY_OFF); - - if (me->IsWithinDistInMap(Check, 75)) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - Enraged = true; - DoScriptText(SAY_ENRAGE, me); - } - } - CheckDistanceTimer = 5000; - } else CheckDistanceTimer -= diff; - } - - if (BelowTenPercent) - { - if (!HasProtected) - { - me->GetMotionMaster()->Clear(false); - me->GetMotionMaster()->MoveIdle(); - - //all members of raid must get this buff - DoCast(me->getVictim(), SPELL_PROTECTION_OF_ELUNE); - HasProtected = true; - Enraged = true; - } - - if (SummonWispTimer <= diff) - { - DoSpawnCreature(CREATURE_ANCIENT_WISP, rand()%40, rand()%40, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - SummonWispTimer = 1500; - ++WispCount; - } else SummonWispTimer -= diff; - - if (WispCount >= 30) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (Enraged) - { - if (HandOfDeathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_HAND_OF_DEATH); - HandOfDeathTimer = 2000; - } else HandOfDeathTimer -= diff; - return; // Don't do anything after this point. - } - - if (SoulChargeCount) - { - if (SoulChargeTimer <= diff) - UnleashSoulCharge(); - else SoulChargeTimer -= diff; - } - - if (GripOfTheLegionTimer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_GRIP_OF_THE_LEGION); - GripOfTheLegionTimer = urand(5000,25000); - } else GripOfTheLegionTimer -= diff; - - if (AirBurstTimer <= diff) - { - if (urand(0,1)) - DoScriptText(SAY_AIR_BURST1, me); - else - DoScriptText(SAY_AIR_BURST2, me); - - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_AIR_BURST);//not on tank - AirBurstTimer = urand(25000,40000); - } else AirBurstTimer -= diff; - - if (FearTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FEAR); - FearTimer = 42000; - } else FearTimer -= diff; - - if (DoomfireTimer <= diff) - { - if (urand(0,1)) - DoScriptText(SAY_DOOMFIRE1, me); - else - DoScriptText(SAY_DOOMFIRE2, me); - - Unit *temp = SelectUnit(SELECT_TARGET_RANDOM, 1); - if (!temp) - temp = me->getVictim(); - - //replace with spell cast 31903 once implicitTarget 73 implemented - SummonDoomfire(temp); - - //supposedly three doomfire can be up at the same time - DoomfireTimer = 20000; - } else DoomfireTimer -= diff; - - if (MeleeRangeCheckTimer <= diff) - { - if (CanUseFingerOfDeath()) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_FINGER_OF_DEATH); - MeleeRangeCheckTimer = 1000; - } - - MeleeRangeCheckTimer = 5000; - } else MeleeRangeCheckTimer -= diff; - - DoMeleeAttackIfReady(); - } - void WaypointReached(uint32 /*i*/){} -}; - -CreatureAI* GetAI_boss_archimonde(Creature* pCreature) -{ - return new boss_archimondeAI (pCreature); -} - -CreatureAI* GetAI_mob_doomfire(Creature* pCreature) -{ - return new mob_doomfireAI(pCreature); -} - -CreatureAI* GetAI_mob_doomfire_targetting(Creature* pCreature) -{ - return new mob_doomfire_targettingAI(pCreature); -} - -CreatureAI* GetAI_mob_ancient_wisp(Creature* pCreature) -{ - return new mob_ancient_wispAI(pCreature); -} - -void AddSC_boss_archimonde() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_archimonde"; - newscript->GetAI = &GetAI_boss_archimonde; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_doomfire"; - newscript->GetAI = &GetAI_mob_doomfire; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_doomfire_targetting"; - newscript->GetAI = &GetAI_mob_doomfire_targetting; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ancient_wisp"; - newscript->GetAI = &GetAI_mob_ancient_wisp; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp deleted file mode 100644 index 69e37f7f740..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_azgalor.cpp +++ /dev/null @@ -1,285 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_RAIN_OF_FIRE 31340 -#define SPELL_DOOM 31347 -#define SPELL_HOWL_OF_AZGALOR 31344 -#define SPELL_CLEAVE 31345 -#define SPELL_BERSERK 26662 - -#define SAY_ONDEATH "Your time is almost... up" -#define SOUND_ONDEATH 11002 - -#define SAY_ONSLAY1 "Reesh, hokta!" -#define SAY_ONSLAY2 "Don't fight it" -#define SAY_ONSLAY3 "No one is going to save you" -#define SOUND_ONSLAY1 11001 -#define SOUND_ONSLAY2 11048 -#define SOUND_ONSLAY3 11047 - -#define SAY_DOOM1 "Just a taste... of what awaits you" -#define SAY_DOOM2 "Suffer you despicable insect!" -#define SOUND_DOOM1 11046 -#define SOUND_DOOM2 11000 - -#define SAY_ONAGGRO "Abandon all hope! The legion has returned to finish what was begun so many years ago. This time there will be no escape!" -#define SOUND_ONAGGRO 10999 - -struct boss_azgalorAI : public hyjal_trashAI -{ - boss_azgalorAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_HOWL_OF_AZGALOR); - if (TempSpell) - TempSpell->EffectRadiusIndex[0] = 12;//100yards instead of 50000?! - } - - uint32 RainTimer; - uint32 DoomTimer; - uint32 HowlTimer; - uint32 CleaveTimer; - uint32 EnrageTimer; - bool enraged; - - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - RainTimer = 20000; - DoomTimer = 50000; - HowlTimer = 30000; - CleaveTimer = 10000; - EnrageTimer = 600000; - enraged = false; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_AZGALOREVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 5492.91, -2404.61, 1462.63); - AddWaypoint(1, 5531.76, -2460.87, 1469.55); - AddWaypoint(2, 5554.58, -2514.66, 1476.12); - AddWaypoint(3, 5554.16, -2567.23, 1479.90); - AddWaypoint(4, 5540.67, -2625.99, 1480.89); - AddWaypoint(5, 5508.16, -2659.2, 1480.15); - AddWaypoint(6, 5489.62, -2704.05, 1482.18); - AddWaypoint(7, 5457.04, -2726.26, 1485.10); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (RainTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,30,true), SPELL_RAIN_OF_FIRE); - RainTimer = 20000+rand()%15000; - } else RainTimer -= diff; - - if (DoomTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,1,100,true), SPELL_DOOM);//never on tank - DoomTimer = 45000+rand()%5000; - } else DoomTimer -= diff; - - if (HowlTimer <= diff) - { - DoCast(me, SPELL_HOWL_OF_AZGALOR); - HowlTimer = 30000; - } else HowlTimer -= diff; - - if (CleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - CleaveTimer = 10000+rand()%5000; - } else CleaveTimer -= diff; - - if (EnrageTimer < diff && !enraged) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_BERSERK, true); - enraged = true; - EnrageTimer = 600000; - } else EnrageTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_azgalor(Creature* pCreature) -{ - return new boss_azgalorAI (pCreature); -} - -#define SPELL_THRASH 12787 -#define SPELL_CRIPPLE 31406 -#define SPELL_WARSTOMP 31408 - -struct mob_lesser_doomguardAI : public hyjal_trashAI -{ - mob_lesser_doomguardAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - if (pInstance) - AzgalorGUID = pInstance->GetData64(DATA_AZGALOR); - } - - uint32 CrippleTimer; - uint32 WarstompTimer; - uint32 CheckTimer; - uint64 AzgalorGUID; - ScriptedInstance* pInstance; - - void Reset() - { - CrippleTimer = 50000; - WarstompTimer = 10000; - DoCast(me, SPELL_THRASH); - CheckTimer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void KilledUnit(Unit * /*victim*/) - { - } - - void WaypointReached(uint32 /*i*/) - { - } - - void MoveInLineOfSight(Unit *who) - { - if (me->IsWithinDist(who, 50) && !me->isInCombat() && me->IsHostileTo(who)) - AttackStart(who); - } - - void JustDied(Unit * /*victim*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (CheckTimer <= diff) - { - if (AzgalorGUID) - { - Creature* boss = Unit::GetCreature((*me),AzgalorGUID); - if (!boss || (boss && boss->isDead())) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - return; - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (WarstompTimer <= diff) - { - DoCast(me, SPELL_WARSTOMP); - WarstompTimer = 10000+rand()%5000; - } else WarstompTimer -= diff; - - if (CrippleTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true), SPELL_CRIPPLE); - CrippleTimer = 25000+rand()%5000; - } else CrippleTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_lesser_doomguard(Creature* pCreature) -{ - return new mob_lesser_doomguardAI (pCreature); -} - -void AddSC_boss_azgalor() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_azgalor"; - newscript->GetAI = &GetAI_boss_azgalor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lesser_doomguard"; - newscript->GetAI = &GetAI_mob_lesser_doomguard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp deleted file mode 100644 index b52d22842e3..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_kazrogal.cpp +++ /dev/null @@ -1,197 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_CLEAVE 31436 -#define SPELL_WARSTOMP 31480 -#define SPELL_MARK 31447 - -#define SOUND_ONDEATH 11018 - -#define SAY_ONSLAY1 "Shaza-Kiel!" -#define SAY_ONSLAY2 "You... are nothing!" -#define SAY_ONSLAY3 "Miserable nuisance!" -#define SOUND_ONSLAY1 11017 -#define SOUND_ONSLAY2 11053 -#define SOUND_ONSLAY3 11054 - -#define SAY_MARK1 "Your death will be a painful one." -#define SAY_MARK2 "You... are marked." -#define SOUND_MARK1 11016 -#define SOUND_MARK2 11052 - -#define SAY_ONAGGRO "Cry for mercy! Your meaningless lives will soon be forfeit." -#define SOUND_ONAGGRO 11015 - -struct boss_kazrogalAI : public hyjal_trashAI -{ - boss_kazrogalAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - SpellEntry *TempSpell = GET_SPELL(SPELL_MARK); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 1) - { - TempSpell->EffectImplicitTargetA[0] = 1; - TempSpell->EffectImplicitTargetB[0] = 0; - } - } - - uint32 CleaveTimer; - uint32 WarStompTimer; - uint32 MarkTimer; - uint32 MarkTimerBase; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - CleaveTimer = 5000; - WarStompTimer = 15000; - MarkTimer = 45000; - MarkTimerBase = 45000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, NULL); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - case 2: - DoPlaySoundToSet(me, SOUND_ONSLAY3); - me->MonsterYell(SAY_ONSLAY3, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_KAZROGALEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 5492.91, -2404.61, 1462.63); - AddWaypoint(1, 5531.76, -2460.87, 1469.55); - AddWaypoint(2, 5554.58, -2514.66, 1476.12); - AddWaypoint(3, 5554.16, -2567.23, 1479.90); - AddWaypoint(4, 5540.67, -2625.99, 1480.89); - AddWaypoint(5, 5508.16, -2659.2, 1480.15); - AddWaypoint(6, 5489.62, -2704.05, 1482.18); - AddWaypoint(7, 5457.04, -2726.26, 1485.10); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (CleaveTimer <= diff) - { - DoCast(me, SPELL_CLEAVE); - CleaveTimer = 6000+rand()%15000; - } else CleaveTimer -= diff; - - if (WarStompTimer <= diff) - { - DoCast(me, SPELL_WARSTOMP); - WarStompTimer = 60000; - } else WarStompTimer -= diff; - - if (me->HasAura(SPELL_MARK)) - me->RemoveAurasDueToSpell(SPELL_MARK); - if (MarkTimer <= diff) - { - //cast dummy, useful for bos addons - me->CastCustomSpell(me, SPELL_MARK, NULL, NULL, NULL, false, NULL, NULL, me->GetGUID()); - - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->getPowerType() == POWER_MANA) - { - pTarget->CastSpell(pTarget, SPELL_MARK,true);//only cast on mana users - } - } - MarkTimerBase -= 5000; - if (MarkTimerBase < 5500) - MarkTimerBase = 5500; - MarkTimer = MarkTimerBase; - switch (urand(0,2)) - { - case 0: - DoPlaySoundToSet(me, SOUND_MARK1); - me->MonsterYell(SAY_MARK1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_MARK2); - me->MonsterYell(SAY_MARK2, LANG_UNIVERSAL, NULL); - break; - } - } else MarkTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_kazrogal(Creature* pCreature) -{ - return new boss_kazrogalAI (pCreature); -} - -void AddSC_boss_kazrogal() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kazrogal"; - newscript->GetAI = &GetAI_boss_kazrogal; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp deleted file mode 100644 index 7465b997117..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/boss_rage_winterchill.cpp +++ /dev/null @@ -1,192 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -#define SPELL_FROST_ARMOR 31256 -#define SPELL_DEATH_AND_DECAY 31258 - -#define SPELL_FROST_NOVA 31250 -#define SPELL_ICEBOLT 31249 - -#define SAY_ONDEATH "You have won this battle, but not... the... war" -#define SOUND_ONDEATH 11026 - -#define SAY_ONSLAY1 "All life must perish!" -#define SAY_ONSLAY2 "Victory to the Legion!" -#define SOUND_ONSLAY1 11025 -#define SOUND_ONSLAY2 11057 - -#define SAY_DECAY1 "Crumble and rot!" -#define SAY_DECAY2 "Ashes to ashes, dust to dust" -#define SOUND_DECAY1 11023 -#define SOUND_DECAY2 11055 - -#define SAY_NOVA1 "Succumb to the icy chill... of death!" -#define SAY_NOVA2 "It will be much colder in your grave" -#define SOUND_NOVA1 11024 -#define SOUND_NOVA2 11058 - -#define SAY_ONAGGRO "The Legion's final conquest has begun! Once again the subjugation of this world is within our grasp. Let none survive!" -#define SOUND_ONAGGRO 11022 - -struct boss_rage_winterchillAI : public hyjal_trashAI -{ - boss_rage_winterchillAI(Creature *c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - } - - uint32 FrostArmorTimer; - uint32 DecayTimer; - uint32 NovaTimer; - uint32 IceboltTimer; - bool pGo; - uint32 pos; - - void Reset() - { - damageTaken = 0; - FrostArmorTimer = 37000; - DecayTimer = 45000; - NovaTimer = 15000; - IceboltTimer = 10000; - - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, IN_PROGRESS); - DoPlaySoundToSet(me, SOUND_ONAGGRO); - me->MonsterYell(SAY_ONAGGRO, LANG_UNIVERSAL, 0); - } - - void KilledUnit(Unit * /*victim*/) - { - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_ONSLAY1); - me->MonsterYell(SAY_ONSLAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_ONSLAY2); - me->MonsterYell(SAY_ONSLAY2, LANG_UNIVERSAL, NULL); - break; - } - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0f); - } - } - - void JustDied(Unit *victim) - { - hyjal_trashAI::JustDied(victim); - if (pInstance && IsEvent) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, DONE); - DoPlaySoundToSet(me, SOUND_ONDEATH); - me->MonsterYell(SAY_ONDEATH, LANG_UNIVERSAL, NULL); - } - - void UpdateAI(const uint32 diff) - { - if (IsEvent) - { - //Must update npc_escortAI - npc_escortAI::UpdateAI(diff); - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, 4896.08, -1576.35, 1333.65); - AddWaypoint(1, 4898.68, -1615.02, 1329.48); - AddWaypoint(2, 4907.12, -1667.08, 1321.00); - AddWaypoint(3, 4963.18, -1699.35, 1340.51); - AddWaypoint(4, 4989.16, -1716.67, 1335.74); - AddWaypoint(5, 5026.27, -1736.89, 1323.02); - AddWaypoint(6, 5037.77, -1770.56, 1324.36); - AddWaypoint(7, 5067.23, -1789.95, 1321.17); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (FrostArmorTimer <= diff) - { - DoCast(me, SPELL_FROST_ARMOR); - FrostArmorTimer = 40000+rand()%20000; - } else FrostArmorTimer -= diff; - if (DecayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_DEATH_AND_DECAY); - DecayTimer = 60000+rand()%20000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_DECAY1); - me->MonsterYell(SAY_DECAY1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_DECAY2); - me->MonsterYell(SAY_DECAY2, LANG_UNIVERSAL, NULL); - break; - } - } else DecayTimer -= diff; - if (NovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_NOVA); - NovaTimer = 30000+rand()%15000; - switch (urand(0,1)) - { - case 0: - DoPlaySoundToSet(me, SOUND_NOVA1); - me->MonsterYell(SAY_NOVA1, LANG_UNIVERSAL, NULL); - break; - case 1: - DoPlaySoundToSet(me, SOUND_NOVA2); - me->MonsterYell(SAY_NOVA2, LANG_UNIVERSAL, NULL); - break; - } - } else NovaTimer -= diff; - if (IceboltTimer <= diff) - { - DoCast(SelectTarget(SELECT_TARGET_RANDOM,0,40,true), SPELL_ICEBOLT); - IceboltTimer = 11000+rand()%20000; - } else IceboltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_rage_winterchill(Creature* pCreature) -{ - return new boss_rage_winterchillAI (pCreature); -} - -void AddSC_boss_rage_winterchill() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_rage_winterchill"; - newscript->GetAI = &GetAI_boss_rage_winterchill; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp deleted file mode 100644 index 16a050939cc..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.cpp +++ /dev/null @@ -1,247 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Hyjal -SD%Complete: 80 -SDComment: gossip text id's unknown -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -/* ContentData -npc_jaina_proudmoore -npc_thrall -npc_tyrande_whisperwind -EndContentData */ - -#include "ScriptedPch.h" -#include "hyjalAI.h" - -#define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore." -#define GOSSIP_ITEM_ANETHERON "We are ready for whatever Archimonde might send our way, Lady Proudmoore." - -#define GOSSIP_ITEM_BEGIN_HORDE "I am with you, Thrall." -#define GOSSIP_ITEM_AZGALOR "We have nothing to fear." - -#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!" - -#define GOSSIP_ITEM_TYRANDE "Aid us in defending Nordrassil" -#define ITEM_TEAR_OF_GODDESS 24494 - -#define GOSSIP_ITEM_GM1 "[GM] Toggle Debug Timers" - -CreatureAI* GetAI_npc_jaina_proudmoore(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - - ai->Reset(); - ai->EnterEvadeMode(); - - ai->Spell[0].SpellId = SPELL_BLIZZARD; - ai->Spell[0].Cooldown = 15000 + rand()%20000; - ai->Spell[0].TargetType = TARGETTYPE_RANDOM; - - ai->Spell[1].SpellId = SPELL_PYROBLAST; - ai->Spell[1].Cooldown = 5500 + rand()%4000; - ai->Spell[1].TargetType = TARGETTYPE_RANDOM; - - ai->Spell[2].SpellId = SPELL_SUMMON_ELEMENTALS; - ai->Spell[2].Cooldown = 15000 + rand()%30000; - ai->Spell[2].TargetType = TARGETTYPE_SELF; - - return ai; -} - -bool GossipHello_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - if (ai->EventBegun) - return false; - - uint32 RageEncounter = ai->GetInstanceData(DATA_RAGEWINTERCHILLEVENT); - uint32 AnetheronEncounter = ai->GetInstanceData(DATA_ANETHERONEVENT); - if (RageEncounter == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - else if (RageEncounter == DONE && AnetheronEncounter == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - else if (RageEncounter == DONE && AnetheronEncounter == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - - if (pPlayer->isGameMaster()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - ai->FirstBossDead = true; - ai->WaveCount = 9; - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - ai->Retreat(); - break; - case GOSSIP_ACTION_INFO_DEF: - ai->Debug = !ai->Debug; - debug_log("TSCR: HyjalAI - Debug mode has been toggled"); - break; - } - return true; -} - -CreatureAI* GetAI_npc_thrall(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - - ai->Reset(); - ai->EnterEvadeMode(); - - ai->Spell[0].SpellId = SPELL_CHAIN_LIGHTNING; - ai->Spell[0].Cooldown = 3000 + rand()%5000; - ai->Spell[0].TargetType = TARGETTYPE_VICTIM; - - ai->Spell[1].SpellId = SPELL_SUMMON_DIRE_WOLF; - ai->Spell[1].Cooldown = 6000 + rand()%35000; - ai->Spell[1].TargetType = TARGETTYPE_RANDOM; - - return ai; -} - -bool GossipHello_npc_thrall(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - if (ai->EventBegun) - return false; - - uint32 AnetheronEvent = ai->GetInstanceData(DATA_ANETHERONEVENT); - // Only let them start the Horde phases if Anetheron is dead. - if (AnetheronEvent == DONE && ai->GetInstanceData(DATA_ALLIANCE_RETREAT)) - { - uint32 KazrogalEvent = ai->GetInstanceData(DATA_KAZROGALEVENT); - uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); - if (KazrogalEvent == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - else if (KazrogalEvent == DONE && AzgalorEvent == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - else if (AzgalorEvent == DONE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - } - - if (pPlayer->isGameMaster()) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_TRAINER, GOSSIP_ITEM_GM1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_thrall(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - ai->DeSpawnVeins();//despawn the alliance veins - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 2: - ai->FirstBossDead = true; - ai->WaveCount = 9; - ai->StartEvent(pPlayer); - break; - case GOSSIP_ACTION_INFO_DEF + 3: - ai->Retreat(); - break; - case GOSSIP_ACTION_INFO_DEF: - ai->Debug = !ai->Debug; - debug_log("TSCR: HyjalAI - Debug mode has been toggled"); - break; - } - return true; -} - -CreatureAI* GetAI_npc_tyrande_whisperwind(Creature* pCreature) -{ - hyjalAI* ai = new hyjalAI(pCreature); - ai->Reset(); - ai->EnterEvadeMode(); - return ai; -} - -bool GossipHello_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature) -{ - hyjalAI* ai = CAST_AI(hyjalAI, pCreature->AI()); - uint32 AzgalorEvent = ai->GetInstanceData(DATA_AZGALOREVENT); - - // Only let them get item if Azgalor is dead. - if (AzgalorEvent == DONE && !pPlayer->HasItemCount(ITEM_TEAR_OF_GODDESS,1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TYRANDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_TEAR_OF_GODDESS, 1); - if (msg == EQUIP_ERR_OK) - { - Item* item = pPlayer->StoreNewItem(dest, ITEM_TEAR_OF_GODDESS, true); - if (item && pPlayer) - pPlayer->SendNewItem(item,1,true,false,true); - } - pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID()); - CAST_AI(hyjalAI, pCreature->AI()); - } - return true; -} - -void AddSC_hyjal() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_jaina_proudmoore"; - newscript->GetAI = &GetAI_npc_jaina_proudmoore; - newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore; - newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thrall"; - newscript->GetAI = &GetAI_npc_thrall; - newscript->pGossipHello = &GossipHello_npc_thrall; - newscript->pGossipSelect = &GossipSelect_npc_thrall; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tyrande_whisperwind"; - newscript->pGossipHello = &GossipHello_npc_tyrande_whisperwind; - newscript->pGossipSelect = &GossipSelect_npc_tyrande_whisperwind; - newscript->GetAI = &GetAI_npc_tyrande_whisperwind; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h deleted file mode 100644 index bfc9a54dfd9..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_HYJAL_H -#define DEF_HYJAL_H - -#define ERROR_INST_DATA "TSCR: Instance data not set properly for Mount Hyjal. Encounters will be buggy." - -enum eTypes -{ - WORLD_STATE_WAVES = 2842, - WORLD_STATE_ENEMY = 2453, - WORLD_STATE_ENEMYCOUNT = 2454, - - DATA_ANETHERON = 1, - DATA_ANETHERONEVENT = 2, - DATA_ARCHIMONDE = 3, - DATA_ARCHIMONDEEVENT = 4, - DATA_AZGALOR = 5, - DATA_AZGALOREVENT = 6, - DATA_JAINAPROUDMOORE = 7, - DATA_KAZROGAL = 8, - DATA_KAZROGALEVENT = 9, - DATA_RAGEWINTERCHILL = 10, - DATA_RAGEWINTERCHILLEVENT = 11, - DATA_THRALL = 12, - DATA_TYRANDEWHISPERWIND = 13, - DATA_TRASH = 14, - DATA_RESET_TRASH_COUNT = 15, - DATA_ALLIANCE_RETREAT = 16, - DATA_HORDE_RETREAT = 17, - DATA_RAIDDAMAGE = 18, - DATA_RESET_RAIDDAMAGE = 19, - TYPE_RETREAT = 20 -}; -#endif - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp deleted file mode 100644 index 3c12b54f3f4..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.cpp +++ /dev/null @@ -1,1157 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: HyjalAI -SD%Complete: 90 -SDComment: -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjalAI.h" -#include "hyjal_trash.h" -#include "MapManager.h" -#include "Language.h" -#include "Chat.h" -#include "Object.h" - -#define SPAWN_GARG_GATE 0 -#define SPAWN_WYRM_GATE 1 -#define SPAWN_NEAR_TOWER 2 - -#define YELL_HURRY "Hurry, we don't have much time" - -// Locations for summoning gargoyls and frost wyrms in special cases -float SpawnPointSpecial[3][3]= -{ - {5497.08, -2493.23, 1535.72}, //spawn point for the gargoyles near the horde gate - {5624.53, -2548.12, 1551.54}, //spawn point for the frost wyrm near the horde gate - {5604.41, -2811.98, 1547.77} //spawn point for the gargoyles and wyrms near the horde tower -}; - -// Locations for summoning waves in Alliance base -float AllianceBase[4][3]= -{ - {4928.48, -1526.38, 1326.83}, - {4923.54, -1514.29, 1327.98}, - {4928.41, -1510.35, 1327.99}, - {4938.35, -1521.00, 1326.69} -}; - -float JainaDummySpawn[2][4]= -{ - {5497.01, -2719.03, 1483.08, 2.90426}, - {5484.98, -2721.69, 1483.39, 6.00656} -}; - -// Locations for summoning waves in Horde base -float HordeBase[4][3]= -{ - {5458.01, -2340.27, 1459.60}, - {5466.01, -2334.69, 1460.06}, - {5468.45, -2355.13, 1459.99}, - {5479.06, -2344.16, 1461.74} -}; - -// Lady Jaina's waypoints when retreathing -float JainaWPs[2][3]= -{ - {5078.56, -1789.79, 1320.73},//next to the small stairs - {5037.38, -1778.39, 1322.61},//center of alliance base -}; - -float InfernalPos[8][3]=//spawn points for the infernals in the horde base -{ - {5453.59, -2764.52, 1493.50}, - {5478.4, -2781.77, 1497.52}, - {5506.09, -2780.53, 1496.32}, - {5532.1, -2763.42, 1492.37}, - {5544.16, -2733.99, 1487.14}, - {5536.19, -2708.18, 1480.01}, - {5510.16, -2691.75, 1479.66}, - {5482.39, -2689.19, 1481.09} -}; - -float InfernalSPWP[26][4]=//spawn points for the infernals in the horde base used in the cleaning wave -{ - {5490.96, -2718.72, 1482.96, 0.49773}, - {5449.51, -2723.32, 1485.69, 2.69685}, - {5520.83, -2624.68, 1483.82, 1.20459}, - {5558.28, -2629.26, 1485.76, 0.37992}, - {5567.97, -2758.69, 1494.10, 5.04125}, - {5384.90, -2793.47, 1503.90, 5.55412}, - {5495.33, -2814.06, 1501.56, 1.12055}, - {5472.63, -2929.39, 1538.31, 1.95777}, - {5334.72, -2952.29, 1534.34, 0.50869}, - {5398.36, -2872.46, 1512.38, 0.76787}, - {5514.39, -2768.63, 1492.30, 1.55721}, - {5598.91, -2703.75, 1495.64, 2.56644}, - {5467.80, -2655.93, 1482.27, 0.85819}, - {5399.83, -2985.24, 1545.04, 5.92559}, - {5232.13, -2967.05, 1553.09, 5.41351}, - {5272.02, -3082.52, 1567.09, 3.40681}, - {5343.26, -3120.71, 1582.92, 3.16727}, - {5371.26, -3175.24, 1587.41, 6.10466}, - {5434.67, -3177.91, 1579.25, 2.77850}, - {5237.39, -3149.25, 1593.59, 0.83855}, - {5202.15, -3016.64, 1566.28, 3.31256}, - {5302.54, -2914.37, 1528.53, 3.37146}, - {5439.04, -2834.81, 1508.80, 2.14231}, - {5421.33, -2771.04, 1494.28, 6.06223}, - {5549.76, -2692.93, 1482.68, 2.19414}, - {5459.78, -2755.71, 1490.68, 1.05139} -}; - -float VeinPos[14][8]=//spawn points of the ancient gem veins -{ - {5184.84, -1982.59, 1382.66, 2.58079, 0, 0, 0.960944, 0.276742}, //alliance - {5107.66, -2071.16, 1368.37, 2.65148, 0, 0, 0.970124, 0.242611}, //alliance - {5040.53, -2227.65, 1403.17, 3.35049, 0, 0, 0.99455, -0.104257}, //alliance - {5187.59, -2453.12, 1455.51, 5.87943, 0, 0, 0.20051, -0.979692}, //alliance - {5429.43, -2340.65, 1465.38, 4.7681, 0, 0, 0.687138, -0.726527}, //alliance - {5463.99, -2315.95, 1470.29, 1.52045, 0, 0, 0.689084, 0.724682}, //alliance - {5624.65, -2495.09, 1510.11, 0.0124869, 0, 0, 0.00624342, 0.999981}, //alliance - {5285.41, -3348.32, 1663.01, 1.57152, 0, 0, 0.707362, 0.706852}, //horde - {5417.69, -3372.52, 1656.31, 0.361993, 0, 0, 0.18001, 0.983665}, //horde - {5315.34, -3238.32, 1622.88, 3.03627, 0, 0, 0.998614, 0.0526347}, //horde - {5303.4, -3096.44, 1596.41, 1.72073, 0, 0, 0.758081, 0.65216}, //horde - {5265.13, -3177.27, 1616.22, 0.813604, 0, 0, 0.395674, 0.918391}, //horde - {5374.3, -3420.59, 1653.43, 1.45762, 0, 0, 0.665981, 0.745969}, //horde - {5441.54, -3321.59, 1651.55, 0.258306, 0, 0, 0.128794, 0.991671} //horde -}; - -float AllianceOverrunGargPos[5][4]=//gargoyle spawn points in the alliance overrun -{ - {5279.94, -2049.68, 1311.38, 0},//garg1 - {5289.15, -2219.06, 1291.12, 0},//garg2 - {5202.07, -2136.10, 1305.07, 2.8},//garg3 - {5071.52, -2425.63, 1454.48, 5.54},//garg4 - {5120.65, -2467.92, 1463.93, 2.54}//garg5 -}; - -float AllianceFirePos[92][8]=//spawn points for the fire visuals (GO) in the alliance base -{ - {5039.9, -1796.84, 1323.88, 2.59222, 0, 0, 0.962511, 0.271243}, - {5087.2, -1795.2, 1320.68, 1.03946, 0, 0, 0.496644, 0.867954}, - {5112.68, -1806.66, 1359.93, 1.37799, 0, 0, 0.63576, 0.771887}, - {5095.61, -1793.27, 1359.78, 0.580806, 0, 0, 0.286338, 0.958129}, - {5090.43, -1784.45, 1360.44, 0.796784, 0, 0, 0.387937, 0.921686}, - {5139.25, -1783.11, 1359.39, 3.30849, 0, 0, 0.99652, -0.0833509}, - {5112.16, -1763.72, 1361.35, 5.10312, 0, 0, 0.556388, -0.830922}, - {4981.18, -1793.98, 1335.7, 3.23072, 0, 0, 0.999007, -0.0445498}, - {4996.57, -1766.75, 1341.62, 3.5331, 0, 0, 0.980902, -0.194505}, - {4983.74, -1769.25, 1345.75, 3.79228, 0, 0, 0.947541, -0.319635}, - {4996.01, -1774.43, 1330.71, 3.07364, 0, 0, 0.999423, 0.0339693}, - {5094.2, -1726.13, 1330.55, 1.56175, 0, 0, 0.703901, 0.710298}, - {5079.82, -1721.24, 1336.26, 1.18868, 0, 0, 0.559964, 0.828517}, - {5077.68, -1717.15, 1327.78, 0.0145145, 0, 0, 0.00725717, 0.999974}, - {5122.27, -1738.22, 1341.67, 0.835256, 0, 0, 0.405593, 0.914054}, - {5131.88, -1741.15, 1335.25, 2.15472, 0, 0, 0.880712, 0.473653}, - {5196.93, -1772.99, 1345.2, 0.128397, 0, 0, 0.0641544, 0.99794}, - {5225.33, -1756.06, 1344.17, 3.04223, 0, 0, 0.998766, 0.0496599}, - {5224.84, -1767.05, 1360.06, 3.19538, 0, 0, 0.999638, -0.0268922}, - {5202.05, -1763.47, 1361.68, 2.59455, 0, 0, 0.962826, 0.270122}, - {5194.74, -1766.66, 1356.94, 0.0734191, 0, 0, 0.0367013, 0.999326}, - {5159.67, -1832.97, 1344.5, 5.17457, 0, 0, 0.526356, -0.850264}, - {5096.17, -1858.73, 1332.46, 5.30021, 0, 0, 0.471939, -0.881631}, - {5110.7, -1856.59, 1342.84, 5.97564, 0, 0, 0.153167, -0.9882}, - {5109.76, -1855.3, 1332.38, 4.89572, 0, 0, 0.639411, -0.768865}, - {5068.95, -1837.37, 1328.81, 2.61569, 0, 0, 0.965628, 0.25993}, - {5064.4, -1824.77, 1329.02, 2.16409, 0, 0, 0.88292, 0.469524}, - {5059.89, -1848.79, 1329.59, 0.0709955, 0, 0, 0.0354903, 0.99937}, - {5014.37, -1851.39, 1322.56, 4.66949, 0, 0, 0.722111, -0.691777}, - {5025.1, -1848.27, 1323.39, 4.44565, 0, 0, 0.794854, -0.606801}, - {4942.63, -1890.13, 1326.59, 3.28719, 0, 0, 0.997351, -0.0727343}, - {4937.95, -1888.71, 1352.41, 3.41678, 0, 0, 0.990549, -0.13716}, - {4922.48, -1881.92, 1352.41, 5.03077, 0, 0, 0.586075, -0.810257}, - {4915.35, -1894.32, 1351.24, 6.22457, 0, 0, 0.0293048, -0.999571}, - {4922.71, -1904.84, 1352.56, 1.37866, 0, 0, 0.63602, 0.771672}, - {4932.89, -1905.49, 1352.56, 1.89702, 0, 0, 0.812549, 0.582893}, - {5011.83, -1861.05, 1345.86, 4.43777, 0, 0, 0.797239, -0.603664}, - {5011.83, -1861.05, 1363.26, 4.748, 0, 0, 0.694406, -0.719583}, - {5021.46, -1858.35, 1342.17, 4.86188, 0, 0, 0.652329, -0.757936}, - {4995.02, -1698.3, 1370.38, 6.15779, 0, 0, 0.0626579, -0.998035}, - {5119.85, -1728.9, 1336.04, 5.87112, 0, 0, 0.204579, -0.97885}, - {5214.75, -1751.02, 1342.5, 5.08965, 0, 0, 0.561972, -0.827156}, - {5075.04, -1822.43, 1328.87, 3.99951, 0, 0, 0.9094, -0.415924}, - {5057.09, -1823.32, 1350.35, 3.88169, 0, 0, 0.93231, -0.361659}, - {4984.6, -1816.99, 1329.21, 3.05308, 0, 0, 0.999021, 0.0442417}, - {4983.35, -1811.55, 1356.82, 3.33975, 0, 0, 0.995096, -0.098917}, - {4984.11, -1825.73, 1350.76, 2.26375, 0, 0, 0.905211, 0.424962}, - {4968.47, -1786.46, 1354.09, 3.07663, 0, 0, 0.999473, 0.0324733}, - {5061.82, -1751.16, 1339.07, 5.94727, 0, 0, 0.167171, -0.985928}, - {5063.75, -1763, 1351.91, 0.759707, 0, 0, 0.370784, 0.928719}, - {5078.65, -1708.26, 1353.9, 1.27022, 0, 0, 0.593264, 0.805008}, - {4983.19, -1755.96, 1331.13, 4.28221, 0, 0, 0.841733, -0.539894}, - {4972.76, -1755.3, 1332.5, 4.21938, 0, 0, 0.858276, -0.513188}, - {4961.65, -1760.82, 1351.69, 3.56515, 0, 0, 0.977659, -0.210198}, - {5086.45, -1779.83, 1321.62, 6.23157, 0, 0, 0.0258051, -0.999667}, - {5063.15, -1756.74, 1328.56, 0.886926, 0, 0, 0.42907, 0.903271}, - {5042.45, -1800.61, 1323.88, 2.50093, 0, 0, 0.949131, 0.31488}, - {5084.74, -1725.35, 1327.89, 1.65034, 0, 0, 0.734663, 0.678432}, - {4993.25, -1758.1, 1331.07, 3.49995, 0, 0, 0.98399, -0.178223}, - {5078.53, -1867.85, 1348.91, 5.85612, 0, 0, 0.211913, -0.977288}, - {5080.74, -1869.73, 1333.18, 6.18206, 0, 0, 0.0505424, -0.998722}, - {5089.55, -1894.13, 1356.08, 1.52072, 0, 0, 0.689181, 0.724589}, - {5113.24, -1899.49, 1363.77, 1.50108, 0, 0, 0.682034, 0.731321}, - {4984.18, -1907.69, 1325.62, 3.82193, 0, 0, 0.942698, -0.333646}, - {5094.14, -2432.08, 1429.38, 4.70083, 0, 0, 0.711182, -0.703007}, - {5329.89, -2113.30, 1281.06, 5.60560, 0, 0, 0.332347, -0.943157}, - {5170.87, -2148.13, 1278.32, 1.63540, 0, 0, 0.729573, 0.683903 }, - {5132.94, -1960.25, 1367.8, 3.69787, 0, 0, 0.961568, -0.274566}, - {5280.82, -2351.55, 1431.57, 4.46913, 0, 0, 0.787677, -0.616088}, - {5176.78, -2121.43, 1295.27, 3.24153, 0, 0, 0.998752, -0.04995}, - {5332.75, -2101.41, 1296.37, 5.50350, 0, 0, 0.380043, -0.924969}, - {5265.70, -2050.27, 1287.57, 0.50051, 0, 0, 0.247655, 0.968848 }, - {5194.21, -2129.89, 1274.04, 3.08053, 0, 0, 0.999534, 0.0305272}, - {5225.81, -1985.50, 1364.15, 0.37247, 0, 0, 0.185163, 0.982708 }, - {5339.46, -2204.47, 1280.45, 0.99921, 0, 0, 0.479081, 0.877771 }, - {5269.63, -2020.57, 1299.62, 3.00201, 0, 0, 0.997566, 0.0697332}, - {5111.54, -2445.70, 1435.31, 2.70983, 0, 0, 0.976788, 0.214207 }, - {5111.24, -1901.14, 1355.33, 1.61028, 0, 0, 0.720929, 0.693009 }, - {5310.42, -2207.82, 1277.46, 0.50441, 0, 0, 0.249544, 0.968363 }, - {5150.81, -2042.13, 1394.3, 2.21031, 0, 0, 0.893534, 0.448995 }, - {5224.84, -2376.61, 1366.33, 5.0621, 0, 0, 0.573311, -0.819338}, - {5105.41, -2454.86, 1446.16, 4.64584, 0, 0, 0.730239, -0.683191}, - {5309.65, -2188.28, 1266.84, 5.56631, 0, 0, 0.350811, -0.936446}, - {5281.46, -2047.82, 1287.67, 2.44909, 0, 0, 0.940652, 0.339373 }, - {5325.45, -2189.41, 1309.6, 6.23783, 0, 0, 0.0226771, -0.999743}, - {5190.96, -2142.54, 1293.03, 6.25668, 0, 0, 0.0132544, -0.999912}, - {5089.99, -2467.49, 1441.8, 0.77381, 0, 0, 0.377326, 0.92608 }, - {5195.08, -2129.01, 1285.36, 3.55727, 0, 0, 0.978480, -0.206344}, - {5353.76, -2116.28, 1299.27, 6.17894, 0, 0, 0.0521006, -0.998642}, - {5271.14, -2037.38, 1299.24, 4.07879, 0, 0, 0.892201, -0.451638}, - {5332.5 , -2181.28, 1279.95, 4.6906, 0, 0, 0.714768, -0.699362}, - {5108.2 , -2429.84, 1427.73, 4.5194, 0, 0, 0.771943, -0.635691} -}; - -float HordeFirePos[65][8]=//spawn points for the fire visuals (GO) in the horde base -{ - {5524.11, -2612.73, 1483.38, 1.96198, 0, 0, 0.831047, 0.556202}, - {5514.42, -2617.19, 1505.77, 1.82453, 0, 0, 0.790892, 0.611956}, - {5510.21, -2624.77, 1485.34, 1.71065, 0, 0, 0.754783, 0.655974}, - {5570.72, -2619.04, 1487.62, 0.728898, 0, 0, 0.356435, 0.93432}, - {5570.29, -2639.37, 1487.31, 1.49308, 0, 0, 0.679104, 0.734042}, - {5583.56, -2637.2, 1503.78, 1.46559, 0, 0, 0.668951, 0.743307}, - {5571.53, -2626.81, 1510.99, 0.362107, 0, 0, 0.180066, 0.983654}, - {5545.97, -2659.62, 1489.64, 5.07055, 0, 0, 0.569845, -0.821752}, - {5557.44, -2675.91, 1482.58, 1.70118, 0, 0, 0.751671, 0.659539}, - {5594.98, -2742.31, 1495.51, 4.5993, 0, 0, 0.74594, -0.666013}, - {5599.65, -2755.6, 1505.05, 1.66896, 0, 0, 0.740947, 0.671564}, - {5565.95, -2774.75, 1499.48, 6.22425, 0, 0, 0.0294611, -0.999566}, - {5567.1, -2769.7, 1511.17, 5.99257, 0, 0, 0.144799, -0.989461}, - {5572.84, -2774.16, 1527.06, 0.836428, 0, 0, 0.406129, 0.913816}, - {5538.32, -2805.94, 1498.87, 4.30082, 0, 0, 0.836674, -0.547701}, - {5515.66, -2801.74, 1503.53, 5.57316, 0, 0, 0.347602, -0.937642}, - {5516.76, -2827.14, 1501.15, 0.35026, 0, 0, 0.174236, 0.984704}, - {5536.13, -2813.51, 1537.21, 4.51681, 0, 0, 0.772765, -0.634692}, - {5525.05, -2825.16, 1538.53, 0.489275, 0, 0, 0.242205, 0.970225}, - {5534.42, -2815.45, 1562.84, 4.62834, 0, 0, 0.736191, -0.676774}, - {5519.64, -2831.12, 1526.46, 0.611008, 0, 0, 0.300774, 0.953696}, - {5551.04, -2827.55, 1523.5, 3.35206, 0, 0, 0.994468, -0.10504}, - {5469.22, -2802.87, 1503.5, 4.99509, 0, 0, 0.600436, -0.799673}, - {5427.8, -2737.26, 1487.12, 1.78673, 0, 0, 0.779186, 0.626793}, - {5454.1, -2709.1, 1485.92, 3.03552, 0, 0, 0.998594, 0.0530137}, - {5436.3, -2718.2, 1506.02, 2.7567, 0, 0, 0.981539, 0.191261}, - {5412.6, -2740.55, 1510.79, 2.98446, 0, 0, 0.996915, 0.0784832}, - {5406.12, -2752.48, 1521.01, 2.05769, 0, 0, 0.856705, 0.515807}, - {5445.24, -2676.35, 1521.89, 2.91378, 0, 0, 0.99352, 0.113661}, - {5481.4, -2665.08, 1482.23, 4.30001, 0, 0, 0.836895, -0.547363}, - {5443.51, -2675.44, 1487.12, 2.90986, 0, 0, 0.993295, 0.115606}, - {5391.72, -2647.3, 1528.9, 3.76987, 0, 0, 0.951063, -0.308997}, - {5421.09, -2734.12, 1521.01, 2.70567, 0, 0, 0.97634, 0.216242}, - {5405.39, -2710.33, 1533.77, 2.51324, 0, 0, 0.951052, 0.309032}, - {5423.96, -2703.76, 1516.34, 2.79206, 0, 0, 0.984767, 0.173879}, - {5444.75, -2735.23, 1486.37, 2.22657, 0, 0, 0.897155, 0.441715}, - {5570.98, -2747.91, 1495.7, 5.14433, 0, 0, 0.53915, -0.84221}, - {5567.79, -2673.9, 1484.66, 2.72529, 0, 0, 0.978415, 0.20665}, - {5600.71, -2696.8, 1500.42, 0.443704, 0, 0, 0.220036, 0.975492}, - {5600.7, -2693.04, 1515.2, 5.16003, 0, 0, 0.532522, -0.846416}, - {5627.56, -2839.66, 1510.53, 5.41527, 0, 0, 0.420463, -0.907309}, - {5622.02, -2868.71, 1516.22, 2.25482, 0, 0, 0.903303, 0.429002}, - {5586.61, -2878.97, 1510.34, 4.55604, 0, 0, 0.76017, -0.649724}, - {5583.78, -2843.71, 1509.54, 5.35715, 0, 0, 0.44665, -0.894709}, - {5580.95, -2811.3, 1513.3, 3.57587, 0, 0, 0.976518, -0.215434}, - {5542.52, -2869.31, 1523.13, 5.23304, 0, 0, 0.501275, -0.865288}, - {5557.35, -2866.36, 1518.76, 4.48299, 0, 0, 0.783388, -0.621533}, - {5380.91, -2849.36, 1512.81, 3.90962, 0, 0, 0.927168, -0.374646}, - {5395.76, -2881.41, 1521.11, 4.28426, 0, 0, 0.84118, -0.540755}, - {5374.87, -2859.63, 1528.98, 3.30252, 0, 0, 0.996765, -0.0803745}, - {5356.07, -2854.66, 1520.34, 5.83933, 0, 0, 0.220108, -0.975475}, - {5363.01, -2975.72, 1539.02, 4.13738, 0, 0, 0.87859, -0.477576}, - {5336.85, -2980.74, 1561.24, 5.11126, 0, 0, 0.553001, -0.83318}, - {5335.23, -2974.62, 1540.05, 5.04451, 0, 0, 0.580496, -0.814263}, - {5422.37, -2998.87, 1549.98, 4.51831, 0, 0, 0.772288, -0.635272}, - {5405.54, -3014.6, 1562.16, 5.86761, 0, 0, 0.206298, -0.978489}, - {5427.96, -3019.4, 1561.58, 3.53498, 0, 0, 0.980718, -0.19543}, - {5348.12, -2977.84, 1582.47, 3.94025, 0, 0, 0.921323, -0.388799}, - {5331.12, -2993.71, 1576.14, 0.0642734, 0, 0, 0.0321311, 0.999484}, - {5321.63, -2986.55, 1552.2, 5.29503, 0, 0, 0.474219, -0.880407}, - {5292.1, -2914.36, 1529.52, 2.9742, 0, 0, 0.996499, 0.083601}, - {5281.77, -2926.5, 1530.62, 1.67829, 0, 0, 0.744071, 0.6681}, - {5287.19, -2909.94, 1543.49, 3.31192, 0, 0, 0.996376, -0.0850591}, - {5534.15, -2679.35, 1483.61, 0.428685, 0, 0, 0.212705, 0.977116}, - {5545.43, -2647.82, 1483.05, 5.38848, 0, 0, 0.432578, -0.901596} -}; - -hyjalAI::hyjalAI(Creature *c) : npc_escortAI(c), Summons(me) -{ - pInstance = c->GetInstanceData(); - VeinsSpawned[0] = false; - VeinsSpawned[1] = false; - for (uint8 i=0; i<14; ++i) - VeinGUID[i] = 0; - InfernalCount = 0; - TeleportTimer = 1000; - Overrun = false; - Teleported = false; - WaitForTeleport = false; - OverrunCounter = 0; - OverrunCounter2 = 0; - InfernalPoint = 0; - RespawnTimer = 10000; - DoRespawn = false; - DoHide = false; - MassTeleportTimer = 0; - DoMassTeleport = false; -} - -void hyjalAI::JustSummoned(Creature *summoned) -{ - Summons.Summon(summoned); -} - -void hyjalAI::SummonedCreatureDespawn(Creature* summoned) -{ - Summons.Despawn(summoned); -} - -void hyjalAI::Reset() -{ - IsDummy = false; - me->setActive(true); - // GUIDs - PlayerGUID = 0; - BossGUID[0] = 0; - BossGUID[1] = 0; - - // Timers - NextWaveTimer = 10000; - CheckTimer = 0; - RetreatTimer = 1000; - - // Misc - WaveCount = 0; - EnemyCount = 0; - - // Set faction properly based on Creature entry - switch(me->GetEntry()) - { - case JAINA: - Faction = 0; - DoCast(me, SPELL_BRILLIANCE_AURA, true); - break; - - case THRALL: - Faction = 1; - break; - - case TYRANDE: - Faction = 2; - break; - } - - //Bools - EventBegun = false; - FirstBossDead = false; - SecondBossDead = false; - Summon = false; - bRetreat = false; - Debug = false; - - //Flags - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - //Initialize spells - memset(Spell, 0, sizeof(Spell)); - - //Reset Instance Data for trash count - if (pInstance) - { - if ((!pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == JAINA) || (pInstance->GetData(DATA_ALLIANCE_RETREAT) && me->GetEntry() == THRALL)) - { - //Reset World States - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); - pInstance->SetData(DATA_RESET_TRASH_COUNT, 0); - } - } else error_log(ERROR_INST_DATA); - - //Visibility - DoHide = true; -} - -void hyjalAI::EnterEvadeMode() -{ - if (me->GetEntry() != JAINA) - me->RemoveAllAuras(); - me->DeleteThreatList(); - me->CombatStop(true); - me->LoadCreaturesAddon(); - - if (me->isAlive()) - me->GetMotionMaster()->MoveTargetedHome(); - - me->SetLootRecipient(NULL); -} - -void hyjalAI::EnterCombat(Unit * /*who*/) -{ - if (IsDummy)return; - for (uint8 i = 0; i < 3; ++i) - if (Spell[i].Cooldown) - SpellTimer[i] = Spell[i].Cooldown; - - Talk(ATTACKED); -} - -void hyjalAI::MoveInLineOfSight(Unit *who) -{ - if (IsDummy) - return; - - npc_escortAI::MoveInLineOfSight(who); -} - -void hyjalAI::SummonCreature(uint32 entry, float Base[4][3]) -{ - uint32 random = rand()%4; - float SpawnLoc[3]; - - for (uint8 i = 0; i < 3; ++i) - { - SpawnLoc[i] = Base[random][i]; - } - Creature* pCreature = NULL; - switch(entry) - { - case 17906: //GARGOYLE - - if (!FirstBossDead && (WaveCount == 1 || WaveCount == 3)) - {//summon at tower - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][1]+irand(-20,20), SpawnPointSpecial[SPAWN_NEAR_TOWER][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - if (pCreature) - CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; - }else{//summon at gate - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_GARG_GATE][0]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][1]+irand(-10,10), SpawnPointSpecial[SPAWN_GARG_GATE][2]+irand(-10,10), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - } - break; - case 17907: //FROST_WYRM , - if (FirstBossDead && WaveCount == 1) //summon at gate - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_WYRM_GATE][0],SpawnPointSpecial[SPAWN_WYRM_GATE][1],SpawnPointSpecial[SPAWN_WYRM_GATE][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - else - { - pCreature = me->SummonCreature(entry, SpawnPointSpecial[SPAWN_NEAR_TOWER][0], SpawnPointSpecial[SPAWN_NEAR_TOWER][1],SpawnPointSpecial[SPAWN_NEAR_TOWER][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - if (pCreature) - CAST_AI(hyjal_trashAI, pCreature->AI())->useFlyPath = true; - } - break; - case 17908: //GIANT_INFERNAL - ++InfernalCount; - if (InfernalCount > 7) - InfernalCount = 0; - pCreature = me->SummonCreature(entry, InfernalPos[InfernalCount][0], InfernalPos[InfernalCount][1], InfernalPos[InfernalCount][2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - break; - default: - pCreature = me->SummonCreature(entry, SpawnLoc[0], SpawnLoc[1], SpawnLoc[2], 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000); - break; - - } - - if (pCreature) - { - // Increment Enemy Count to be used in World States and instance script - ++EnemyCount; - - pCreature->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - pCreature->setActive(true); - switch(entry) - { - case NECROMANCER: - case ABOMINATION: - case GHOUL: - case BANSHEE: - case CRYPT_FIEND: - case GARGOYLE: - case FROST_WYRM: - case GIANT_INFERNAL: - case FEL_STALKER: - case RAGE_WINTERCHILL: - case ANETHERON: - case KAZROGAL: - case AZGALOR: - CAST_AI(hyjal_trashAI, pCreature->AI())->IsEvent = true; - break; - } - if (pInstance) - { - if (pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE) - pCreature->SetDisableReputationGain(true);//no repu for solo farming - } - // Check if Creature is a boss. - if (pCreature->isWorldBoss()) - { - if (!FirstBossDead) BossGUID[0] = pCreature->GetGUID(); - else BossGUID[1] = pCreature->GetGUID(); - CheckTimer = 5000; - } - } -} - -void hyjalAI::SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]) -{ - // 1 in 4 chance we give a rally yell. Not sure if the chance is offilike. - if (rand()%4 == 0) - Talk(RALLY); - - if (!pInstance) - { - error_log(ERROR_INST_DATA); - return; - } - InfernalCount = 0;//reset infernal count every new wave - - EnemyCount = pInstance->GetData(DATA_TRASH); - for (uint8 i = 0; i < 18; ++i) - { - if (wave[Count].Mob[i]) - SummonCreature(wave[Count].Mob[i], Base); - } - - if (!wave[Count].IsBoss) - { - uint32 stateValue = Count+1; - if (FirstBossDead) - stateValue -= 9; // Subtract 9 from it to give the proper wave number if we are greater than 8 - - // Set world state to our current wave number - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, stateValue); // Set world state to our current wave number - // Enable world state - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); // Enable world state - - pInstance->SetData(DATA_TRASH, EnemyCount); // Send data for instance script to update count - - if (!Debug) - NextWaveTimer = wave[Count].WaveTimer; - else - { - NextWaveTimer = 15000; - debug_log("TSCR: HyjalAI: debug mode is enabled. Next Wave in 15 seconds"); - } - } - else - { - // Set world state for waves to 0 to disable it. - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1); - - // Set World State for enemies invading to 1. - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 1); - - Summon = false; - } - CheckTimer = 5000; -} - -void hyjalAI::StartEvent(Player* pPlayer) -{ - if (!pPlayer || IsDummy || !pInstance) - return; - - Talk(BEGIN); - - EventBegun = true; - Summon = true; - - NextWaveTimer = 15000; - CheckTimer = 5000; - PlayerGUID = pPlayer->GetGUID(); - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0); - - DeSpawnVeins(); -} - -uint32 hyjalAI::GetInstanceData(uint32 Event) -{ - if (pInstance) - return pInstance->GetData(Event); - else error_log(ERROR_INST_DATA); - - return 0; -} - -void hyjalAI::Talk(uint32 id) -{ - std::list index; - for (uint8 i = 0; i < 9; ++i) - { - if (Faction == 0) // Alliance - { - if (JainaQuotes[i].id == id) - index.push_back(i); - } - else if (Faction == 1) // Horde - { - if (ThrallQuotes[i].id == id) - index.push_back(i); - } - } - - if (index.empty()) - return; // No quotes found, no use to continue - - uint8 ind = *(index.begin()) + rand()%index.size(); - - int32 YellId = 0; - if (Faction == 0) // Alliance - { - YellId = JainaQuotes[ind].textid; - } - else if (Faction == 1) // Horde - { - YellId = ThrallQuotes[ind].textid; - } - - if (YellId) - DoScriptText(YellId, me); -} - -void hyjalAI::Retreat() -{ - if (pInstance) - { - pInstance->SetData(TYPE_RETREAT,SPECIAL); - - if (Faction == 0) - { - pInstance->SetData(DATA_ALLIANCE_RETREAT, 1); - AddWaypoint(0,JainaWPs[0][0],JainaWPs[0][1],JainaWPs[0][2]); - AddWaypoint(1,JainaWPs[1][0],JainaWPs[1][1],JainaWPs[1][2]); - Start(false, false); - SetDespawnAtEnd(false);//move to center of alliance base - } - if (Faction == 1) - { - pInstance->SetData(DATA_HORDE_RETREAT, 1); - Creature* JainaDummy = me->SummonCreature(JAINA,JainaDummySpawn[0][0],JainaDummySpawn[0][1],JainaDummySpawn[0][2],JainaDummySpawn[0][3],TEMPSUMMON_TIMED_DESPAWN,60000); - if (JainaDummy) - { - JainaDummy->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - CAST_AI(hyjalAI, JainaDummy->AI())->IsDummy = true; - DummyGuid = JainaDummy->GetGUID(); - } - AddWaypoint(0,JainaDummySpawn[1][0],JainaDummySpawn[1][1],JainaDummySpawn[1][2]); - Start(false, false); - SetDespawnAtEnd(false);//move to center of alliance base - } - } - SpawnVeins(); - Overrun = true; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);//cant talk after overrun event started -} - -void hyjalAI::SpawnVeins() -{ - if (Faction == 0) - { - if (VeinsSpawned[0])//prevent any buggers - return; - for (uint8 i = 0; i<7; ++i) - { - GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); - if (gem) - VeinGUID[i]=gem->GetGUID(); - } - VeinsSpawned[0] = true; - }else{ - if (VeinsSpawned[1]) - return; - for (uint8 i = 7; i<14; ++i) - { - GameObject* gem = me->SummonGameObject(ANCIENT_VEIN,VeinPos[i][0],VeinPos[i][1],VeinPos[i][2],VeinPos[i][3],VeinPos[i][4],VeinPos[i][5],VeinPos[i][6],VeinPos[i][7],0); - if (gem) - VeinGUID[i]=gem->GetGUID(); - } - VeinsSpawned[1] = true; - } -} - -void hyjalAI::DeSpawnVeins() -{ - if (!pInstance) - return; - if (Faction == 1) - { - Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (!pUnit)return; - hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); - if (!ai)return; - for (uint8 i = 0; i<7; ++i) - { - if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) - gem->Delete(); - } - } else if (Faction) - { - Creature* pUnit=Unit::GetCreature((*me),pInstance->GetData64(DATA_THRALL)); - if (!pUnit)return; - hyjalAI* ai = CAST_AI(hyjalAI, pUnit->AI()); - if (!ai)return; - for (uint8 i = 7; i<14; ++i) - { - if (GameObject* gem = pInstance->instance->GetGameObject(pInstance->GetData64(ai->VeinGUID[i]))) - gem->Delete(); - } - } -} - -void hyjalAI::UpdateAI(const uint32 diff) -{ - if (IsDummy) - { - if (MassTeleportTimer < diff && DoMassTeleport) - { - DoCast(me, SPELL_MASS_TELEPORT, false); - DoMassTeleport = false; - } else MassTeleportTimer -= diff; - return; - } - if (DoHide) - { - DoHide = false; - switch(me->GetEntry()) - { - case JAINA: - if (pInstance && pInstance->GetData(DATA_ALLIANCE_RETREAT)) - { - me->SetVisibility(VISIBILITY_OFF); - HideNearPos(me->GetPositionX(), me->GetPositionY()); - HideNearPos(5037.76, -1889.71); - for (uint8 i = 0; i < 92; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); - - } - else me->SetVisibility(VISIBILITY_ON); - break; - case THRALL: //thrall - if (pInstance && pInstance->GetData(DATA_HORDE_RETREAT)) - { - me->SetVisibility(VISIBILITY_OFF); - HideNearPos(me->GetPositionX(), me->GetPositionY()); - HideNearPos(5563, -2763.19); - HideNearPos(5542.2, -2629.36); - for (uint8 i = 0; i < 65; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); - - } - else me->SetVisibility(VISIBILITY_ON); - break; - } - } - if (DoRespawn) - { - if (RespawnTimer <= diff) - { - DoRespawn = false; - RespawnNearPos(me->GetPositionX(), me->GetPositionY()); - if (Faction == 0) - { - RespawnNearPos(5037.76, -1889.71); - } else if (Faction == 1) - { - RespawnNearPos(5563, -2763.19); - RespawnNearPos(5542.2, -2629.36); - } - me->SetVisibility(VISIBILITY_ON); - }else{ - RespawnTimer -= diff; - me->SetVisibility(VISIBILITY_OFF); - } - return; - } - if (Overrun) - DoOverrun(Faction, diff); - if (bRetreat) - { - if (RetreatTimer <= diff) - { - IsDummy = true; - bRetreat = false; - HideNearPos(me->GetPositionX(), me->GetPositionY()); - switch(me->GetEntry()) - { - case JAINA://jaina - HideNearPos(5037.76, -1889.71); - break; - case THRALL://thrall - HideNearPos(5563, -2763.19); - HideNearPos(5542.2, -2629.36); - HideNearPos(5603.75, -2853.12); - break; - } - me->SetVisibility(VISIBILITY_OFF); - } else RetreatTimer -= diff; - } - - if (!EventBegun) - return; - - if (Summon) - { - if (pInstance && EnemyCount) - { - EnemyCount = pInstance->GetData(DATA_TRASH); - if (!EnemyCount) - NextWaveTimer = 5000; - } - - if (NextWaveTimer <= diff) - { - if (Faction == 0) - SummonNextWave(AllianceWaves, WaveCount, AllianceBase); - else if (Faction == 1) - SummonNextWave(HordeWaves, WaveCount, HordeBase); - ++WaveCount; - } else NextWaveTimer -= diff; - } - - if (CheckTimer <= diff) - { - for (uint8 i = 0; i < 2; ++i) - { - if (BossGUID[i]) - { - Unit* pUnit = Unit::GetUnit((*me), BossGUID[i]); - if (pUnit && (!pUnit->isAlive())) - { - if (BossGUID[i] == BossGUID[0]) - { - Talk(INCOMING); - FirstBossDead = true; - } - else if (BossGUID[i] == BossGUID[1]) - { - Talk(SUCCESS); - SecondBossDead = true; - } - EventBegun = false; - CheckTimer = 0; - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - BossGUID[i] = 0; - if (pInstance) - pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0); // Reset world state for enemies to disable it - } - } - } - CheckTimer = 5000; - } else CheckTimer -= diff; - - if (!UpdateVictim()) - return; - - for (uint8 i = 0; i < 3; ++i) - { - if (Spell[i].SpellId) - { - if (SpellTimer[i] <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - Unit *pTarget = NULL; - - switch(Spell[i].TargetType) - { - case TARGETTYPE_SELF: pTarget = me; break; - case TARGETTYPE_RANDOM: pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); break; - case TARGETTYPE_VICTIM: pTarget = me->getVictim(); break; - } - - if (pTarget && pTarget->isAlive()) - { - DoCast(pTarget, Spell[i].SpellId); - SpellTimer[i] = Spell[i].Cooldown; - } - } else SpellTimer[i] -= diff; - } - } - - DoMeleeAttackIfReady(); -} -void hyjalAI::JustDied(Unit* /*killer*/) -{ - if (IsDummy)return; - me->Respawn(); - me->SetVisibility(VISIBILITY_OFF); - DoRespawn = true; - RespawnTimer = 120000; - Talk(DEATH); - Summons.DespawnAll();//despawn all wave's summons - if (pInstance) - {//reset encounter if boss is despawned (ex: thrall is killed, boss despawns, event stucks at inprogress) - if (pInstance->GetData(DATA_RAGEWINTERCHILLEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_RAGEWINTERCHILLEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_ANETHERONEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_ANETHERONEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_KAZROGALEVENT) == IN_PROGRESS) - pInstance->SetData(DATA_KAZROGALEVENT, NOT_STARTED); - if (pInstance->GetData(DATA_AZGALOREVENT) == IN_PROGRESS) - pInstance->SetData(DATA_AZGALOREVENT, NOT_STARTED); - pInstance->SetData(DATA_RESET_RAIDDAMAGE, NULL);//reset damage on die - } -} -void hyjalAI::HideNearPos(float x, float y) -{ - CellPair pair(Trinity::ComputeCellPair(x, y)); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - // First get all creatures. - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - // Get Creatures - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - (*itr)->SetVisibility(VISIBILITY_OFF); - (*itr)->setFaction(35);//make them friendly so mobs won't attack them - } - } -} -void hyjalAI::RespawnNearPos(float x, float y) -{ - CellPair p(Trinity::ComputeCellPair(x, y)); - Cell cell(p); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - Trinity::RespawnDo u_do; - Trinity::WorldObjectWorker worker(me, u_do); - TypeContainerVisitor, GridTypeMapContainer > obj_worker(worker); - cell.Visit(p, obj_worker, *me->GetMap()); -} -void hyjalAI::WaypointReached(uint32 i) -{ - if (i == 1 || (i == 0 && me->GetEntry() == THRALL)) - { - me->MonsterYell(YELL_HURRY,0,0); - WaitForTeleport = true; - TeleportTimer = 20000; - if (me->GetEntry() == JAINA) - DoCast(me, SPELL_MASS_TELEPORT, false); - if (me->GetEntry() == THRALL && DummyGuid) - { - Unit* Dummy = Unit::GetUnit((*me),DummyGuid); - if (Dummy) - { - CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->DoMassTeleport = true; - CAST_AI(hyjalAI, CAST_CRE(Dummy)->AI())->MassTeleportTimer = 20000; - Dummy->CastSpell(me, SPELL_MASS_TELEPORT, false); - } - } - //do some talking - //all alive guards walk near here - CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - // First get all creatures. - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive() && (*itr) != me && (*itr)->GetEntry() != JAINA) - { - if (!(*itr)->IsWithinDist(me, 60)) - (*itr)->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - float x, y, z; - (*itr)->SetDefaultMovementType(IDLE_MOTION_TYPE); - (*itr)->GetMotionMaster()->Initialize(); - float range = 10; - if (me->GetEntry() == THRALL)range = 20; - me->GetNearPoint(me, x, y, z, range, 0, me->GetAngle((*itr))); - (*itr)->GetMotionMaster()->MovePoint(0, x+irand(-5,5), y+irand(-5,5), me->GetPositionZ()); - } - } - } - } -} -void hyjalAI::DoOverrun(uint32 faction, const uint32 diff) -{ - npc_escortAI::UpdateAI(diff); - if (WaitForTeleport) - { - if (TeleportTimer <= diff) - { - CellPair pair(Trinity::ComputeCellPair(me->GetPositionX(), me->GetPositionY())); - Cell cell(pair); - cell.data.Part.reserved = ALL_DISTRICT; - cell.SetNoCreate(); - - std::list creatures; - Trinity::AllFriendlyCreaturesInGrid creature_check(me); - Trinity::CreatureListSearcher creature_searcher(me, creatures, creature_check); - TypeContainerVisitor - , - GridTypeMapContainer> creature_visitor(creature_searcher); - - cell.Visit(pair, creature_visitor, *(me->GetMap())); - - if (!creatures.empty()) - { - for (std::list::const_iterator itr = creatures.begin(); itr != creatures.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive()) - { - (*itr)->CastSpell(*itr, SPELL_TELEPORT_VISUAL, true); - (*itr)->setFaction(35);//make them friendly so mobs won't attack them - (*itr)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - DoCast(me, SPELL_TELEPORT_VISUAL); - bRetreat = true; - RetreatTimer = 1000; - } - - WaitForTeleport = false; - Teleported = true; - }TeleportTimer -= diff; - } - if (!Teleported) - return; - Overrun = false;//execute once - switch(faction) - { - case 0://alliance - for (uint8 i = 0; i < 92; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,AllianceFirePos[i][0],AllianceFirePos[i][1],AllianceFirePos[i][2],AllianceFirePos[i][3],AllianceFirePos[i][4],AllianceFirePos[i][5],AllianceFirePos[i][6],AllianceFirePos[i][7],0); - - for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(GHOUL, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 3; ++i)//summon 3 abominations - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(ABOMINATION, AllianceBase[r][0]+irand(-15,15), AllianceBase[r][1]+irand(-15,15), AllianceBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 5; ++i)//summon 5 gargoyles - { - Creature* pUnit = me->SummonCreature(GARGOYLE, AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - pUnit->SetHomePosition(AllianceOverrunGargPos[i][0], AllianceOverrunGargPos[i][1], AllianceOverrunGargPos[i][2], AllianceOverrunGargPos[i][3]); - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - break; - case 1://horde - for (uint8 i = 0; i < 65; ++i)//summon fires - me->SummonGameObject(FLAMEOBJECT,HordeFirePos[i][0],HordeFirePos[i][1],HordeFirePos[i][2],HordeFirePos[i][3],HordeFirePos[i][4],HordeFirePos[i][5],HordeFirePos[i][6],HordeFirePos[i][7],0); - - for (uint8 i = 0; i < 26; ++i)//summon infernals - { - Creature* pUnit = me->SummonCreature(GIANT_INFERNAL, InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3], TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - pUnit->SetHomePosition(InfernalSPWP[i][0], InfernalSPWP[i][1], InfernalSPWP[i][2], InfernalSPWP[i][3]); - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 25; ++i)//summon 25 ghouls - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(GHOUL, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - for (uint8 i = 0; i < 5; ++i)//summon 5 abominations - { - uint8 r = rand()%4; - Creature* pUnit = me->SummonCreature(ABOMINATION, HordeBase[r][0]+irand(-15,15), HordeBase[r][1]+irand(-15,15), HordeBase[r][2], 0, TEMPSUMMON_MANUAL_DESPAWN, 2*60*1000); - if (pUnit) - { - CAST_AI(hyjal_trashAI, pUnit->AI())->faction = Faction; - CAST_AI(hyjal_trashAI, pUnit->AI())->IsOverrun = true; - CAST_AI(hyjal_trashAI, pUnit->AI())->OverrunType = i; - pUnit->setActive(true); - } - } - break; - } -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h deleted file mode 100644 index 5c75465b7b4..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjalAI.h +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef SC_HYJALAI_H -#define SC_HYJALAI_H - -#include "hyjal.h" -#include "ScriptedEscortAI.h" - -// Trash Mobs summoned in waves -#define NECROMANCER 17899//done -#define ABOMINATION 17898//done -#define GHOUL 17895//done -#define BANSHEE 17905//done -#define CRYPT_FIEND 17897//done -#define GARGOYLE 17906//done -#define FROST_WYRM 17907//done -#define GIANT_INFERNAL 17908//done -#define FEL_STALKER 17916//done - -#define JAINA 17772 -#define THRALL 17852 -#define TYRANDE 17948 - -#define ANCIENT_VEIN 185557 -#define FLAMEOBJECT 182592 - -// Bosses summoned after every 8 waves -#define RAGE_WINTERCHILL 17767 -#define ANETHERON 17808 -#define KAZROGAL 17888 -#define AZGALOR 17842 -#define ARCHIMONDE 17968 - -#define SPELL_TELEPORT_VISUAL 41232 -#define SPELL_MASS_TELEPORT 16807 - -//Spells for Jaina -#define SPELL_BRILLIANCE_AURA 31260 // The database must handle this spell via creature_addon(it should, but is removed in evade..) -#define SPELL_BLIZZARD 31266 -#define SPELL_PYROBLAST 31263 -#define SPELL_SUMMON_ELEMENTALS 31264 - -//Thrall spells -#define SPELL_CHAIN_LIGHTNING 31330 -#define SPELL_SUMMON_DIRE_WOLF 31331 - -struct Wave -{ - uint32 Mob[18]; // Stores Creature Entries to be summoned in Waves - uint32 WaveTimer; // The timer before the next wave is summoned - bool IsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that -}; - -static Wave AllianceWaves[]= // Waves that will be summoned in the Alliance Base -{ // Rage Winterchill Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron - {RAGE_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, - // Anetheron Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 120000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, BANSHEE, BANSHEE, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, GHOUL, GHOUL, 0, 0, 0, 0, 120000, false}, - {GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - // All 8 Waves are summoned, summon Anatheron - {ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} -}; - -static Wave HordeWaves[]= // Waves that are summoned in the Horde base -{ // Kaz'Rogal Wave 1-8 - {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, FROST_WYRM, 0, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, - // All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor - {KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}, - // Azgalor Wave 1-8 - {ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, FROST_WYRM, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, GARGOYLE, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GHOUL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, - {GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, 0, 0, 0, 0, 180000, false}, - {FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, 0, 0, 0, 0, 180000, false}, - {NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, NECROMANCER, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, BANSHEE, 0, 0, 0, 0, 0, 0, 180000, false}, - {GHOUL, GHOUL, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, GIANT_INFERNAL, 0, 0, 0, 0, 180000, false}, - {CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, CRYPT_FIEND, FEL_STALKER, FEL_STALKER, ABOMINATION, ABOMINATION, ABOMINATION, ABOMINATION, BANSHEE, BANSHEE, BANSHEE, BANSHEE, NECROMANCER, NECROMANCER, 0, 0, 240000, false}, - // All 8 Waves are summoned, summon Azgalor - {AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true} -}; - -enum TargetType // Used in the spell cast system for the AI -{ - TARGETTYPE_SELF = 0, - TARGETTYPE_RANDOM = 1, - TARGETTYPE_VICTIM = 2, -}; - -struct Yells -{ - uint32 id; // Used to determine the type of yell (attack, rally, etc) - int32 textid; // The text id to be yelled -}; - -enum YellId -{ - ATTACKED = 0, // Used when attacked and set in combat - BEGIN = 1, // Used when the event is begun - INCOMING = 2, // Used to warn the raid that another wave phase is coming - RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned - FAILURE = 4, // Used when raid has failed (unsure where to place) - SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase - DEATH = 6, // Used on death -}; - -static Yells JainaQuotes[]= -{ - {ATTACKED, -1534000}, - {ATTACKED, -1534001}, - {INCOMING, -1534002}, - {BEGIN, -1534003}, - {RALLY, -1534004}, - {RALLY, -1534005}, - {FAILURE, -1534006}, - {SUCCESS, -1534007}, - {DEATH, -1534008}, -}; - -static Yells ThrallQuotes[]= -{ - {ATTACKED, -1534009}, - {ATTACKED, -1534010}, - {INCOMING, -1534011}, - {BEGIN, -1534012}, - {RALLY, -1534013}, - {RALLY, -1534014}, - {FAILURE, -1534015}, - {SUCCESS, -1534016}, - {DEATH, -1534017}, -}; - -struct hyjalAI : public npc_escortAI -{ - hyjalAI(Creature *c); - - void Reset(); // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat - - void EnterEvadeMode(); // Send creature back to spawn location and evade. - - void EnterCombat(Unit * /*who*/); // Used to reset cooldowns for our spells and to inform the raid that we're under attack - - void UpdateAI(const uint32 diff); // Called to summon waves, check for boss deaths and to cast our spells. - - void JustDied(Unit* /*killer*/); // Called on death, informs the raid that they have failed. - - void SetFaction(uint32 _faction) // Set the faction to either Alliance or Horde in Hyjal - { - Faction = _faction; - } - - void Retreat(); // "Teleport" (teleport visual + set invisible) all friendly creatures away from the base. - - void SpawnVeins(); - void DeSpawnVeins(); - void JustSummoned(Creature *summoned); - void SummonedCreatureDespawn(Creature* summoned); - void HideNearPos(float x, float y); - void RespawnNearPos(float x, float y); - void WaypointReached(uint32 i); - void DoOverrun(uint32 faction, const uint32 diff); - void MoveInLineOfSight(Unit *who); - - void SummonCreature(uint32 entry, float Base[4][3]); // Summons a creature for that wave in that base - - // Summons the next wave, calls SummonCreature - void SummonNextWave(Wave wave[18], uint32 Count, float Base[4][3]); - - void StartEvent(Player* player); // Begins the event by gossip click - - uint32 GetInstanceData(uint32 Event); // Gets instance data for this instance, used to check if raid has gotten past a certain point and can access the next phase - - void Talk(uint32 id); // Searches for the appropriate yell and sound and uses it to inform the raid of various things - - public: - ScriptedInstance* pInstance; - - uint64 PlayerGUID; - uint64 BossGUID[2]; - uint64 VeinGUID[14]; - - uint32 NextWaveTimer; - uint32 WaveCount; - uint32 CheckTimer; - uint32 Faction; - uint32 EnemyCount; - uint32 RetreatTimer; - - bool EventBegun; - bool FirstBossDead; - bool SecondBossDead; - bool Summon; - bool bRetreat; - bool Debug; - bool VeinsSpawned[2]; - uint8 InfernalCount; - SummonList Summons; - bool Overrun; - bool Teleported; - bool WaitForTeleport; - uint32 TeleportTimer; - uint32 OverrunCounter; - uint32 OverrunCounter2; - uint32 InfernalPoint; - uint32 RespawnTimer; - bool DoRespawn; - bool DoHide; - bool IsDummy; - uint32 MassTeleportTimer; - bool DoMassTeleport; - uint64 DummyGuid; - - struct Spell - { - uint32 SpellId; - uint32 Cooldown; - uint32 TargetType; - }Spell[3]; - - private: - uint32 SpellTimer[3]; - //std::list CreatureList; -}; -#endif - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp deleted file mode 100644 index c4cf9ede397..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.cpp +++ /dev/null @@ -1,1440 +0,0 @@ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" -#include "hyjalAI.h" - -#define SPELL_METEOR 33814 //infernal visual -#define SPELL_IMMOLATION 37059 -#define SPELL_FLAME_BUFFET 31724 -#define NPC_TRIGGER 21987 //World Trigger (Tiny) -#define MODEL_INVIS 11686 //invisible model - -float HordeWPs[8][3]=//basic waypoints from spawn to leader -{ - {5492.91, -2404.61, 1462.63}, - {5531.76, -2460.87, 1469.55}, - {5554.58, -2514.66, 1476.12}, - {5554.16, -2567.23, 1479.90}, - {5540.67, -2625.99, 1480.89}, - {5508.16, -2659.20, 1480.15},//random rush starts from here - {5489.62, -2704.05, 1482.18}, - {5457.04, -2726.26, 1485.10} -}; -float AllianceWPs[8][3]=//basic waypoints from spawn to leader -{ - {4896.08, -1576.35, 1333.65}, - {4898.68, -1615.02, 1329.48}, - {4907.12, -1667.08, 1321.00}, - {4963.18, -1699.35, 1340.51}, - {4989.16, -1716.67, 1335.74},//first WP in the base, after the gate - {5026.27, -1736.89, 1323.02}, - {5037.77, -1770.56, 1324.36}, - {5067.23, -1789.95, 1321.17} -}; - -float FrostWyrmWPs[3][3]=//waypoints for the frost wyrms in horde base -{ - {5580.82, -2628.83, 1528.28}, - {5550.90, -2667.16, 1505.45}, - {5459.64, -2725.91, 1484.83} -}; - -float GargoyleWPs[3][3]=//waypoints for the gargoyles in horde base -{ - {5533.66, -2634.32, 1495.33}, - {5517.88, -2712.05, 1490.54}, - {5459.64, -2725.91, 1484.83} -}; - -float FlyPathWPs[3][3]=//waypoints for the gargoyls and frost wyrms in horde base in wave 1/3 -{ - {5531.96, -2772.83, 1516.68}, - {5498.32, -2734.84, 1497.01}, - {5456.67, -2725.48, 1493.08} -}; - -float AllianceOverrunWP[55][3]=//waypoints in the alliance base used in the end in the cleaning wave -{ - {4976.37,-1708.02,1339.43},//0spawn - {4994.83,-1725.52,1333.25},//1 start - {4982.92,-1753.7,1330.69},//2 end - {4996.75,-1721.47,1332.95},//3 start - {5015.74,-1755.05,1322.49},//4 - {4998.68,-1773.44,1329.59},//5 - {4994.83,-1725.52,1333.25},//6 start - {5022.8,-1735.46,1323.53},//7 - {5052.15,-1729.02,1320.88},//8 - {5082.43,-1726.29,1327.87},//9 - {4994.83,-1725.52,1333.25},//10 start - {5018.92,-1751.14,1322.19},//11 - {5040.09,-1792.09,1322.1},//12 - {4994.83,-1725.52,1333.25},//13 start - {5023.47,-1748.1,1322.51},//14 - {5013.43,-1842.39,1322.07},//15 - {4994.83,-1725.52,1333.25},//16 start - {5020.8,-1756.86,1322.2},//17 - {5019.53,-1824.6,1321.96},//18 - {5043.42,-1853.75,1324.52},//19 - {5053.02,-1864.13,1330.36},//20 - {5062.49,-1852.47,1330.49},//21 - {5015.27, -1738.77, 1324.83},//35//start 22 - {5027.97, -1775.25, 1321.87},//34 23 - {5015.94, -1821.24, 1321.86},//33 24 - {4983.25, -1857.4, 1320.48},//32 25 - {4981.51, -1883.7, 1322.34},//31 26 - {5002.33, -1893.98, 1325.88},//30 27 - {5049.32, -1886.54, 1331.69},//29 28 - {5089.68, -1846.88, 1328.99},//28 29 - {5127.90, -1825.14, 1335.58},//27 30 - {5163.27, -1789.08, 1337.04},//26 31 - {5138.97, -1755.88, 1334.57},//25 32 - {5096.63, -1742.22, 1329.61},//24 33 - {5065.81, -1729.43, 1325.66},//23 34 - {5049.32, -1726.31, 1320.64},//22 start - {5081.07, -1902.10, 1346.36},//36 abo start - {5107.65, -1912.03, 1356.49},//37 - {5132.83, -1927.07, 1362.42},//38 - {5147.78, -1954.41, 1365.98},//39 - {5164.96, -1966.48, 1367.04},//40 - {5189.04, -1961.06, 1367.90},//41 - {5212.27, -1975.30, 1365.58},//42 - {5221.82, -1994.18, 1364.97},//43 end1 - {5202.23, -1994.94, 1367.59},//44 end2 - {5279.94, -2049.68, 1311.38},//45 garg1 - {5289.15, -2219.06, 1291.12},//46 garg2 - {5202.07, -2136.10, 1305.07},//47 garg3 - {5071.52, -2425.63, 1454.48},//48 garg4 - {5120.65, -2467.92, 1463.93},//49 garg5 - {5283.04, -2043.26, 1300.11},//50 garg target1 - {5313.22, -2207.60, 1290.06},//51 garg target2 - {5180.41, -2121.87, 1292.62},//52 garg target3 - {5088.68, -2432.04, 1441.73},//53 garg target4 - {5111.26, -2454.73, 1449.63}//54 garg target5 - -}; - -float HordeOverrunWP[21][3]=//waypoints in the horde base used in the end in the cleaning wave -{ - {5490.72,-2702.94,1482.14},//0 start - {5469.77,-2741.34,1486.95}, - {5439.47,-2771.02,1494.59}, - {5408.85,-2811.92,1505.68}, - {5423.87,-2857.80,1515.55}, - {5428.19,-2898.15,1524.61}, - {5394.59,-2930.05,1528.23}, - {5351.11,-2935.80,1532.24}, - {5312.37,-2959.06,1536.21}, - {5264.93,-2989.80,1545.70}, - {5256.63,-3056.16,1559.24}, - {5267.32,-3119.55,1575.36}, - {5305.61,-3139.88,1586.38}, - {5330.56,-3135.37,1588.58}, - {5365.87,-3139.78,1583.96}, - {5389.39,-3163.57,1582.57},//15 end - {5500.86,-2669.89,1481.04},//16 start - {5472.08,-2715.14,1483.55}, - {5450.11,-2721.47,1485.61}, - {5433.25,-2712.93,1493.02},//19 end 1 - {5429.91,-2718.44,1493.42}//20 end 2 -}; - -hyjal_trashAI::hyjal_trashAI(Creature *c) : npc_escortAI(c) -{ - pInstance = c->GetInstanceData(); - IsEvent = false; - Delay = 0; - LastOverronPos = 0; - IsOverrun = false; - OverrunType = 0; - SetupOverrun = false; - faction = 0; - useFlyPath = false; - damageTaken = 0; - Reset(); -} - -void hyjal_trashAI::DamageTaken(Unit *done_by, uint32 &damage) -{ - if (done_by->GetTypeId() == TYPEID_PLAYER || (done_by->GetTypeId() == TYPEID_UNIT && CAST_CRE(done_by)->isPet())) - { - damageTaken += damage; - if (pInstance) - pInstance->SetData(DATA_RAIDDAMAGE,damage);//store raid's damage - } -} - -void hyjal_trashAI::UpdateAI(const uint32 /*diff*/) -{ - if (IsOverrun && !SetupOverrun) - { - SetupOverrun = true; - if (faction == 0) - { - if (me->GetEntry() == GARGOYLE) - { - DummyTarget[0] = AllianceOverrunWP[50+OverrunType][0]; //+OverrunType 0 - 4 - DummyTarget[1] = AllianceOverrunWP[50+OverrunType][1]; - DummyTarget[2] = AllianceOverrunWP[50+OverrunType][2]; - } - if (me->GetEntry() == ABOMINATION) - { - for (uint8 i = 0; i < 4; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); - AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); - AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); - AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); - AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); - AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); - AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); - - AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); - AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); - AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); - AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); - AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); - AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); - AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); - AddWaypoint(18, AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2]); - me->SetHomePosition(AllianceOverrunWP[43][0]+irand(-3,3), AllianceOverrunWP[43][1]+irand(-3,3), AllianceOverrunWP[43][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 18; - Start(true, true); - break; - case 1: - AddWaypoint(4, AllianceOverrunWP[22][0]+irand(-3,3), AllianceOverrunWP[22][1]+irand(-3,3), AllianceOverrunWP[22][2]); - AddWaypoint(5, AllianceOverrunWP[23][0]+irand(-3,3), AllianceOverrunWP[23][1]+irand(-3,3), AllianceOverrunWP[23][2]); - AddWaypoint(6, AllianceOverrunWP[24][0]+irand(-3,3), AllianceOverrunWP[24][1]+irand(-3,3), AllianceOverrunWP[24][2]); - AddWaypoint(7, AllianceOverrunWP[25][0]+irand(-3,3), AllianceOverrunWP[25][1]+irand(-3,3), AllianceOverrunWP[25][2]); - AddWaypoint(8, AllianceOverrunWP[26][0]+irand(-3,3), AllianceOverrunWP[26][1]+irand(-3,3), AllianceOverrunWP[26][2]); - AddWaypoint(9, AllianceOverrunWP[27][0]+irand(-3,3), AllianceOverrunWP[27][1]+irand(-3,3), AllianceOverrunWP[27][2]); - AddWaypoint(10, AllianceOverrunWP[28][0]+irand(-3,3), AllianceOverrunWP[28][1]+irand(-3,3), AllianceOverrunWP[28][2]); - - AddWaypoint(11, AllianceOverrunWP[36][0]+irand(-3,3), AllianceOverrunWP[36][1]+irand(-3,3), AllianceOverrunWP[36][2]); - AddWaypoint(12, AllianceOverrunWP[37][0]+irand(-3,3), AllianceOverrunWP[37][1]+irand(-3,3), AllianceOverrunWP[37][2]); - AddWaypoint(13, AllianceOverrunWP[38][0]+irand(-3,3), AllianceOverrunWP[38][1]+irand(-3,3), AllianceOverrunWP[38][2]); - AddWaypoint(14, AllianceOverrunWP[39][0]+irand(-3,3), AllianceOverrunWP[39][1]+irand(-3,3), AllianceOverrunWP[39][2]); - AddWaypoint(15, AllianceOverrunWP[40][0]+irand(-3,3), AllianceOverrunWP[40][1]+irand(-3,3), AllianceOverrunWP[40][2]); - AddWaypoint(16, AllianceOverrunWP[41][0]+irand(-3,3), AllianceOverrunWP[41][1]+irand(-3,3), AllianceOverrunWP[41][2]); - AddWaypoint(17, AllianceOverrunWP[42][0]+irand(-3,3), AllianceOverrunWP[42][1]+irand(-3,3), AllianceOverrunWP[42][2]); - AddWaypoint(18, AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2]); - me->SetHomePosition(AllianceOverrunWP[44][0]+irand(-3,3), AllianceOverrunWP[44][1]+irand(-3,3), AllianceOverrunWP[44][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 18; - Start(true, true); - break; - default: - for (uint8 i = 22; i < 36; ++i) - AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); - - SetDespawnAtEnd(true); - LastOverronPos = 17; - Start(true, true); - break; - } - } - if (me->GetEntry() == GHOUL) - { - for (uint8 i = 0; i < 4; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(4, AllianceOverrunWP[1][0]+irand(-3,3), AllianceOverrunWP[1][1]+irand(-3,3), AllianceOverrunWP[1][2]); - AddWaypoint(5, AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2]); - me->SetHomePosition(AllianceOverrunWP[2][0]+irand(-3,3), AllianceOverrunWP[2][1]+irand(-3,3), AllianceOverrunWP[2][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 5; - Start(true, true); - break; - case 1: - AddWaypoint(4, AllianceOverrunWP[3][0]+irand(-3,3), AllianceOverrunWP[3][1]+irand(-3,3), AllianceOverrunWP[3][2]); - AddWaypoint(5, AllianceOverrunWP[4][0]+irand(-3,3), AllianceOverrunWP[4][1]+irand(-3,3), AllianceOverrunWP[4][2]); - AddWaypoint(6, AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2]); - me->SetHomePosition(AllianceOverrunWP[5][0]+irand(-3,3), AllianceOverrunWP[5][1]+irand(-3,3), AllianceOverrunWP[5][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 2: - AddWaypoint(4, AllianceOverrunWP[6][0]+irand(-3,3), AllianceOverrunWP[6][1]+irand(-3,3), AllianceOverrunWP[6][2]); - AddWaypoint(5, AllianceOverrunWP[7][0]+irand(-3,3), AllianceOverrunWP[7][1]+irand(-3,3), AllianceOverrunWP[7][2]); - AddWaypoint(6, AllianceOverrunWP[8][0]+irand(-3,3), AllianceOverrunWP[8][1]+irand(-3,3), AllianceOverrunWP[8][2]); - AddWaypoint(7, AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2]); - me->SetHomePosition(AllianceOverrunWP[9][0]+irand(-3,3), AllianceOverrunWP[9][1]+irand(-3,3), AllianceOverrunWP[9][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 7; - Start(true, true); - break; - case 3: - AddWaypoint(4, AllianceOverrunWP[10][0]+irand(-3,3), AllianceOverrunWP[10][1]+irand(-3,3), AllianceOverrunWP[10][2]); - AddWaypoint(5, AllianceOverrunWP[11][0]+irand(-3,3), AllianceOverrunWP[11][1]+irand(-3,3), AllianceOverrunWP[11][2]); - AddWaypoint(6, AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2]); - me->SetHomePosition(AllianceOverrunWP[12][0]+irand(-3,3), AllianceOverrunWP[12][1]+irand(-3,3), AllianceOverrunWP[12][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 4: - AddWaypoint(4, AllianceOverrunWP[13][0]+irand(-3,3), AllianceOverrunWP[13][1]+irand(-3,3), AllianceOverrunWP[13][2]); - AddWaypoint(5, AllianceOverrunWP[14][0]+irand(-3,3), AllianceOverrunWP[14][1]+irand(-3,3), AllianceOverrunWP[14][2]); - AddWaypoint(6, AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2]); - me->SetHomePosition(AllianceOverrunWP[15][0]+irand(-3,3), AllianceOverrunWP[15][1]+irand(-3,3), AllianceOverrunWP[15][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 6; - Start(true, true); - break; - case 5: - AddWaypoint(4, AllianceOverrunWP[16][0]+irand(-3,3), AllianceOverrunWP[16][1]+irand(-3,3), AllianceOverrunWP[16][2]); - AddWaypoint(5, AllianceOverrunWP[17][0]+irand(-3,3), AllianceOverrunWP[17][1]+irand(-3,3), AllianceOverrunWP[17][2]); - AddWaypoint(6, AllianceOverrunWP[18][0]+irand(-3,3), AllianceOverrunWP[18][1]+irand(-3,3), AllianceOverrunWP[18][2]); - AddWaypoint(7, AllianceOverrunWP[19][0]+irand(-3,3), AllianceOverrunWP[19][1]+irand(-3,3), AllianceOverrunWP[19][2]); - AddWaypoint(8, AllianceOverrunWP[20][0]+irand(-3,3), AllianceOverrunWP[20][1]+irand(-3,3), AllianceOverrunWP[20][2]); - AddWaypoint(9, AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2]); - me->SetHomePosition(AllianceOverrunWP[21][0]+irand(-3,3), AllianceOverrunWP[21][1]+irand(-3,3), AllianceOverrunWP[21][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 9; - Start(true, true); - break; - default: - for (uint8 i = 22; i < 36; ++i) - AddWaypoint(i-18, AllianceOverrunWP[i][0]+irand(-3,3), AllianceOverrunWP[i][1]+irand(-3,3), AllianceOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 17; - Start(true, true); - break; - } - } - } - if (faction == 1) - { - if (me->GetEntry() == GHOUL) - { - for (uint8 i = 0; i < 6; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - switch(OverrunType) - { - case 0: - AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); - AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); - AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); - AddWaypoint(8, HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2]); - me->SetHomePosition(HordeOverrunWP[19][0], HordeOverrunWP[19][1], HordeOverrunWP[19][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 8; - Start(true, true); - break; - case 1: - AddWaypoint(5, HordeOverrunWP[16][0]+irand(-10,10), HordeOverrunWP[16][1]+irand(-10,10), HordeOverrunWP[16][2]); - AddWaypoint(6, HordeOverrunWP[17][0]+irand(-10,10), HordeOverrunWP[17][1]+irand(-10,10), HordeOverrunWP[17][2]); - AddWaypoint(7, HordeOverrunWP[18][0], HordeOverrunWP[18][1], HordeOverrunWP[18][2]); - AddWaypoint(8, HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2]); - me->SetHomePosition(HordeOverrunWP[20][0], HordeOverrunWP[20][1], HordeOverrunWP[20][2],0); - SetDespawnAtEnd(false); - LastOverronPos = 8; - Start(true, true); - break; - default: - for (uint8 i = 0; i < 16; ++i) - AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 21; - Start(true, true); - break; - } - } - if (me->GetEntry() == ABOMINATION) - { - for (uint8 i = 0; i < 6; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-10,10), HordeWPs[i][1]+irand(-10,10), HordeWPs[i][2]); - for (uint8 i = 0; i < 16; ++i) - AddWaypoint(i+6, HordeOverrunWP[i][0]+irand(-10,10), HordeOverrunWP[i][1]+irand(-10,10), HordeOverrunWP[i][2]); - SetDespawnAtEnd(true); - LastOverronPos = 21; - Start(true, true); - } - } - } -} - -void hyjal_trashAI::JustDied(Unit * /*victim*/) -{ - if (!pInstance) - return; - if (IsEvent && !me->isWorldBoss()) - pInstance->SetData(DATA_TRASH, 0);//signal trash is dead - - if ((pInstance->GetData(DATA_RAIDDAMAGE) < MINRAIDDAMAGE && !me->isWorldBoss()) || (damageTaken < me->GetMaxHealth()/4 && me->isWorldBoss())) - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);//no loot -} - -struct mob_giant_infernalAI : public hyjal_trashAI -{ - mob_giant_infernalAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - meteor = false;//call once! - CanMove = false; - Delay = rand()%30000; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(MODEL_INVIS); - pGo = false; - pos = 0; - Reset(); - } - - bool meteor; - bool CanMove; - bool WpEnabled; - bool pGo; - uint32 pos; - uint32 spawnTimer; - uint32 FlameBuffetTimer; - bool imol; - - void Reset() - { - spawnTimer = 2000; - FlameBuffetTimer= 2000; - imol = false; - } - - void EnterCombat(Unit* /*who*/) {} - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 0 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (Delay <= diff) - { - Delay=0; - }else{ - Delay-=diff; - return; - } - if (!meteor) - { - float x,y,z; - me->GetPosition(x,y,z); - Creature* trigger = me->SummonCreature(NPC_TRIGGER,x+8,y+8,z+25+rand()%10,me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,1000); - if (trigger) - { - trigger->SetVisibility(VISIBILITY_OFF); - trigger->setFaction(me->getFaction()); - trigger->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - trigger->CastSpell(me,SPELL_METEOR,true); - } - me->GetMotionMaster()->Clear(); - meteor = true; - } else if (!CanMove){ - if (spawnTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(me->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID)); - CanMove = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && !pInstance->GetData(DATA_HORDE_RETREAT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } else if (pInstance->GetData(DATA_ALLIANCE_RETREAT) && pInstance->GetData(DATA_HORDE_RETREAT)){ - //do overrun - } - } - } else spawnTimer -= diff; - } - if (!CanMove)return; - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - AddWaypoint(0, HordeWPs[7][0]+irand(-3,3), HordeWPs[7][1]+irand(-3,3), HordeWPs[7][2]);//HordeWPs[7] infront of thrall - Start(true, true); - SetDespawnAtEnd(false); - } - } - } - - if (!UpdateVictim()) - return; - if (!imol) - { - DoCast(me, SPELL_IMMOLATION); - imol=true; - } - if (FlameBuffetTimer <= diff) - { - DoCast(me->getVictim(), SPELL_FLAME_BUFFET, true); - FlameBuffetTimer = 7000; - } else FlameBuffetTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_giant_infernal(Creature* pCreature) -{ - return new mob_giant_infernalAI(pCreature); -} - -#define SPELL_DISEASE_CLOUD 31607 -#define SPELL_KNOCKDOWN 31610 - -struct mob_abominationAI : public hyjal_trashAI -{ - mob_abominationAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 KnockDownTimer; - uint32 pos; - void Reset() - { - KnockDownTimer = 10000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - if (i == LastOverronPos && IsOverrun) - { - if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) - { - me->setDeathState(DEAD); - me->RemoveCorpse(); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!me->HasAura(SPELL_DISEASE_CLOUD)) - DoCast(me, SPELL_DISEASE_CLOUD); - if (!UpdateVictim()) - return; - if (KnockDownTimer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - KnockDownTimer = 15000+rand()%10000; - } else KnockDownTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_abomination(Creature* pCreature) -{ - return new mob_abominationAI(pCreature); -} - -#define SPELL_FRENZY 31540 - -struct mob_ghoulAI : public hyjal_trashAI -{ - mob_ghoulAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 FrenzyTimer; - uint32 pos; - uint32 MoveTimer; - bool RandomMove; - void Reset() - { - FrenzyTimer = 5000+rand()%5000; - MoveTimer = 2000; - RandomMove = false; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - if (i == LastOverronPos && IsOverrun) - { - me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_ATTACKUNARMED); - if ((faction == 0 && LastOverronPos == 17) || (faction == 1 && LastOverronPos == 21)) - { - me->setDeathState(DEAD); - me->RemoveCorpse(); - } - - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (FrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - FrenzyTimer = 15000+rand()%15000; - } else FrenzyTimer -= diff; - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_ghoul(Creature* pCreature) -{ - return new mob_ghoulAI(pCreature); -} - -#define SPELL_RAISE_DEAD_1 31617 -#define SPELL_RAISE_DEAD_2 31624 -#define SPELL_RAISE_DEAD_3 31625 -#define SPELL_SHADOW_BOLT 31627 - -struct mob_necromancerAI : public hyjal_trashAI -{ - mob_necromancerAI(Creature* c) : hyjal_trashAI(c), summons(me) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - SummonList summons; - bool pGo; - uint32 ShadowBoltTimer; - uint32 pos; - void Reset() - { - ShadowBoltTimer = 1000+rand()%5000; - summons.DespawnAll(); - } - - void JustSummoned(Creature* summon) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,true); - if (pTarget && summon) - summon->Attack(pTarget,false); - summons.Summon(summon); - } - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - switch (urand(0,2)) - { - case 0: - DoSpawnCreature(17902,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - DoSpawnCreature(17902,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - case 1: - DoSpawnCreature(17903,3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - DoSpawnCreature(17903,-3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - case 2: - DoSpawnCreature(RAND(17902,17903),3,0,0,0,TEMPSUMMON_TIMED_DESPAWN, 60000); - break; - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(true, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(true, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (ShadowBoltTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - ShadowBoltTimer = 20000+rand()%10000; - } else ShadowBoltTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_necromancer(Creature* pCreature) -{ - return new mob_necromancerAI(pCreature); -} - -#define SPELL_BANSHEE_CURSE 31651 -#define SPELL_BANSHEE_WAIL 38183 -#define SPELL_ANTI_MAGIC_SHELL 31662 - -struct mob_bansheeAI : public hyjal_trashAI -{ - mob_bansheeAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 CourseTimer; - uint32 WailTimer; - uint32 ShellTimer; - uint32 pos; - void Reset() - { - CourseTimer = 20000+rand()%5000; - WailTimer = 15000+rand()%5000; - ShellTimer = 50000+rand()%10000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (CourseTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BANSHEE_CURSE); - CourseTimer = 20000+rand()%5000; - } else CourseTimer -= diff; - if (WailTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BANSHEE_WAIL); - WailTimer = 15000+rand()%5000; - } else WailTimer -= diff; - if (ShellTimer <= diff) - { - DoCast(me, SPELL_ANTI_MAGIC_SHELL); - ShellTimer = 50000+rand()%10000; - } else ShellTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_banshee(Creature* pCreature) -{ - return new mob_bansheeAI(pCreature); -} - -#define SPELL_WEB 28991 - -struct mob_crypt_fiendAI : public hyjal_trashAI -{ - mob_crypt_fiendAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 WebTimer; - uint32 pos; - void Reset() - { - WebTimer = 20000+rand()%5000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - - } - } - } - if (!UpdateVictim()) - return; - if (WebTimer <= diff) - { - DoCast(me->getVictim(), SPELL_WEB); - WebTimer = 20000+rand()%5000; - } else WebTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_crypt_fiend(Creature* pCreature) -{ - return new mob_crypt_fiendAI(pCreature); -} - -#define SPELL_MANA_BURN 31729 - -struct mob_fel_stalkerAI : public hyjal_trashAI -{ - mob_fel_stalkerAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 ManaBurnTimer; - uint32 pos; - void Reset() - { - ManaBurnTimer = 9000+rand()%5000; - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 7 && pInstance && !IsOverrun) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, attack thrall - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - }else{ - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_JAINAPROUDMOORE)); - if (pTarget && pTarget->isAlive()) - me->AddThreat(pTarget,0.0); - } - } - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - npc_escortAI::UpdateAI(diff); - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (pInstance->GetData(DATA_ALLIANCE_RETREAT))//2.alliance boss down, use horde WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, HordeWPs[i][0]+irand(-3,3), HordeWPs[i][1]+irand(-3,3), HordeWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else//use alliance WPs - { - for (uint8 i = 0; i < 8; ++i) - AddWaypoint(i, AllianceWPs[i][0]+irand(-3,3), AllianceWPs[i][1]+irand(-3,3), AllianceWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - - } - } - } - if (!UpdateVictim()) - return; - if (ManaBurnTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MANA_BURN); - ManaBurnTimer = 9000+rand()%5000; - } else ManaBurnTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_fel_stalker(Creature* pCreature) -{ - return new mob_fel_stalkerAI(pCreature); -} - -#define SPELL_FROST_BREATH 31688 - -struct mob_frost_wyrmAI : public hyjal_trashAI -{ - mob_frost_wyrmAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - Reset(); - } - - bool pGo; - uint32 FrostBreathTimer; - uint32 pos; - uint32 MoveTimer; - - void Reset() - { - FrostBreathTimer = 5000; - MoveTimer = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 2 && pInstance && !IsOverrun) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - { - me->AddThreat(pTarget,0.0); - DoCast(pTarget, SPELL_FROST_BREATH, true); - } - } - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance && IsEvent) - pInstance->SetData(DATA_TRASH, 0);//signal trash is dead - - float x,y,z; - me->GetPosition(x,y,z); - z = me->GetMap()->GetHeight(x, y, z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - me->GetMap()->CreatureRelocation(me, x,y,z,0); - } - - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - { - CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); - npc_escortAI::UpdateAI(diff); - } - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (!useFlyPath) - { - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FrostWyrmWPs[i][0], FrostWyrmWPs[i][1], FrostWyrmWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else{//fly path FlyPathWPs - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (!UpdateVictim()) - return; - if (!me->IsWithinDist(me->getVictim(), 25)){ - if (MoveTimer <= diff) - { - me->GetMotionMaster()->MoveChase(me->getVictim()); - MoveTimer = 2000; - } else MoveTimer-=diff; - } - - if (FrostBreathTimer <= diff) - { - if (!me->IsWithinDist(me->getVictim(), 25)) - { - DoCast(me->getVictim(), SPELL_FROST_BREATH); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - FrostBreathTimer = 4000; - } - } else FrostBreathTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_frost_wyrm(Creature* pCreature) -{ - return new mob_frost_wyrmAI(pCreature); -} - -#define SPELL_GARGOYLE_STRIKE 31664 - -struct mob_gargoyleAI : public hyjal_trashAI -{ - mob_gargoyleAI(Creature* c) : hyjal_trashAI(c) - { - pInstance = c->GetInstanceData(); - pGo = false; - pos = 0; - DummyTarget[0] = 0;DummyTarget[1] = 0;DummyTarget[2] = 0; - Reset(); - } - - bool pGo; - uint32 StrikeTimer; - uint32 pos; - uint32 MoveTimer; - float Zpos; - bool forcemove; - - void Reset() - { - forcemove = true; - Zpos = 10.0; - StrikeTimer = 2000+rand()%5000; - MoveTimer = 0; - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - } - - void WaypointReached(uint32 i) - { - pos = i; - if (i == 2 && pInstance && !IsOverrun) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_THRALL)); - if (pTarget && pTarget->isAlive()) - { - me->AddThreat(pTarget,0.0); - DoCast(pTarget, SPELL_GARGOYLE_STRIKE, true); - } - } - } - - void JustDied(Unit *victim) - { - float x,y,z; - me->GetPosition(x,y,z); - z = me->GetMap()->GetHeight(x, y, z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - me->GetMap()->CreatureRelocation(me, x,y,z,0); - hyjal_trashAI::JustDied(victim); - } - - void UpdateAI(const uint32 diff) - { - hyjal_trashAI::UpdateAI(diff); - if (IsEvent || IsOverrun) - { - CAST_AI(hyjal_trashAI, me->AI())->SetCanAttack(false); - npc_escortAI::UpdateAI(diff); - } - if (IsEvent) - { - if (!pGo) - { - pGo = true; - if (pInstance) - { - if (!useFlyPath) - { - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, GargoyleWPs[i][0]+irand(-10,10), GargoyleWPs[i][1]+irand(-10,10), GargoyleWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - }else{//fly path FlyPathWPs - for (uint8 i = 0; i < 3; ++i) - AddWaypoint(i, FlyPathWPs[i][0]+irand(-10,10), FlyPathWPs[i][1]+irand(-10,10), FlyPathWPs[i][2]); - Start(false, true); - SetDespawnAtEnd(false); - } - } - } - } - if (IsOverrun && !UpdateVictim()) - { - if (faction == 0)//alliance - { - if (StrikeTimer <= diff) - { - me->CastSpell(DummyTarget[0],DummyTarget[1],DummyTarget[2],SPELL_GARGOYLE_STRIKE,false); - StrikeTimer = 2000+rand()%1000; - } else StrikeTimer -= diff; - } - } - if (!UpdateVictim()) - return; - if (!me->IsWithinDist(me->getVictim(), 20) || forcemove) - { - forcemove = false; - if (forcemove) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - me->Attack(pTarget,false); - } - if (MoveTimer <= diff) - { - float x,y,z; - me->getVictim()->GetPosition(x,y,z); - me->GetMotionMaster()->MovePoint(0,x,y,z+Zpos); - Zpos-=1.0; - if (Zpos <= 0)Zpos=0; - MoveTimer = 2000; - } else MoveTimer-=diff; - } - if (StrikeTimer <= diff) - { - if (me->IsWithinDist(me->getVictim(), 20)) - { - DoCast(me->getVictim(), SPELL_GARGOYLE_STRIKE); - me->StopMoving(); - me->GetMotionMaster()->Clear(); - StrikeTimer = 2000+rand()%1000; - } else StrikeTimer=0; - } else StrikeTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_gargoyle(Creature* pCreature) -{ - return new mob_gargoyleAI(pCreature); -} - -#define SPELL_EXPLODING_SHOT 7896 - -struct alliance_riflemanAI : public Scripted_NoMovementAI -{ - alliance_riflemanAI(Creature *c) : Scripted_NoMovementAI(c) - { - Reset(); - } - - uint32 ExplodeTimer; - - void JustDied(Unit* /*who*/) - { - } - - void Reset() - { - ExplodeTimer = 5000+rand()%5000; - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && me->IsHostileTo(who)) - { - //float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, 30)) - AttackStart(who); - } - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Check if we have a target - if (!UpdateVictim()) - return; - if (ExplodeTimer <= diff) - { - if (!me->IsWithinDistInMap(me->getVictim(), 30)) - { - EnterEvadeMode(); - return; - } - int dmg = 500+rand()%700; - me->CastCustomSpell(me->getVictim(), SPELL_EXPLODING_SHOT, &dmg, 0, 0, false); - ExplodeTimer = 5000+rand()%5000; - } else ExplodeTimer -= diff; - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_alliance_rifleman(Creature* pCreature) -{ - return new alliance_riflemanAI(pCreature); -} - -void AddSC_hyjal_trash() -{ - Script *newscript = new Script; - newscript->Name = "mob_giant_infernal"; - newscript->GetAI = &GetAI_mob_giant_infernal; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_abomination"; - newscript->GetAI = &GetAI_mob_abomination; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ghoul"; - newscript->GetAI = &GetAI_mob_ghoul; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_necromancer"; - newscript->GetAI = &GetAI_mob_necromancer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_banshee"; - newscript->GetAI = &GetAI_mob_banshee; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crypt_fiend"; - newscript->GetAI = &GetAI_mob_crypt_fiend; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fel_stalker"; - newscript->GetAI = &GetAI_mob_fel_stalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frost_wyrm"; - newscript->GetAI = &GetAI_mob_frost_wyrm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_gargoyle"; - newscript->GetAI = &GetAI_mob_gargoyle; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "alliance_rifleman"; - newscript->GetAI = &GetAI_alliance_rifleman; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h deleted file mode 100644 index 21ee4bc06cc..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/hyjal_trash.h +++ /dev/null @@ -1,35 +0,0 @@ - -#ifndef SC_HYJAL_TRASH_AI_H -#define SC_HYJAL_TRASH_AI_H - -#include "hyjal.h" -#include "ScriptedEscortAI.h" - -#define MINRAIDDAMAGE 700000//minimal damage before trash can drop loot and reputation, resets if faction leader dies - -struct hyjal_trashAI : public npc_escortAI -{ - hyjal_trashAI(Creature *c); - - void UpdateAI(const uint32 diff); - - void JustDied(Unit* /*killer*/); - - void DamageTaken(Unit *done_by, uint32 &damage); - - public: - ScriptedInstance* pInstance; - bool IsEvent; - uint32 Delay; - uint32 LastOverronPos; - bool IsOverrun; - bool SetupOverrun; - uint32 OverrunType; - uint8 faction; - bool useFlyPath; - uint32 damageTaken; - float DummyTarget[3]; - - //private: -}; -#endif diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp deleted file mode 100644 index e89d518c5bc..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/hyjal/instance_hyjal.cpp +++ /dev/null @@ -1,324 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Mount_Hyjal -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts -SDCategory: Caverns of Time, Mount Hyjal -EndScriptData */ - -#include "ScriptedPch.h" -#include "hyjal.h" -#include "hyjal_trash.h" - -enum eEnums -{ - MAX_ENCOUNTER = 5, - - GO_ANCIENT_GEM = 185557 -}; -/* Battle of Mount Hyjal encounters: -0 - Rage Winterchill event -1 - Anetheron event -2 - Kaz'rogal event -3 - Azgalor event -4 - Archimonde event -*/ - -struct instance_mount_hyjal : public ScriptedInstance -{ - instance_mount_hyjal(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - std::list m_uiAncientGemGUID; - - uint64 RageWinterchill; - uint64 Anetheron; - uint64 Kazrogal; - uint64 Azgalor; - uint64 Archimonde; - uint64 JainaProudmoore; - uint64 Thrall; - uint64 TyrandeWhisperwind; - uint64 HordeGate; - uint64 ElfGate; - - uint32 Trash; - - uint32 hordeRetreat; - uint32 allianceRetreat; - bool ArchiYell; - - uint32 RaidDamage; - - #define YELL_EFFORTS "All of your efforts have been in vain, for the draining of the World Tree has already begun. Soon the heart of your world will beat no more." - #define YELL_EFFORTS_NAME "Archimonde" - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiAncientGemGUID.clear(); - - RageWinterchill = 0; - Anetheron = 0; - Kazrogal = 0; - Azgalor = 0; - Archimonde = 0; - JainaProudmoore = 0; - Thrall = 0; - TyrandeWhisperwind = 0; - HordeGate = 0; - ElfGate = 0; - ArchiYell = false; - RaidDamage = 0; - - Trash = 0; - - hordeRetreat = 0; - allianceRetreat = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 182060: - HordeGate = pGo->GetGUID(); - if (allianceRetreat) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - case 182061: - ElfGate = pGo->GetGUID(); - if (hordeRetreat) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - case GO_ANCIENT_GEM: - m_uiAncientGemGUID.push_back(pGo->GetGUID()); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17767: RageWinterchill = pCreature->GetGUID(); break; - case 17808: Anetheron = pCreature->GetGUID(); break; - case 17888: Kazrogal = pCreature->GetGUID(); break; - case 17842: Azgalor = pCreature->GetGUID(); break; - case 17968: Archimonde = pCreature->GetGUID(); break; - case 17772: JainaProudmoore = pCreature->GetGUID(); break; - case 17852: Thrall = pCreature->GetGUID(); break; - case 17948: TyrandeWhisperwind = pCreature->GetGUID(); break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_RAGEWINTERCHILL: return RageWinterchill; - case DATA_ANETHERON: return Anetheron; - case DATA_KAZROGAL: return Kazrogal; - case DATA_AZGALOR: return Azgalor; - case DATA_ARCHIMONDE: return Archimonde; - case DATA_JAINAPROUDMOORE: return JainaProudmoore; - case DATA_THRALL: return Thrall; - case DATA_TYRANDEWHISPERWIND: return TyrandeWhisperwind; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_RAGEWINTERCHILLEVENT: m_auiEncounter[0] = data; break; - case DATA_ANETHERONEVENT: - m_auiEncounter[1] = data; - break; - case DATA_KAZROGALEVENT: m_auiEncounter[2] = data; break; - case DATA_AZGALOREVENT: - { - m_auiEncounter[3] = data; - if (data == DONE) - { - if (ArchiYell)break; - ArchiYell = true; - - Creature* pCreature = instance->GetCreature(Azgalor); - if (pCreature) - { - Creature* pUnit = pCreature->SummonCreature(21987,pCreature->GetPositionX(),pCreature->GetPositionY(),pCreature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,10000); - - Map* pMap = pCreature->GetMap(); - if (pMap->IsDungeon() && pUnit) - { - pUnit->SetVisibility(VISIBILITY_OFF); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource()) - { - WorldPacket data(SMSG_MESSAGECHAT, 200); - pUnit->BuildMonsterChat(&data,CHAT_MSG_MONSTER_YELL,YELL_EFFORTS,0,YELL_EFFORTS_NAME,i->getSource()->GetGUID()); - i->getSource()->GetSession()->SendPacket(&data); - - WorldPacket data2(SMSG_PLAY_SOUND, 4); - data2 << 10986; - i->getSource()->GetSession()->SendPacket(&data2); - } - } - } - } - } - } - break; - case DATA_ARCHIMONDEEVENT: m_auiEncounter[4] = data; break; - case DATA_RESET_TRASH_COUNT: Trash = 0; break; - - case DATA_TRASH: - if (data) Trash = data; - else Trash--; - DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, Trash); - break; - case TYPE_RETREAT: - if (data == SPECIAL) - { - if (!m_uiAncientGemGUID.empty()) - { - for (std::list::const_iterator itr = m_uiAncientGemGUID.begin(); itr != m_uiAncientGemGUID.end(); ++itr) - { - //don't know how long it expected - DoRespawnGameObject(*itr,DAY); - } - } - } - break; - case DATA_ALLIANCE_RETREAT: - allianceRetreat = data; - HandleGameObject(HordeGate, true); - SaveToDB(); - break; - case DATA_HORDE_RETREAT: - hordeRetreat = data; - HandleGameObject(ElfGate, true); - SaveToDB(); - break; - case DATA_RAIDDAMAGE: - RaidDamage += data; - if (RaidDamage >= MINRAIDDAMAGE) - RaidDamage = MINRAIDDAMAGE; - break; - case DATA_RESET_RAIDDAMAGE: - RaidDamage = 0; - break; - } - - debug_log("TSCR: Instance Hyjal: Instance data updated for event %u (Data=%u)",type,data); - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] - << " " << allianceRetreat << " " << hordeRetreat - << " " << RaidDamage; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_RAGEWINTERCHILLEVENT: return m_auiEncounter[0]; - case DATA_ANETHERONEVENT: return m_auiEncounter[1]; - case DATA_KAZROGALEVENT: return m_auiEncounter[2]; - case DATA_AZGALOREVENT: return m_auiEncounter[3]; - case DATA_ARCHIMONDEEVENT: return m_auiEncounter[4]; - case DATA_TRASH: return Trash; - case DATA_ALLIANCE_RETREAT: return allianceRetreat; - case DATA_HORDE_RETREAT: return hordeRetreat; - case DATA_RAIDDAMAGE: return RaidDamage; - } - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4] >> allianceRetreat >> hordeRetreat >> RaidDamage; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_mount_hyjal(Map* pMap) -{ - return new instance_mount_hyjal(pMap); -} - -void AddSC_instance_mount_hyjal() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_hyjal"; - newscript->GetInstanceData = &GetInstanceData_instance_mount_hyjal; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp deleted file mode 100644 index 91c9e274b83..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_captain_skarloc.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Captain_Skarloc -SD%Complete: 75 -SDComment: Missing adds, missing waypoints to move up to Thrall once spawned + speech before enter combat. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define SAY_ENTER -1560000 -#define SAY_TAUNT1 -1560001 -#define SAY_TAUNT2 -1560002 -#define SAY_SLAY1 -1560003 -#define SAY_SLAY2 -1560004 -#define SAY_DEATH -1560005 - -#define SPELL_HOLY_LIGHT 29427 -#define SPELL_CLEANSE 29380 -#define SPELL_HAMMER_OF_JUSTICE 13005 -#define SPELL_HOLY_SHIELD 31904 -#define SPELL_DEVOTION_AURA 8258 -#define SPELL_CONSECRATION 38385 - -struct boss_captain_skarlocAI : public ScriptedAI -{ - boss_captain_skarlocAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Holy_Light_Timer; - uint32 Cleanse_Timer; - uint32 HammerOfJustice_Timer; - uint32 HolyShield_Timer; - uint32 DevotionAura_Timer; - uint32 Consecration_Timer; - - void Reset() - { - Holy_Light_Timer = 20000 + rand()%10000; - Cleanse_Timer = 10000; - HammerOfJustice_Timer = 20000 + rand()%15000; - HolyShield_Timer = 240000; - DevotionAura_Timer = 3000; - Consecration_Timer = 8000; - } - - void EnterCombat(Unit * /*who*/) - { - //This is not correct. Should taunt Thrall before engage in combat - DoScriptText(SAY_TAUNT1, me); - DoScriptText(SAY_TAUNT2, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - pInstance->SetData(TYPE_THRALL_PART1, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Holy_Light - if (Holy_Light_Timer <= diff) - { - DoCast(me, SPELL_HOLY_LIGHT); - Holy_Light_Timer = 30000; - } else Holy_Light_Timer -= diff; - - //Cleanse - if (Cleanse_Timer <= diff) - { - DoCast(me, SPELL_CLEANSE); - Cleanse_Timer = 10000; - } else Cleanse_Timer -= diff; - - //Hammer of Justice - if (HammerOfJustice_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); - HammerOfJustice_Timer = 60000; - } else HammerOfJustice_Timer -= diff; - - //Holy Shield - if (HolyShield_Timer <= diff) - { - DoCast(me, SPELL_HOLY_SHIELD); - HolyShield_Timer = 240000; - } else HolyShield_Timer -= diff; - - //Devotion_Aura - if (DevotionAura_Timer <= diff) - { - DoCast(me, SPELL_DEVOTION_AURA); - DevotionAura_Timer = 45000 + rand()%10000; - } else DevotionAura_Timer -= diff; - - //Consecration - if (Consecration_Timer <= diff) - { - //DoCast(me->getVictim(), SPELL_CONSECRATION); - Consecration_Timer = 5000 + rand()%5000; - } else Consecration_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_captain_skarloc(Creature* pCreature) -{ - return new boss_captain_skarlocAI (pCreature); -} - -void AddSC_boss_captain_skarloc() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_captain_skarloc"; - newscript->GetAI = &GetAI_boss_captain_skarloc; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp deleted file mode 100644 index 2c2ad96ddb7..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_epoch_hunter.cpp +++ /dev/null @@ -1,138 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Epoch_Hunter -SD%Complete: 60 -SDComment: Missing spawns pre-event, missing speech to be coordinated with rest of escort event. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define SAY_ENTER1 -1560013 -#define SAY_ENTER2 -1560014 -#define SAY_ENTER3 -1560015 -#define SAY_AGGRO1 -1560016 -#define SAY_AGGRO2 -1560017 -#define SAY_SLAY1 -1560018 -#define SAY_SLAY2 -1560019 -#define SAY_BREATH1 -1560020 -#define SAY_BREATH2 -1560021 -#define SAY_DEATH -1560022 - -#define SPELL_SAND_BREATH 31914 -#define SPELL_IMPENDING_DEATH 31916 -#define SPELL_MAGIC_DISRUPTION_AURA 33834 -#define SPELL_WING_BUFFET 31475 - -struct boss_epoch_hunterAI : public ScriptedAI -{ - boss_epoch_hunterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 SandBreath_Timer; - uint32 ImpendingDeath_Timer; - uint32 WingBuffet_Timer; - uint32 Mda_Timer; - - void Reset() - { - SandBreath_Timer = 8000 + rand()%8000; - ImpendingDeath_Timer = 25000 + rand()%5000; - WingBuffet_Timer = 35000; - Mda_Timer = 40000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2), me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - pInstance->SetData(TYPE_THRALL_PART4, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Sand Breath - if (SandBreath_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me->getVictim(), SPELL_SAND_BREATH); - - DoScriptText(RAND(SAY_BREATH1,SAY_BREATH2), me); - - SandBreath_Timer = 10000 + rand()%10000; - } else SandBreath_Timer -= diff; - - if (ImpendingDeath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_IMPENDING_DEATH); - ImpendingDeath_Timer = 25000+rand()%5000; - } else ImpendingDeath_Timer -= diff; - - if (WingBuffet_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_WING_BUFFET); - WingBuffet_Timer = 25000+rand()%10000; - } else WingBuffet_Timer -= diff; - - if (Mda_Timer <= diff) - { - DoCast(me, SPELL_MAGIC_DISRUPTION_AURA); - Mda_Timer = 15000; - } else Mda_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_epoch_hunter(Creature* pCreature) -{ - return new boss_epoch_hunterAI (pCreature); -} - -void AddSC_boss_epoch_hunter() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_epoch_hunter"; - newscript->GetAI = &GetAI_boss_epoch_hunter; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp deleted file mode 100644 index dae0f5390b1..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/boss_leutenant_drake.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Luetenant_Drake -SD%Complete: 70 -SDComment: Missing proper code for patrolling area after being spawned. Script for GO (barrels) quest 10283 -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" -#include "ScriptedEscortAI.h" - -/*###### -## go_barrel_old_hillsbrad -######*/ - -bool GOHello_go_barrel_old_hillsbrad(Player* /*pPlayer*/, GameObject* pGO) -{ - if (ScriptedInstance* pInstance = pGO->GetInstanceData()) - { - if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE) - return false; - - pInstance->SetData(TYPE_BARREL_DIVERSION, IN_PROGRESS); - } - - return false; -} - -/*###### -## boss_lieutenant_drake -######*/ - -#define SAY_ENTER -1560006 -#define SAY_AGGRO -1560007 -#define SAY_SLAY1 -1560008 -#define SAY_SLAY2 -1560009 -#define SAY_MORTAL -1560010 -#define SAY_SHOUT -1560011 -#define SAY_DEATH -1560012 - -#define SPELL_WHIRLWIND 31909 -#define SPELL_HAMSTRING 9080 -#define SPELL_MORTAL_STRIKE 31911 -#define SPELL_FRIGHTENING_SHOUT 33789 - -struct Location -{ - uint32 wpId; - float x; - float y; - float z; -}; - -static Location DrakeWP[]= -{ - {0, 2125.84, 88.2535, 54.8830}, - {1, 2111.01, 93.8022, 52.6356}, - {2, 2106.70, 114.753, 53.1965}, - {3, 2107.76, 138.746, 52.5109}, - {4, 2114.83, 160.142, 52.4738}, - {5, 2125.24, 178.909, 52.7283}, - {6, 2151.02, 208.901, 53.1551}, - {7, 2177.00, 233.069, 52.4409}, - {8, 2190.71, 227.831, 53.2742}, - {9, 2178.14, 214.219, 53.0779}, - {10, 2154.99, 202.795, 52.6446}, - {11, 2132.00, 191.834, 52.5709}, - {12, 2117.59, 166.708, 52.7686}, - {13, 2093.61, 139.441, 52.7616}, - {14, 2086.29, 104.950, 52.9246}, - {15, 2094.23, 81.2788, 52.6946}, - {16, 2108.70, 85.3075, 53.3294}, - {17, 2125.50, 88.9481, 54.7953}, - {18, 2128.20, 70.9763, 64.4221} -}; - -struct boss_lieutenant_drakeAI : public ScriptedAI -{ - boss_lieutenant_drakeAI(Creature *c) : ScriptedAI(c) {} - - bool CanPatrol; - uint32 wpId; - - uint32 Whirlwind_Timer; - uint32 Fear_Timer; - uint32 MortalStrike_Timer; - uint32 ExplodingShout_Timer; - - void Reset() - { - CanPatrol = true; - wpId = 0; - - Whirlwind_Timer = 20000; - Fear_Timer = 30000; - MortalStrike_Timer = 45000; - ExplodingShout_Timer = 25000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - //TODO: make this work - if (CanPatrol && wpId == 0) - { - me->GetMotionMaster()->MovePoint(DrakeWP[0].wpId, DrakeWP[0].x, DrakeWP[0].y, DrakeWP[0].z); - ++wpId; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Whirlwind - if (Whirlwind_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WHIRLWIND); - Whirlwind_Timer = 20000+rand()%5000; - } else Whirlwind_Timer -= diff; - - //Fear - if (Fear_Timer <= diff) - { - DoScriptText(SAY_SHOUT, me); - DoCast(me->getVictim(), SPELL_FRIGHTENING_SHOUT); - Fear_Timer = 25000+rand()%10000; - } else Fear_Timer -= diff; - - //Mortal Strike - if (MortalStrike_Timer <= diff) - { - DoScriptText(SAY_MORTAL, me); - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - MortalStrike_Timer = 20000+rand()%10000; - } else MortalStrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_lieutenant_drake(Creature* pCreature) -{ - return new boss_lieutenant_drakeAI (pCreature); -} - -void AddSC_boss_lieutenant_drake() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_barrel_old_hillsbrad"; - newscript->pGOHello = &GOHello_go_barrel_old_hillsbrad; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lieutenant_drake"; - newscript->GetAI = &GetAI_boss_lieutenant_drake; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp deleted file mode 100644 index fa0b7c14595..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/instance_old_hillsbrad.cpp +++ /dev/null @@ -1,238 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Old_Hillsbrad -SD%Complete: 75 -SDComment: If thrall escort fail, all parts will reset. In future, save sub-parts and continue from last known. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -#include "ScriptedPch.h" -#include "old_hillsbrad.h" - -#define MAX_ENCOUNTER 6 - -#define THRALL_ENTRY 17876 -#define TARETHA_ENTRY 18887 -#define EPOCH_ENTRY 18096 - -#define DRAKE_ENTRY 17848 - -#define QUEST_ENTRY_DIVERSION 10283 -#define LODGE_QUEST_TRIGGER 20155 - -struct instance_old_hillsbrad : public ScriptedInstance -{ - instance_old_hillsbrad(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 mBarrelCount; - uint32 mThrallEventCount; - - uint64 ThrallGUID; - uint64 TarethaGUID; - uint64 EpochGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - mBarrelCount = 0; - mThrallEventCount = 0; - ThrallGUID = 0; - TarethaGUID = 0; - EpochGUID = 0; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - - debug_log("TSCR: Instance Old Hillsbrad: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void UpdateQuestCredit() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->KilledMonsterCredit(LODGE_QUEST_TRIGGER,0); - } - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case THRALL_ENTRY: - ThrallGUID = pCreature->GetGUID(); - break; - case TARETHA_ENTRY: - TarethaGUID = pCreature->GetGUID(); - break; - case EPOCH_ENTRY: - EpochGUID = pCreature->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - Player* pPlayer = GetPlayerInMap(); - - if (!pPlayer) - { - debug_log("TSCR: Instance Old Hillsbrad: SetData (Type: %u Data %u) cannot find any player.", type, data); - return; - } - - switch(type) - { - case TYPE_BARREL_DIVERSION: - { - if (data == IN_PROGRESS) - { - if (mBarrelCount >= 5) - return; - - ++mBarrelCount; - DoUpdateWorldState(WORLD_STATE_OH, mBarrelCount); - - debug_log("TSCR: Instance Old Hillsbrad: go_barrel_old_hillsbrad count %u",mBarrelCount); - - m_auiEncounter[0] = IN_PROGRESS; - - if (mBarrelCount == 5) - { - UpdateQuestCredit(); - pPlayer->SummonCreature(DRAKE_ENTRY, 2128.43, 71.01, 64.42, 1.74, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000); - m_auiEncounter[0] = DONE; - } - } - break; - } - case TYPE_THRALL_EVENT: - { - if (data == FAIL) - { - if (mThrallEventCount <= 20) - { - ++mThrallEventCount; - m_auiEncounter[1] = NOT_STARTED; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); - m_auiEncounter[2] = NOT_STARTED; - m_auiEncounter[3] = NOT_STARTED; - m_auiEncounter[4] = NOT_STARTED; - m_auiEncounter[5] = NOT_STARTED; - } - else if (mThrallEventCount > 20) - { - m_auiEncounter[1] = data; - m_auiEncounter[2] = data; - m_auiEncounter[3] = data; - m_auiEncounter[4] = data; - m_auiEncounter[5] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event failed %u times. Resetting all sub-events.",mThrallEventCount); - } - } - else - m_auiEncounter[1] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall escort event adjusted to data %u.",data); - break; - } - case TYPE_THRALL_PART1: - m_auiEncounter[2] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part I adjusted to data %u.",data); - break; - case TYPE_THRALL_PART2: - m_auiEncounter[3] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part II adjusted to data %u.",data); - break; - case TYPE_THRALL_PART3: - m_auiEncounter[4] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part III adjusted to data %u.",data); - break; - case TYPE_THRALL_PART4: - m_auiEncounter[5] = data; - debug_log("TSCR: Instance Old Hillsbrad: Thrall event part IV adjusted to data %u.",data); - break; - } - } - - uint32 GetData(uint32 data) - { - switch(data) - { - case TYPE_BARREL_DIVERSION: - return m_auiEncounter[0]; - case TYPE_THRALL_EVENT: - return m_auiEncounter[1]; - case TYPE_THRALL_PART1: - return m_auiEncounter[2]; - case TYPE_THRALL_PART2: - return m_auiEncounter[3]; - case TYPE_THRALL_PART3: - return m_auiEncounter[4]; - case TYPE_THRALL_PART4: - return m_auiEncounter[5]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THRALL: - return ThrallGUID; - case DATA_TARETHA: - return TarethaGUID; - case DATA_EPOCH: - return EpochGUID; - } - return 0; - } -}; -InstanceData* GetInstanceData_instance_old_hillsbrad(Map* pMap) -{ - return new instance_old_hillsbrad(pMap); -} - -void AddSC_instance_old_hillsbrad() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_old_hillsbrad"; - newscript->GetInstanceData = &GetInstanceData_instance_old_hillsbrad; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp deleted file mode 100644 index 08c63954db5..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.cpp +++ /dev/null @@ -1,658 +0,0 @@ - /* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Old_Hillsbrad -SD%Complete: 40 -SDComment: Quest support: 10283, 10284. All friendly NPC's. Thrall waypoints fairly complete, missing many details, but possible to complete escort. -SDCategory: Caverns of Time, Old Hillsbrad Foothills -EndScriptData */ - -/* ContentData -npc_erozion -npc_thrall_old_hillsbrad -npc_taretha -EndContentData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "old_hillsbrad.h" - -#define QUEST_ENTRY_HILLSBRAD 10282 -#define QUEST_ENTRY_DIVERSION 10283 -#define QUEST_ENTRY_ESCAPE 10284 -#define QUEST_ENTRY_RETURN 10285 -#define ITEM_ENTRY_BOMBS 25853 - -#define GOSSIP_HELLO_EROZION1 "I need a pack of Incendiary Bombs." -#define GOSSIP_HELLO_EROZION2 "[PH] Teleport please, i'm tired." - -/*###### -## npc_erozion -######*/ - -bool GossipHello_npc_erozion(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance && pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE && !pPlayer->HasItemCount(ITEM_ENTRY_BOMBS,1)) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - if (!pPlayer->GetQuestRewardStatus(QUEST_ENTRY_RETURN) && pPlayer->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HELLO_EROZION2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(9778, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_erozion(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_ENTRY_BOMBS, 1); - if (msg == EQUIP_ERR_OK) - { - pPlayer->StoreNewItem(dest, ITEM_ENTRY_BOMBS, true); - } - pPlayer->SEND_GOSSIP_MENU(9515, pCreature->GetGUID()); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - } - return true; -} - -/*###### -## npc_thrall_old_hillsbrad -######*/ - -//Thrall texts -#define SAY_TH_START_EVENT_PART1 -1560023 -#define SAY_TH_ARMORY -1560024 -#define SAY_TH_SKARLOC_MEET -1560025 -#define SAY_TH_SKARLOC_TAUNT -1560026 -#define SAY_TH_START_EVENT_PART2 -1560027 -#define SAY_TH_MOUNTS_UP -1560028 -#define SAY_TH_CHURCH_END -1560029 -#define SAY_TH_MEET_TARETHA -1560030 -#define SAY_TH_EPOCH_WONDER -1560031 -#define SAY_TH_EPOCH_KILL_TARETHA -1560032 -#define SAY_TH_EVENT_COMPLETE -1560033 - -#define SAY_TH_RANDOM_LOW_HP1 -1560034 -#define SAY_TH_RANDOM_LOW_HP2 -1560035 - -#define SAY_TH_RANDOM_DIE1 -1560036 -#define SAY_TH_RANDOM_DIE2 -1560037 - -#define SAY_TH_RANDOM_AGGRO1 -1560038 -#define SAY_TH_RANDOM_AGGRO2 -1560039 -#define SAY_TH_RANDOM_AGGRO3 -1560040 -#define SAY_TH_RANDOM_AGGRO4 -1560041 - -#define SAY_TH_RANDOM_KILL1 -1560042 -#define SAY_TH_RANDOM_KILL2 -1560043 -#define SAY_TH_RANDOM_KILL3 -1560044 - -#define SAY_TH_LEAVE_COMBAT1 -1560045 -#define SAY_TH_LEAVE_COMBAT2 -1560046 -#define SAY_TH_LEAVE_COMBAT3 -1560047 - -//Taretha texts -#define SAY_TA_FREE -1560048 -#define SAY_TA_ESCAPED -1560049 - -//Misc for Thrall -#define SPELL_STRIKE 14516 -#define SPELL_SHIELD_BLOCK 12169 -#define SPELL_SUMMON_EROZION_IMAGE 33954 //if thrall dies during escort? - -#define SPEED_WALK (0.5f) -#define SPEED_RUN (1.0f) -#define SPEED_MOUNT (1.6f) - -#define THRALL_WEAPON_MODEL 22106 -#define THRALL_WEAPON_INFO 218169346 -#define THRALL_SHIELD_MODEL 18662 -#define THRALL_SHIELD_INFO 234948100 -#define THRALL_MODEL_UNEQUIPPED 17292 -#define THRALL_MODEL_EQUIPPED 18165 - -//Misc Creature entries -#define ENTRY_ARMORER 18764 -#define ENTRY_SCARLOC 17862 - -#define MOB_ENTRY_RIFLE 17820 -#define MOB_ENTRY_WARDEN 17833 -#define MOB_ENTRY_VETERAN 17860 -#define MOB_ENTRY_WATCHMAN 17814 -#define MOB_ENTRY_SENTRY 17815 - -#define MOB_ENTRY_BARN_GUARDSMAN 18092 -#define MOB_ENTRY_BARN_PROTECTOR 18093 -#define MOB_ENTRY_BARN_LOOKOUT 18094 - -#define MOB_ENTRY_CHURCH_GUARDSMAN 23175 -#define MOB_ENTRY_CHURCH_PROTECTOR 23179 -#define MOB_ENTRY_CHURCH_LOOKOUT 23177 - -#define MOB_ENTRY_INN_GUARDSMAN 23176 -#define MOB_ENTRY_INN_PROTECTOR 23180 -#define MOB_ENTRY_INN_LOOKOUT 23178 - -#define SKARLOC_MOUNT 18798 -#define SKARLOC_MOUNT_MODEL 18223 -#define EROZION_ENTRY 18723 -#define ENTRY_EPOCH 18096 - -//gossip items -#define GOSSIP_ID_START 9568 -#define GOSSIP_ID_SKARLOC1 9614 //I'm glad Taretha is alive. We now must find a way to free her... -#define GOSSIP_ITEM_SKARLOC1 "Taretha cannot see you, Thrall." -#define GOSSIP_ID_SKARLOC2 9579 //What do you mean by this? Is Taretha in danger? -#define GOSSIP_ITEM_SKARLOC2 "The situation is rather complicated, Thrall. It would be best for you to head into the mountains now, before more of Blackmoore's men show up. We'll make sure Taretha is safe." -#define GOSSIP_ID_SKARLOC3 9580 - -#define GOSSIP_ID_TARREN 9597 //tarren mill is beyond these trees -#define GOSSIP_ITEM_TARREN "We're ready, Thrall." - -#define GOSSIP_ID_COMPLETE 9578 //Thank you friends, I owe my freedom to you. Where is Taretha? I hoped to see her - -#define GOSSIP_ITEM_WALKING "[PH] Start walking." - -struct npc_thrall_old_hillsbradAI : public npc_escortAI -{ - npc_thrall_old_hillsbradAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - HadMount = false; - me->setActive(true); - } - - ScriptedInstance *pInstance; - - uint64 TarethaGUID; - - bool LowHp; - bool HadMount; - - void WaypointReached(uint32 i) - { - if (!pInstance) - return; - - switch(i) - { - case 8: - SetRun(false); - me->SummonCreature(18764,2181.87,112.46,89.45,0.26,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 9: - DoScriptText(SAY_TH_ARMORY, me); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, THRALL_WEAPON_MODEL); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO, THRALL_WEAPON_INFO); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+1, 781); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, THRALL_SHIELD_MODEL); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+2, THRALL_SHIELD_INFO); - //me->SetUInt32Value(UNIT_VIRTUAL_ITEM_INFO+3, 1038); - break; - case 10: - me->SetDisplayId(THRALL_MODEL_EQUIPPED); - break; - case 11: - SetRun(); - break; - case 15: - me->SummonCreature(MOB_ENTRY_RIFLE,2200.28,137.37,87.93,5.07,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2197.44,131.83,87.93,0.78,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2203.62,135.40,87.93,3.70,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2200.75,130.13,87.93,1.48,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 21: - me->SummonCreature(MOB_ENTRY_RIFLE,2135.80,154.01,67.45,4.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2144.36,151.87,67.74,4.46,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2142.12,154.41,67.12,4.56,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2138.08,155.38,67.24,4.60,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 25: - me->SummonCreature(MOB_ENTRY_RIFLE,2102.98,192.17,65.24,6.02,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WARDEN,2108.48,198.75,65.18,5.15,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2106.11,197.29,65.18,5.63,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_VETERAN,2104.18,194.82,65.18,5.75,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 29: - DoScriptText(SAY_TH_SKARLOC_MEET, me); - me->SummonCreature(ENTRY_SCARLOC,2036.48,271.22,63.43,5.27,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - //temporary,skarloc should rather be triggered to walk up to thrall - break; - case 30: - SetEscortPaused(true); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetRun(false); - break; - case 31: - DoScriptText(SAY_TH_MOUNTS_UP, me); - DoMount(); - SetRun(); - break; - case 37: - //possibly regular patrollers? If so, remove this and let database handle them - me->SummonCreature(MOB_ENTRY_WATCHMAN,2124.26,522.16,56.87,3.99,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_WATCHMAN,2121.69,525.37,57.11,4.01,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_SENTRY,2124.65,524.55,56.63,3.98,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 59: - me->SummonCreature(SKARLOC_MOUNT,2488.64,625.77,58.26,4.71,TEMPSUMMON_TIMED_DESPAWN,10000); - DoUnmount(); - HadMount = false; - SetRun(false); - break; - case 60: - me->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); - //make horsie run off - SetEscortPaused(true); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pInstance->SetData(TYPE_THRALL_PART2, DONE); - SetRun(); - break; - case 64: - SetRun(false); - break; - case 68: - me->SummonCreature(MOB_ENTRY_BARN_PROTECTOR,2500.22,692.60,55.50,2.84,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_LOOKOUT,2500.13,696.55,55.51,3.38,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.55,693.64,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_BARN_GUARDSMAN,2500.94,695.81,55.50,3.14,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 71: - SetRun(); - break; - case 81: - SetRun(false); - break; - case 83: - me->SummonCreature(MOB_ENTRY_CHURCH_PROTECTOR,2627.33,646.82,56.03,4.28,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_LOOKOUT,2624.14,648.03,56.03,4.50,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2625.32,649.60,56.03,4.38,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - me->SummonCreature(MOB_ENTRY_CHURCH_GUARDSMAN,2627.22,649.00,56.03,4.34,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,5000); - break; - case 84: - DoScriptText(SAY_TH_CHURCH_END, me); - SetRun(); - break; - case 91: - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - SetRun(false); - break; - case 93: - me->SummonCreature(MOB_ENTRY_INN_PROTECTOR,2652.71,660.31,61.93,1.67,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_LOOKOUT,2648.96,662.59,61.93,0.79,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2657.36,662.34,61.93,2.68,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - me->SummonCreature(MOB_ENTRY_INN_GUARDSMAN,2656.39,659.77,61.93,2.61,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000); - break; - case 94: - if (uint64 TarethaGUID = pInstance->GetData64(DATA_TARETHA)) - { - if (Unit* Taretha = Unit::GetUnit((*me), TarethaGUID)) - DoScriptText(SAY_TA_ESCAPED, Taretha, me); - } - break; - case 95: - DoScriptText(SAY_TH_MEET_TARETHA, me); - pInstance->SetData(TYPE_THRALL_PART3,DONE); - SetEscortPaused(true); - break; - case 96: - DoScriptText(SAY_TH_EPOCH_WONDER, me); - break; - case 97: - DoScriptText(SAY_TH_EPOCH_KILL_TARETHA, me); - SetRun(); - break; - case 98: - //trigger epoch Yell("Thrall! Come outside and face your fate! ....") - //from here, thrall should not never be allowed to move to point 106 which he currently does. - break; - - case 106: - { - //trigger taretha to run down outside - if (Creature* Taretha = pInstance->instance->GetCreature(pInstance->GetData64(DATA_TARETHA))) - { - if (Player* pPlayer = GetPlayerForEscort()) - CAST_AI(npc_escortAI, (Taretha->AI()))->Start(false, true, pPlayer->GetGUID()); - } - - //kill credit Creature for quest - Map* pMap = me->GetMap(); - Map::PlayerList const& players = pMap->GetPlayers(); - if (!players.isEmpty() && pMap->IsDungeon()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->KilledMonsterCredit(20156,me->GetGUID()); - } - } - - //alot will happen here, thrall and taretha talk, erozion appear at spot to explain - me->SummonCreature(EROZION_ENTRY,2646.47,680.416,55.38,4.16,TEMPSUMMON_TIMED_DESPAWN,120000); - } - break; - case 108: - //last waypoint, just set Thrall invisible, respawn is turned off - me->SetVisibility(VISIBILITY_OFF); - break; - } - } - - void Reset() - { - LowHp = false; - - if (HadMount) - DoMount(); - - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - DoUnmount(); - HadMount = false; - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - me->SetDisplayId(THRALL_MODEL_UNEQUIPPED); - } - if (HasEscortState(STATE_ESCORT_ESCORTING)) - { - DoScriptText(RAND(SAY_TH_LEAVE_COMBAT1,SAY_TH_LEAVE_COMBAT2,SAY_TH_LEAVE_COMBAT3), me); - } - } - void StartWP() - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetEscortPaused(false); - } - void DoMount() - { - me->Mount(SKARLOC_MOUNT_MODEL); - me->SetSpeed(MOVE_RUN,SPEED_MOUNT); - } - void DoUnmount() - { - me->Unmount(); - me->SetSpeed(MOVE_RUN,SPEED_RUN); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(RAND(SAY_TH_RANDOM_AGGRO1,SAY_TH_RANDOM_AGGRO2,SAY_TH_RANDOM_AGGRO3,SAY_TH_RANDOM_AGGRO4), me); - if (me->IsMounted()) - { - DoUnmount(); - HadMount = true; - } - } - - void JustSummoned(Creature* summoned) - { - switch(summoned->GetEntry()) - { - //TODO: make Scarloc start into event instead, and not start attack directly - case MOB_ENTRY_BARN_GUARDSMAN: - case MOB_ENTRY_BARN_PROTECTOR: - case MOB_ENTRY_BARN_LOOKOUT: - case SKARLOC_MOUNT: - case EROZION_ENTRY: - break; - default: - summoned->AI()->AttackStart(me); - break; - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_TH_RANDOM_KILL1,SAY_TH_RANDOM_KILL2,SAY_TH_RANDOM_KILL3), me); - } - void JustDied(Unit *slayer) - { - if (pInstance) - pInstance->SetData(TYPE_THRALL_EVENT,FAIL); - - // Don't do a yell if he kills self (if player goes too far or at the end). - if (slayer == me) - return; - - DoScriptText(RAND(SAY_TH_RANDOM_DIE1,SAY_TH_RANDOM_DIE2), me); - } - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - //TODO: add his abilities'n-crap here - if (!LowHp && ((me->GetHealth()*100 / me->GetMaxHealth()) < 20)) - { - DoScriptText(RAND(SAY_TH_RANDOM_LOW_HP1,SAY_TH_RANDOM_LOW_HP2), me); - LowHp = true; - } - } -}; - -CreatureAI* GetAI_npc_thrall_old_hillsbrad(Creature* pCreature) -{ - return new npc_thrall_old_hillsbradAI(pCreature); -} - -bool GossipHello_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - { - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - pPlayer->SendPreparedQuest(pCreature->GetGUID()); - } - - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance) - { - if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE && !pInstance->GetData(TYPE_THRALL_EVENT)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_WALKING, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_START, pCreature->GetGUID()); - } - - if (pInstance->GetData(TYPE_THRALL_PART1) == DONE && !pInstance->GetData(TYPE_THRALL_PART2)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC1, pCreature->GetGUID()); - } - - if (pInstance->GetData(TYPE_THRALL_PART2) == DONE && !pInstance->GetData(TYPE_THRALL_PART3)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TARREN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_TARREN, pCreature->GetGUID()); - } - } - return true; -} - -bool GossipSelect_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pInstance) - { - pInstance->SetData(TYPE_THRALL_EVENT,IN_PROGRESS); - pInstance->SetData(TYPE_THRALL_PART1,IN_PROGRESS); - } - - DoScriptText(SAY_TH_START_EVENT_PART1, pCreature); - - if (npc_escortAI* pEscortAI = CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())) - pEscortAI->Start(true, true, pPlayer->GetGUID()); - - CAST_AI(npc_escortAI, (pCreature->AI()))->SetMaxPlayerDistance(100.0f);//not really needed, because it will not despawn if player is too far - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtEnd(false); - CAST_AI(npc_escortAI, (pCreature->AI()))->SetDespawnAtFar(false); - break; - - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC2, pCreature->GetGUID()); - break; - - case GOSSIP_ACTION_INFO_DEF+20: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_SKARLOC3, pCreature->GetGUID()); - pCreature->SummonCreature(SKARLOC_MOUNT,2038.81,270.26,63.20,5.41,TEMPSUMMON_TIMED_DESPAWN,12000); - if (pInstance) - pInstance->SetData(TYPE_THRALL_PART2,IN_PROGRESS); - - DoScriptText(SAY_TH_START_EVENT_PART2, pCreature); - - CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); - break; - - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pInstance) - pInstance->SetData(TYPE_THRALL_PART3,IN_PROGRESS); - CAST_AI(npc_thrall_old_hillsbradAI, pCreature->AI())->StartWP(); - break; - } - return true; -} - -/*###### -## npc_taretha -######*/ - -#define GOSSIP_ID_EPOCH1 9610 //Thank you for helping Thrall escape, friends. Now I only hope -#define GOSSIP_ITEM_EPOCH1 "Strange wizard?" -#define GOSSIP_ID_EPOCH2 9613 //Yes, friends. This man was no wizard of -#define GOSSIP_ITEM_EPOCH2 "We'll get you out. Taretha. Don't worry. I doubt the wizard would wander too far away." - -struct npc_tarethaAI : public npc_escortAI -{ - npc_tarethaAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void WaypointReached(uint32 i) - { - switch(i) - { - case 6: - DoScriptText(SAY_TA_FREE, me); - break; - case 7: - me->HandleEmoteCommand(EMOTE_ONESHOT_CHEER); - break; - } - } - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - npc_escortAI::UpdateAI(diff); - } -}; -CreatureAI* GetAI_npc_taretha(Creature* pCreature) -{ - return new npc_tarethaAI(pCreature); -} - -bool GossipHello_npc_taretha(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (pInstance && pInstance->GetData(TYPE_THRALL_PART3) == DONE && pInstance->GetData(TYPE_THRALL_PART4) == NOT_STARTED) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH1, pCreature->GetGUID()); - } - return true; -} - -bool GossipSelect_npc_taretha(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_ID_EPOCH2, pCreature->GetGUID()); - } - if (uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS) - { - pInstance->SetData(TYPE_THRALL_PART4,IN_PROGRESS); - if (pInstance->GetData64(DATA_EPOCH) == 0) - pCreature->SummonCreature(ENTRY_EPOCH,2639.13,698.55,65.43,4.59,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,120000); - - if (uint64 ThrallGUID = pInstance->GetData64(DATA_THRALL)) - { - Creature* Thrall = (Unit::GetCreature((*pCreature), ThrallGUID)); - if (Thrall) - CAST_AI(npc_thrall_old_hillsbradAI, Thrall->AI())->StartWP(); - } - } - } - return true; -} - -/*###### -## AddSC -######*/ - -void AddSC_old_hillsbrad() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_erozion"; - newscript->pGossipHello = &GossipHello_npc_erozion; - newscript->pGossipSelect = &GossipSelect_npc_erozion; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_thrall_old_hillsbrad"; - newscript->pGossipHello = &GossipHello_npc_thrall_old_hillsbrad; - newscript->pGossipSelect = &GossipSelect_npc_thrall_old_hillsbrad; - newscript->GetAI = &GetAI_npc_thrall_old_hillsbrad; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_taretha"; - newscript->pGossipHello = &GossipHello_npc_taretha; - newscript->pGossipSelect = &GossipSelect_npc_taretha; - newscript->GetAI = &GetAI_npc_taretha; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h b/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h deleted file mode 100644 index 5c398cc2647..00000000000 --- a/src/server/scripts/Kalimdor/CavernsOfTime/old_hillsbrad/old_hillsbrad.h +++ /dev/null @@ -1,19 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_OLD_HILLSBRAD_H -#define DEF_OLD_HILLSBRAD_H - -#define TYPE_BARREL_DIVERSION 1 -#define TYPE_THRALL_EVENT 2 -#define TYPE_THRALL_PART1 3 -#define TYPE_THRALL_PART2 4 -#define TYPE_THRALL_PART3 5 -#define TYPE_THRALL_PART4 6 -#define DATA_THRALL 7 -#define DATA_TARETHA 8 -#define DATA_EPOCH 9 -#define WORLD_STATE_OH 2436 -#endif - diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h new file mode 100644 index 00000000000..4113885b6f4 --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/azjol_nerub.h @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_AZJOL_NERUB_H +#define DEF_AZJOL_NERUB_H + +enum Data64 +{ + DATA_KRIKTHIR_THE_GATEWATCHER, + DATA_HADRONOX, + DATA_ANUBARAK, + DATA_WATCHER_GASHRA, + DATA_WATCHER_SILTHIK, + DATA_WATCHER_NARJIL +}; +enum Data +{ + DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, + DATA_HADRONOX_EVENT, + DATA_ANUBARAK_EVENT +}; + +#endif diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp new file mode 100644 index 00000000000..6de6578f7bb --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_anubarak.cpp @@ -0,0 +1,360 @@ +/* +* Copyright (C) 2009 - 2010 TrinityCore +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +//SQL: UPDATE creature_template SET mechanic_immune_mask = 1073741823 WHERE name like "anub'arak%"; + +enum Spells +{ + SPELL_CARRION_BEETLES = 53520, + SPELL_SUMMON_CARRION_BEETLES = 53521, + SPELL_LEECHING_SWARM = 53467, + SPELL_POUND = 53472, + SPELL_POUND_H = 59433, + SPELL_SUBMERGE = 53421, + SPELL_IMPALE_DMG = 53454, + SPELL_IMPALE_DMG_H = 59446, + SPELL_IMPALE_SHAKEGROUND = 53455, + SPELL_IMPALE_SPIKE = 53539, //this is not the correct visual effect + //SPELL_IMPALE_TARGET = 53458, +}; + +enum Creatures +{ + CREATURE_GUARDIAN = 29216, + CREATURE_VENOMANCER = 29217, + CREATURE_DATTER = 29213, + CREATURE_IMPALE_TARGET = 89, + DISPLAY_INVISIBLE = 11686 +}; + +// not in db +enum Yells +{ + SAY_INTRO = -1601010, + SAY_AGGRO = -1601000, + SAY_SLAY_1 = -1601001, + SAY_SLAY_2 = -1601002, + SAY_SLAY_3 = -1601003, + SAY_LOCUST_1 = -1601005, + SAY_LOCUST_2 = -1601006, + SAY_LOCUST_3 = -1601007, + SAY_SUBMERGE_1 = -1601008, + SAY_SUBMERGE_2 = -1601009, + SAY_DEATH = -1601004 +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 20381, +}; + +enum Phases +{ + PHASE_MELEE = 0, + PHASE_UNDERGROUND = 1, + IMPALE_PHASE_TARGET = 0, + IMPALE_PHASE_ATTACK = 1, + IMPALE_PHASE_DMG = 2 +}; + +const Position SpawnPoint[2] = +{ + { 550.7, 282.8, 224.3 }, + { 551.1, 229.4, 224.3 }, +}; + +const Position SpawnPointGuardian[2] = +{ + { 550.348633, 316.006805, 234.2947 }, + { 550.188660, 324.264557, 237.7412 }, +}; + +struct boss_anub_arakAI : public ScriptedAI +{ + boss_anub_arakAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + bool bChanneling; + bool bGuardianSummoned; + bool bVenomancerSummoned; + bool bDatterSummoned; + uint8 uiPhase; + uint32 uiUndergroundPhase; + uint32 uiCarrionBeetlesTimer; + uint32 uiLeechingSwarmTimer; + uint32 uiPoundTimer; + uint32 uiSubmergeTimer; + uint32 uiUndergroundTimer; + uint32 uiVenomancerTimer; + uint32 uiDatterTimer; + + uint32 uiImpaleTimer; + uint32 uiImpalePhase; + uint64 uiImpaleTarget; + + SummonList lSummons; + + void Reset() + { + uiCarrionBeetlesTimer = 8*IN_MILISECONDS; + uiLeechingSwarmTimer = 20*IN_MILISECONDS; + uiImpaleTimer = 9*IN_MILISECONDS; + uiPoundTimer = 15*IN_MILISECONDS; + + uiPhase = PHASE_MELEE; + uiUndergroundPhase = 0; + bChanneling = false; + uiImpalePhase = IMPALE_PHASE_TARGET; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->RemoveAura(SPELL_SUBMERGE); + + lSummons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_ANUBARAK_EVENT, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + Creature* DoSummonImpaleTarget(Unit *pTarget) + { + Position targetPos; + pTarget->GetPosition(&targetPos); + + if (TempSummon* pImpaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILISECONDS)) + { + uiImpaleTarget = pImpaleTarget->GetGUID(); + pImpaleTarget->SetReactState(REACT_PASSIVE); + pImpaleTarget->SetDisplayId(DISPLAY_INVISIBLE); + pImpaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + return pImpaleTarget; + } + + return NULL; + } + + void EnterCombat(Unit * /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + pInstance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + switch (uiPhase) + { + case PHASE_UNDERGROUND: + if (uiImpaleTimer <= diff) + { + switch(uiImpalePhase) + { + case IMPALE_PHASE_TARGET: + if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) + pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SHAKEGROUND, true); + uiImpaleTimer = 3*IN_MILISECONDS; + uiImpalePhase = IMPALE_PHASE_ATTACK; + } + break; + case IMPALE_PHASE_ATTACK: + if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) + { + pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SPIKE, false); + pImpaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND); + } + uiImpalePhase = IMPALE_PHASE_DMG; + uiImpaleTimer = 1*IN_MILISECONDS; + break; + case IMPALE_PHASE_DMG: + if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) + me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_IMPALE_DMG, SPELL_IMPALE_DMG_H), true); + uiImpalePhase = IMPALE_PHASE_TARGET; + uiImpaleTimer = 9*IN_MILISECONDS; + break; + } + } else uiImpaleTimer -= diff; + + if (!bGuardianSummoned) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Guardian = me->SummonCreature(CREATURE_GUARDIAN,SpawnPointGuardian[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Guardian->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Guardian); + } + } + bGuardianSummoned = true; + } + + if (!bVenomancerSummoned) + { + if (uiVenomancerTimer <= diff) + { + if (uiUndergroundPhase > 1) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Venomancer = me->SummonCreature(CREATURE_VENOMANCER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Venomancer->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Venomancer); + } + } + bVenomancerSummoned = true; + } + } else uiVenomancerTimer -= diff; + } + + if (!bDatterSummoned) + { + if (uiDatterTimer <= diff) + { + if (uiUndergroundPhase > 2) + { + for (uint8 i = 0; i < 2; ++i) + { + if (Creature *Datter = me->SummonCreature(CREATURE_DATTER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) + { + Datter->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Datter); + } + } + bDatterSummoned = true; + } + } else uiDatterTimer -= diff; + } + + if (uiUndergroundTimer <= diff) + { + me->RemoveAura(SPELL_SUBMERGE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + uiPhase = PHASE_MELEE; + } else uiUndergroundTimer -= diff; + break; + + case PHASE_MELEE: + if (((uiUndergroundPhase == 0 && HealthBelowPct(75)) + || (uiUndergroundPhase == 1 && HealthBelowPct(50)) + || (uiUndergroundPhase == 2 && HealthBelowPct(25))) + && !me->hasUnitState(UNIT_STAT_CASTING)) + { + bGuardianSummoned = false; + bVenomancerSummoned = false; + bDatterSummoned = false; + + uiUndergroundTimer = 40*IN_MILISECONDS; + uiVenomancerTimer = 25*IN_MILISECONDS; + uiDatterTimer = 32*IN_MILISECONDS; + + uiImpalePhase = 0; + uiImpaleTimer = 9*IN_MILISECONDS; + + DoCast(me, SPELL_SUBMERGE, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + + uiPhase = PHASE_UNDERGROUND; + ++uiUndergroundPhase; + } + + if (bChanneling == true) + { + for (uint8 i = 0; i < 8; ++i) + DoCast(me->getVictim(), SPELL_SUMMON_CARRION_BEETLES, true); + bChanneling = false; + } + else if (uiCarrionBeetlesTimer <= diff) + { + bChanneling = true; + DoCastVictim(SPELL_CARRION_BEETLES); + uiCarrionBeetlesTimer = 25*IN_MILISECONDS; + } else uiCarrionBeetlesTimer -= diff; + + if (uiLeechingSwarmTimer <= diff) + { + DoCast(me, SPELL_LEECHING_SWARM, true); + uiLeechingSwarmTimer = 19*IN_MILISECONDS; + } else uiLeechingSwarmTimer -= diff; + + if (uiPoundTimer <= diff) + { + if (Unit *target = me->getVictim()) + { + if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) + me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_POUND, SPELL_POUND_H), false); + } + uiPoundTimer = 16.5*IN_MILISECONDS; + } else uiPoundTimer -= diff; + + DoMeleeAttackIfReady(); + break; + } + } + + void JustDied(Unit * /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + lSummons.DespawnAll(); + if (pInstance) + pInstance->SetData(DATA_ANUBARAK_EVENT, DONE); + } + + void KilledUnit(Unit *pVictim) + { + if (pVictim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustSummoned(Creature* summon) + { + lSummons.Summon(summon); + } +}; + +CreatureAI* GetAI_boss_anub_arak(Creature *pCreature) +{ + return new boss_anub_arakAI (pCreature); +} + +void AddSC_boss_anub_arak() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_anub_arak"; + newscript->GetAI = &GetAI_boss_anub_arak; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp new file mode 100644 index 00000000000..0fc4e87d7c5 --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* +* Comment: No Waves atm and the doors spells are crazy... +* +* When your group enters the main room (the one after the bridge), you will notice a group of 3 Nerubians. +* When you engage them, 2 more groups like this one spawn behind the first one - it is important to pull the first group back, +* so you don't aggro all 3. Hadronox will be under you, fighting Nerubians. +* +* This is the timed gauntlet - waves of non-elite spiders +* will spawn from the 3 doors located a little above the main room, and will then head down to fight Hadronox. After clearing the +* main room, it is recommended to just stay in it, kill the occasional non-elites that will attack you instead of the boss, and wait for +* Hadronox to make his way to you. When Hadronox enters the main room, she will web the doors, and no more non-elites will spawn. +*/ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +enum Spells +{ + SPELL_ACID_CLOUD = 53400, // Victim + SPELL_LEECH_POISON = 53030, // Victim + SPELL_PIERCE_ARMOR = 53418, // Victim + SPELL_WEB_GRAB = 57731, // Victim + SPELL_WEB_FRONT_DOORS = 53177, // Self + SPELL_WEB_SIDE_DOORS = 53185, // Self + H_SPELL_ACID_CLOUD = 59419, + H_SPELL_LEECH_POISON = 59417, + H_SPELL_WEB_GRAB = 59421 +}; + +struct boss_hadronoxAI : public ScriptedAI +{ + boss_hadronoxAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + fMaxDistance = 50.0f; + bFirstTime = true; + } + + ScriptedInstance* pInstance; + + uint32 uiAcidTimer; + uint32 uiLeechTimer; + uint32 uiPierceTimer; + uint32 uiGrabTimer; + uint32 uiDoorsTimer; + uint32 uiCheckDistanceTimer; + + bool bFirstTime; + + float fMaxDistance; + + void Reset() + { + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 9.0f); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 9.0f); + + uiAcidTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); + uiLeechTimer = urand(3*IN_MILISECONDS,9*IN_MILISECONDS); + uiPierceTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); + uiGrabTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); + uiDoorsTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + uiCheckDistanceTimer = 2*IN_MILISECONDS; + + if (pInstance && (pInstance->GetData(DATA_HADRONOX_EVENT) != DONE && !bFirstTime)) + pInstance->SetData(DATA_HADRONOX_EVENT, FAIL); + + bFirstTime = false; + } + + //when Hadronox kills any enemy (that includes a party member) she will regain 10% of her HP if the target had Leech Poison on + void KilledUnit(Unit* Victim) + { + // not sure if this aura check is correct, I think it is though + if (!Victim || !Victim->HasAura(DUNGEON_MODE(SPELL_LEECH_POISON, H_SPELL_LEECH_POISON)) || !me->isAlive()) + return; + + uint32 health = me->GetMaxHealth()/10; + + if ((me->GetHealth()+health) >= me->GetMaxHealth()) + me->SetHealth(me->GetMaxHealth()); + else + me->SetHealth(me->GetHealth()+health); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_HADRONOX_EVENT, DONE); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_HADRONOX_EVENT, IN_PROGRESS); + me->SetInCombatWithZone(); + } + + void CheckDistance(float dist, const uint32 uiDiff) + { + if (!me->isInCombat()) + return; + + float x=0.0f, y=0.0f, z=0.0f; + me->GetRespawnCoord(x,y,z); + + if (uiCheckDistanceTimer <= uiDiff) + uiCheckDistanceTimer = 5*IN_MILISECONDS; + else + { + uiCheckDistanceTimer -= uiDiff; + return; + } + if (me->IsInEvadeMode() || !me->getVictim()) + return; + if (me->GetDistance(x,y,z) > dist) + EnterEvadeMode(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) return; + + // Without he comes up through the air to players on the bridge after krikthir if players crossing this bridge! + CheckDistance(fMaxDistance, diff); + + if (me->HasAura(SPELL_WEB_FRONT_DOORS) || me->HasAura(SPELL_WEB_SIDE_DOORS)) + { + if (IsCombatMovement()) + SetCombatMovement(false); + } + else if (!IsCombatMovement()) + SetCombatMovement(true); + + if (uiPierceTimer <= diff) + { + DoCast(me->getVictim(), SPELL_PIERCE_ARMOR); + uiPierceTimer = 8*IN_MILISECONDS; + } else uiPierceTimer -= diff; + + if (uiAcidTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ACID_CLOUD); + + uiAcidTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiAcidTimer -= diff; + + if (uiLeechTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_LEECH_POISON); + + uiLeechTimer = urand(11*IN_MILISECONDS,14*IN_MILISECONDS); + } else uiLeechTimer -= diff; + + if (uiGrabTimer <= diff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) // Draws all players (and attacking Mobs) to itself. + DoCast(pTarget, SPELL_WEB_GRAB); + + uiGrabTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); + } else uiGrabTimer -= diff; + + if (uiDoorsTimer <= diff) + { + //DoCast(me, RAND(SPELL_WEB_FRONT_DOORS, SPELL_WEB_SIDE_DOORS)); + uiDoorsTimer = urand(30*IN_MILISECONDS,60*IN_MILISECONDS); + } else uiDoorsTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_hadronox(Creature* pCreature) +{ + return new boss_hadronoxAI (pCreature); +} + +void AddSC_boss_hadronox() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_hadronox"; + newscript->GetAI = &GetAI_boss_hadronox; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp new file mode 100644 index 00000000000..4863bdcb032 --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_krikthir_the_gatewatcher.cpp @@ -0,0 +1,553 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: Find in the future best timers and the event is not implemented. + */ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +enum Spells +{ + SPELL_MIND_FLAY = 52586, + H_SPELL_MIND_FLAY = 59367, + SPELL_CURSE_OF_FATIGUE = 52592, + H_SPELL_CURSE_OF_FATIGUE = 59368, + SPELL_FRENZY = 28747, //maybe 53361 + SPELL_SUMMON_SKITTERING_SWARMER = 52438, //AOE Effect 140, maybe 52439 + SPELL_SUMMON_SKITTERING_SWARMER_1 = 52439, //Summon 3x 28735 + H_SPELL_ACID_SPLASH = 59363, + SPELL_ACID_SPLASH = 52446, + SPELL_CHARGE = 16979,//maybe is another spell + SPELL_BACKSTAB = 52540, + SPELL_SHADOW_BOLT = 52534, + H_SPELL_SHADOW_BOLT = 59357, + SPELL_SHADOW_NOVA = 52535, + H_SPELL_SHADOW_NOVA = 59358, + SPELL_STRIKE = 52532, + SPELL_CLEAVE = 49806, + SPELL_ENRAGE = 52470, + SPELL_INFECTED_BITE = 52469, + H_SPELL_INFECTED_BITE = 59364, + SPELL_WEB_WRAP = 52086,//the spell is not working properly + SPELL_BLINDING_WEBS = 52524, + H_SPELL_BLINDING_WEBS = 59365, + SPELL_POSION_SPRAY = 52493, + H_SPELL_POSION_SPRAY = 59366 +}; + +enum Mobs +{ + MOB_SKITTERING_SWARMER = 28735, + MOB_SKITTERING_SWARMER_CONTROLLER = 32593, + MOB_SKITTERING_INFECTIOR = 28736 +}; + +enum Yells +{ + SAY_AGGRO = -1601011, + SAY_SLAY_1 = -1601012, + SAY_SLAY_2 = -1601013, + SAY_DEATH = -1601014, + //Not in db + SAY_SEND_GROUP_1 = -1601020, + SAY_SEND_GROUP_2 = -1601021, + SAY_SEND_GROUP_3 = -1601022, + SAY_SWARM_1 = -1601015, + SAY_SWARM_2 = -1601016, + SAY_PREFIGHT_1 = -1601017, + SAY_PREFIGHT_2 = -1601018, + SAY_PREFIGHT_3 = -1601019 +}; + +enum Misc +{ + ACHIEV_WATH_HIM_DIE = 1296 +}; + +const Position SpawnPoint[] = +{ + { 566.164, 682.087, 769.079, 2.21657 }, + { 529.042, 706.941, 777.298, 1.0821 }, + { 489.975, 671.239, 772.131, 0.261799 }, + { 488.556, 692.95, 771.764, 4.88692 }, + { 553.34, 640.387, 777.419, 1.20428 }, + { 517.486, 706.398, 777.335, 5.35816 }, + { 504.01, 637.693, 777.479, 0.506145 }, + { 552.625, 706.408, 777.177, 3.4383 } +}; +struct boss_krik_thirAI : public ScriptedAI +{ + boss_krik_thirAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiMindFlayTimer; + uint32 uiCurseFatigueTimer; + uint32 uiSummonTimer; + + void Reset() + { + uiMindFlayTimer = 15*IN_MILISECONDS; + uiCurseFatigueTimer = 12*IN_MILISECONDS; + + if (pInstance) + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + Summon(); + uiSummonTimer = 15*IN_MILISECONDS; + + if (pInstance) + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, IN_PROGRESS); + } + + void Summon() + { + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiSummonTimer <= diff) + { + Summon(); + uiSummonTimer = 15*IN_MILISECONDS; + } else uiSummonTimer -= diff; + + if (uiMindFlayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MIND_FLAY); + uiMindFlayTimer = 15*IN_MILISECONDS; + } else uiMindFlayTimer -= diff; + + if (uiCurseFatigueTimer <= diff) + { + //WowWiki say "Curse of Fatigue-Kirk'thir will cast Curse of Fatigue on 2-3 targets periodically." + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + Unit *pTarget_1 = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + + DoCast(pTarget, SPELL_CURSE_OF_FATIGUE); + DoCast(pTarget_1, SPELL_CURSE_OF_FATIGUE); + + uiCurseFatigueTimer = 10*IN_MILISECONDS; + } else uiCurseFatigueTimer -= diff; + + if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10)) + DoCast(me, SPELL_FRENZY, true); + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (!pInstance) + return; + + pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DONE); + //Achievement: Watch him die + Creature *pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_GASHRA)); + if (!pAdd || !pAdd->isAlive()) + return; + + pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_SILTHIK)); + if (!pAdd || !pAdd->isAlive()) + return; + + pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_NARJIL)); + if (!pAdd || !pAdd->isAlive()) + return; + + pInstance->DoCompleteAchievement(ACHIEV_WATH_HIM_DIE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustSummoned(Creature* summoned) + { + summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); + } +}; + +struct npc_skittering_infectorAI : public ScriptedAI +{ + npc_skittering_infectorAI(Creature *c) : ScriptedAI(c) {} + + void JustDied(Unit* /*killer*/) + { + //The spell is not working propperly + DoCast(me->getVictim(),SPELL_ACID_SPLASH, true); + } + +}; + +struct npc_anub_ar_skirmisherAI : public ScriptedAI +{ + npc_anub_ar_skirmisherAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiChargeTimer; + uint32 uiBackstabTimer; + + void Reset() + { + uiChargeTimer = 11*IN_MILISECONDS; + uiBackstabTimer = 7*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiChargeTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoResetThreat(); + me->AddThreat(pTarget,1.0f); + DoCast(pTarget, SPELL_CHARGE, true); + } + uiChargeTimer = 15*IN_MILISECONDS; + } else uiChargeTimer -= diff; + + if (uiBackstabTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BACKSTAB); + uiBackstabTimer = 12*IN_MILISECONDS; + } else uiBackstabTimer -= diff; + + DoMeleeAttackIfReady(); + + } +}; + +struct npc_anub_ar_shadowcasterAI : public ScriptedAI +{ + npc_anub_ar_shadowcasterAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiShadowBoltTimer; + uint32 uiShadowNovaTimer; + + void Reset() + { + uiShadowBoltTimer = 6*IN_MILISECONDS; + uiShadowNovaTimer = 15*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiShadowBoltTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_SHADOW_BOLT, true); + uiShadowBoltTimer = 15*IN_MILISECONDS; + } else uiShadowBoltTimer -= diff; + + if (uiShadowNovaTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_NOVA, true); + uiShadowNovaTimer = 17*IN_MILISECONDS; + } else uiShadowNovaTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_anub_ar_warriorAI : public ScriptedAI +{ + npc_anub_ar_warriorAI(Creature *c) : ScriptedAI(c){} + + uint32 uiCleaveTimer; + uint32 uiStrikeTimer; + + void Reset() + { + uiCleaveTimer = 11*IN_MILISECONDS; + uiStrikeTimer = 6*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STRIKE, true); + uiStrikeTimer = 15*IN_MILISECONDS; + } else uiStrikeTimer -= diff; + + if (uiCleaveTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE, true); + uiCleaveTimer = 17*IN_MILISECONDS; + } else uiCleaveTimer -= diff; + + DoMeleeAttackIfReady(); + + } + +}; + +struct npc_watcher_gashraAI : public ScriptedAI +{ + npc_watcher_gashraAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + } + + void EnterCombat(Unit* /*who*/) + { + DoCast(me, SPELL_ENRAGE, true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + uiWebWrapTimer = 17*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 15*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_watcher_narjilAI : public ScriptedAI +{ + npc_watcher_narjilAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + uint32 uiBindingWebsTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + uiBindingWebsTimer = 17*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + uiWebWrapTimer = 15*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 11*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + if (uiBindingWebsTimer <= diff) + { + DoCast(me->getVictim(), SPELL_BLINDING_WEBS, true); + uiBindingWebsTimer = 17*IN_MILISECONDS; + } else uiBindingWebsTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct npc_watcher_silthikAI : public ScriptedAI +{ + npc_watcher_silthikAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiWebWrapTimer; + uint32 uiInfectedBiteTimer; + uint32 uiPoisonSprayTimer; + + void Reset() + { + uiWebWrapTimer = 11*IN_MILISECONDS; + uiInfectedBiteTimer = 4*IN_MILISECONDS; + uiPoisonSprayTimer = 15*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiWebWrapTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_WEB_WRAP, true); + + uiWebWrapTimer = 15*IN_MILISECONDS; + } else uiWebWrapTimer -= diff; + + if (uiInfectedBiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); + uiInfectedBiteTimer = 15*IN_MILISECONDS; + } else uiInfectedBiteTimer -= diff; + + if (uiPoisonSprayTimer <= diff) + { + DoCast(me->getVictim(), SPELL_POSION_SPRAY, true); + uiPoisonSprayTimer = 17*IN_MILISECONDS; + } else uiPoisonSprayTimer -= diff; + + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_boss_krik_thir(Creature* pCreature) +{ + return new boss_krik_thirAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_skirmisher (Creature* pCreature) +{ + return new npc_anub_ar_skirmisherAI (pCreature); +} + +CreatureAI* GetAI_npc_skittering_infector (Creature* pCreature) +{ + return new npc_skittering_infectorAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_shadowcaster (Creature* pCreature) +{ + return new npc_anub_ar_shadowcasterAI (pCreature); +} + +CreatureAI* GetAI_npc_anub_ar_warrior (Creature* pCreature) +{ + return new npc_anub_ar_warriorAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_gashra (Creature* pCreature) +{ + return new npc_watcher_gashraAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_narjil (Creature* pCreature) +{ + return new npc_watcher_narjilAI (pCreature); +} + +CreatureAI* GetAI_npc_watcher_silthik (Creature* pCreature) +{ + return new npc_watcher_silthikAI (pCreature); +} + +void AddSC_boss_krik_thir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_krik_thir"; + newscript->GetAI = &GetAI_boss_krik_thir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_skittering_infector"; + newscript->GetAI = &GetAI_npc_skittering_infector; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_skirmisher"; + newscript->GetAI = &GetAI_npc_anub_ar_skirmisher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_shadowcaster"; + newscript->GetAI = &GetAI_npc_anub_ar_shadowcaster; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_gashra"; + newscript->GetAI = &GetAI_npc_watcher_gashra; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_anub_ar_warrior"; + newscript->GetAI = &GetAI_npc_anub_ar_warrior; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_silthik"; + newscript->GetAI = &GetAI_npc_watcher_silthik; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_watcher_narjil"; + newscript->GetAI = &GetAI_npc_watcher_narjil; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp new file mode 100644 index 00000000000..d12dbd604ba --- /dev/null +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/instance_azjol_nerub.cpp @@ -0,0 +1,215 @@ +/* + * Copyright (C) 2009 - 2010 TrinityCore + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "azjol_nerub.h" + +#define MAX_ENCOUNTER 3 + +/* Azjol Nerub encounters: +0 - Krik'thir the Gatewatcher +1 - Hadronox +2 - Anub'arak +*/ + +struct instance_azjol_nerub : public ScriptedInstance +{ + instance_azjol_nerub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiKrikthir; + uint64 uiHadronox; + uint64 uiAnubarak; + uint64 uiWatcherGashra; + uint64 uiWatcherSilthik; + uint64 uiWatcherNarjil; + uint64 uiAnubarakDoor[3]; + + uint64 uiKrikthirDoor; + + uint32 auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&auiEncounter, 0, sizeof(auiEncounter)); + memset(&uiAnubarakDoor, 0, sizeof(uiAnubarakDoor)); + + uiKrikthir = 0; + uiHadronox = 0; + uiAnubarak = 0; + uiWatcherGashra = 0; + uiWatcherSilthik = 0; + uiWatcherNarjil = 0; + uiKrikthirDoor = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 28684: uiKrikthir = pCreature->GetGUID(); break; + case 28921: uiHadronox = pCreature->GetGUID(); break; + case 29120: uiAnubarak = pCreature->GetGUID(); break; + case 28730: uiWatcherGashra = pCreature->GetGUID(); break; + case 28731: uiWatcherSilthik = pCreature->GetGUID(); break; + case 28729: uiWatcherNarjil = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch (pGo->GetEntry()) + { + case 192395: + uiKrikthirDoor = pGo->GetGUID(); + if (auiEncounter[0] == DONE) + HandleGameObject(NULL,true,pGo); + break; + case 192396: + uiAnubarakDoor[0] = pGo->GetGUID(); + break; + case 192397: + uiAnubarakDoor[1] = pGo->GetGUID(); + break; + case 192398: + uiAnubarakDoor[2] = pGo->GetGUID(); + break; + } + } + + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_KRIKTHIR_THE_GATEWATCHER: return uiKrikthir; + case DATA_HADRONOX: return uiHadronox; + case DATA_ANUBARAK: return uiAnubarak; + case DATA_WATCHER_GASHRA: return uiWatcherGashra; + case DATA_WATCHER_SILTHIK: return uiWatcherSilthik; + case DATA_WATCHER_NARJIL: return uiWatcherNarjil; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: + auiEncounter[0] = data; + if (data == DONE) + HandleGameObject(uiKrikthirDoor,true); + break; + case DATA_HADRONOX_EVENT: + auiEncounter[1] = data; + break; + case DATA_ANUBARAK_EVENT: + auiEncounter[2] = data; + if (data == IN_PROGRESS) + for (uint8 i = 0; i < 3; ++i) + HandleGameObject(uiAnubarakDoor[i], false); + else if (data == NOT_STARTED || data == DONE) + for (uint8 i = 0; i < 3; ++i) + HandleGameObject(uiAnubarakDoor[i], true); + break; + } + + if (data == DONE) + { + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: return auiEncounter[0]; + case DATA_HADRONOX_EVENT: return auiEncounter[1]; + case DATA_ANUBARAK_EVENT: return auiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "A N " << auiEncounter[0] << " " << auiEncounter[1] << " " + << auiEncounter[2]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0,data1,data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; + + if (dataHead1 == 'A' && dataHead2 == 'N') + { + auiEncounter[0] = data0; + auiEncounter[1] = data1; + auiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (auiEncounter[i] == IN_PROGRESS) + auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_azjol_nerub(Map* pMap) +{ + return new instance_azjol_nerub(pMap); +} + +void AddSC_instance_azjol_nerub() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_azjol_nerub"; + newscript->GetInstanceData = &GetInstanceData_instance_azjol_nerub; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h deleted file mode 100644 index 4113885b6f4..00000000000 --- a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/azjol_nerub.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_AZJOL_NERUB_H -#define DEF_AZJOL_NERUB_H - -enum Data64 -{ - DATA_KRIKTHIR_THE_GATEWATCHER, - DATA_HADRONOX, - DATA_ANUBARAK, - DATA_WATCHER_GASHRA, - DATA_WATCHER_SILTHIK, - DATA_WATCHER_NARJIL -}; -enum Data -{ - DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, - DATA_HADRONOX_EVENT, - DATA_ANUBARAK_EVENT -}; - -#endif diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp deleted file mode 100644 index 6de6578f7bb..00000000000 --- a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_anubarak.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/* -* Copyright (C) 2009 - 2010 TrinityCore -* -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -//SQL: UPDATE creature_template SET mechanic_immune_mask = 1073741823 WHERE name like "anub'arak%"; - -enum Spells -{ - SPELL_CARRION_BEETLES = 53520, - SPELL_SUMMON_CARRION_BEETLES = 53521, - SPELL_LEECHING_SWARM = 53467, - SPELL_POUND = 53472, - SPELL_POUND_H = 59433, - SPELL_SUBMERGE = 53421, - SPELL_IMPALE_DMG = 53454, - SPELL_IMPALE_DMG_H = 59446, - SPELL_IMPALE_SHAKEGROUND = 53455, - SPELL_IMPALE_SPIKE = 53539, //this is not the correct visual effect - //SPELL_IMPALE_TARGET = 53458, -}; - -enum Creatures -{ - CREATURE_GUARDIAN = 29216, - CREATURE_VENOMANCER = 29217, - CREATURE_DATTER = 29213, - CREATURE_IMPALE_TARGET = 89, - DISPLAY_INVISIBLE = 11686 -}; - -// not in db -enum Yells -{ - SAY_INTRO = -1601010, - SAY_AGGRO = -1601000, - SAY_SLAY_1 = -1601001, - SAY_SLAY_2 = -1601002, - SAY_SLAY_3 = -1601003, - SAY_LOCUST_1 = -1601005, - SAY_LOCUST_2 = -1601006, - SAY_LOCUST_3 = -1601007, - SAY_SUBMERGE_1 = -1601008, - SAY_SUBMERGE_2 = -1601009, - SAY_DEATH = -1601004 -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 20381, -}; - -enum Phases -{ - PHASE_MELEE = 0, - PHASE_UNDERGROUND = 1, - IMPALE_PHASE_TARGET = 0, - IMPALE_PHASE_ATTACK = 1, - IMPALE_PHASE_DMG = 2 -}; - -const Position SpawnPoint[2] = -{ - { 550.7, 282.8, 224.3 }, - { 551.1, 229.4, 224.3 }, -}; - -const Position SpawnPointGuardian[2] = -{ - { 550.348633, 316.006805, 234.2947 }, - { 550.188660, 324.264557, 237.7412 }, -}; - -struct boss_anub_arakAI : public ScriptedAI -{ - boss_anub_arakAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - bool bChanneling; - bool bGuardianSummoned; - bool bVenomancerSummoned; - bool bDatterSummoned; - uint8 uiPhase; - uint32 uiUndergroundPhase; - uint32 uiCarrionBeetlesTimer; - uint32 uiLeechingSwarmTimer; - uint32 uiPoundTimer; - uint32 uiSubmergeTimer; - uint32 uiUndergroundTimer; - uint32 uiVenomancerTimer; - uint32 uiDatterTimer; - - uint32 uiImpaleTimer; - uint32 uiImpalePhase; - uint64 uiImpaleTarget; - - SummonList lSummons; - - void Reset() - { - uiCarrionBeetlesTimer = 8*IN_MILISECONDS; - uiLeechingSwarmTimer = 20*IN_MILISECONDS; - uiImpaleTimer = 9*IN_MILISECONDS; - uiPoundTimer = 15*IN_MILISECONDS; - - uiPhase = PHASE_MELEE; - uiUndergroundPhase = 0; - bChanneling = false; - uiImpalePhase = IMPALE_PHASE_TARGET; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->RemoveAura(SPELL_SUBMERGE); - - lSummons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_ANUBARAK_EVENT, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - Creature* DoSummonImpaleTarget(Unit *pTarget) - { - Position targetPos; - pTarget->GetPosition(&targetPos); - - if (TempSummon* pImpaleTarget = me->SummonCreature(CREATURE_IMPALE_TARGET, targetPos, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 6*IN_MILISECONDS)) - { - uiImpaleTarget = pImpaleTarget->GetGUID(); - pImpaleTarget->SetReactState(REACT_PASSIVE); - pImpaleTarget->SetDisplayId(DISPLAY_INVISIBLE); - pImpaleTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - return pImpaleTarget; - } - - return NULL; - } - - void EnterCombat(Unit * /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - pInstance->SetData(DATA_ANUBARAK_EVENT, IN_PROGRESS); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - switch (uiPhase) - { - case PHASE_UNDERGROUND: - if (uiImpaleTimer <= diff) - { - switch(uiImpalePhase) - { - case IMPALE_PHASE_TARGET: - if (Unit *target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) - pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SHAKEGROUND, true); - uiImpaleTimer = 3*IN_MILISECONDS; - uiImpalePhase = IMPALE_PHASE_ATTACK; - } - break; - case IMPALE_PHASE_ATTACK: - if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) - { - pImpaleTarget->CastSpell(pImpaleTarget, SPELL_IMPALE_SPIKE, false); - pImpaleTarget->RemoveAurasDueToSpell(SPELL_IMPALE_SHAKEGROUND); - } - uiImpalePhase = IMPALE_PHASE_DMG; - uiImpaleTimer = 1*IN_MILISECONDS; - break; - case IMPALE_PHASE_DMG: - if (Creature* pImpaleTarget = Unit::GetCreature(*me, uiImpaleTarget)) - me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_IMPALE_DMG, SPELL_IMPALE_DMG_H), true); - uiImpalePhase = IMPALE_PHASE_TARGET; - uiImpaleTimer = 9*IN_MILISECONDS; - break; - } - } else uiImpaleTimer -= diff; - - if (!bGuardianSummoned) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Guardian = me->SummonCreature(CREATURE_GUARDIAN,SpawnPointGuardian[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Guardian->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Guardian); - } - } - bGuardianSummoned = true; - } - - if (!bVenomancerSummoned) - { - if (uiVenomancerTimer <= diff) - { - if (uiUndergroundPhase > 1) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Venomancer = me->SummonCreature(CREATURE_VENOMANCER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Venomancer->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Venomancer); - } - } - bVenomancerSummoned = true; - } - } else uiVenomancerTimer -= diff; - } - - if (!bDatterSummoned) - { - if (uiDatterTimer <= diff) - { - if (uiUndergroundPhase > 2) - { - for (uint8 i = 0; i < 2; ++i) - { - if (Creature *Datter = me->SummonCreature(CREATURE_DATTER,SpawnPoint[i],TEMPSUMMON_CORPSE_DESPAWN,0)) - { - Datter->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Datter); - } - } - bDatterSummoned = true; - } - } else uiDatterTimer -= diff; - } - - if (uiUndergroundTimer <= diff) - { - me->RemoveAura(SPELL_SUBMERGE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - uiPhase = PHASE_MELEE; - } else uiUndergroundTimer -= diff; - break; - - case PHASE_MELEE: - if (((uiUndergroundPhase == 0 && HealthBelowPct(75)) - || (uiUndergroundPhase == 1 && HealthBelowPct(50)) - || (uiUndergroundPhase == 2 && HealthBelowPct(25))) - && !me->hasUnitState(UNIT_STAT_CASTING)) - { - bGuardianSummoned = false; - bVenomancerSummoned = false; - bDatterSummoned = false; - - uiUndergroundTimer = 40*IN_MILISECONDS; - uiVenomancerTimer = 25*IN_MILISECONDS; - uiDatterTimer = 32*IN_MILISECONDS; - - uiImpalePhase = 0; - uiImpaleTimer = 9*IN_MILISECONDS; - - DoCast(me, SPELL_SUBMERGE, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - - uiPhase = PHASE_UNDERGROUND; - ++uiUndergroundPhase; - } - - if (bChanneling == true) - { - for (uint8 i = 0; i < 8; ++i) - DoCast(me->getVictim(), SPELL_SUMMON_CARRION_BEETLES, true); - bChanneling = false; - } - else if (uiCarrionBeetlesTimer <= diff) - { - bChanneling = true; - DoCastVictim(SPELL_CARRION_BEETLES); - uiCarrionBeetlesTimer = 25*IN_MILISECONDS; - } else uiCarrionBeetlesTimer -= diff; - - if (uiLeechingSwarmTimer <= diff) - { - DoCast(me, SPELL_LEECHING_SWARM, true); - uiLeechingSwarmTimer = 19*IN_MILISECONDS; - } else uiLeechingSwarmTimer -= diff; - - if (uiPoundTimer <= diff) - { - if (Unit *target = me->getVictim()) - { - if (Creature *pImpaleTarget = DoSummonImpaleTarget(target)) - me->CastSpell(pImpaleTarget, DUNGEON_MODE(SPELL_POUND, SPELL_POUND_H), false); - } - uiPoundTimer = 16.5*IN_MILISECONDS; - } else uiPoundTimer -= diff; - - DoMeleeAttackIfReady(); - break; - } - } - - void JustDied(Unit * /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - lSummons.DespawnAll(); - if (pInstance) - pInstance->SetData(DATA_ANUBARAK_EVENT, DONE); - } - - void KilledUnit(Unit *pVictim) - { - if (pVictim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustSummoned(Creature* summon) - { - lSummons.Summon(summon); - } -}; - -CreatureAI* GetAI_boss_anub_arak(Creature *pCreature) -{ - return new boss_anub_arakAI (pCreature); -} - -void AddSC_boss_anub_arak() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_anub_arak"; - newscript->GetAI = &GetAI_boss_anub_arak; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp deleted file mode 100644 index 0fc4e87d7c5..00000000000 --- a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_hadronox.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* -* Comment: No Waves atm and the doors spells are crazy... -* -* When your group enters the main room (the one after the bridge), you will notice a group of 3 Nerubians. -* When you engage them, 2 more groups like this one spawn behind the first one - it is important to pull the first group back, -* so you don't aggro all 3. Hadronox will be under you, fighting Nerubians. -* -* This is the timed gauntlet - waves of non-elite spiders -* will spawn from the 3 doors located a little above the main room, and will then head down to fight Hadronox. After clearing the -* main room, it is recommended to just stay in it, kill the occasional non-elites that will attack you instead of the boss, and wait for -* Hadronox to make his way to you. When Hadronox enters the main room, she will web the doors, and no more non-elites will spawn. -*/ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -enum Spells -{ - SPELL_ACID_CLOUD = 53400, // Victim - SPELL_LEECH_POISON = 53030, // Victim - SPELL_PIERCE_ARMOR = 53418, // Victim - SPELL_WEB_GRAB = 57731, // Victim - SPELL_WEB_FRONT_DOORS = 53177, // Self - SPELL_WEB_SIDE_DOORS = 53185, // Self - H_SPELL_ACID_CLOUD = 59419, - H_SPELL_LEECH_POISON = 59417, - H_SPELL_WEB_GRAB = 59421 -}; - -struct boss_hadronoxAI : public ScriptedAI -{ - boss_hadronoxAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - fMaxDistance = 50.0f; - bFirstTime = true; - } - - ScriptedInstance* pInstance; - - uint32 uiAcidTimer; - uint32 uiLeechTimer; - uint32 uiPierceTimer; - uint32 uiGrabTimer; - uint32 uiDoorsTimer; - uint32 uiCheckDistanceTimer; - - bool bFirstTime; - - float fMaxDistance; - - void Reset() - { - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 9.0f); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 9.0f); - - uiAcidTimer = urand(10*IN_MILISECONDS,14*IN_MILISECONDS); - uiLeechTimer = urand(3*IN_MILISECONDS,9*IN_MILISECONDS); - uiPierceTimer = urand(1*IN_MILISECONDS,3*IN_MILISECONDS); - uiGrabTimer = urand(15*IN_MILISECONDS,19*IN_MILISECONDS); - uiDoorsTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - uiCheckDistanceTimer = 2*IN_MILISECONDS; - - if (pInstance && (pInstance->GetData(DATA_HADRONOX_EVENT) != DONE && !bFirstTime)) - pInstance->SetData(DATA_HADRONOX_EVENT, FAIL); - - bFirstTime = false; - } - - //when Hadronox kills any enemy (that includes a party member) she will regain 10% of her HP if the target had Leech Poison on - void KilledUnit(Unit* Victim) - { - // not sure if this aura check is correct, I think it is though - if (!Victim || !Victim->HasAura(DUNGEON_MODE(SPELL_LEECH_POISON, H_SPELL_LEECH_POISON)) || !me->isAlive()) - return; - - uint32 health = me->GetMaxHealth()/10; - - if ((me->GetHealth()+health) >= me->GetMaxHealth()) - me->SetHealth(me->GetMaxHealth()); - else - me->SetHealth(me->GetHealth()+health); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_HADRONOX_EVENT, DONE); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_HADRONOX_EVENT, IN_PROGRESS); - me->SetInCombatWithZone(); - } - - void CheckDistance(float dist, const uint32 uiDiff) - { - if (!me->isInCombat()) - return; - - float x=0.0f, y=0.0f, z=0.0f; - me->GetRespawnCoord(x,y,z); - - if (uiCheckDistanceTimer <= uiDiff) - uiCheckDistanceTimer = 5*IN_MILISECONDS; - else - { - uiCheckDistanceTimer -= uiDiff; - return; - } - if (me->IsInEvadeMode() || !me->getVictim()) - return; - if (me->GetDistance(x,y,z) > dist) - EnterEvadeMode(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) return; - - // Without he comes up through the air to players on the bridge after krikthir if players crossing this bridge! - CheckDistance(fMaxDistance, diff); - - if (me->HasAura(SPELL_WEB_FRONT_DOORS) || me->HasAura(SPELL_WEB_SIDE_DOORS)) - { - if (IsCombatMovement()) - SetCombatMovement(false); - } - else if (!IsCombatMovement()) - SetCombatMovement(true); - - if (uiPierceTimer <= diff) - { - DoCast(me->getVictim(), SPELL_PIERCE_ARMOR); - uiPierceTimer = 8*IN_MILISECONDS; - } else uiPierceTimer -= diff; - - if (uiAcidTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ACID_CLOUD); - - uiAcidTimer = urand(20*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiAcidTimer -= diff; - - if (uiLeechTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_LEECH_POISON); - - uiLeechTimer = urand(11*IN_MILISECONDS,14*IN_MILISECONDS); - } else uiLeechTimer -= diff; - - if (uiGrabTimer <= diff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) // Draws all players (and attacking Mobs) to itself. - DoCast(pTarget, SPELL_WEB_GRAB); - - uiGrabTimer = urand(15*IN_MILISECONDS,30*IN_MILISECONDS); - } else uiGrabTimer -= diff; - - if (uiDoorsTimer <= diff) - { - //DoCast(me, RAND(SPELL_WEB_FRONT_DOORS, SPELL_WEB_SIDE_DOORS)); - uiDoorsTimer = urand(30*IN_MILISECONDS,60*IN_MILISECONDS); - } else uiDoorsTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_hadronox(Creature* pCreature) -{ - return new boss_hadronoxAI (pCreature); -} - -void AddSC_boss_hadronox() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_hadronox"; - newscript->GetAI = &GetAI_boss_hadronox; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp deleted file mode 100644 index 4863bdcb032..00000000000 --- a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp +++ /dev/null @@ -1,553 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: Find in the future best timers and the event is not implemented. - */ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -enum Spells -{ - SPELL_MIND_FLAY = 52586, - H_SPELL_MIND_FLAY = 59367, - SPELL_CURSE_OF_FATIGUE = 52592, - H_SPELL_CURSE_OF_FATIGUE = 59368, - SPELL_FRENZY = 28747, //maybe 53361 - SPELL_SUMMON_SKITTERING_SWARMER = 52438, //AOE Effect 140, maybe 52439 - SPELL_SUMMON_SKITTERING_SWARMER_1 = 52439, //Summon 3x 28735 - H_SPELL_ACID_SPLASH = 59363, - SPELL_ACID_SPLASH = 52446, - SPELL_CHARGE = 16979,//maybe is another spell - SPELL_BACKSTAB = 52540, - SPELL_SHADOW_BOLT = 52534, - H_SPELL_SHADOW_BOLT = 59357, - SPELL_SHADOW_NOVA = 52535, - H_SPELL_SHADOW_NOVA = 59358, - SPELL_STRIKE = 52532, - SPELL_CLEAVE = 49806, - SPELL_ENRAGE = 52470, - SPELL_INFECTED_BITE = 52469, - H_SPELL_INFECTED_BITE = 59364, - SPELL_WEB_WRAP = 52086,//the spell is not working properly - SPELL_BLINDING_WEBS = 52524, - H_SPELL_BLINDING_WEBS = 59365, - SPELL_POSION_SPRAY = 52493, - H_SPELL_POSION_SPRAY = 59366 -}; - -enum Mobs -{ - MOB_SKITTERING_SWARMER = 28735, - MOB_SKITTERING_SWARMER_CONTROLLER = 32593, - MOB_SKITTERING_INFECTIOR = 28736 -}; - -enum Yells -{ - SAY_AGGRO = -1601011, - SAY_SLAY_1 = -1601012, - SAY_SLAY_2 = -1601013, - SAY_DEATH = -1601014, - //Not in db - SAY_SEND_GROUP_1 = -1601020, - SAY_SEND_GROUP_2 = -1601021, - SAY_SEND_GROUP_3 = -1601022, - SAY_SWARM_1 = -1601015, - SAY_SWARM_2 = -1601016, - SAY_PREFIGHT_1 = -1601017, - SAY_PREFIGHT_2 = -1601018, - SAY_PREFIGHT_3 = -1601019 -}; - -enum Misc -{ - ACHIEV_WATH_HIM_DIE = 1296 -}; - -const Position SpawnPoint[] = -{ - { 566.164, 682.087, 769.079, 2.21657 }, - { 529.042, 706.941, 777.298, 1.0821 }, - { 489.975, 671.239, 772.131, 0.261799 }, - { 488.556, 692.95, 771.764, 4.88692 }, - { 553.34, 640.387, 777.419, 1.20428 }, - { 517.486, 706.398, 777.335, 5.35816 }, - { 504.01, 637.693, 777.479, 0.506145 }, - { 552.625, 706.408, 777.177, 3.4383 } -}; -struct boss_krik_thirAI : public ScriptedAI -{ - boss_krik_thirAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiMindFlayTimer; - uint32 uiCurseFatigueTimer; - uint32 uiSummonTimer; - - void Reset() - { - uiMindFlayTimer = 15*IN_MILISECONDS; - uiCurseFatigueTimer = 12*IN_MILISECONDS; - - if (pInstance) - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - Summon(); - uiSummonTimer = 15*IN_MILISECONDS; - - if (pInstance) - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, IN_PROGRESS); - } - - void Summon() - { - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[0],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[1],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[2],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[3],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[4],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[5],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_INFECTIOR,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[6],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - me->SummonCreature(MOB_SKITTERING_SWARMER,SpawnPoint[7],TEMPSUMMON_TIMED_DESPAWN,25*IN_MILISECONDS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiSummonTimer <= diff) - { - Summon(); - uiSummonTimer = 15*IN_MILISECONDS; - } else uiSummonTimer -= diff; - - if (uiMindFlayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MIND_FLAY); - uiMindFlayTimer = 15*IN_MILISECONDS; - } else uiMindFlayTimer -= diff; - - if (uiCurseFatigueTimer <= diff) - { - //WowWiki say "Curse of Fatigue-Kirk'thir will cast Curse of Fatigue on 2-3 targets periodically." - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - Unit *pTarget_1 = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - - DoCast(pTarget, SPELL_CURSE_OF_FATIGUE); - DoCast(pTarget_1, SPELL_CURSE_OF_FATIGUE); - - uiCurseFatigueTimer = 10*IN_MILISECONDS; - } else uiCurseFatigueTimer -= diff; - - if (!me->HasAura(SPELL_FRENZY) && HealthBelowPct(10)) - DoCast(me, SPELL_FRENZY, true); - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (!pInstance) - return; - - pInstance->SetData(DATA_KRIKTHIR_THE_GATEWATCHER_EVENT, DONE); - //Achievement: Watch him die - Creature *pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_GASHRA)); - if (!pAdd || !pAdd->isAlive()) - return; - - pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_SILTHIK)); - if (!pAdd || !pAdd->isAlive()) - return; - - pAdd = Unit::GetCreature(*me, pInstance->GetData64(DATA_WATCHER_NARJIL)); - if (!pAdd || !pAdd->isAlive()) - return; - - pInstance->DoCompleteAchievement(ACHIEV_WATH_HIM_DIE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustSummoned(Creature* summoned) - { - summoned->GetMotionMaster()->MovePoint(0,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ()); - } -}; - -struct npc_skittering_infectorAI : public ScriptedAI -{ - npc_skittering_infectorAI(Creature *c) : ScriptedAI(c) {} - - void JustDied(Unit* /*killer*/) - { - //The spell is not working propperly - DoCast(me->getVictim(),SPELL_ACID_SPLASH, true); - } - -}; - -struct npc_anub_ar_skirmisherAI : public ScriptedAI -{ - npc_anub_ar_skirmisherAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiChargeTimer; - uint32 uiBackstabTimer; - - void Reset() - { - uiChargeTimer = 11*IN_MILISECONDS; - uiBackstabTimer = 7*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiChargeTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoResetThreat(); - me->AddThreat(pTarget,1.0f); - DoCast(pTarget, SPELL_CHARGE, true); - } - uiChargeTimer = 15*IN_MILISECONDS; - } else uiChargeTimer -= diff; - - if (uiBackstabTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BACKSTAB); - uiBackstabTimer = 12*IN_MILISECONDS; - } else uiBackstabTimer -= diff; - - DoMeleeAttackIfReady(); - - } -}; - -struct npc_anub_ar_shadowcasterAI : public ScriptedAI -{ - npc_anub_ar_shadowcasterAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiShadowBoltTimer; - uint32 uiShadowNovaTimer; - - void Reset() - { - uiShadowBoltTimer = 6*IN_MILISECONDS; - uiShadowNovaTimer = 15*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiShadowBoltTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_SHADOW_BOLT, true); - uiShadowBoltTimer = 15*IN_MILISECONDS; - } else uiShadowBoltTimer -= diff; - - if (uiShadowNovaTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_NOVA, true); - uiShadowNovaTimer = 17*IN_MILISECONDS; - } else uiShadowNovaTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_anub_ar_warriorAI : public ScriptedAI -{ - npc_anub_ar_warriorAI(Creature *c) : ScriptedAI(c){} - - uint32 uiCleaveTimer; - uint32 uiStrikeTimer; - - void Reset() - { - uiCleaveTimer = 11*IN_MILISECONDS; - uiStrikeTimer = 6*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STRIKE, true); - uiStrikeTimer = 15*IN_MILISECONDS; - } else uiStrikeTimer -= diff; - - if (uiCleaveTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE, true); - uiCleaveTimer = 17*IN_MILISECONDS; - } else uiCleaveTimer -= diff; - - DoMeleeAttackIfReady(); - - } - -}; - -struct npc_watcher_gashraAI : public ScriptedAI -{ - npc_watcher_gashraAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - } - - void EnterCombat(Unit* /*who*/) - { - DoCast(me, SPELL_ENRAGE, true); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - uiWebWrapTimer = 17*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 15*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_watcher_narjilAI : public ScriptedAI -{ - npc_watcher_narjilAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - uint32 uiBindingWebsTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - uiBindingWebsTimer = 17*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - uiWebWrapTimer = 15*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 11*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - if (uiBindingWebsTimer <= diff) - { - DoCast(me->getVictim(), SPELL_BLINDING_WEBS, true); - uiBindingWebsTimer = 17*IN_MILISECONDS; - } else uiBindingWebsTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct npc_watcher_silthikAI : public ScriptedAI -{ - npc_watcher_silthikAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiWebWrapTimer; - uint32 uiInfectedBiteTimer; - uint32 uiPoisonSprayTimer; - - void Reset() - { - uiWebWrapTimer = 11*IN_MILISECONDS; - uiInfectedBiteTimer = 4*IN_MILISECONDS; - uiPoisonSprayTimer = 15*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiWebWrapTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_WEB_WRAP, true); - - uiWebWrapTimer = 15*IN_MILISECONDS; - } else uiWebWrapTimer -= diff; - - if (uiInfectedBiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_INFECTED_BITE, true); - uiInfectedBiteTimer = 15*IN_MILISECONDS; - } else uiInfectedBiteTimer -= diff; - - if (uiPoisonSprayTimer <= diff) - { - DoCast(me->getVictim(), SPELL_POSION_SPRAY, true); - uiPoisonSprayTimer = 17*IN_MILISECONDS; - } else uiPoisonSprayTimer -= diff; - - DoMeleeAttackIfReady(); - - } -}; - -CreatureAI* GetAI_boss_krik_thir(Creature* pCreature) -{ - return new boss_krik_thirAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_skirmisher (Creature* pCreature) -{ - return new npc_anub_ar_skirmisherAI (pCreature); -} - -CreatureAI* GetAI_npc_skittering_infector (Creature* pCreature) -{ - return new npc_skittering_infectorAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_shadowcaster (Creature* pCreature) -{ - return new npc_anub_ar_shadowcasterAI (pCreature); -} - -CreatureAI* GetAI_npc_anub_ar_warrior (Creature* pCreature) -{ - return new npc_anub_ar_warriorAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_gashra (Creature* pCreature) -{ - return new npc_watcher_gashraAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_narjil (Creature* pCreature) -{ - return new npc_watcher_narjilAI (pCreature); -} - -CreatureAI* GetAI_npc_watcher_silthik (Creature* pCreature) -{ - return new npc_watcher_silthikAI (pCreature); -} - -void AddSC_boss_krik_thir() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_krik_thir"; - newscript->GetAI = &GetAI_boss_krik_thir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_skittering_infector"; - newscript->GetAI = &GetAI_npc_skittering_infector; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_skirmisher"; - newscript->GetAI = &GetAI_npc_anub_ar_skirmisher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_shadowcaster"; - newscript->GetAI = &GetAI_npc_anub_ar_shadowcaster; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_gashra"; - newscript->GetAI = &GetAI_npc_watcher_gashra; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_anub_ar_warrior"; - newscript->GetAI = &GetAI_npc_anub_ar_warrior; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_silthik"; - newscript->GetAI = &GetAI_npc_watcher_silthik; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_watcher_narjil"; - newscript->GetAI = &GetAI_npc_watcher_narjil; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp b/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp deleted file mode 100644 index d12dbd604ba..00000000000 --- a/src/server/scripts/Northrend/AzjolNerub/azjol_nerub/instance_azjol_nerub.cpp +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright (C) 2009 - 2010 TrinityCore - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "azjol_nerub.h" - -#define MAX_ENCOUNTER 3 - -/* Azjol Nerub encounters: -0 - Krik'thir the Gatewatcher -1 - Hadronox -2 - Anub'arak -*/ - -struct instance_azjol_nerub : public ScriptedInstance -{ - instance_azjol_nerub(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiKrikthir; - uint64 uiHadronox; - uint64 uiAnubarak; - uint64 uiWatcherGashra; - uint64 uiWatcherSilthik; - uint64 uiWatcherNarjil; - uint64 uiAnubarakDoor[3]; - - uint64 uiKrikthirDoor; - - uint32 auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&auiEncounter, 0, sizeof(auiEncounter)); - memset(&uiAnubarakDoor, 0, sizeof(uiAnubarakDoor)); - - uiKrikthir = 0; - uiHadronox = 0; - uiAnubarak = 0; - uiWatcherGashra = 0; - uiWatcherSilthik = 0; - uiWatcherNarjil = 0; - uiKrikthirDoor = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 28684: uiKrikthir = pCreature->GetGUID(); break; - case 28921: uiHadronox = pCreature->GetGUID(); break; - case 29120: uiAnubarak = pCreature->GetGUID(); break; - case 28730: uiWatcherGashra = pCreature->GetGUID(); break; - case 28731: uiWatcherSilthik = pCreature->GetGUID(); break; - case 28729: uiWatcherNarjil = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch (pGo->GetEntry()) - { - case 192395: - uiKrikthirDoor = pGo->GetGUID(); - if (auiEncounter[0] == DONE) - HandleGameObject(NULL,true,pGo); - break; - case 192396: - uiAnubarakDoor[0] = pGo->GetGUID(); - break; - case 192397: - uiAnubarakDoor[1] = pGo->GetGUID(); - break; - case 192398: - uiAnubarakDoor[2] = pGo->GetGUID(); - break; - } - } - - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_KRIKTHIR_THE_GATEWATCHER: return uiKrikthir; - case DATA_HADRONOX: return uiHadronox; - case DATA_ANUBARAK: return uiAnubarak; - case DATA_WATCHER_GASHRA: return uiWatcherGashra; - case DATA_WATCHER_SILTHIK: return uiWatcherSilthik; - case DATA_WATCHER_NARJIL: return uiWatcherNarjil; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: - auiEncounter[0] = data; - if (data == DONE) - HandleGameObject(uiKrikthirDoor,true); - break; - case DATA_HADRONOX_EVENT: - auiEncounter[1] = data; - break; - case DATA_ANUBARAK_EVENT: - auiEncounter[2] = data; - if (data == IN_PROGRESS) - for (uint8 i = 0; i < 3; ++i) - HandleGameObject(uiAnubarakDoor[i], false); - else if (data == NOT_STARTED || data == DONE) - for (uint8 i = 0; i < 3; ++i) - HandleGameObject(uiAnubarakDoor[i], true); - break; - } - - if (data == DONE) - { - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_KRIKTHIR_THE_GATEWATCHER_EVENT: return auiEncounter[0]; - case DATA_HADRONOX_EVENT: return auiEncounter[1]; - case DATA_ANUBARAK_EVENT: return auiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "A N " << auiEncounter[0] << " " << auiEncounter[1] << " " - << auiEncounter[2]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0,data1,data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'A' && dataHead2 == 'N') - { - auiEncounter[0] = data0; - auiEncounter[1] = data1; - auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (auiEncounter[i] == IN_PROGRESS) - auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_azjol_nerub(Map* pMap) -{ - return new instance_azjol_nerub(pMap); -} - -void AddSC_instance_azjol_nerub() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_azjol_nerub"; - newscript->GetInstanceData = &GetInstanceData_instance_azjol_nerub; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp new file mode 100644 index 00000000000..c33ea69fa2d --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_argent_challenge.cpp @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Argent Challenge Encounter. +SD%Complete: 50 % +SDComment: AI for Argent Soldiers are not implemented. AI from bosses need more improvements. +SDCategory: Trial of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" +#include "ScriptedEscortAI.h" + +enum eSpells +{ + //Eadric + SPELL_EADRIC_ACHIEVEMENT = 68197, + SPELL_HAMMER_JUSTICE = 66863, + SPELL_HAMMER_RIGHTEOUS = 66867, + SPELL_RADIANCE = 66935, + SPELL_VENGEANCE = 66865, + + //Paletress + SPELL_SMITE = 66536, + SPELL_SMITE_H = 67674, + SPELL_HOLY_FIRE = 66538, + SPELL_HOLY_FIRE_H = 67676, + SPELL_RENEW = 66537, + SPELL_RENEW_H = 67675, + SPELL_HOLY_NOVA = 66546, + SPELL_SHIELD = 66515, + SPELL_CONFESS = 66680, + SPELL_SUMMON_MEMORY = 66545, + + //Memory + SPELL_OLD_WOUNDS = 66620, + SPELL_OLD_WOUNDS_H = 67679, + SPELL_SHADOWS_PAST = 66619, + SPELL_SHADOWS_PAST_H = 67678, + SPELL_WAKING_NIGHTMARE = 66552, + SPELL_WAKING_NIGHTMARE_H = 67677 +}; + +struct boss_eadricAI : public ScriptedAI +{ + boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + pCreature->SetReactState(REACT_PASSIVE); + pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint32 uiVenganceTimer; + uint32 uiRadianceTimer; + uint32 uiHammerJusticeTimer; + uint32 uiResetTimer; + + bool bDone; + + void Reset() + { + uiVenganceTimer = 10000; + uiRadianceTimer = 16000; + uiHammerJusticeTimer = 25000; + uiResetTimer = 5000; + + bDone = false; + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + damage = 0; + EnterEvadeMode(); + me->setFaction(35); + bDone = true; + } + } + + void MovementInform(uint32 MovementType, uint32 /*Data*/) + { + if (MovementType != POINT_MOTION_TYPE) + return; + + if (pInstance) + pInstance->SetData(BOSS_ARGENT_CHALLENGE_E, DONE); + + me->DisappearAndDie(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (bDone && uiResetTimer <= uiDiff) + { + me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); + bDone = false; + } else uiResetTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + if (uiHammerJusticeTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + { + DoCast(pTarget, SPELL_HAMMER_JUSTICE); + DoCast(pTarget, SPELL_HAMMER_RIGHTEOUS); + } + } + uiHammerJusticeTimer = 25000; + } else uiHammerJusticeTimer -= uiDiff; + + if (uiVenganceTimer <= uiDiff) + { + DoCast(me,SPELL_VENGEANCE); + + uiVenganceTimer = 10000; + } else uiVenganceTimer -= uiDiff; + + if (uiRadianceTimer <= uiDiff) + { + DoCastAOE(SPELL_RADIANCE); + + uiRadianceTimer = 16000; + } else uiRadianceTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_eadric(Creature* pCreature) +{ + return new boss_eadricAI(pCreature); +} + +struct boss_paletressAI : public ScriptedAI +{ + boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + MemoryGUID = 0; + pCreature->SetReactState(REACT_PASSIVE); + pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pCreature->RestoreFaction(); + } + + ScriptedInstance* pInstance; + + Creature* pMemory; + uint64 MemoryGUID; + + bool bHealth; + bool bDone; + + uint32 uiHolyFireTimer; + uint32 uiHolySmiteTimer; + uint32 uiRenewTimer; + uint32 uiResetTimer; + + void Reset() + { + me->RemoveAllAuras(); + + uiHolyFireTimer = urand(9000,12000); + uiHolySmiteTimer = urand(5000,7000); + uiRenewTimer = urand(2000,5000); + + uiResetTimer = 7000; + + bHealth = false; + bDone = false; + + if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) + if (pMemory->isAlive()) + pMemory->RemoveFromWorld(); + } + + void SetData(uint32 uiId, uint32 /*uiValue*/) + { + if (uiId == 1) + me->RemoveAura(SPELL_SHIELD); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth()) + { + damage = 0; + EnterEvadeMode(); + me->setFaction(35); + bDone = true; + } + } + + void MovementInform(uint32 MovementType, uint32 Point) + { + if (MovementType != POINT_MOTION_TYPE || Point != 0) + return; + + if (pInstance) + pInstance->SetData(BOSS_ARGENT_CHALLENGE_P, DONE); + + me->DisappearAndDie(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (bDone && uiResetTimer <= uiDiff) + { + me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); + bDone = false; + } else uiResetTimer -= uiDiff; + + if (!UpdateVictim()) + return; + + if (uiHolyFireTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_HOLY_FIRE); + } + if (me->HasAura(SPELL_SHIELD)) + uiHolyFireTimer = 13000; + else + uiHolyFireTimer = urand(9000,12000); + } else uiHolyFireTimer -= uiDiff; + + if (uiHolySmiteTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_SMITE); + } + if (me->HasAura(SPELL_SHIELD)) + uiHolySmiteTimer = 9000; + else + uiHolySmiteTimer = urand(5000,7000); + } else uiHolySmiteTimer -= uiDiff; + + if (me->HasAura(SPELL_SHIELD)) + if (uiRenewTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + uint8 uiTarget = urand(0,1); + switch(uiTarget) + { + case 0: + DoCast(me,SPELL_RENEW); + break; + case 1: + if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) + if (pMemory->isAlive()) + DoCast(pMemory, SPELL_RENEW); + break; + } + uiRenewTimer = urand(15000,17000); + } else uiRenewTimer -= uiDiff; + + + if (!bHealth && me->GetHealth()*100 / me->GetMaxHealth() <= 25) + { + me->InterruptNonMeleeSpells(true); + DoCastAOE(SPELL_HOLY_NOVA,false); + DoCast(me, SPELL_SHIELD); + DoCastAOE(SPELL_SUMMON_MEMORY,false); + DoCastAOE(SPELL_CONFESS,false); + + bHealth = true; + } + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* pSummon) + { + MemoryGUID = pSummon->GetGUID(); + } +}; + +CreatureAI* GetAI_boss_paletress(Creature* pCreature) +{ + return new boss_paletressAI(pCreature); +} + +struct npc_memoryAI : public ScriptedAI +{ + npc_memoryAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiOldWoundsTimer; + uint32 uiShadowPastTimer; + uint32 uiWakingNightmare; + + void Reset() + { + uiOldWoundsTimer = 12000; + uiShadowPastTimer = 5000; + uiWakingNightmare = 7000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiOldWoundsTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, SPELL_OLD_WOUNDS); + } + uiOldWoundsTimer = 12000; + }else uiOldWoundsTimer -= uiDiff; + + if (uiWakingNightmare <= uiDiff) + { + DoCast(me, SPELL_WAKING_NIGHTMARE); + uiWakingNightmare = 7000; + }else uiWakingNightmare -= uiDiff; + + if (uiShadowPastTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_SHADOWS_PAST); + } + uiShadowPastTimer = 5000; + }else uiShadowPastTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (me->isSummon()) + { + if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) + { + if (pSummoner && pSummoner->isAlive()) + CAST_CRE(pSummoner)->AI()->SetData(1,0); + } + } + } +}; + +CreatureAI* GetAI_npc_memory(Creature* pCreature) +{ + return new npc_memoryAI(pCreature); +} + +// THIS AI NEEDS MORE IMPROVEMENTS +struct npc_argent_soldierAI : public npc_escortAI +{ + npc_argent_soldierAI(Creature* pCreature) : npc_escortAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + me->SetReactState(REACT_DEFENSIVE); + SetDespawnAtEnd(false); + uiWaypoint = 0; + } + + ScriptedInstance* pInstance; + + uint8 uiWaypoint; + + void WaypointReached(uint32 uiPoint) + { + if (uiPoint == 0) + { + switch(uiWaypoint) + { + case 0: + me->SetOrientation(5.81); + break; + case 1: + me->SetOrientation(4.60); + break; + case 2: + me->SetOrientation(2.79); + break; + } + + me->SendMovementFlagUpdate(); + } + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch(me->GetEntry()) + { + case NPC_ARGENT_LIGHWIELDER: + switch(uiType) + { + case 0: + AddWaypoint(0,712.14,628.42,411.88); + break; + case 1: + AddWaypoint(0,742.44,650.29,411.79); + break; + case 2: + AddWaypoint(0,783.33,615.29,411.84); + break; + } + break; + case NPC_ARGENT_MONK: + switch(uiType) + { + case 0: + AddWaypoint(0,713.12,632.97,411.90); + break; + case 1: + AddWaypoint(0,746.73,650.24,411.56); + break; + case 2: + AddWaypoint(0,781.32,610.54,411.82); + break; + } + break; + case NPC_PRIESTESS: + switch(uiType) + { + case 0: + AddWaypoint(0,715.06,637.07,411.91); + break; + case 1: + AddWaypoint(0,750.72,650.20,411.77); + break; + case 2: + AddWaypoint(0,779.77,607.03,411.81); + break; + } + break; + } + + Start(false,true,0); + uiWaypoint = uiType; + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(DATA_ARGENT_SOLDIER_DEFEATED,pInstance->GetData(DATA_ARGENT_SOLDIER_DEFEATED) + 1); + } +}; + +CreatureAI* GetAI_npc_argent_soldier(Creature* pCreature) +{ + return new npc_argent_soldierAI(pCreature); +} + +void AddSC_boss_argent_challenge() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_eadric"; + NewScript->GetAI = &GetAI_boss_eadric; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_paletress"; + NewScript->GetAI = &GetAI_boss_paletress; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_memory"; + NewScript->GetAI = &GetAI_npc_memory; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_argent_soldier"; + NewScript->GetAI = &GetAI_npc_argent_soldier; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp new file mode 100644 index 00000000000..e1f4586ca6c --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_black_knight.cpp @@ -0,0 +1,373 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Black Knight +SD%Complete: 80% +SDComment: missing yells. not sure about timers. +SDCategory: Trial of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "trial_of_the_champion.h" + +enum eSpells +{ + //phase 1 + SPELL_PLAGUE_STRIKE = 67884, + SPELL_PLAGUE_STRIKE_2 = 67724, + SPELL_ICY_TOUCH_H = 67881, + SPELL_ICY_TOUCH = 67718, + SPELL_DEATH_RESPITE = 67745, + SPELL_DEATH_RESPITE_2 = 68306, + SPELL_DEATH_RESPITE_3 = 66798, + SPELL_OBLITERATE_H = 67883, + SPELL_OBLITERATE = 67725, + //in this phase should rise herald (the spell is missing) + + //phase 2 - During this phase, the Black Knight will use the same abilities as in phase 1, except for Death's Respite + SPELL_ARMY_DEAD = 67761, + SPELL_DESECRATION = 67778, + SPELL_DESECRATION_2 = 67778, + SPELL_GHOUL_EXPLODE = 67751, + + //phase 3 + SPELL_DEATH_BITE_H = 67875, + SPELL_DEATH_BITE = 67808, + SPELL_MARKED_DEATH = 67882, + SPELL_MARKED_DEATH_2 = 67823, + + SPELL_BLACK_KNIGHT_RES = 67693, + + SPELL_LEAP = 67749, + SPELL_LEAP_H = 67880 +}; + +enum eModels +{ + MODEL_SKELETON = 29846, + MODEL_GHOST = 21300 +}; + +enum ePhases +{ + PHASE_UNDEAD = 1, + PHASE_SKELETON = 2, + PHASE_GHOST = 3 +}; + +struct boss_black_knightAI : public ScriptedAI +{ + boss_black_knightAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + std::list SummonList; + + bool bEventInProgress; + bool bEvent; + bool bSummonArmy; + bool bDeathArmyDone; + + uint8 uiPhase; + + uint32 uiPlagueStrikeTimer; + uint32 uiIcyTouchTimer; + uint32 uiDeathRespiteTimer; + uint32 uiObliterateTimer; + uint32 uiDesecration; + uint32 uiResurrectTimer; + uint32 uiDeathArmyCheckTimer; + uint32 uiGhoulExplodeTimer; + uint32 uiDeathBiteTimer; + uint32 uiMarkedDeathTimer; + + void Reset() + { + RemoveSummons(); + me->SetDisplayId(me->GetNativeDisplayId()); + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + + bEventInProgress = false; + bEvent = false; + bSummonArmy = false; + bDeathArmyDone = false; + + uiPhase = PHASE_UNDEAD; + + uiIcyTouchTimer = urand(5000,9000); + uiPlagueStrikeTimer = urand(10000,13000); + uiDeathRespiteTimer = urand(15000,16000); + uiObliterateTimer = urand(17000,19000); + uiDesecration = urand(15000,16000); + uiDeathArmyCheckTimer = 7000; + uiResurrectTimer = 4000; + uiGhoulExplodeTimer = 8000; + uiDeathBiteTimer = urand (2000,4000); + uiMarkedDeathTimer = urand (5000,7000); + } + + void RemoveSummons() + { + if (SummonList.empty()) + return; + + for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + if (pTemp) + pTemp->DisappearAndDie(); + } + SummonList.clear(); + } + + void JustSummoned(Creature* pSummon) + { + SummonList.push_back(pSummon->GetGUID()); + pSummon->AI()->AttackStart(me->getVictim()); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (bEventInProgress) + if (uiResurrectTimer <= uiDiff) + { + me->SetHealth(me->GetMaxHealth()); + DoCast(me,SPELL_BLACK_KNIGHT_RES,true); + uiPhase++; + uiResurrectTimer = 4000; + bEventInProgress = false; + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + } else uiResurrectTimer -= uiDiff; + + switch(uiPhase) + { + case PHASE_UNDEAD: + case PHASE_SKELETON: + { + if (uiIcyTouchTimer <= uiDiff) + { + DoCastVictim(SPELL_ICY_TOUCH); + uiIcyTouchTimer = urand(5000,7000); + } else uiIcyTouchTimer -= uiDiff; + if (uiPlagueStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_ICY_TOUCH); + uiPlagueStrikeTimer = urand(12000,15000); + } else uiPlagueStrikeTimer -= uiDiff; + if (uiObliterateTimer <= uiDiff) + { + DoCastVictim(SPELL_OBLITERATE); + uiObliterateTimer = urand(17000,19000); + } else uiObliterateTimer -= uiDiff; + switch(uiPhase) + { + case PHASE_UNDEAD: + { + if (uiDeathRespiteTimer <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_DEATH_RESPITE); + } + uiDeathRespiteTimer = urand(15000,16000); + } else uiDeathRespiteTimer -= uiDiff; + break; + } + case PHASE_SKELETON: + { + if (!bSummonArmy) + { + bSummonArmy = true; + me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + DoCast(me, SPELL_ARMY_DEAD); + } + if (!bDeathArmyDone) + if (uiDeathArmyCheckTimer <= uiDiff) + { + me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + uiDeathArmyCheckTimer = 0; + bDeathArmyDone = true; + } else uiDeathArmyCheckTimer -= uiDiff; + if (uiDesecration <= uiDiff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_DESECRATION); + } + uiDesecration = urand(15000,16000); + } else uiDesecration -= uiDiff; + if (uiGhoulExplodeTimer <= uiDiff) + { + DoCast(me, SPELL_GHOUL_EXPLODE); + uiGhoulExplodeTimer = 8000; + } else uiGhoulExplodeTimer -= uiDiff; + break; + } + break; + } + break; + } + case PHASE_GHOST: + { + if (uiDeathBiteTimer <= uiDiff) + { + DoCastAOE(SPELL_DEATH_BITE); + uiDeathBiteTimer = urand (2000, 4000); + } else uiDeathBiteTimer -= uiDiff; + if (uiMarkedDeathTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget,SPELL_MARKED_DEATH); + } + uiMarkedDeathTimer = urand (5000, 7000); + } else uiMarkedDeathTimer -= uiDiff; + break; + } + } + + if (!me->hasUnitState(UNIT_STAT_ROOT) && !me->GetHealth()*100 / me->GetMaxHealth() <= 0) + DoMeleeAttackIfReady(); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) + { + if (uiDamage > me->GetHealth() && uiPhase <= PHASE_SKELETON) + { + uiDamage = 0; + me->SetHealth(0); + me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); + RemoveSummons(); + switch(uiPhase) + { + case PHASE_UNDEAD: + me->SetDisplayId(MODEL_SKELETON); + break; + case PHASE_SKELETON: + me->SetDisplayId(MODEL_GHOST); + break; + } + bEventInProgress = true; + } + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_BLACK_KNIGHT,DONE); + } +}; + +CreatureAI* GetAI_boss_black_knight(Creature *pCreature) +{ + return new boss_black_knightAI (pCreature); +} + +struct npc_risen_ghoulAI : public ScriptedAI +{ + npc_risen_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiAttackTimer; + + void Reset() + { + uiAttackTimer = 3500; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!UpdateVictim()) + return; + + if (uiAttackTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + { + if (pTarget && pTarget->isAlive()) + DoCast(pTarget, (SPELL_LEAP)); + } + uiAttackTimer = 3500; + } else uiAttackTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_risen_ghoul(Creature* pCreature) +{ + return new npc_risen_ghoulAI(pCreature); +} + +struct npc_black_knight_skeletal_gryphonAI : public npc_escortAI +{ + npc_black_knight_skeletal_gryphonAI(Creature* pCreature) : npc_escortAI(pCreature) + { + Start(false,true,0,NULL); + } + + void WaypointReached(uint32 /*i*/) + { + + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + } + +}; + +CreatureAI* GetAI_npc_black_knight_skeletal_gryphon(Creature* pCreature) +{ + return new npc_black_knight_skeletal_gryphonAI(pCreature); +} + +void AddSC_boss_black_knight() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_black_knight"; + NewScript->GetAI = &GetAI_boss_black_knight; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_risen_ghoul"; + NewScript->GetAI = &GetAI_npc_risen_ghoul; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_black_knight_skeletal_gryphon"; + NewScript->GetAI = &GetAI_npc_black_knight_skeletal_gryphon; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp new file mode 100644 index 00000000000..4bf8143a210 --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp @@ -0,0 +1,993 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_grand_champions +SD%Complete: 50 % +SDComment: Is missing the ai to make the npcs look for a new mount and use it. +SDCategory: Trial Of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "Vehicle.h" +#include "trial_of_the_champion.h" + +enum eSpells +{ + //Vehicle + SPELL_CHARGE = 63010, + SPELL_SHIELD_BREAKER = 68504, + SPELL_SHIELD = 66482, + + // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior + SPELL_MORTAL_STRIKE = 68783, + SPELL_MORTAL_STRIKE_H = 68784, + SPELL_BLADESTORM = 63784, + SPELL_INTERCEPT = 67540, + SPELL_ROLLING_THROW = 47115, //not implemented in the AI yet... + + // Ambrose Boltspark && Eressea Dawnsinger || Mage + SPELL_FIREBALL = 66042, + SPELL_FIREBALL_H = 68310, + SPELL_BLAST_WAVE = 66044, + SPELL_BLAST_WAVE_H = 68312, + SPELL_HASTE = 66045, + SPELL_POLYMORPH = 66043, + SPELL_POLYMORPH_H = 68311, + + // Colosos && Runok Wildmane || Shaman + SPELL_CHAIN_LIGHTNING = 67529, + SPELL_CHAIN_LIGHTNING_H = 68319, + SPELL_EARTH_SHIELD = 67530, + SPELL_HEALING_WAVE = 67528, + SPELL_HEALING_WAVE_H = 68318, + SPELL_HEX_OF_MENDING = 67534, + + // Jaelyne Evensong && Zul'tore || Hunter + SPELL_DISENGAGE = 68340, //not implemented in the AI yet... + SPELL_LIGHTNING_ARROWS = 66083, + SPELL_MULTI_SHOT = 66081, + SPELL_SHOOT = 65868, + SPELL_SHOOT_H = 67988, + + // Lana Stouthammer Evensong && Deathstalker Visceri || Rouge + SPELL_EVISCERATE = 67709, + SPELL_EVISCERATE_H = 68317, + SPELL_FAN_OF_KNIVES = 67706, + SPELL_POISON_BOTTLE = 67701 +}; + +enum eSeat +{ + SEAT_ID_0 = 0 +}; + +struct Point +{ + float x,y,z; +}; + +const Point MovementPoint[] = +{ + {746.84,623.15,411.41}, + {747.96,620.29,411.09}, + {750.23,618.35,411.09} +}; + +void AggroAllPlayers(Creature* pTemp) +{ + Map::PlayerList const &PlList = pTemp->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(pTemp); + pTemp->AddThreat(pPlayer, 0.0f); + } + } + } +} + +bool GrandChampionsOutVehicle(Creature* me) +{ + ScriptedInstance* pInstance = me->GetInstanceData(); + + if (!pInstance) + return false; + + Creature* pGrandChampion1 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_1)); + Creature* pGrandChampion2 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_2)); + Creature* pGrandChampion3 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_3)); + + if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) + { + if (!pGrandChampion1->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && + !pGrandChampion2->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && + !pGrandChampion3->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return true; + } + + return false; +} + +/* +* Generic AI for vehicles used by npcs in ToC, it needs more improvements. * +* Script Complete: 25%. * +*/ + +struct generic_vehicleAI_toc5AI : public npc_escortAI +{ + generic_vehicleAI_toc5AI(Creature* pCreature) : npc_escortAI(pCreature) + { + SetDespawnAtEnd(false); + uiWaypointPath = 0; + + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiChargeTimer; + uint32 uiShieldBreakerTimer; + uint32 uiBuffTimer; + + uint32 uiWaypointPath; + + void Reset() + { + uiChargeTimer = 5000; + uiShieldBreakerTimer = 8000; + uiBuffTimer = urand(30000,60000); + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch(uiType) + { + case 1: + AddWaypoint(0,747.36,634.07,411.572); + AddWaypoint(1,780.43,607.15,411.82); + AddWaypoint(2,785.99,599.41,411.92); + AddWaypoint(3,778.44,601.64,411.79); + uiWaypointPath = 1; + break; + case 2: + AddWaypoint(0,747.35,634.07,411.57); + AddWaypoint(1,768.72,581.01,411.92); + AddWaypoint(2,763.55,590.52,411.71); + uiWaypointPath = 2; + break; + case 3: + AddWaypoint(0,747.35,634.07,411.57); + AddWaypoint(1,784.02,645.33,412.39); + AddWaypoint(2,775.67,641.91,411.91); + uiWaypointPath = 3; + break; + } + + if (uiType <= 3) + Start(false,true,0,NULL); + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 2: + if (pInstance && uiWaypointPath == 3 || uiWaypointPath == 2) + pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); + break; + case 3: + if (pInstance) + pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); + break; + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoCastSpellShield(); + } + + void DoCastSpellShield() + { + for (uint8 i = 0; i < 3; ++i) + DoCast(me,SPELL_SHIELD,true); + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if (!UpdateVictim()) + return; + + if (uiBuffTimer <= uiDiff) + { + if (!me->HasAura(SPELL_SHIELD)) + DoCastSpellShield(); + + uiBuffTimer = urand(30000,45000); + }else uiBuffTimer -= uiDiff; + + if (uiChargeTimer <= uiDiff) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) + { + DoResetThreat(); + me->AddThreat(pPlayer,1.0f); + DoCast(pPlayer, SPELL_CHARGE); + break; + } + } + } + uiChargeTimer = 5000; + }else uiChargeTimer -= uiDiff; + + //dosen't work at all + if (uiShieldBreakerTimer <= uiDiff) + { + Vehicle *pVehicle = me->GetVehicleKit(); + if (!pVehicle) + return; + + if (Unit* pPassenger = pVehicle->GetPassenger(SEAT_ID_0)) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,10.0f,30.0f,false)) + { + pPassenger->CastSpell(pPlayer,SPELL_SHIELD_BREAKER,true); + break; + } + } + } + } + uiShieldBreakerTimer = 7000; + }else uiShieldBreakerTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_generic_vehicleAI_toc5(Creature* pCreature) +{ + return new generic_vehicleAI_toc5AI(pCreature); +} + +// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior +struct boss_warrior_toc5AI : public ScriptedAI +{ + boss_warrior_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiBladeStormTimer; + uint32 uiInterceptTimer; + uint32 uiMortalStrikeTimer; + uint32 uiAttackTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiBladeStormTimer = urand(15000,20000); + uiInterceptTimer = 7000; + uiMortalStrikeTimer = urand(8000,12000); + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiInterceptTimer <= uiDiff) + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) + { + DoResetThreat(); + me->AddThreat(pPlayer,5.0f); + DoCast(pPlayer,SPELL_INTERCEPT); + break; + } + } + } + uiInterceptTimer = 7000; + } else uiInterceptTimer -= uiDiff; + + if (uiBladeStormTimer <= uiDiff) + { + DoCastVictim(SPELL_BLADESTORM); + uiBladeStormTimer = urand(15000,20000); + } else uiBladeStormTimer -= uiDiff; + + if (uiMortalStrikeTimer <= uiDiff) + { + DoCastVictim(SPELL_MORTAL_STRIKE); + uiMortalStrikeTimer = urand(8000,12000); + } else uiMortalStrikeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_warrior_toc5(Creature* pCreature) +{ + return new boss_warrior_toc5AI(pCreature); +} + +// Ambrose Boltspark && Eressea Dawnsinger || Mage +struct boss_mage_toc5AI : public ScriptedAI +{ + boss_mage_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiFireBallTimer; + uint32 uiBlastWaveTimer; + uint32 uiHasteTimer; + uint32 uiPolymorphTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiFireBallTimer = 5000; + uiPolymorphTimer = 8000; + uiBlastWaveTimer = 12000; + uiHasteTimer = 22000; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (uiFireBallTimer <= uiDiff) + { + if (me->getVictim()) + DoCastVictim(SPELL_FIREBALL); + uiFireBallTimer = 5000; + } else uiFireBallTimer -= uiDiff; + + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiFireBallTimer <= uiDiff) + { + DoCastVictim(SPELL_FIREBALL); + uiFireBallTimer = 5000; + } else uiFireBallTimer -= uiDiff; + + if (uiPolymorphTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_POLYMORPH); + uiPolymorphTimer = 8000; + } else uiPolymorphTimer -= uiDiff; + + if (uiBlastWaveTimer <= uiDiff) + { + DoCastAOE(SPELL_BLAST_WAVE,false); + uiBlastWaveTimer = 13000; + } else uiBlastWaveTimer -= uiDiff; + + if (uiHasteTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + + DoCast(me,SPELL_HASTE); + uiHasteTimer = 22000; + } else uiHasteTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_mage_toc5(Creature* pCreature) +{ + return new boss_mage_toc5AI(pCreature); +} + +// Colosos && Runok Wildmane || Shaman +struct boss_shaman_toc5AI : public ScriptedAI +{ + boss_shaman_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiChainLightningTimer; + uint32 uiEartShieldTimer; + uint32 uiHealingWaveTimer; + uint32 uiHexMendingTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiChainLightningTimer = 16000; + uiHealingWaveTimer = 12000; + uiEartShieldTimer = urand(30000,35000); + uiHexMendingTimer = urand(20000,25000); + } + + void EnterCombat(Unit* pWho) + { + DoCast(me,SPELL_EARTH_SHIELD); + DoCast(pWho,SPELL_HEX_OF_MENDING); + }; + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiChainLightningTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_CHAIN_LIGHTNING); + + uiChainLightningTimer = 16000; + } else uiChainLightningTimer -= uiDiff; + + if (uiHealingWaveTimer <= uiDiff) + { + bool bChance = urand(0,1); + + if (!bChance) + { + if (Unit* pFriend = DoSelectLowestHpFriendly(40)) + DoCast(pFriend,SPELL_HEALING_WAVE); + } else + DoCast(me,SPELL_HEALING_WAVE); + + uiHealingWaveTimer = 12000; + } else uiHealingWaveTimer -= uiDiff; + + if (uiEartShieldTimer <= uiDiff) + { + DoCast(me,SPELL_EARTH_SHIELD); + + uiEartShieldTimer = urand(30000,35000); + } else uiEartShieldTimer -= uiDiff; + + if (uiHexMendingTimer <= uiDiff) + { + DoCastVictim(SPELL_HEX_OF_MENDING,true); + + uiHexMendingTimer = urand(20000,25000); + } else uiHexMendingTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_shaman_toc5(Creature* pCreature) +{ + return new boss_shaman_toc5AI(pCreature); +} + +// Jaelyne Evensong && Zul'tore || Hunter +struct boss_hunter_toc5AI : public ScriptedAI +{ + boss_hunter_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + + uint32 uiShootTimer; + uint32 uiMultiShotTimer; + uint32 uiLightningArrowsTimer; + + uint64 uiTargetGUID; + + bool bShoot; + bool bDone; + bool bHome; + + void Reset() + { + uiShootTimer = 12000; + uiMultiShotTimer = 0; + uiLightningArrowsTimer = 7000; + + uiTargetGUID = 0; + + bShoot = false; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + }else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiLightningArrowsTimer <= uiDiff) + { + DoCastAOE(SPELL_LIGHTNING_ARROWS,false); + uiLightningArrowsTimer = 7000; + } else uiLightningArrowsTimer -= uiDiff; + + if (uiShootTimer <= uiDiff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_FARTHEST,0,30.0f)) + { + uiTargetGUID = pTarget->GetGUID(); + DoCast(pTarget, SPELL_SHOOT); + } + uiShootTimer = 12000; + uiMultiShotTimer = 3000; + bShoot = true; + } else uiShootTimer -= uiDiff; + + if (bShoot && uiMultiShotTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(true); + Unit* pTarget = Unit::GetUnit(*me, uiTargetGUID); + + if (pTarget && me->IsInRange(pTarget,5.0f,30.0f,false)) + { + DoCast(pTarget,SPELL_MULTI_SHOT); + } else + { + Map::PlayerList const& players = me->GetMap()->GetPlayers(); + if (me->GetMap()->IsDungeon() && !players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + Player* pPlayer = itr->getSource(); + if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,5.0f,30.0f,false)) + { + DoCast(pTarget,SPELL_MULTI_SHOT); + break; + } + } + } + } + bShoot = false; + } else uiMultiShotTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_hunter_toc5(Creature* pCreature) +{ + return new boss_hunter_toc5AI(pCreature); +} + +// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge +struct boss_rouge_toc5AI : public ScriptedAI +{ + boss_rouge_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + bDone = false; + bHome = false; + + uiPhase = 0; + uiPhaseTimer = 0; + + me->SetReactState(REACT_PASSIVE); + // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + ScriptedInstance* pInstance; + + uint8 uiPhase; + uint32 uiPhaseTimer; + uint32 uiEviscerateTimer; + uint32 uiFanKivesTimer; + uint32 uiPosionBottleTimer; + + bool bDone; + bool bHome; + + void Reset() + { + uiEviscerateTimer = 8000; + uiFanKivesTimer = 14000; + uiPosionBottleTimer = 19000; + } + + void JustReachedHome() + { + ScriptedAI::JustReachedHome(); + + if (!bHome) + return; + + uiPhaseTimer = 15000; + uiPhase = 1; + + bHome = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!bDone && GrandChampionsOutVehicle(me)) + { + bDone = true; + + if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) + me->SetHomePosition(739.678,662.541,412.393,4.49); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) + me->SetHomePosition(746.71,661.02,411.69,4.6); + else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) + me->SetHomePosition(754.34,660.70,412.39,4.79); + + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); + + EnterEvadeMode(); + bHome = true; + } + + if (uiPhaseTimer <= uiDiff) + { + if (uiPhase == 1) + { + AggroAllPlayers(me); + uiPhase = 0; + } + } else uiPhaseTimer -= uiDiff; + + if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) + return; + + if (uiEviscerateTimer <= uiDiff) + { + DoCast(me->getVictim(),SPELL_EVISCERATE); + uiEviscerateTimer = 8000; + } else uiEviscerateTimer -= uiDiff; + + if (uiFanKivesTimer <= uiDiff) + { + DoCastAOE(SPELL_FAN_OF_KNIVES,false); + uiFanKivesTimer = 14000; + } else uiFanKivesTimer -= uiDiff; + + if (uiPosionBottleTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget,SPELL_POISON_BOTTLE); + uiPosionBottleTimer = 19000; + } else uiPosionBottleTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); + } +}; + +CreatureAI* GetAI_boss_rouge_toc5(Creature* pCreature) +{ + return new boss_rouge_toc5AI(pCreature); +} + +void AddSC_boss_grand_champions() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "generic_vehicleAI_toc5"; + NewScript->GetAI = &GetAI_generic_vehicleAI_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_warrior_toc5"; + NewScript->GetAI = &GetAI_boss_warrior_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_mage_toc5"; + NewScript->GetAI = &GetAI_boss_mage_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_shaman_toc5"; + NewScript->GetAI = &GetAI_boss_shaman_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_hunter_toc5"; + NewScript->GetAI = &GetAI_boss_hunter_toc5; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_rouge_toc5"; + NewScript->GetAI = &GetAI_boss_rouge_toc5; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp new file mode 100644 index 00000000000..04b671ec11c --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/instance_trial_of_the_champion.cpp @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + + +/* ScriptData +SDName: Instance Trial of the Champion +SDComment: +SDCategory: Trial Of the Champion +EndScriptData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" + +#define MAX_ENCOUNTER 4 + +struct instance_trial_of_the_champion : public ScriptedInstance +{ + instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint8 uiMovementDone; + uint8 uiGrandChampionsDeaths; + uint8 uiArgentSoldierDeaths; + + uint64 uiAnnouncerGUID; + uint64 uiMainGateGUID; + uint64 uiGrandChampionVehicle1GUID; + uint64 uiGrandChampionVehicle2GUID; + uint64 uiGrandChampionVehicle3GUID; + uint64 uiGrandChampion1GUID; + uint64 uiGrandChampion2GUID; + uint64 uiGrandChampion3GUID; + uint64 uiChampionLootGUID; + uint64 uiArgentChampionGUID; + + std::list VehicleList; + + std::string str_data; + + bool bDone; + + void Initialize() + { + uiMovementDone = 0; + uiGrandChampionsDeaths = 0; + uiArgentSoldierDeaths = 0; + + uiAnnouncerGUID = 0; + uiMainGateGUID = 0; + uiGrandChampionVehicle1GUID = 0; + uiGrandChampionVehicle2GUID = 0; + uiGrandChampionVehicle3GUID = 0; + uiGrandChampion1GUID = 0; + uiGrandChampion2GUID = 0; + uiGrandChampion3GUID = 0; + uiChampionLootGUID = 0; + uiArgentChampionGUID = 0; + + bDone = false; + + VehicleList.clear(); + + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + } + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + uint32 TeamInInstance = 0; + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + TeamInInstance = pPlayer->GetTeam(); + } + + switch(pCreature->GetEntry()) + { + // Champions + case VEHICLE_MOKRA_SKILLCRUSHER_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT, ALLIANCE); + break; + case VEHICLE_ERESSEA_DAWNSINGER_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_AMBROSE_BOLTSPARK_MOUNT, ALLIANCE); + break; + case VEHICLE_RUNOK_WILDMANE_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_COLOSOS_MOUNT, ALLIANCE); + break; + case VEHICLE_ZUL_TORE_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_EVENSONG_MOUNT, ALLIANCE); + break; + case VEHICLE_DEATHSTALKER_VESCERI_MOUNT: + if (TeamInInstance == HORDE) + pCreature->UpdateEntry(VEHICLE_LANA_STOUTHAMMER_MOUNT, ALLIANCE); + break; + // Coliseum Announcer || Just NPC_JAEREN must be spawned. + case NPC_JAEREN: + uiAnnouncerGUID = pCreature->GetGUID(); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_ARELAS,ALLIANCE); + break; + case VEHICLE_ARGENT_WARHORSE: + case VEHICLE_ARGENT_BATTLEWORG: + VehicleList.push_back(pCreature->GetGUID()); + break; + case NPC_EADRIC: + case NPC_PALETRESS: + uiArgentChampionGUID = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGO, bool /*bAdd*/) + { + switch(pGO->GetEntry()) + { + case GO_MAIN_GATE: + uiMainGateGUID = pGO->GetGUID(); + break; + case GO_CHAMPIONS_LOOT: + case GO_CHAMPIONS_LOOT_H: + uiChampionLootGUID = pGO->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case DATA_MOVEMENT_DONE: + uiMovementDone = uiData; + if (uiMovementDone == 3) + { + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + pAnnouncer->AI()->SetData(DATA_IN_POSITION,0); + } + break; + case BOSS_GRAND_CHAMPIONS: + m_auiEncounter[0] = uiData; + if (uiData == IN_PROGRESS) + { + for (std::list::const_iterator itr = VehicleList.begin(); itr != VehicleList.end(); ++itr) + if (Creature* pSummon = instance->GetCreature(*itr)) + pSummon->RemoveFromWorld(); + }else if (uiData == DONE) + { + ++uiGrandChampionsDeaths; + if (uiGrandChampionsDeaths == 3) + { + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + } + } + break; + case DATA_ARGENT_SOLDIER_DEFEATED: + uiArgentSoldierDeaths = uiData; + if (uiArgentSoldierDeaths == 9) + { + if (Creature* pBoss = instance->GetCreature(uiArgentChampionGUID)) + { + pBoss->GetMotionMaster()->MovePoint(0,746.88,618.74,411.06); + pBoss->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pBoss->SetReactState(REACT_AGGRESSIVE); + } + } + break; + case BOSS_ARGENT_CHALLENGE_E: + m_auiEncounter[1] = uiData; + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + break; + case BOSS_ARGENT_CHALLENGE_P: + m_auiEncounter[2] = uiData; + if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) + { + pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); + pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); + } + break; + } + + if (uiData == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 uiData) + { + switch(uiData) + { + case BOSS_GRAND_CHAMPIONS: return m_auiEncounter[0]; + case BOSS_ARGENT_CHALLENGE_E: return m_auiEncounter[1]; + case BOSS_ARGENT_CHALLENGE_P: return m_auiEncounter[2]; + case BOSS_BLACK_KNIGHT: return m_auiEncounter[3]; + + case DATA_MOVEMENT_DONE: return uiMovementDone; + case DATA_ARGENT_SOLDIER_DEFEATED: return uiArgentSoldierDeaths; + } + + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_ANNOUNCER: return uiAnnouncerGUID; + case DATA_MAIN_GATE: return uiMainGateGUID; + + case DATA_GRAND_CHAMPION_1: return uiGrandChampion1GUID; + case DATA_GRAND_CHAMPION_2: return uiGrandChampion2GUID; + case DATA_GRAND_CHAMPION_3: return uiGrandChampion3GUID; + } + + return 0; + } + + void SetData64(uint32 uiType, uint64 uiData) + { + switch(uiType) + { + case DATA_GRAND_CHAMPION_1: + uiGrandChampion1GUID = uiData; + break; + case DATA_GRAND_CHAMPION_2: + uiGrandChampion2GUID = uiData; + break; + case DATA_GRAND_CHAMPION_3: + uiGrandChampion3GUID = uiData; + break; + } + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + saveStream << "T C " << m_auiEncounter[0] + << " " << m_auiEncounter[1] + << " " << m_auiEncounter[2] + << " " << m_auiEncounter[3] + << " " << uiGrandChampionsDeaths + << " " << uiMovementDone; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + + if (dataHead1 == 'T' && dataHead2 == 'C') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + uiGrandChampionsDeaths = data4; + uiMovementDone = data5; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_trial_of_the_champion(Map* pMap) +{ + return new instance_trial_of_the_champion(pMap); +} + +void AddSC_instance_trial_of_the_champion() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_trial_of_the_champion"; + newscript->GetInstanceData = &GetInstanceData_instance_trial_of_the_champion; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp new file mode 100644 index 00000000000..090b64b96cc --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp @@ -0,0 +1,512 @@ +/* + * Copyright (C) 2010 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Trial Of the Champion +SD%Complete: +SDComment: +SDCategory: trial_of_the_champion +EndScriptData */ + +/* ContentData +npc_announcer_toc5 +EndContentData */ + +#include "ScriptedPch.h" +#include "trial_of_the_champion.h" +#include "Vehicle.h" + +#define GOSSIP_START_EVENT1 "I'm ready to start challenge." +#define GOSSIP_START_EVENT2 "I'm ready for the next challenge." + +#define ORIENTATION 4.714 + +/*###### +## npc_announcer_toc5 +######*/ + +const Position SpawnPosition = {746.261,657.401,411.681,4.65}; + +struct npc_announcer_toc5AI : public ScriptedAI +{ + npc_announcer_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + + uiSummonTimes = 0; + uiPosition = 0; + uiLesserChampions = 0; + + uiFirstBoss = 0; + uiSecondBoss = 0; + uiThirdBoss = 0; + + uiArgentChampion = 0; + + uiPhase = 0; + uiTimer = 0; + + uiVehicle1GUID = 0; + uiVehicle2GUID = 0; + uiVehicle3GUID = 0; + + Champion1List.clear(); + Champion2List.clear(); + Champion3List.clear(); + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + SetGrandChampionsForEncounter(); + SetArgentChampion(); + } + + ScriptedInstance* pInstance; + + uint8 uiSummonTimes; + uint8 uiPosition; + uint8 uiLesserChampions; + + uint32 uiArgentChampion; + + uint32 uiFirstBoss; + uint32 uiSecondBoss; + uint32 uiThirdBoss; + + uint32 uiPhase; + uint32 uiTimer; + + uint64 uiVehicle1GUID; + uint64 uiVehicle2GUID; + uint64 uiVehicle3GUID; + + uint64 uiGrandChampionBoss1; + + std::list Champion1List; + std::list Champion2List; + std::list Champion3List; + + void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) + { + uiTimer = uiTimerStep; + if (bNextStep) + ++uiPhase; + else + uiPhase = uiPhaseStep; + } + + void SetData(uint32 uiType, uint32 /*uiData*/) + { + switch (uiType) + { + case DATA_START: + DoSummonGrandChampion(uiFirstBoss); + NextStep(10000,false,1); + break; + case DATA_IN_POSITION: //movement done. + me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); + if (GameObject* pGO = GameObject::GetGameObject(*me, pInstance->GetData64(DATA_MAIN_GATE))) + pInstance->HandleGameObject(pGO->GetGUID(),false); + NextStep(10000,false,3); + break; + case DATA_LESSER_CHAMPIONS_DEFEATED: + { + ++uiLesserChampions; + std::list TempList; + if (uiLesserChampions == 3 || uiLesserChampions == 6) + { + switch(uiLesserChampions) + { + case 3: + TempList = Champion2List; + break; + case 6: + TempList = Champion3List; + break; + } + + for (std::list::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr) + if (Creature* pSummon = Unit::GetCreature(*me, *itr)) + AggroAllPlayers(pSummon); + }else if (uiLesserChampions == 9) + StartGrandChampionsAttack(); + + break; + } + } + } + + void StartGrandChampionsAttack() + { + Creature* pGrandChampion1 = Unit::GetCreature(*me, uiVehicle1GUID); + Creature* pGrandChampion2 = Unit::GetCreature(*me, uiVehicle2GUID); + Creature* pGrandChampion3 = Unit::GetCreature(*me, uiVehicle3GUID); + + if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) + { + AggroAllPlayers(pGrandChampion1); + AggroAllPlayers(pGrandChampion2); + AggroAllPlayers(pGrandChampion3); + } + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE) + return; + + if (uiPointId == 1) + { + me->SetOrientation(ORIENTATION); + me->SendMovementFlagUpdate(); + } + } + + void DoSummonGrandChampion(uint32 uiBoss) + { + ++uiSummonTimes; + uint32 VEHICLE_TO_SUMMON1 = 0; + uint32 VEHICLE_TO_SUMMON2 = 0; + switch(uiBoss) + { + case 0: + VEHICLE_TO_SUMMON1 = VEHICLE_MOKRA_SKILLCRUSHER_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_ORGRIMMAR_WOLF; + break; + case 1: + VEHICLE_TO_SUMMON1 = VEHICLE_ERESSEA_DAWNSINGER_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_SILVERMOON_HAWKSTRIDER; + break; + case 2: + VEHICLE_TO_SUMMON1 = VEHICLE_RUNOK_WILDMANE_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_THUNDER_BLUFF_KODO; + break; + case 3: + VEHICLE_TO_SUMMON1 = VEHICLE_ZUL_TORE_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_DARKSPEAR_RAPTOR; + break; + case 4: + VEHICLE_TO_SUMMON1 = VEHICLE_DEATHSTALKER_VESCERI_MOUNT; + VEHICLE_TO_SUMMON2 = VEHICLE_FORSAKE_WARHORSE; + break; + default: + return; + } + + if (Creature* pBoss = me->SummonCreature(VEHICLE_TO_SUMMON1,SpawnPosition)) + { + switch(uiSummonTimes) + { + case 1: + { + uiVehicle1GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss1 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle1GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss1 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_1,uiVehicle1GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_1,uiGrandChampionBoss1); + } + pBoss->AI()->SetData(1,0); + break; + } + case 2: + { + uiVehicle2GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss2 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle2GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss2 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_2,uiVehicle2GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_2,uiGrandChampionBoss2); + } + pBoss->AI()->SetData(2,0); + break; + } + case 3: + { + uiVehicle3GUID = pBoss->GetGUID(); + uint64 uiGrandChampionBoss3 = 0; + if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle3GUID)) + if (Vehicle* pVehicle = pBoss->GetVehicleKit()) + if (Unit* pUnit = pVehicle->GetPassenger(0)) + uiGrandChampionBoss3 = pUnit->GetGUID(); + if (pInstance) + { + pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_3,uiVehicle3GUID); + pInstance->SetData64(DATA_GRAND_CHAMPION_3,uiGrandChampionBoss3); + } + pBoss->AI()->SetData(3,0); + break; + } + default: + return; + } + + for (uint8 i = 0; i < 3; ++i) + { + if (Creature* pAdd = me->SummonCreature(VEHICLE_TO_SUMMON2,SpawnPosition,TEMPSUMMON_CORPSE_DESPAWN)) + { + switch(uiSummonTimes) + { + case 1: + Champion1List.push_back(pAdd->GetGUID()); + break; + case 2: + Champion2List.push_back(pAdd->GetGUID()); + break; + case 3: + Champion3List.push_back(pAdd->GetGUID()); + break; + } + + switch(i) + { + case 0: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI); + break; + case 1: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2); + break; + case 2: + pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2 + M_PI); + break; + } + } + + } + } + } + + void DoStartArgentChampionEncounter() + { + me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); + + if (Creature* pBoss = me->SummonCreature(uiArgentChampion,SpawnPosition)) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_LIGHWIELDER,SpawnPosition)) + pTrash->AI()->SetData(i,0); + if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_MONK,SpawnPosition)) + pTrash->AI()->SetData(i,0); + if (Creature* pTrash = me->SummonCreature(NPC_PRIESTESS,SpawnPosition)) + pTrash->AI()->SetData(i,0); + } + } + } + + void SetGrandChampionsForEncounter() + { + uiFirstBoss = urand(0,4); + + while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss) + { + uiSecondBoss = urand(0,4); + uiThirdBoss = urand(0,4); + } + } + + void SetArgentChampion() + { + uint8 uiTempBoss = urand(0,1); + + switch(uiTempBoss) + { + case 0: + uiArgentChampion = NPC_EADRIC; + break; + case 1: + uiArgentChampion = NPC_PALETRESS; + break; + } + } + + void StartEncounter() + { + if (!pInstance) + return; + + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + if (pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) + { + if (pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED) + { + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) + me->AI()->SetData(DATA_START,0); + + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE) + DoStartArgentChampionEncounter(); + } + + if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) + me->SummonCreature(VEHICLE_BLACK_KNIGHT,769.834,651.915,447.035,0); + } + } + + void AggroAllPlayers(Creature* pTemp) + { + Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); + + if (PlList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isGameMaster()) + continue; + + if (pPlayer->isAlive()) + { + pTemp->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetReactState(REACT_AGGRESSIVE); + pTemp->SetInCombatWith(pPlayer); + pPlayer->SetInCombatWith(pTemp); + pTemp->AddThreat(pPlayer, 0.0f); + } + } + } + } + + + void UpdateAI(const uint32 uiDiff) + { + ScriptedAI::UpdateAI(uiDiff); + + if (uiTimer <= uiDiff) + { + switch(uiPhase) + { + case 1: + DoSummonGrandChampion(uiSecondBoss); + NextStep(10000,true); + break; + case 2: + DoSummonGrandChampion(uiThirdBoss); + NextStep(0,false); + break; + case 3: + if (!Champion1List.empty()) + { + for (std::list::const_iterator itr = Champion1List.begin(); itr != Champion1List.end(); ++itr) + if (Creature* pSummon = Unit::GetCreature(*me, *itr)) + AggroAllPlayers(pSummon); + NextStep(0,false); + } + break; + } + } else uiTimer -= uiDiff; + + if (!UpdateVictim()) + return; + } + + void JustSummoned(Creature* pSummon) + { + if (pInstance && pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) + { + pSummon->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + pSummon->SetReactState(REACT_PASSIVE); + } + } + + void SummonedCreatureDespawn(Creature* pSummon) + { + switch(pSummon->GetEntry()) + { + case VEHICLE_DARNASSIA_NIGHTSABER: + case VEHICLE_EXODAR_ELEKK: + case VEHICLE_STORMWIND_STEED: + case VEHICLE_GNOMEREGAN_MECHANOSTRIDER: + case VEHICLE_IRONFORGE_RAM: + case VEHICLE_FORSAKE_WARHORSE: + case VEHICLE_THUNDER_BLUFF_KODO: + case VEHICLE_ORGRIMMAR_WOLF: + case VEHICLE_SILVERMOON_HAWKSTRIDER: + case VEHICLE_DARKSPEAR_RAPTOR: + me->AI()->SetData(DATA_LESSER_CHAMPIONS_DEFEATED,0); + break; + } + } +}; + +CreatureAI* GetAI_npc_announcer_toc5(Creature* pCreature) +{ + return new npc_announcer_toc5AI(pCreature); +} + +bool GossipHello_npc_announcer_toc5(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = pCreature->GetInstanceData(); + + if (pInstance && + pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && + pInstance->GetData(BOSS_BLACK_KNIGHT) == DONE && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) + return false; + + if (pInstance && + pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && + pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED && + pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + else if (pInstance) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_announcer_toc5(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_announcer_toc5AI, pCreature->AI())->StartEncounter(); + } + + return true; +} + +void AddSC_trial_of_the_champion() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "npc_announcer_toc5"; + NewScript->GetAI = &GetAI_npc_announcer_toc5; + NewScript->pGossipHello = &GossipHello_npc_announcer_toc5; + NewScript->pGossipSelect = &GossipSelect_npc_announcer_toc5; + NewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h new file mode 100644 index 00000000000..221c7c0412f --- /dev/null +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software licensed under GPL version 2 +* Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_TOC_H +#define DEF_TOC_H + + +enum eData +{ + BOSS_GRAND_CHAMPIONS, + BOSS_ARGENT_CHALLENGE_E, + BOSS_ARGENT_CHALLENGE_P, + BOSS_BLACK_KNIGHT, + DATA_MOVEMENT_DONE, + DATA_LESSER_CHAMPIONS_DEFEATED, + DATA_START, + DATA_IN_POSITION, + DATA_ARGENT_SOLDIER_DEFEATED +}; + +enum Data64 +{ + DATA_ANNOUNCER, + DATA_MAIN_GATE, + + DATA_GRAND_CHAMPION_VEHICLE_1, + DATA_GRAND_CHAMPION_VEHICLE_2, + DATA_GRAND_CHAMPION_VEHICLE_3, + + DATA_GRAND_CHAMPION_1, + DATA_GRAND_CHAMPION_2, + DATA_GRAND_CHAMPION_3 +}; + +enum eNpcs +{ + // Horde Champions + NPC_MOKRA = 35572, + NPC_ERESSEA = 35569, + NPC_RUNOK = 35571, + NPC_ZULTORE = 35570, + NPC_VISCERI = 35617, + + // Alliance Champions + NPC_JACOB = 34705, + NPC_AMBROSE = 34702, + NPC_COLOSOS = 34701, + NPC_JAELYNE = 34657, + NPC_LANA = 34703, + + NPC_EADRIC = 35119, + NPC_PALETRESS = 34928, + + NPC_ARGENT_LIGHWIELDER = 35309, + NPC_ARGENT_MONK = 35305, + NPC_PRIESTESS = 35307, + + NPC_BLACK_KNIGHT = 35451, + + NPC_RISEN_JAEREN = 35545, + NPC_RISEN_ARELAS = 35564, + + NPC_JAEREN = 35004, + NPC_ARELAS = 35005 +}; + +enum eGameObjects +{ + GO_MAIN_GATE = 195647, + + GO_CHAMPIONS_LOOT = 195709, + GO_CHAMPIONS_LOOT_H = 195710, + + GO_EADRIC_LOOT = 195374, + GO_EADRIC_LOOT_H = 195375, + + GO_PALETRESS_LOOT = 195323, + GO_PALETRESS_LOOT_H = 195324 +}; + +enum eVehicles +{ + //Grand Champions Alliance Vehicles + VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT = 35637, + VEHICLE_AMBROSE_BOLTSPARK_MOUNT = 35633, + VEHICLE_COLOSOS_MOUNT = 35768, + VEHICLE_EVENSONG_MOUNT = 34658, + VEHICLE_LANA_STOUTHAMMER_MOUNT = 35636, + //Faction Champions (ALLIANCE) + VEHICLE_DARNASSIA_NIGHTSABER = 33298, + VEHICLE_EXODAR_ELEKK = 33416, + VEHICLE_STORMWIND_STEED = 33297, + VEHICLE_GNOMEREGAN_MECHANOSTRIDER = 33301, + VEHICLE_IRONFORGE_RAM = 33408, + //Grand Champions Horde Vehicles + VEHICLE_MOKRA_SKILLCRUSHER_MOUNT = 35638, + VEHICLE_ERESSEA_DAWNSINGER_MOUNT = 35635, + VEHICLE_RUNOK_WILDMANE_MOUNT = 35640, + VEHICLE_ZUL_TORE_MOUNT = 35641, + VEHICLE_DEATHSTALKER_VESCERI_MOUNT = 35634, + //Faction Champions (HORDE) + VEHICLE_FORSAKE_WARHORSE = 33414, + VEHICLE_THUNDER_BLUFF_KODO = 33300, + VEHICLE_ORGRIMMAR_WOLF = 33409, + VEHICLE_SILVERMOON_HAWKSTRIDER = 33418, + VEHICLE_DARKSPEAR_RAPTOR = 33299, + + VEHICLE_ARGENT_WARHORSE = 35644, + VEHICLE_ARGENT_BATTLEWORG = 36558, + + VEHICLE_BLACK_KNIGHT = 35491 +}; + +#endif diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp deleted file mode 100644 index c33ea69fa2d..00000000000 --- a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_argent_challenge.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Argent Challenge Encounter. -SD%Complete: 50 % -SDComment: AI for Argent Soldiers are not implemented. AI from bosses need more improvements. -SDCategory: Trial of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" -#include "ScriptedEscortAI.h" - -enum eSpells -{ - //Eadric - SPELL_EADRIC_ACHIEVEMENT = 68197, - SPELL_HAMMER_JUSTICE = 66863, - SPELL_HAMMER_RIGHTEOUS = 66867, - SPELL_RADIANCE = 66935, - SPELL_VENGEANCE = 66865, - - //Paletress - SPELL_SMITE = 66536, - SPELL_SMITE_H = 67674, - SPELL_HOLY_FIRE = 66538, - SPELL_HOLY_FIRE_H = 67676, - SPELL_RENEW = 66537, - SPELL_RENEW_H = 67675, - SPELL_HOLY_NOVA = 66546, - SPELL_SHIELD = 66515, - SPELL_CONFESS = 66680, - SPELL_SUMMON_MEMORY = 66545, - - //Memory - SPELL_OLD_WOUNDS = 66620, - SPELL_OLD_WOUNDS_H = 67679, - SPELL_SHADOWS_PAST = 66619, - SPELL_SHADOWS_PAST_H = 67678, - SPELL_WAKING_NIGHTMARE = 66552, - SPELL_WAKING_NIGHTMARE_H = 67677 -}; - -struct boss_eadricAI : public ScriptedAI -{ - boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - pCreature->SetReactState(REACT_PASSIVE); - pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint32 uiVenganceTimer; - uint32 uiRadianceTimer; - uint32 uiHammerJusticeTimer; - uint32 uiResetTimer; - - bool bDone; - - void Reset() - { - uiVenganceTimer = 10000; - uiRadianceTimer = 16000; - uiHammerJusticeTimer = 25000; - uiResetTimer = 5000; - - bDone = false; - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - damage = 0; - EnterEvadeMode(); - me->setFaction(35); - bDone = true; - } - } - - void MovementInform(uint32 MovementType, uint32 /*Data*/) - { - if (MovementType != POINT_MOTION_TYPE) - return; - - if (pInstance) - pInstance->SetData(BOSS_ARGENT_CHALLENGE_E, DONE); - - me->DisappearAndDie(); - } - - void UpdateAI(const uint32 uiDiff) - { - if (bDone && uiResetTimer <= uiDiff) - { - me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); - bDone = false; - } else uiResetTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - if (uiHammerJusticeTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - { - DoCast(pTarget, SPELL_HAMMER_JUSTICE); - DoCast(pTarget, SPELL_HAMMER_RIGHTEOUS); - } - } - uiHammerJusticeTimer = 25000; - } else uiHammerJusticeTimer -= uiDiff; - - if (uiVenganceTimer <= uiDiff) - { - DoCast(me,SPELL_VENGEANCE); - - uiVenganceTimer = 10000; - } else uiVenganceTimer -= uiDiff; - - if (uiRadianceTimer <= uiDiff) - { - DoCastAOE(SPELL_RADIANCE); - - uiRadianceTimer = 16000; - } else uiRadianceTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_eadric(Creature* pCreature) -{ - return new boss_eadricAI(pCreature); -} - -struct boss_paletressAI : public ScriptedAI -{ - boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - MemoryGUID = 0; - pCreature->SetReactState(REACT_PASSIVE); - pCreature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pCreature->RestoreFaction(); - } - - ScriptedInstance* pInstance; - - Creature* pMemory; - uint64 MemoryGUID; - - bool bHealth; - bool bDone; - - uint32 uiHolyFireTimer; - uint32 uiHolySmiteTimer; - uint32 uiRenewTimer; - uint32 uiResetTimer; - - void Reset() - { - me->RemoveAllAuras(); - - uiHolyFireTimer = urand(9000,12000); - uiHolySmiteTimer = urand(5000,7000); - uiRenewTimer = urand(2000,5000); - - uiResetTimer = 7000; - - bHealth = false; - bDone = false; - - if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) - if (pMemory->isAlive()) - pMemory->RemoveFromWorld(); - } - - void SetData(uint32 uiId, uint32 /*uiValue*/) - { - if (uiId == 1) - me->RemoveAura(SPELL_SHIELD); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth()) - { - damage = 0; - EnterEvadeMode(); - me->setFaction(35); - bDone = true; - } - } - - void MovementInform(uint32 MovementType, uint32 Point) - { - if (MovementType != POINT_MOTION_TYPE || Point != 0) - return; - - if (pInstance) - pInstance->SetData(BOSS_ARGENT_CHALLENGE_P, DONE); - - me->DisappearAndDie(); - } - - void UpdateAI(const uint32 uiDiff) - { - if (bDone && uiResetTimer <= uiDiff) - { - me->GetMotionMaster()->MovePoint(0,746.87,665.87,411.75); - bDone = false; - } else uiResetTimer -= uiDiff; - - if (!UpdateVictim()) - return; - - if (uiHolyFireTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_HOLY_FIRE); - } - if (me->HasAura(SPELL_SHIELD)) - uiHolyFireTimer = 13000; - else - uiHolyFireTimer = urand(9000,12000); - } else uiHolyFireTimer -= uiDiff; - - if (uiHolySmiteTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 250, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_SMITE); - } - if (me->HasAura(SPELL_SHIELD)) - uiHolySmiteTimer = 9000; - else - uiHolySmiteTimer = urand(5000,7000); - } else uiHolySmiteTimer -= uiDiff; - - if (me->HasAura(SPELL_SHIELD)) - if (uiRenewTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - uint8 uiTarget = urand(0,1); - switch(uiTarget) - { - case 0: - DoCast(me,SPELL_RENEW); - break; - case 1: - if (Creature *pMemory = Unit::GetCreature(*me, MemoryGUID)) - if (pMemory->isAlive()) - DoCast(pMemory, SPELL_RENEW); - break; - } - uiRenewTimer = urand(15000,17000); - } else uiRenewTimer -= uiDiff; - - - if (!bHealth && me->GetHealth()*100 / me->GetMaxHealth() <= 25) - { - me->InterruptNonMeleeSpells(true); - DoCastAOE(SPELL_HOLY_NOVA,false); - DoCast(me, SPELL_SHIELD); - DoCastAOE(SPELL_SUMMON_MEMORY,false); - DoCastAOE(SPELL_CONFESS,false); - - bHealth = true; - } - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* pSummon) - { - MemoryGUID = pSummon->GetGUID(); - } -}; - -CreatureAI* GetAI_boss_paletress(Creature* pCreature) -{ - return new boss_paletressAI(pCreature); -} - -struct npc_memoryAI : public ScriptedAI -{ - npc_memoryAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiOldWoundsTimer; - uint32 uiShadowPastTimer; - uint32 uiWakingNightmare; - - void Reset() - { - uiOldWoundsTimer = 12000; - uiShadowPastTimer = 5000; - uiWakingNightmare = 7000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiOldWoundsTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, SPELL_OLD_WOUNDS); - } - uiOldWoundsTimer = 12000; - }else uiOldWoundsTimer -= uiDiff; - - if (uiWakingNightmare <= uiDiff) - { - DoCast(me, SPELL_WAKING_NIGHTMARE); - uiWakingNightmare = 7000; - }else uiWakingNightmare -= uiDiff; - - if (uiShadowPastTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_SHADOWS_PAST); - } - uiShadowPastTimer = 5000; - }else uiShadowPastTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (me->isSummon()) - { - if (Unit* pSummoner = CAST_SUM(me)->GetSummoner()) - { - if (pSummoner && pSummoner->isAlive()) - CAST_CRE(pSummoner)->AI()->SetData(1,0); - } - } - } -}; - -CreatureAI* GetAI_npc_memory(Creature* pCreature) -{ - return new npc_memoryAI(pCreature); -} - -// THIS AI NEEDS MORE IMPROVEMENTS -struct npc_argent_soldierAI : public npc_escortAI -{ - npc_argent_soldierAI(Creature* pCreature) : npc_escortAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - me->SetReactState(REACT_DEFENSIVE); - SetDespawnAtEnd(false); - uiWaypoint = 0; - } - - ScriptedInstance* pInstance; - - uint8 uiWaypoint; - - void WaypointReached(uint32 uiPoint) - { - if (uiPoint == 0) - { - switch(uiWaypoint) - { - case 0: - me->SetOrientation(5.81); - break; - case 1: - me->SetOrientation(4.60); - break; - case 2: - me->SetOrientation(2.79); - break; - } - - me->SendMovementFlagUpdate(); - } - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch(me->GetEntry()) - { - case NPC_ARGENT_LIGHWIELDER: - switch(uiType) - { - case 0: - AddWaypoint(0,712.14,628.42,411.88); - break; - case 1: - AddWaypoint(0,742.44,650.29,411.79); - break; - case 2: - AddWaypoint(0,783.33,615.29,411.84); - break; - } - break; - case NPC_ARGENT_MONK: - switch(uiType) - { - case 0: - AddWaypoint(0,713.12,632.97,411.90); - break; - case 1: - AddWaypoint(0,746.73,650.24,411.56); - break; - case 2: - AddWaypoint(0,781.32,610.54,411.82); - break; - } - break; - case NPC_PRIESTESS: - switch(uiType) - { - case 0: - AddWaypoint(0,715.06,637.07,411.91); - break; - case 1: - AddWaypoint(0,750.72,650.20,411.77); - break; - case 2: - AddWaypoint(0,779.77,607.03,411.81); - break; - } - break; - } - - Start(false,true,0); - uiWaypoint = uiType; - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(DATA_ARGENT_SOLDIER_DEFEATED,pInstance->GetData(DATA_ARGENT_SOLDIER_DEFEATED) + 1); - } -}; - -CreatureAI* GetAI_npc_argent_soldier(Creature* pCreature) -{ - return new npc_argent_soldierAI(pCreature); -} - -void AddSC_boss_argent_challenge() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "boss_eadric"; - NewScript->GetAI = &GetAI_boss_eadric; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_paletress"; - NewScript->GetAI = &GetAI_boss_paletress; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_memory"; - NewScript->GetAI = &GetAI_npc_memory; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_argent_soldier"; - NewScript->GetAI = &GetAI_npc_argent_soldier; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp deleted file mode 100644 index e1f4586ca6c..00000000000 --- a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_black_knight.cpp +++ /dev/null @@ -1,373 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Black Knight -SD%Complete: 80% -SDComment: missing yells. not sure about timers. -SDCategory: Trial of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "trial_of_the_champion.h" - -enum eSpells -{ - //phase 1 - SPELL_PLAGUE_STRIKE = 67884, - SPELL_PLAGUE_STRIKE_2 = 67724, - SPELL_ICY_TOUCH_H = 67881, - SPELL_ICY_TOUCH = 67718, - SPELL_DEATH_RESPITE = 67745, - SPELL_DEATH_RESPITE_2 = 68306, - SPELL_DEATH_RESPITE_3 = 66798, - SPELL_OBLITERATE_H = 67883, - SPELL_OBLITERATE = 67725, - //in this phase should rise herald (the spell is missing) - - //phase 2 - During this phase, the Black Knight will use the same abilities as in phase 1, except for Death's Respite - SPELL_ARMY_DEAD = 67761, - SPELL_DESECRATION = 67778, - SPELL_DESECRATION_2 = 67778, - SPELL_GHOUL_EXPLODE = 67751, - - //phase 3 - SPELL_DEATH_BITE_H = 67875, - SPELL_DEATH_BITE = 67808, - SPELL_MARKED_DEATH = 67882, - SPELL_MARKED_DEATH_2 = 67823, - - SPELL_BLACK_KNIGHT_RES = 67693, - - SPELL_LEAP = 67749, - SPELL_LEAP_H = 67880 -}; - -enum eModels -{ - MODEL_SKELETON = 29846, - MODEL_GHOST = 21300 -}; - -enum ePhases -{ - PHASE_UNDEAD = 1, - PHASE_SKELETON = 2, - PHASE_GHOST = 3 -}; - -struct boss_black_knightAI : public ScriptedAI -{ - boss_black_knightAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - std::list SummonList; - - bool bEventInProgress; - bool bEvent; - bool bSummonArmy; - bool bDeathArmyDone; - - uint8 uiPhase; - - uint32 uiPlagueStrikeTimer; - uint32 uiIcyTouchTimer; - uint32 uiDeathRespiteTimer; - uint32 uiObliterateTimer; - uint32 uiDesecration; - uint32 uiResurrectTimer; - uint32 uiDeathArmyCheckTimer; - uint32 uiGhoulExplodeTimer; - uint32 uiDeathBiteTimer; - uint32 uiMarkedDeathTimer; - - void Reset() - { - RemoveSummons(); - me->SetDisplayId(me->GetNativeDisplayId()); - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - - bEventInProgress = false; - bEvent = false; - bSummonArmy = false; - bDeathArmyDone = false; - - uiPhase = PHASE_UNDEAD; - - uiIcyTouchTimer = urand(5000,9000); - uiPlagueStrikeTimer = urand(10000,13000); - uiDeathRespiteTimer = urand(15000,16000); - uiObliterateTimer = urand(17000,19000); - uiDesecration = urand(15000,16000); - uiDeathArmyCheckTimer = 7000; - uiResurrectTimer = 4000; - uiGhoulExplodeTimer = 8000; - uiDeathBiteTimer = urand (2000,4000); - uiMarkedDeathTimer = urand (5000,7000); - } - - void RemoveSummons() - { - if (SummonList.empty()) - return; - - for (std::list::const_iterator itr = SummonList.begin(); itr != SummonList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - if (pTemp) - pTemp->DisappearAndDie(); - } - SummonList.clear(); - } - - void JustSummoned(Creature* pSummon) - { - SummonList.push_back(pSummon->GetGUID()); - pSummon->AI()->AttackStart(me->getVictim()); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (bEventInProgress) - if (uiResurrectTimer <= uiDiff) - { - me->SetHealth(me->GetMaxHealth()); - DoCast(me,SPELL_BLACK_KNIGHT_RES,true); - uiPhase++; - uiResurrectTimer = 4000; - bEventInProgress = false; - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - } else uiResurrectTimer -= uiDiff; - - switch(uiPhase) - { - case PHASE_UNDEAD: - case PHASE_SKELETON: - { - if (uiIcyTouchTimer <= uiDiff) - { - DoCastVictim(SPELL_ICY_TOUCH); - uiIcyTouchTimer = urand(5000,7000); - } else uiIcyTouchTimer -= uiDiff; - if (uiPlagueStrikeTimer <= uiDiff) - { - DoCastVictim(SPELL_ICY_TOUCH); - uiPlagueStrikeTimer = urand(12000,15000); - } else uiPlagueStrikeTimer -= uiDiff; - if (uiObliterateTimer <= uiDiff) - { - DoCastVictim(SPELL_OBLITERATE); - uiObliterateTimer = urand(17000,19000); - } else uiObliterateTimer -= uiDiff; - switch(uiPhase) - { - case PHASE_UNDEAD: - { - if (uiDeathRespiteTimer <= uiDiff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_DEATH_RESPITE); - } - uiDeathRespiteTimer = urand(15000,16000); - } else uiDeathRespiteTimer -= uiDiff; - break; - } - case PHASE_SKELETON: - { - if (!bSummonArmy) - { - bSummonArmy = true; - me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - DoCast(me, SPELL_ARMY_DEAD); - } - if (!bDeathArmyDone) - if (uiDeathArmyCheckTimer <= uiDiff) - { - me->clearUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - uiDeathArmyCheckTimer = 0; - bDeathArmyDone = true; - } else uiDeathArmyCheckTimer -= uiDiff; - if (uiDesecration <= uiDiff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_DESECRATION); - } - uiDesecration = urand(15000,16000); - } else uiDesecration -= uiDiff; - if (uiGhoulExplodeTimer <= uiDiff) - { - DoCast(me, SPELL_GHOUL_EXPLODE); - uiGhoulExplodeTimer = 8000; - } else uiGhoulExplodeTimer -= uiDiff; - break; - } - break; - } - break; - } - case PHASE_GHOST: - { - if (uiDeathBiteTimer <= uiDiff) - { - DoCastAOE(SPELL_DEATH_BITE); - uiDeathBiteTimer = urand (2000, 4000); - } else uiDeathBiteTimer -= uiDiff; - if (uiMarkedDeathTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget,SPELL_MARKED_DEATH); - } - uiMarkedDeathTimer = urand (5000, 7000); - } else uiMarkedDeathTimer -= uiDiff; - break; - } - } - - if (!me->hasUnitState(UNIT_STAT_ROOT) && !me->GetHealth()*100 / me->GetMaxHealth() <= 0) - DoMeleeAttackIfReady(); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) - { - if (uiDamage > me->GetHealth() && uiPhase <= PHASE_SKELETON) - { - uiDamage = 0; - me->SetHealth(0); - me->addUnitState(UNIT_STAT_ROOT | UNIT_STAT_STUNNED); - RemoveSummons(); - switch(uiPhase) - { - case PHASE_UNDEAD: - me->SetDisplayId(MODEL_SKELETON); - break; - case PHASE_SKELETON: - me->SetDisplayId(MODEL_GHOST); - break; - } - bEventInProgress = true; - } - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_BLACK_KNIGHT,DONE); - } -}; - -CreatureAI* GetAI_boss_black_knight(Creature *pCreature) -{ - return new boss_black_knightAI (pCreature); -} - -struct npc_risen_ghoulAI : public ScriptedAI -{ - npc_risen_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiAttackTimer; - - void Reset() - { - uiAttackTimer = 3500; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!UpdateVictim()) - return; - - if (uiAttackTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - { - if (pTarget && pTarget->isAlive()) - DoCast(pTarget, (SPELL_LEAP)); - } - uiAttackTimer = 3500; - } else uiAttackTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_risen_ghoul(Creature* pCreature) -{ - return new npc_risen_ghoulAI(pCreature); -} - -struct npc_black_knight_skeletal_gryphonAI : public npc_escortAI -{ - npc_black_knight_skeletal_gryphonAI(Creature* pCreature) : npc_escortAI(pCreature) - { - Start(false,true,0,NULL); - } - - void WaypointReached(uint32 /*i*/) - { - - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - } - -}; - -CreatureAI* GetAI_npc_black_knight_skeletal_gryphon(Creature* pCreature) -{ - return new npc_black_knight_skeletal_gryphonAI(pCreature); -} - -void AddSC_boss_black_knight() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "boss_black_knight"; - NewScript->GetAI = &GetAI_boss_black_knight; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_risen_ghoul"; - NewScript->GetAI = &GetAI_npc_risen_ghoul; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "npc_black_knight_skeletal_gryphon"; - NewScript->GetAI = &GetAI_npc_black_knight_skeletal_gryphon; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp deleted file mode 100644 index 4bf8143a210..00000000000 --- a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/boss_grand_champions.cpp +++ /dev/null @@ -1,993 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: boss_grand_champions -SD%Complete: 50 % -SDComment: Is missing the ai to make the npcs look for a new mount and use it. -SDCategory: Trial Of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "Vehicle.h" -#include "trial_of_the_champion.h" - -enum eSpells -{ - //Vehicle - SPELL_CHARGE = 63010, - SPELL_SHIELD_BREAKER = 68504, - SPELL_SHIELD = 66482, - - // Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior - SPELL_MORTAL_STRIKE = 68783, - SPELL_MORTAL_STRIKE_H = 68784, - SPELL_BLADESTORM = 63784, - SPELL_INTERCEPT = 67540, - SPELL_ROLLING_THROW = 47115, //not implemented in the AI yet... - - // Ambrose Boltspark && Eressea Dawnsinger || Mage - SPELL_FIREBALL = 66042, - SPELL_FIREBALL_H = 68310, - SPELL_BLAST_WAVE = 66044, - SPELL_BLAST_WAVE_H = 68312, - SPELL_HASTE = 66045, - SPELL_POLYMORPH = 66043, - SPELL_POLYMORPH_H = 68311, - - // Colosos && Runok Wildmane || Shaman - SPELL_CHAIN_LIGHTNING = 67529, - SPELL_CHAIN_LIGHTNING_H = 68319, - SPELL_EARTH_SHIELD = 67530, - SPELL_HEALING_WAVE = 67528, - SPELL_HEALING_WAVE_H = 68318, - SPELL_HEX_OF_MENDING = 67534, - - // Jaelyne Evensong && Zul'tore || Hunter - SPELL_DISENGAGE = 68340, //not implemented in the AI yet... - SPELL_LIGHTNING_ARROWS = 66083, - SPELL_MULTI_SHOT = 66081, - SPELL_SHOOT = 65868, - SPELL_SHOOT_H = 67988, - - // Lana Stouthammer Evensong && Deathstalker Visceri || Rouge - SPELL_EVISCERATE = 67709, - SPELL_EVISCERATE_H = 68317, - SPELL_FAN_OF_KNIVES = 67706, - SPELL_POISON_BOTTLE = 67701 -}; - -enum eSeat -{ - SEAT_ID_0 = 0 -}; - -struct Point -{ - float x,y,z; -}; - -const Point MovementPoint[] = -{ - {746.84,623.15,411.41}, - {747.96,620.29,411.09}, - {750.23,618.35,411.09} -}; - -void AggroAllPlayers(Creature* pTemp) -{ - Map::PlayerList const &PlList = pTemp->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - pTemp->SetReactState(REACT_AGGRESSIVE); - pTemp->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(pTemp); - pTemp->AddThreat(pPlayer, 0.0f); - } - } - } -} - -bool GrandChampionsOutVehicle(Creature* me) -{ - ScriptedInstance* pInstance = me->GetInstanceData(); - - if (!pInstance) - return false; - - Creature* pGrandChampion1 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_1)); - Creature* pGrandChampion2 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_2)); - Creature* pGrandChampion3 = Unit::GetCreature(*me, pInstance->GetData64(DATA_GRAND_CHAMPION_3)); - - if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) - { - if (!pGrandChampion1->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && - !pGrandChampion2->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT) && - !pGrandChampion3->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return true; - } - - return false; -} - -/* -* Generic AI for vehicles used by npcs in ToC, it needs more improvements. * -* Script Complete: 25%. * -*/ - -struct generic_vehicleAI_toc5AI : public npc_escortAI -{ - generic_vehicleAI_toc5AI(Creature* pCreature) : npc_escortAI(pCreature) - { - SetDespawnAtEnd(false); - uiWaypointPath = 0; - - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiChargeTimer; - uint32 uiShieldBreakerTimer; - uint32 uiBuffTimer; - - uint32 uiWaypointPath; - - void Reset() - { - uiChargeTimer = 5000; - uiShieldBreakerTimer = 8000; - uiBuffTimer = urand(30000,60000); - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch(uiType) - { - case 1: - AddWaypoint(0,747.36,634.07,411.572); - AddWaypoint(1,780.43,607.15,411.82); - AddWaypoint(2,785.99,599.41,411.92); - AddWaypoint(3,778.44,601.64,411.79); - uiWaypointPath = 1; - break; - case 2: - AddWaypoint(0,747.35,634.07,411.57); - AddWaypoint(1,768.72,581.01,411.92); - AddWaypoint(2,763.55,590.52,411.71); - uiWaypointPath = 2; - break; - case 3: - AddWaypoint(0,747.35,634.07,411.57); - AddWaypoint(1,784.02,645.33,412.39); - AddWaypoint(2,775.67,641.91,411.91); - uiWaypointPath = 3; - break; - } - - if (uiType <= 3) - Start(false,true,0,NULL); - } - - void WaypointReached(uint32 i) - { - switch(i) - { - case 2: - if (pInstance && uiWaypointPath == 3 || uiWaypointPath == 2) - pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); - break; - case 3: - if (pInstance) - pInstance->SetData(DATA_MOVEMENT_DONE, pInstance->GetData(DATA_MOVEMENT_DONE)+1); - break; - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoCastSpellShield(); - } - - void DoCastSpellShield() - { - for (uint8 i = 0; i < 3; ++i) - DoCast(me,SPELL_SHIELD,true); - } - - void UpdateAI(const uint32 uiDiff) - { - npc_escortAI::UpdateAI(uiDiff); - - if (!UpdateVictim()) - return; - - if (uiBuffTimer <= uiDiff) - { - if (!me->HasAura(SPELL_SHIELD)) - DoCastSpellShield(); - - uiBuffTimer = urand(30000,45000); - }else uiBuffTimer -= uiDiff; - - if (uiChargeTimer <= uiDiff) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) - { - DoResetThreat(); - me->AddThreat(pPlayer,1.0f); - DoCast(pPlayer, SPELL_CHARGE); - break; - } - } - } - uiChargeTimer = 5000; - }else uiChargeTimer -= uiDiff; - - //dosen't work at all - if (uiShieldBreakerTimer <= uiDiff) - { - Vehicle *pVehicle = me->GetVehicleKit(); - if (!pVehicle) - return; - - if (Unit* pPassenger = pVehicle->GetPassenger(SEAT_ID_0)) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,10.0f,30.0f,false)) - { - pPassenger->CastSpell(pPlayer,SPELL_SHIELD_BREAKER,true); - break; - } - } - } - } - uiShieldBreakerTimer = 7000; - }else uiShieldBreakerTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_generic_vehicleAI_toc5(Creature* pCreature) -{ - return new generic_vehicleAI_toc5AI(pCreature); -} - -// Marshal Jacob Alerius && Mokra the Skullcrusher || Warrior -struct boss_warrior_toc5AI : public ScriptedAI -{ - boss_warrior_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiBladeStormTimer; - uint32 uiInterceptTimer; - uint32 uiMortalStrikeTimer; - uint32 uiAttackTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiBladeStormTimer = urand(15000,20000); - uiInterceptTimer = 7000; - uiMortalStrikeTimer = urand(8000,12000); - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiInterceptTimer <= uiDiff) - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,8.0f,25.0f,false)) - { - DoResetThreat(); - me->AddThreat(pPlayer,5.0f); - DoCast(pPlayer,SPELL_INTERCEPT); - break; - } - } - } - uiInterceptTimer = 7000; - } else uiInterceptTimer -= uiDiff; - - if (uiBladeStormTimer <= uiDiff) - { - DoCastVictim(SPELL_BLADESTORM); - uiBladeStormTimer = urand(15000,20000); - } else uiBladeStormTimer -= uiDiff; - - if (uiMortalStrikeTimer <= uiDiff) - { - DoCastVictim(SPELL_MORTAL_STRIKE); - uiMortalStrikeTimer = urand(8000,12000); - } else uiMortalStrikeTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_warrior_toc5(Creature* pCreature) -{ - return new boss_warrior_toc5AI(pCreature); -} - -// Ambrose Boltspark && Eressea Dawnsinger || Mage -struct boss_mage_toc5AI : public ScriptedAI -{ - boss_mage_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiFireBallTimer; - uint32 uiBlastWaveTimer; - uint32 uiHasteTimer; - uint32 uiPolymorphTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiFireBallTimer = 5000; - uiPolymorphTimer = 8000; - uiBlastWaveTimer = 12000; - uiHasteTimer = 22000; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (uiFireBallTimer <= uiDiff) - { - if (me->getVictim()) - DoCastVictim(SPELL_FIREBALL); - uiFireBallTimer = 5000; - } else uiFireBallTimer -= uiDiff; - - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiFireBallTimer <= uiDiff) - { - DoCastVictim(SPELL_FIREBALL); - uiFireBallTimer = 5000; - } else uiFireBallTimer -= uiDiff; - - if (uiPolymorphTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_POLYMORPH); - uiPolymorphTimer = 8000; - } else uiPolymorphTimer -= uiDiff; - - if (uiBlastWaveTimer <= uiDiff) - { - DoCastAOE(SPELL_BLAST_WAVE,false); - uiBlastWaveTimer = 13000; - } else uiBlastWaveTimer -= uiDiff; - - if (uiHasteTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - - DoCast(me,SPELL_HASTE); - uiHasteTimer = 22000; - } else uiHasteTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_mage_toc5(Creature* pCreature) -{ - return new boss_mage_toc5AI(pCreature); -} - -// Colosos && Runok Wildmane || Shaman -struct boss_shaman_toc5AI : public ScriptedAI -{ - boss_shaman_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiChainLightningTimer; - uint32 uiEartShieldTimer; - uint32 uiHealingWaveTimer; - uint32 uiHexMendingTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiChainLightningTimer = 16000; - uiHealingWaveTimer = 12000; - uiEartShieldTimer = urand(30000,35000); - uiHexMendingTimer = urand(20000,25000); - } - - void EnterCombat(Unit* pWho) - { - DoCast(me,SPELL_EARTH_SHIELD); - DoCast(pWho,SPELL_HEX_OF_MENDING); - }; - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiChainLightningTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget,SPELL_CHAIN_LIGHTNING); - - uiChainLightningTimer = 16000; - } else uiChainLightningTimer -= uiDiff; - - if (uiHealingWaveTimer <= uiDiff) - { - bool bChance = urand(0,1); - - if (!bChance) - { - if (Unit* pFriend = DoSelectLowestHpFriendly(40)) - DoCast(pFriend,SPELL_HEALING_WAVE); - } else - DoCast(me,SPELL_HEALING_WAVE); - - uiHealingWaveTimer = 12000; - } else uiHealingWaveTimer -= uiDiff; - - if (uiEartShieldTimer <= uiDiff) - { - DoCast(me,SPELL_EARTH_SHIELD); - - uiEartShieldTimer = urand(30000,35000); - } else uiEartShieldTimer -= uiDiff; - - if (uiHexMendingTimer <= uiDiff) - { - DoCastVictim(SPELL_HEX_OF_MENDING,true); - - uiHexMendingTimer = urand(20000,25000); - } else uiHexMendingTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_shaman_toc5(Creature* pCreature) -{ - return new boss_shaman_toc5AI(pCreature); -} - -// Jaelyne Evensong && Zul'tore || Hunter -struct boss_hunter_toc5AI : public ScriptedAI -{ - boss_hunter_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - - uint32 uiShootTimer; - uint32 uiMultiShotTimer; - uint32 uiLightningArrowsTimer; - - uint64 uiTargetGUID; - - bool bShoot; - bool bDone; - bool bHome; - - void Reset() - { - uiShootTimer = 12000; - uiMultiShotTimer = 0; - uiLightningArrowsTimer = 7000; - - uiTargetGUID = 0; - - bShoot = false; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - }else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiLightningArrowsTimer <= uiDiff) - { - DoCastAOE(SPELL_LIGHTNING_ARROWS,false); - uiLightningArrowsTimer = 7000; - } else uiLightningArrowsTimer -= uiDiff; - - if (uiShootTimer <= uiDiff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_FARTHEST,0,30.0f)) - { - uiTargetGUID = pTarget->GetGUID(); - DoCast(pTarget, SPELL_SHOOT); - } - uiShootTimer = 12000; - uiMultiShotTimer = 3000; - bShoot = true; - } else uiShootTimer -= uiDiff; - - if (bShoot && uiMultiShotTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(true); - Unit* pTarget = Unit::GetUnit(*me, uiTargetGUID); - - if (pTarget && me->IsInRange(pTarget,5.0f,30.0f,false)) - { - DoCast(pTarget,SPELL_MULTI_SHOT); - } else - { - Map::PlayerList const& players = me->GetMap()->GetPlayers(); - if (me->GetMap()->IsDungeon() && !players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - Player* pPlayer = itr->getSource(); - if (pPlayer && !pPlayer->isGameMaster() && me->IsInRange(pPlayer,5.0f,30.0f,false)) - { - DoCast(pTarget,SPELL_MULTI_SHOT); - break; - } - } - } - } - bShoot = false; - } else uiMultiShotTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_hunter_toc5(Creature* pCreature) -{ - return new boss_hunter_toc5AI(pCreature); -} - -// Lana Stouthammer Evensong && Deathstalker Visceri || Rouge -struct boss_rouge_toc5AI : public ScriptedAI -{ - boss_rouge_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - bDone = false; - bHome = false; - - uiPhase = 0; - uiPhaseTimer = 0; - - me->SetReactState(REACT_PASSIVE); - // THIS IS A HACK, SHOULD BE REMOVED WHEN THE EVENT IS FULL SCRIPTED - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - ScriptedInstance* pInstance; - - uint8 uiPhase; - uint32 uiPhaseTimer; - uint32 uiEviscerateTimer; - uint32 uiFanKivesTimer; - uint32 uiPosionBottleTimer; - - bool bDone; - bool bHome; - - void Reset() - { - uiEviscerateTimer = 8000; - uiFanKivesTimer = 14000; - uiPosionBottleTimer = 19000; - } - - void JustReachedHome() - { - ScriptedAI::JustReachedHome(); - - if (!bHome) - return; - - uiPhaseTimer = 15000; - uiPhase = 1; - - bHome = false; - } - - void UpdateAI(const uint32 uiDiff) - { - if (!bDone && GrandChampionsOutVehicle(me)) - { - bDone = true; - - if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_1)) - me->SetHomePosition(739.678,662.541,412.393,4.49); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_2)) - me->SetHomePosition(746.71,661.02,411.69,4.6); - else if (pInstance && me->GetGUID() == pInstance->GetData64(DATA_GRAND_CHAMPION_3)) - me->SetHomePosition(754.34,660.70,412.39,4.79); - - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, IN_PROGRESS); - - EnterEvadeMode(); - bHome = true; - } - - if (uiPhaseTimer <= uiDiff) - { - if (uiPhase == 1) - { - AggroAllPlayers(me); - uiPhase = 0; - } - } else uiPhaseTimer -= uiDiff; - - if (!UpdateVictim() || me->HasUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT)) - return; - - if (uiEviscerateTimer <= uiDiff) - { - DoCast(me->getVictim(),SPELL_EVISCERATE); - uiEviscerateTimer = 8000; - } else uiEviscerateTimer -= uiDiff; - - if (uiFanKivesTimer <= uiDiff) - { - DoCastAOE(SPELL_FAN_OF_KNIVES,false); - uiFanKivesTimer = 14000; - } else uiFanKivesTimer -= uiDiff; - - if (uiPosionBottleTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget,SPELL_POISON_BOTTLE); - uiPosionBottleTimer = 19000; - } else uiPosionBottleTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - pInstance->SetData(BOSS_GRAND_CHAMPIONS, DONE); - } -}; - -CreatureAI* GetAI_boss_rouge_toc5(Creature* pCreature) -{ - return new boss_rouge_toc5AI(pCreature); -} - -void AddSC_boss_grand_champions() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "generic_vehicleAI_toc5"; - NewScript->GetAI = &GetAI_generic_vehicleAI_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_warrior_toc5"; - NewScript->GetAI = &GetAI_boss_warrior_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_mage_toc5"; - NewScript->GetAI = &GetAI_boss_mage_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_shaman_toc5"; - NewScript->GetAI = &GetAI_boss_shaman_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_hunter_toc5"; - NewScript->GetAI = &GetAI_boss_hunter_toc5; - NewScript->RegisterSelf(); - - NewScript = new Script; - NewScript->Name = "boss_rouge_toc5"; - NewScript->GetAI = &GetAI_boss_rouge_toc5; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp deleted file mode 100644 index 04b671ec11c..00000000000 --- a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/instance_trial_of_the_champion.cpp +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - - -/* ScriptData -SDName: Instance Trial of the Champion -SDComment: -SDCategory: Trial Of the Champion -EndScriptData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" - -#define MAX_ENCOUNTER 4 - -struct instance_trial_of_the_champion : public ScriptedInstance -{ - instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint8 uiMovementDone; - uint8 uiGrandChampionsDeaths; - uint8 uiArgentSoldierDeaths; - - uint64 uiAnnouncerGUID; - uint64 uiMainGateGUID; - uint64 uiGrandChampionVehicle1GUID; - uint64 uiGrandChampionVehicle2GUID; - uint64 uiGrandChampionVehicle3GUID; - uint64 uiGrandChampion1GUID; - uint64 uiGrandChampion2GUID; - uint64 uiGrandChampion3GUID; - uint64 uiChampionLootGUID; - uint64 uiArgentChampionGUID; - - std::list VehicleList; - - std::string str_data; - - bool bDone; - - void Initialize() - { - uiMovementDone = 0; - uiGrandChampionsDeaths = 0; - uiArgentSoldierDeaths = 0; - - uiAnnouncerGUID = 0; - uiMainGateGUID = 0; - uiGrandChampionVehicle1GUID = 0; - uiGrandChampionVehicle2GUID = 0; - uiGrandChampionVehicle3GUID = 0; - uiGrandChampion1GUID = 0; - uiGrandChampion2GUID = 0; - uiGrandChampion3GUID = 0; - uiChampionLootGUID = 0; - uiArgentChampionGUID = 0; - - bDone = false; - - VehicleList.clear(); - - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - } - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*bAdd*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - uint32 TeamInInstance = 0; - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - TeamInInstance = pPlayer->GetTeam(); - } - - switch(pCreature->GetEntry()) - { - // Champions - case VEHICLE_MOKRA_SKILLCRUSHER_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT, ALLIANCE); - break; - case VEHICLE_ERESSEA_DAWNSINGER_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_AMBROSE_BOLTSPARK_MOUNT, ALLIANCE); - break; - case VEHICLE_RUNOK_WILDMANE_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_COLOSOS_MOUNT, ALLIANCE); - break; - case VEHICLE_ZUL_TORE_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_EVENSONG_MOUNT, ALLIANCE); - break; - case VEHICLE_DEATHSTALKER_VESCERI_MOUNT: - if (TeamInInstance == HORDE) - pCreature->UpdateEntry(VEHICLE_LANA_STOUTHAMMER_MOUNT, ALLIANCE); - break; - // Coliseum Announcer || Just NPC_JAEREN must be spawned. - case NPC_JAEREN: - uiAnnouncerGUID = pCreature->GetGUID(); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_ARELAS,ALLIANCE); - break; - case VEHICLE_ARGENT_WARHORSE: - case VEHICLE_ARGENT_BATTLEWORG: - VehicleList.push_back(pCreature->GetGUID()); - break; - case NPC_EADRIC: - case NPC_PALETRESS: - uiArgentChampionGUID = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGO, bool /*bAdd*/) - { - switch(pGO->GetEntry()) - { - case GO_MAIN_GATE: - uiMainGateGUID = pGO->GetGUID(); - break; - case GO_CHAMPIONS_LOOT: - case GO_CHAMPIONS_LOOT_H: - uiChampionLootGUID = pGO->GetGUID(); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case DATA_MOVEMENT_DONE: - uiMovementDone = uiData; - if (uiMovementDone == 3) - { - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - pAnnouncer->AI()->SetData(DATA_IN_POSITION,0); - } - break; - case BOSS_GRAND_CHAMPIONS: - m_auiEncounter[0] = uiData; - if (uiData == IN_PROGRESS) - { - for (std::list::const_iterator itr = VehicleList.begin(); itr != VehicleList.end(); ++itr) - if (Creature* pSummon = instance->GetCreature(*itr)) - pSummon->RemoveFromWorld(); - }else if (uiData == DONE) - { - ++uiGrandChampionsDeaths; - if (uiGrandChampionsDeaths == 3) - { - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_CHAMPIONS_LOOT_H : GO_CHAMPIONS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - } - } - break; - case DATA_ARGENT_SOLDIER_DEFEATED: - uiArgentSoldierDeaths = uiData; - if (uiArgentSoldierDeaths == 9) - { - if (Creature* pBoss = instance->GetCreature(uiArgentChampionGUID)) - { - pBoss->GetMotionMaster()->MovePoint(0,746.88,618.74,411.06); - pBoss->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pBoss->SetReactState(REACT_AGGRESSIVE); - } - } - break; - case BOSS_ARGENT_CHALLENGE_E: - m_auiEncounter[1] = uiData; - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_EADRIC_LOOT_H : GO_EADRIC_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - break; - case BOSS_ARGENT_CHALLENGE_P: - m_auiEncounter[2] = uiData; - if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID)) - { - pAnnouncer->GetMotionMaster()->MovePoint(0,748.309,619.487,411.171); - pAnnouncer->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - pAnnouncer->SummonGameObject(instance->IsHeroic()? GO_PALETRESS_LOOT_H : GO_PALETRESS_LOOT,746.59,618.49,411.09,1.42,0, 0, 0, 0,90000000); - } - break; - } - - if (uiData == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 uiData) - { - switch(uiData) - { - case BOSS_GRAND_CHAMPIONS: return m_auiEncounter[0]; - case BOSS_ARGENT_CHALLENGE_E: return m_auiEncounter[1]; - case BOSS_ARGENT_CHALLENGE_P: return m_auiEncounter[2]; - case BOSS_BLACK_KNIGHT: return m_auiEncounter[3]; - - case DATA_MOVEMENT_DONE: return uiMovementDone; - case DATA_ARGENT_SOLDIER_DEFEATED: return uiArgentSoldierDeaths; - } - - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_ANNOUNCER: return uiAnnouncerGUID; - case DATA_MAIN_GATE: return uiMainGateGUID; - - case DATA_GRAND_CHAMPION_1: return uiGrandChampion1GUID; - case DATA_GRAND_CHAMPION_2: return uiGrandChampion2GUID; - case DATA_GRAND_CHAMPION_3: return uiGrandChampion3GUID; - } - - return 0; - } - - void SetData64(uint32 uiType, uint64 uiData) - { - switch(uiType) - { - case DATA_GRAND_CHAMPION_1: - uiGrandChampion1GUID = uiData; - break; - case DATA_GRAND_CHAMPION_2: - uiGrandChampion2GUID = uiData; - break; - case DATA_GRAND_CHAMPION_3: - uiGrandChampion3GUID = uiData; - break; - } - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - - saveStream << "T C " << m_auiEncounter[0] - << " " << m_auiEncounter[1] - << " " << m_auiEncounter[2] - << " " << m_auiEncounter[3] - << " " << uiGrandChampionsDeaths - << " " << uiMovementDone; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; - - if (dataHead1 == 'T' && dataHead2 == 'C') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - uiGrandChampionsDeaths = data4; - uiMovementDone = data5; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_trial_of_the_champion(Map* pMap) -{ - return new instance_trial_of_the_champion(pMap); -} - -void AddSC_instance_trial_of_the_champion() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_trial_of_the_champion"; - newscript->GetInstanceData = &GetInstanceData_instance_trial_of_the_champion; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp deleted file mode 100644 index 090b64b96cc..00000000000 --- a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Copyright (C) 2010 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Trial Of the Champion -SD%Complete: -SDComment: -SDCategory: trial_of_the_champion -EndScriptData */ - -/* ContentData -npc_announcer_toc5 -EndContentData */ - -#include "ScriptedPch.h" -#include "trial_of_the_champion.h" -#include "Vehicle.h" - -#define GOSSIP_START_EVENT1 "I'm ready to start challenge." -#define GOSSIP_START_EVENT2 "I'm ready for the next challenge." - -#define ORIENTATION 4.714 - -/*###### -## npc_announcer_toc5 -######*/ - -const Position SpawnPosition = {746.261,657.401,411.681,4.65}; - -struct npc_announcer_toc5AI : public ScriptedAI -{ - npc_announcer_toc5AI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - - uiSummonTimes = 0; - uiPosition = 0; - uiLesserChampions = 0; - - uiFirstBoss = 0; - uiSecondBoss = 0; - uiThirdBoss = 0; - - uiArgentChampion = 0; - - uiPhase = 0; - uiTimer = 0; - - uiVehicle1GUID = 0; - uiVehicle2GUID = 0; - uiVehicle3GUID = 0; - - Champion1List.clear(); - Champion2List.clear(); - Champion3List.clear(); - - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - SetGrandChampionsForEncounter(); - SetArgentChampion(); - } - - ScriptedInstance* pInstance; - - uint8 uiSummonTimes; - uint8 uiPosition; - uint8 uiLesserChampions; - - uint32 uiArgentChampion; - - uint32 uiFirstBoss; - uint32 uiSecondBoss; - uint32 uiThirdBoss; - - uint32 uiPhase; - uint32 uiTimer; - - uint64 uiVehicle1GUID; - uint64 uiVehicle2GUID; - uint64 uiVehicle3GUID; - - uint64 uiGrandChampionBoss1; - - std::list Champion1List; - std::list Champion2List; - std::list Champion3List; - - void NextStep(uint32 uiTimerStep,bool bNextStep = true,uint8 uiPhaseStep = 0) - { - uiTimer = uiTimerStep; - if (bNextStep) - ++uiPhase; - else - uiPhase = uiPhaseStep; - } - - void SetData(uint32 uiType, uint32 /*uiData*/) - { - switch (uiType) - { - case DATA_START: - DoSummonGrandChampion(uiFirstBoss); - NextStep(10000,false,1); - break; - case DATA_IN_POSITION: //movement done. - me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); - if (GameObject* pGO = GameObject::GetGameObject(*me, pInstance->GetData64(DATA_MAIN_GATE))) - pInstance->HandleGameObject(pGO->GetGUID(),false); - NextStep(10000,false,3); - break; - case DATA_LESSER_CHAMPIONS_DEFEATED: - { - ++uiLesserChampions; - std::list TempList; - if (uiLesserChampions == 3 || uiLesserChampions == 6) - { - switch(uiLesserChampions) - { - case 3: - TempList = Champion2List; - break; - case 6: - TempList = Champion3List; - break; - } - - for (std::list::const_iterator itr = TempList.begin(); itr != TempList.end(); ++itr) - if (Creature* pSummon = Unit::GetCreature(*me, *itr)) - AggroAllPlayers(pSummon); - }else if (uiLesserChampions == 9) - StartGrandChampionsAttack(); - - break; - } - } - } - - void StartGrandChampionsAttack() - { - Creature* pGrandChampion1 = Unit::GetCreature(*me, uiVehicle1GUID); - Creature* pGrandChampion2 = Unit::GetCreature(*me, uiVehicle2GUID); - Creature* pGrandChampion3 = Unit::GetCreature(*me, uiVehicle3GUID); - - if (pGrandChampion1 && pGrandChampion2 && pGrandChampion3) - { - AggroAllPlayers(pGrandChampion1); - AggroAllPlayers(pGrandChampion2); - AggroAllPlayers(pGrandChampion3); - } - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE) - return; - - if (uiPointId == 1) - { - me->SetOrientation(ORIENTATION); - me->SendMovementFlagUpdate(); - } - } - - void DoSummonGrandChampion(uint32 uiBoss) - { - ++uiSummonTimes; - uint32 VEHICLE_TO_SUMMON1 = 0; - uint32 VEHICLE_TO_SUMMON2 = 0; - switch(uiBoss) - { - case 0: - VEHICLE_TO_SUMMON1 = VEHICLE_MOKRA_SKILLCRUSHER_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_ORGRIMMAR_WOLF; - break; - case 1: - VEHICLE_TO_SUMMON1 = VEHICLE_ERESSEA_DAWNSINGER_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_SILVERMOON_HAWKSTRIDER; - break; - case 2: - VEHICLE_TO_SUMMON1 = VEHICLE_RUNOK_WILDMANE_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_THUNDER_BLUFF_KODO; - break; - case 3: - VEHICLE_TO_SUMMON1 = VEHICLE_ZUL_TORE_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_DARKSPEAR_RAPTOR; - break; - case 4: - VEHICLE_TO_SUMMON1 = VEHICLE_DEATHSTALKER_VESCERI_MOUNT; - VEHICLE_TO_SUMMON2 = VEHICLE_FORSAKE_WARHORSE; - break; - default: - return; - } - - if (Creature* pBoss = me->SummonCreature(VEHICLE_TO_SUMMON1,SpawnPosition)) - { - switch(uiSummonTimes) - { - case 1: - { - uiVehicle1GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss1 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle1GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss1 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_1,uiVehicle1GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_1,uiGrandChampionBoss1); - } - pBoss->AI()->SetData(1,0); - break; - } - case 2: - { - uiVehicle2GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss2 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle2GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss2 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_2,uiVehicle2GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_2,uiGrandChampionBoss2); - } - pBoss->AI()->SetData(2,0); - break; - } - case 3: - { - uiVehicle3GUID = pBoss->GetGUID(); - uint64 uiGrandChampionBoss3 = 0; - if (Creature* pBoss = Unit::GetCreature(*me, uiVehicle3GUID)) - if (Vehicle* pVehicle = pBoss->GetVehicleKit()) - if (Unit* pUnit = pVehicle->GetPassenger(0)) - uiGrandChampionBoss3 = pUnit->GetGUID(); - if (pInstance) - { - pInstance->SetData64(DATA_GRAND_CHAMPION_VEHICLE_3,uiVehicle3GUID); - pInstance->SetData64(DATA_GRAND_CHAMPION_3,uiGrandChampionBoss3); - } - pBoss->AI()->SetData(3,0); - break; - } - default: - return; - } - - for (uint8 i = 0; i < 3; ++i) - { - if (Creature* pAdd = me->SummonCreature(VEHICLE_TO_SUMMON2,SpawnPosition,TEMPSUMMON_CORPSE_DESPAWN)) - { - switch(uiSummonTimes) - { - case 1: - Champion1List.push_back(pAdd->GetGUID()); - break; - case 2: - Champion2List.push_back(pAdd->GetGUID()); - break; - case 3: - Champion3List.push_back(pAdd->GetGUID()); - break; - } - - switch(i) - { - case 0: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI); - break; - case 1: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2); - break; - case 2: - pAdd->GetMotionMaster()->MoveFollow(pBoss,2.0f,M_PI / 2 + M_PI); - break; - } - } - - } - } - } - - void DoStartArgentChampionEncounter() - { - me->GetMotionMaster()->MovePoint(1,735.81,661.92,412.39); - - if (Creature* pBoss = me->SummonCreature(uiArgentChampion,SpawnPosition)) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_LIGHWIELDER,SpawnPosition)) - pTrash->AI()->SetData(i,0); - if (Creature* pTrash = me->SummonCreature(NPC_ARGENT_MONK,SpawnPosition)) - pTrash->AI()->SetData(i,0); - if (Creature* pTrash = me->SummonCreature(NPC_PRIESTESS,SpawnPosition)) - pTrash->AI()->SetData(i,0); - } - } - } - - void SetGrandChampionsForEncounter() - { - uiFirstBoss = urand(0,4); - - while (uiSecondBoss == uiFirstBoss || uiThirdBoss == uiFirstBoss || uiThirdBoss == uiSecondBoss) - { - uiSecondBoss = urand(0,4); - uiThirdBoss = urand(0,4); - } - } - - void SetArgentChampion() - { - uint8 uiTempBoss = urand(0,1); - - switch(uiTempBoss) - { - case 0: - uiArgentChampion = NPC_EADRIC; - break; - case 1: - uiArgentChampion = NPC_PALETRESS; - break; - } - } - - void StartEncounter() - { - if (!pInstance) - return; - - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - - if (pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) - { - if (pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED) - { - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) - me->AI()->SetData(DATA_START,0); - - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE) - DoStartArgentChampionEncounter(); - } - - if (pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) - me->SummonCreature(VEHICLE_BLACK_KNIGHT,769.834,651.915,447.035,0); - } - } - - void AggroAllPlayers(Creature* pTemp) - { - Map::PlayerList const &PlList = me->GetMap()->GetPlayers(); - - if (PlList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlList.begin(); i != PlList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isGameMaster()) - continue; - - if (pPlayer->isAlive()) - { - pTemp->SetHomePosition(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - pTemp->RemoveFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetReactState(REACT_AGGRESSIVE); - pTemp->SetInCombatWith(pPlayer); - pPlayer->SetInCombatWith(pTemp); - pTemp->AddThreat(pPlayer, 0.0f); - } - } - } - } - - - void UpdateAI(const uint32 uiDiff) - { - ScriptedAI::UpdateAI(uiDiff); - - if (uiTimer <= uiDiff) - { - switch(uiPhase) - { - case 1: - DoSummonGrandChampion(uiSecondBoss); - NextStep(10000,true); - break; - case 2: - DoSummonGrandChampion(uiThirdBoss); - NextStep(0,false); - break; - case 3: - if (!Champion1List.empty()) - { - for (std::list::const_iterator itr = Champion1List.begin(); itr != Champion1List.end(); ++itr) - if (Creature* pSummon = Unit::GetCreature(*me, *itr)) - AggroAllPlayers(pSummon); - NextStep(0,false); - } - break; - } - } else uiTimer -= uiDiff; - - if (!UpdateVictim()) - return; - } - - void JustSummoned(Creature* pSummon) - { - if (pInstance && pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED) - { - pSummon->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - pSummon->SetReactState(REACT_PASSIVE); - } - } - - void SummonedCreatureDespawn(Creature* pSummon) - { - switch(pSummon->GetEntry()) - { - case VEHICLE_DARNASSIA_NIGHTSABER: - case VEHICLE_EXODAR_ELEKK: - case VEHICLE_STORMWIND_STEED: - case VEHICLE_GNOMEREGAN_MECHANOSTRIDER: - case VEHICLE_IRONFORGE_RAM: - case VEHICLE_FORSAKE_WARHORSE: - case VEHICLE_THUNDER_BLUFF_KODO: - case VEHICLE_ORGRIMMAR_WOLF: - case VEHICLE_SILVERMOON_HAWKSTRIDER: - case VEHICLE_DARKSPEAR_RAPTOR: - me->AI()->SetData(DATA_LESSER_CHAMPIONS_DEFEATED,0); - break; - } - } -}; - -CreatureAI* GetAI_npc_announcer_toc5(Creature* pCreature) -{ - return new npc_announcer_toc5AI(pCreature); -} - -bool GossipHello_npc_announcer_toc5(Player* pPlayer, Creature* pCreature) -{ - ScriptedInstance* pInstance = pCreature->GetInstanceData(); - - if (pInstance && - pInstance->GetData(BOSS_GRAND_CHAMPIONS) == DONE && - pInstance->GetData(BOSS_BLACK_KNIGHT) == DONE && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == DONE || - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == DONE) - return false; - - if (pInstance && - pInstance->GetData(BOSS_GRAND_CHAMPIONS) == NOT_STARTED && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_E) == NOT_STARTED && - pInstance->GetData(BOSS_ARGENT_CHALLENGE_P) == NOT_STARTED && - pInstance->GetData(BOSS_BLACK_KNIGHT) == NOT_STARTED) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - else if (pInstance) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START_EVENT2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_announcer_toc5(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_announcer_toc5AI, pCreature->AI())->StartEncounter(); - } - - return true; -} - -void AddSC_trial_of_the_champion() -{ - Script* NewScript; - - NewScript = new Script; - NewScript->Name = "npc_announcer_toc5"; - NewScript->GetAI = &GetAI_npc_announcer_toc5; - NewScript->pGossipHello = &GossipHello_npc_announcer_toc5; - NewScript->pGossipSelect = &GossipSelect_npc_announcer_toc5; - NewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h b/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h deleted file mode 100644 index 221c7c0412f..00000000000 --- a/src/server/scripts/Northrend/CrusadersColiseum/trial_of_the_champion/trial_of_the_champion.h +++ /dev/null @@ -1,115 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software licensed under GPL version 2 -* Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_TOC_H -#define DEF_TOC_H - - -enum eData -{ - BOSS_GRAND_CHAMPIONS, - BOSS_ARGENT_CHALLENGE_E, - BOSS_ARGENT_CHALLENGE_P, - BOSS_BLACK_KNIGHT, - DATA_MOVEMENT_DONE, - DATA_LESSER_CHAMPIONS_DEFEATED, - DATA_START, - DATA_IN_POSITION, - DATA_ARGENT_SOLDIER_DEFEATED -}; - -enum Data64 -{ - DATA_ANNOUNCER, - DATA_MAIN_GATE, - - DATA_GRAND_CHAMPION_VEHICLE_1, - DATA_GRAND_CHAMPION_VEHICLE_2, - DATA_GRAND_CHAMPION_VEHICLE_3, - - DATA_GRAND_CHAMPION_1, - DATA_GRAND_CHAMPION_2, - DATA_GRAND_CHAMPION_3 -}; - -enum eNpcs -{ - // Horde Champions - NPC_MOKRA = 35572, - NPC_ERESSEA = 35569, - NPC_RUNOK = 35571, - NPC_ZULTORE = 35570, - NPC_VISCERI = 35617, - - // Alliance Champions - NPC_JACOB = 34705, - NPC_AMBROSE = 34702, - NPC_COLOSOS = 34701, - NPC_JAELYNE = 34657, - NPC_LANA = 34703, - - NPC_EADRIC = 35119, - NPC_PALETRESS = 34928, - - NPC_ARGENT_LIGHWIELDER = 35309, - NPC_ARGENT_MONK = 35305, - NPC_PRIESTESS = 35307, - - NPC_BLACK_KNIGHT = 35451, - - NPC_RISEN_JAEREN = 35545, - NPC_RISEN_ARELAS = 35564, - - NPC_JAEREN = 35004, - NPC_ARELAS = 35005 -}; - -enum eGameObjects -{ - GO_MAIN_GATE = 195647, - - GO_CHAMPIONS_LOOT = 195709, - GO_CHAMPIONS_LOOT_H = 195710, - - GO_EADRIC_LOOT = 195374, - GO_EADRIC_LOOT_H = 195375, - - GO_PALETRESS_LOOT = 195323, - GO_PALETRESS_LOOT_H = 195324 -}; - -enum eVehicles -{ - //Grand Champions Alliance Vehicles - VEHICLE_MARSHAL_JACOB_ALERIUS_MOUNT = 35637, - VEHICLE_AMBROSE_BOLTSPARK_MOUNT = 35633, - VEHICLE_COLOSOS_MOUNT = 35768, - VEHICLE_EVENSONG_MOUNT = 34658, - VEHICLE_LANA_STOUTHAMMER_MOUNT = 35636, - //Faction Champions (ALLIANCE) - VEHICLE_DARNASSIA_NIGHTSABER = 33298, - VEHICLE_EXODAR_ELEKK = 33416, - VEHICLE_STORMWIND_STEED = 33297, - VEHICLE_GNOMEREGAN_MECHANOSTRIDER = 33301, - VEHICLE_IRONFORGE_RAM = 33408, - //Grand Champions Horde Vehicles - VEHICLE_MOKRA_SKILLCRUSHER_MOUNT = 35638, - VEHICLE_ERESSEA_DAWNSINGER_MOUNT = 35635, - VEHICLE_RUNOK_WILDMANE_MOUNT = 35640, - VEHICLE_ZUL_TORE_MOUNT = 35641, - VEHICLE_DEATHSTALKER_VESCERI_MOUNT = 35634, - //Faction Champions (HORDE) - VEHICLE_FORSAKE_WARHORSE = 33414, - VEHICLE_THUNDER_BLUFF_KODO = 33300, - VEHICLE_ORGRIMMAR_WOLF = 33409, - VEHICLE_SILVERMOON_HAWKSTRIDER = 33418, - VEHICLE_DARKSPEAR_RAPTOR = 33299, - - VEHICLE_ARGENT_WARHORSE = 35644, - VEHICLE_ARGENT_BATTLEWORG = 36558, - - VEHICLE_BLACK_KNIGHT = 35491 -}; - -#endif diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp new file mode 100644 index 00000000000..59db2842735 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_bronjahm.cpp @@ -0,0 +1,263 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +/* + * TODO: + * - Fix Soul Storm spell and remove work around. + */ + +enum Yells +{ + SAY_AGGRO = -1632001, + SAY_SLAY_1 = -1632002, + SAY_SLAY_2 = -1632003, + SAY_DEATH = -1632004, + SAY_SOUL_STORM = -1632005, + SAY_CORRUPT_SOUL = -1632006, +}; + +enum Spells +{ + SPELL_MAGIC_S_BANE = 68793, + SPELL_CORRUPT_SOUL = 68839, + SPELL_CONSUME_SOUL = 68858, + SPELL_TELEPORT = 68988, + SPELL_FEAR = 68950, + SPELL_SOULSTORM = 68872, + SPELL_SOULSTORM_AURA = 68921, + SPELL_SHADOW_BOLT = 70043, +}; + +enum Events +{ + EVENT_NONE, + EVENT_SHADOW_BOLT, + EVENT_MAGIC_BANE, + EVENT_CORRUPT_SOUL, + EVENT_SOUL_STORM, + EVENT_SOUL_STORM_AURA, + EVENT_FEAR, +}; + +enum CombatPhases +{ + PHASE_1, + PHASE_2 +}; + +struct boss_bronjahmAI : public ScriptedAI +{ + boss_bronjahmAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + CombatPhases phase; + + void Reset() + { + phase = PHASE_1; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + events.Reset(); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); + events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); + events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_BRONJAHM_EVENT, DONE); + } + + void KilledUnit(Unit * /*who*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + // Cast aura spell on all players farther than 10y + void ApplySoulStorm() + { + std::list targetList; + + SelectTargetList(targetList, 100, SELECT_TARGET_TOPAGGRO, -10.0f); + if (targetList.empty()) + return; + + for (std::list::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr) + { + Unit* pUnit = (*itr); + if (pUnit && pUnit->isAlive()) + me->CastSpell(pUnit, SPELL_SOULSTORM_AURA, true); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + if (phase == PHASE_1 && HealthBelowPct(30)) + { + phase = PHASE_2; + DoCast(me,SPELL_TELEPORT); + me->GetMotionMaster()->Clear(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + events.CancelEvent(EVENT_CORRUPT_SOUL); + events.ScheduleEvent(EVENT_SOUL_STORM, 1000); + events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); + return; + } + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CORRUPT_SOUL: + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + DoScriptText(SAY_CORRUPT_SOUL, me); + DoCast(pTarget,SPELL_CORRUPT_SOUL); + } + events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); + break; + case EVENT_SOUL_STORM: + DoScriptText(SAY_SOUL_STORM, me); + // DoCast(me, SPELL_SOULSTORM); bug: put the aura without the limit of 10 yards. + events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); + break; + case EVENT_SOUL_STORM_AURA: + ApplySoulStorm(); + events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); + break; + case EVENT_FEAR: + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget,SPELL_FEAR); + events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); + break; + case EVENT_SHADOW_BOLT: + DoCastVictim(SPELL_SHADOW_BOLT); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); + break; + case EVENT_MAGIC_BANE: + DoCastVictim(SPELL_MAGIC_S_BANE); + events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bronjahm(Creature* pCreature) +{ + return new boss_bronjahmAI(pCreature); +} + +struct mob_corrupted_soul_fragmentAI : public ScriptedAI +{ + mob_corrupted_soul_fragmentAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCheckTimer; + + void Reset() + { + uiCheckTimer = 0; // first check is immediate + } + + void UpdateAI(const uint32 diff) + { + if (uiCheckTimer <= diff) + { + if (pInstance) + { + Creature* pBronjham = Unit::GetCreature(*me, pInstance->GetData64(DATA_BRONJAHM)); + if (pBronjham && pBronjham->isAlive()) + { + if (me->IsWithinMeleeRange(pBronjham)) + { + pBronjham->CastSpell(pBronjham, SPELL_CONSUME_SOUL, true); + me->ForcedDespawn(); + } + else + { + Position pos; + pBronjham->GetPosition(&pos); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, pos); + } + } + else + me->ForcedDespawn(); + } + uiCheckTimer = 500; + } + else + uiCheckTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_corrupted_soul_fragment(Creature* pCreature) +{ + return new mob_corrupted_soul_fragmentAI(pCreature); +} + +void AddSC_boss_bronjahm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_bronjahm"; + newscript->GetAI = &GetAI_boss_bronjahm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_corrupted_soul_fragment"; + newscript->GetAI = &GetAI_mob_corrupted_soul_fragment; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp new file mode 100644 index 00000000000..6811ba953e2 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/boss_devourer_of_souls.cpp @@ -0,0 +1,349 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +/* + * TODO: + * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing). + * - Fix outro npc movement + */ + +#define PI 3.1415f + +enum Yells +{ + SAY_FACE_ANGER_AGGRO = -1632010, + SAY_FACE_DESIRE_AGGRO = -1632011, + SAY_FACE_ANGER_SLAY_1 = -1632012, + SAY_FACE_SORROW_SLAY_1 = -1632013, + SAY_FACE_DESIRE_SLAY_1 = -1632014, + SAY_FACE_ANGER_SLAY_2 = -1632015, + SAY_FACE_SORROW_SLAY_2 = -1632016, + SAY_FACE_DESIRE_SLAY_2 = -1632017, + SAY_FACE_SORROW_DEATH = -1632019, + SAY_FACE_DESIRE_DEATH = -1632020, + EMOTE_MIRRORED_SOUL = -1632021, + EMOTE_UNLEASH_SOUL = -1632022, + SAY_FACE_ANGER_UNLEASH_SOUL = -1632023, + SAY_FACE_SORROW_UNLEASH_SOUL = -1632024, + SAY_FACE_DESIRE_UNLEASH_SOUL = -1632025, + EMOTE_WAILING_SOUL = -1632026, + SAY_FACE_ANGER_WAILING_SOUL = -1632027, + SAY_FACE_DESIRE_WAILING_SOUL = -1632028, + + SAY_JAINA_OUTRO = -1632029, + SAY_SYLVANAS_OUTRO = -1632030, +}; + +enum Spells +{ + SPELL_PHANTOM_BLAST = 68982, + H_SPELL_PHANTOM_BLAST = 70322, + SPELL_MIRRORED_SOUL = 69051, + SPELL_WELL_OF_SOULS = 68820, + SPELL_WELL_OF_SOULS_VIS = 68854, + SPELL_UNLEASHED_SOULS = 68939, + SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase + SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual + SPELL_WAILING_SOULS = 68873, // the actual spell + H_SPELL_WAILING_SOULS = 70324, +// 68871,68873,68875,68876,68899,68912,70324, +// 68899 trigger 68871 +}; + +enum Events +{ + EVENT_NONE, + EVENT_PHANTOM_BLAST, + EVENT_MIRRORED_SOUL, + EVENT_WELL_OF_SOULS, + EVENT_UNLEASHED_SOULS, + EVENT_WAILING_SOULS, + EVENT_WAILING_SOULS_TICK, + EVENT_FACE_ANGER, +}; + +enum eEnum +{ + ACHIEV_THREE_FACED = 4523, + DISPLAY_ANGER = 30148, + DISPLAY_SORROW = 30149, + DISPLAY_DESIRE = 30150, +}; + +struct +{ + uint32 entry[2]; + Position movePosition; +} outroPositions[] = +{ + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5590.47, 2427.79, 705.935, 0.802851 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5593.59, 2428.34, 705.935, 0.977384 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2429.31, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2421.12, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.43, 2426.53, 705.935, 0.890118 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.55, 2418.36, 705.935, 1.15192 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5598, 2429.14, 705.935, 1.0472 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5594.04, 2424.87, 705.935, 1.15192 } }, + { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5597.89, 2421.54, 705.935, 0.610865 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5598.57, 2434.62, 705.935, 1.13446 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5585.46, 2417.99, 705.935, 1.06465 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5605.81, 2428.42, 705.935, 0.820305 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5591.61, 2412.66, 705.935, 0.925025 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5593.9, 2410.64, 705.935, 0.872665 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5586.76, 2416.73, 705.935, 0.942478 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5592.23, 2419.14, 705.935, 0.855211 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5594.61, 2416.87, 705.935, 0.907571 } }, + { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5589.77, 2421.03, 705.935, 0.855211 } }, + + { NPC_KORELN, NPC_LORALEN, { 5602.58, 2435.95, 705.935, 0.959931 } }, + { NPC_ELANDRA, NPC_KALIRA, { 5606.13, 2433.16, 705.935, 0.785398 } }, + { NPC_JAINA_PART2, NPC_SYLVANAS_PART2, { 5606.12, 2436.6, 705.935, 0.890118 } }, + + { 0, 0, { 0, 0, 0, 0 } } +}; + +struct boss_devourer_of_soulsAI : public ScriptedAI +{ + boss_devourer_of_soulsAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + bool bThreeFaceAchievement; + + ScriptedInstance* pInstance; + EventMap events; + + // wailing soul event + float beamAngle; + float beamAngleDiff; + int8 wailingSoulTick; + + uint64 uiMirroredSoulTarget; + + void Reset() + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->SetDisplayId(DISPLAY_ANGER); + me->SetReactState(REACT_AGGRESSIVE); + + events.Reset(); + + bThreeFaceAchievement = true; + uiMirroredSoulTarget = 0; + + if (pInstance) + pInstance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS); + + DoScriptText(RAND(SAY_FACE_ANGER_AGGRO,SAY_FACE_DESIRE_AGGRO), me); + + events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); + events.ScheduleEvent(EVENT_MIRRORED_SOUL, 8000); + events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000); + events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000); + events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + if (uiMirroredSoulTarget && me->HasAura(SPELL_MIRRORED_SOUL)) + { + if (Player *pPlayer = Unit::GetPlayer(uiMirroredSoulTarget)) + { + if (Aura *pAura = pPlayer->GetAura(SPELL_MIRRORED_SOUL)) + { + int32 mirrorDamage = (uiDamage * 45)/100; + me->CastCustomSpell(pPlayer, 69034, &mirrorDamage, 0, 0, true); +// me->DealDamage(pPlayer, (uiDamage * 45)/100, 0, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); + } + else + uiMirroredSoulTarget = 0; + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_FACE_ANGER_SLAY_1,SAY_FACE_SORROW_SLAY_1,SAY_FACE_DESIRE_SLAY_1, + SAY_FACE_ANGER_SLAY_2,SAY_FACE_SORROW_SLAY_2,SAY_FACE_DESIRE_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + Position spawnPoint = { 5618.139, 2451.873, 705.854 }; + + DoScriptText(RAND(SAY_FACE_SORROW_DEATH,SAY_FACE_DESIRE_DEATH), me); + + if (pInstance) + { + pInstance->SetData(DATA_DEVOURER_EVENT, DONE); + + if (bThreeFaceAchievement && IsHeroic()) + pInstance->DoCompleteAchievement(ACHIEV_THREE_FACED); + + int32 entryIndex; + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + entryIndex = 0; + else + entryIndex = 1; + + for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i) + { + if (Creature *pSummon = me->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint, TEMPSUMMON_DEAD_DESPAWN)) + { + pSummon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition); + + if (pSummon->GetEntry() == NPC_JAINA_PART2) + DoScriptText(SAY_JAINA_OUTRO, pSummon); + else if (pSummon->GetEntry() == NPC_SYLVANAS_PART2) + DoScriptText(SAY_SYLVANAS_OUTRO, pSummon); + } + } + } + } + + void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry *pSpell) + { + if (pSpell->Id == H_SPELL_PHANTOM_BLAST) + bThreeFaceAchievement = false; + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_PHANTOM_BLAST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, SPELL_PHANTOM_BLAST); + events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); + break; + case EVENT_MIRRORED_SOUL: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) + { + uiMirroredSoulTarget = pTarget->GetGUID(); + DoCast(pTarget, SPELL_MIRRORED_SOUL); + DoScriptText(EMOTE_MIRRORED_SOUL, me); + } + events.ScheduleEvent(EVENT_MIRRORED_SOUL, urand(15000,30000)); + break; + case EVENT_WELL_OF_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_WELL_OF_SOULS); + events.ScheduleEvent(EVENT_WELL_OF_SOULS, 20000); + break; + case EVENT_UNLEASHED_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_UNLEASHED_SOULS); + me->SetDisplayId(DISPLAY_SORROW); + DoScriptText(RAND(SAY_FACE_ANGER_UNLEASH_SOUL,SAY_FACE_SORROW_UNLEASH_SOUL,SAY_FACE_DESIRE_UNLEASH_SOUL), me); + DoScriptText(EMOTE_UNLEASH_SOUL, me); + events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 30000); + events.ScheduleEvent(EVENT_FACE_ANGER, 5000); + break; + case EVENT_FACE_ANGER: + me->SetDisplayId(DISPLAY_ANGER); + break; + + case EVENT_WAILING_SOULS: + me->SetDisplayId(DISPLAY_DESIRE); + DoScriptText(RAND(SAY_FACE_ANGER_WAILING_SOUL,SAY_FACE_DESIRE_WAILING_SOUL), me); + DoScriptText(EMOTE_WAILING_SOUL, me); + DoCast(me, SPELL_WAILING_SOULS_STARTING); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->SetOrientation(me->GetAngle(pTarget)); + DoCast(me, SPELL_WAILING_SOULS_BEAM); + } + + beamAngle = me->GetOrientation(); + + beamAngleDiff = PI/30.0f; // PI/2 in 15 sec = PI/30 per tick + if (RAND(true,false)) + beamAngleDiff = -beamAngleDiff; + + me->InterruptNonMeleeSpells(false); + me->SetReactState(REACT_PASSIVE); + + //Remove any target + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + me->GetMotionMaster()->Clear(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + + wailingSoulTick = 15; + events.DelayEvents(18000); // no other events during wailing souls + events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3000); // first one after 3 secs. + break; + + case EVENT_WAILING_SOULS_TICK: + beamAngle += beamAngleDiff; + me->SetOrientation(beamAngle); + me->StopMoving(); + + DoCast(me, SPELL_WAILING_SOULS); + + if (--wailingSoulTick) + events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 1000); + else + { + me->SetReactState(REACT_AGGRESSIVE); + me->SetDisplayId(DISPLAY_ANGER); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); + me->GetMotionMaster()->MoveChase(me->getVictim()); + events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); + } + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_devourer_of_souls(Creature* pCreature) +{ + return new boss_devourer_of_soulsAI(pCreature); +} + +void AddSC_boss_devourer_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_devourer_of_souls"; + newscript->GetAI = &GetAI_boss_devourer_of_souls; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp new file mode 100644 index 00000000000..5c85da69898 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.cpp @@ -0,0 +1,899 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +enum Spells +{ + //Spiteful Apparition + SPELL_SPITE = 68895, + H_SPELL_SPITE = 70212, + + //Spectral Warden + SPELL_VEIL_OF_SHADOWS = 69633, + SPELL_WAIL_OF_SOULS = 69148, + H_SPELL_WAIL_OF_SOULS = 70210, + + //Soulguard Watchman + SPELL_SHROUD_OF_RUNES = 69056, + SPELL_UNHOLY_RAGE = 69053, + + //Soulguard Reaper + SPELL_FROST_NOVA = 69060, + H_SPELL_FROST_NOVA = 70209, + SPELL_SHADOW_LANCE = 69058, + + //Soulguard Bonecaster + SPELL_BONE_VOLLEY = 69080, + H_SPELL_BONE_VOLLEY = 70206, + SPELL_RAISE_DEAD = 69562, + SPELL_SHIELD_OF_BONES = 69069, + H_SPELL_SHIELD_OF_BONES = 70207, + + //Soulguard Animator + // Raise dead 69562 + SPELL_SHADOW_BOLT = 69068, + H_SPELL_SHADOW_BOLT = 70208, + SPELL_SOUL_SICKNESS = 69131, + SPELL_SOUL_SIPHON = 69128, + + //Soulguard Adept + //Raise dead 69562 + //Shadow Bolt 69068/70208 + SPELL_DRAIN_LIFE = 69066, + H_SPELL_DRAIN_LIFE = 70213, + SPELL_SHADOW_MEND = 69564, + H_SPELL_SHADOW_MEND = 70205, + + //Soul Horror + SPELL_SOUL_STRIKE = 69088, + H_SPELL_SOUL_STRIKE = 70211, +}; + +enum Events +{ + EVENT_NONE, + + // Jaina/Sylvanas Intro + EVENT_INTRO_1, + EVENT_INTRO_2, + EVENT_INTRO_3, + EVENT_INTRO_4, + EVENT_INTRO_5, + EVENT_INTRO_6, + EVENT_INTRO_7, + EVENT_INTRO_8, + + //Spiteful Apparition + EVENT_SPITE, + + //Spectral Warden + EVENT_VEIL_OF_SHADOWS, + EVENT_WAIL_OF_SOULS, + + //Soulguard Watchman + EVENT_SHROUD_OF_RUNES, + EVENT_UNHOLY_RAGE, + + //Soulguard Reaper + EVENT_FROST_NOVA, + EVENT_SHADOW_LANCE, + + //Soulguard Bonecaster + EVENT_BONE_VOLLEY, + EVENT_RAISE_DEAD, + EVENT_SHIELD_OF_BONES, + + //Soulguard Animator + EVENT_SHADOW_BOLT, + EVENT_SOUL_SICKNESS, + EVENT_SOUL_SIPHON, + + //Soulguard Adept + EVENT_DRAIN_LIFE, + EVENT_SHADOW_MEND, + + //Soul Horror + EVENT_SOUL_STRIKE, +}; + +/****************************************SYLVANAS************************************/ +#define GOSSIP_SYLVANAS_ITEM "What would you have of me, Banshee Queen?" +#define GOSSIP_JAINA_ITEM "What would you have of me, my lady?" + +enum Yells +{ + SAY_JAINA_INTRO_1 = -1632040, + SAY_JAINA_INTRO_2 = -1632041, + SAY_JAINA_INTRO_3 = -1632042, + SAY_JAINA_INTRO_4 = -1632043, + SAY_JAINA_INTRO_5 = -1632044, + SAY_JAINA_INTRO_6 = -1632045, + SAY_JAINA_INTRO_7 = -1632046, + SAY_JAINA_INTRO_8 = -1632047, + + SAY_SYLVANAS_INTRO_1 = -1632050, + SAY_SYLVANAS_INTRO_2 = -1632051, + SAY_SYLVANAS_INTRO_3 = -1632052, + SAY_SYLVANAS_INTRO_4 = -1632053, + SAY_SYLVANAS_INTRO_5 = -1632054, + SAY_SYLVANAS_INTRO_6 = -1632055, +}; + +enum eSylvanas +{ + GOSSIP_SPEECHINTRO = 13525, + ACTION_INTRO, +}; + +enum Phase +{ + PHASE_NORMAL, + PHASE_INTRO, +}; + +struct npc_sylvanas_fosAI: public ScriptedAI +{ + npc_sylvanas_fosAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + ScriptedInstance* pInstance; + + EventMap events; + Phase phase; + + void Reset() + { + events.Reset(); + phase = PHASE_NORMAL; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_INTRO: + { + phase = PHASE_INTRO; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.Reset(); + events.ScheduleEvent(EVENT_INTRO_1, 1000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_INTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_INTRO_1: + DoScriptText(SAY_SYLVANAS_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_2, 11500); + break; + + case EVENT_INTRO_2: + DoScriptText(SAY_SYLVANAS_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_3, 10500); + break; + + case EVENT_INTRO_3: + DoScriptText(SAY_SYLVANAS_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_4, 9500); + break; + + case EVENT_INTRO_4: + DoScriptText(SAY_SYLVANAS_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_5, 10500); + break; + + case EVENT_INTRO_5: + DoScriptText(SAY_SYLVANAS_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_6, 9500); + break; + + case EVENT_INTRO_6: + DoScriptText(SAY_SYLVANAS_INTRO_6, me); + // End of Intro + phase = PHASE_NORMAL; + break; + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + //if (me->hasUnitState(UNIT_STAT_CASTING)) + // return; + + //while (uint32 eventId = events.ExecuteEvent()) + //{ + // switch(eventId) + // { + // } + //} + + DoMeleeAttackIfReady(); + } +}; + +struct npc_jaina_fosAI: public ScriptedAI +{ + npc_jaina_fosAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + ScriptedInstance* pInstance; + + EventMap events; + Phase phase; + + void Reset() + { + events.Reset(); + phase = PHASE_NORMAL; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_INTRO: + { + phase = PHASE_INTRO; + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + events.Reset(); + events.ScheduleEvent(EVENT_INTRO_1, 1000); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_INTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_INTRO_1: + DoScriptText(SAY_JAINA_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_2, 8000); + break; + + case EVENT_INTRO_2: + DoScriptText(SAY_JAINA_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_3, 8500); + break; + + case EVENT_INTRO_3: + DoScriptText(SAY_JAINA_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_4, 8000); + break; + + case EVENT_INTRO_4: + DoScriptText(SAY_JAINA_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_5, 10000); + break; + + case EVENT_INTRO_5: + DoScriptText(SAY_JAINA_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_6, 8000); + break; + + case EVENT_INTRO_6: + DoScriptText(SAY_JAINA_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_7, 12000); + break; + + case EVENT_INTRO_7: + DoScriptText(SAY_JAINA_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_8, 8000); + break; + + case EVENT_INTRO_8: + DoScriptText(SAY_JAINA_INTRO_8, me); + // End of Intro + phase = PHASE_NORMAL; + break; + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + //if (me->hasUnitState(UNIT_STAT_CASTING)) + // return; + + //while (uint32 eventId = events.ExecuteEvent()) + //{ + // switch(eventId) + // { + // } + //} + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->GetEntry() == NPC_JAINA_PART1) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_JAINA_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + else + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SYLVANAS_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_INTRO); + break; + } + + return true; +} + +struct mob_spiteful_apparitionAI: public ScriptedAI +{ + mob_spiteful_apparitionAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SPITE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SPITE: + DoCast(me->getVictim(), SPELL_SPITE); + events.RescheduleEvent(EVENT_SPITE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_spectral_wardenAI: public ScriptedAI +{ + mob_spectral_wardenAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_VEIL_OF_SHADOWS, 5000); + events.ScheduleEvent(EVENT_WAIL_OF_SOULS, 10000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_VEIL_OF_SHADOWS: + DoCast(me->getVictim(), SPELL_VEIL_OF_SHADOWS); + events.RescheduleEvent(EVENT_VEIL_OF_SHADOWS, 10000); + return; + case EVENT_WAIL_OF_SOULS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_WAIL_OF_SOULS); + events.RescheduleEvent(EVENT_WAIL_OF_SOULS, 5000); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_watchmanAI: public ScriptedAI +{ + mob_soulguard_watchmanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHROUD_OF_RUNES, 1000); + events.ScheduleEvent(EVENT_UNHOLY_RAGE, 1000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHROUD_OF_RUNES: + DoCast(me, SPELL_SHROUD_OF_RUNES); + events.RescheduleEvent(EVENT_SHROUD_OF_RUNES, 5000); + return; + case EVENT_UNHOLY_RAGE: + DoCast(me, SPELL_UNHOLY_RAGE); + events.RescheduleEvent(EVENT_UNHOLY_RAGE, 99999); + return; + } + } + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_reaperAI: public ScriptedAI +{ + mob_soulguard_reaperAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROST_NOVA, 8000); + events.ScheduleEvent(EVENT_SHADOW_LANCE, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROST_NOVA: + DoCast(me, SPELL_FROST_NOVA); + events.RescheduleEvent(EVENT_FROST_NOVA, 9600); + return; + case EVENT_SHADOW_LANCE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_LANCE); + events.RescheduleEvent(EVENT_SHADOW_LANCE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_bonecasterAI: public ScriptedAI +{ + mob_soulguard_bonecasterAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BONE_VOLLEY, 6000); + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHIELD_OF_BONES, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BONE_VOLLEY: + DoCastAOE(SPELL_BONE_VOLLEY); + events.RescheduleEvent(EVENT_BONE_VOLLEY, 7000); + return; + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHIELD_OF_BONES: + DoCast(me, SPELL_SHIELD_OF_BONES); + events.RescheduleEvent(EVENT_SHIELD_OF_BONES, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_animatorAI: public ScriptedAI +{ + mob_soulguard_animatorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 5000); + events.ScheduleEvent(EVENT_SOUL_SICKNESS, 8000); + events.ScheduleEvent(EVENT_SOUL_SIPHON, 10000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); + return; + case EVENT_SOUL_SICKNESS: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SOUL_SICKNESS); + events.RescheduleEvent(EVENT_SOUL_SICKNESS, 10000); + return; + case EVENT_SOUL_SIPHON: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SOUL_SIPHON); + events.RescheduleEvent(EVENT_SOUL_SIPHON, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soulguard_adeptAI: public ScriptedAI +{ + mob_soulguard_adeptAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 8000); + events.ScheduleEvent(EVENT_DRAIN_LIFE, 7000); + events.ScheduleEvent(EVENT_SHADOW_MEND, 35000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_RAISE_DEAD: + DoCast(me, SPELL_RAISE_DEAD); + events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); + return; + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 4000); + return; + case EVENT_DRAIN_LIFE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DRAIN_LIFE); + events.RescheduleEvent(EVENT_DRAIN_LIFE, 9000); + return; + case EVENT_SHADOW_MEND: + DoCast(me, SPELL_SHADOW_MEND); + events.RescheduleEvent(EVENT_SHADOW_MEND, 20000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_soul_horrorAI: public ScriptedAI +{ + mob_soul_horrorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SOUL_STRIKE, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SOUL_STRIKE: + DoCast(me->getVictim(), SPELL_SOUL_STRIKE); + events.RescheduleEvent(EVENT_SOUL_STRIKE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_jaina_fosAI(Creature* pCreature) +{ + return new npc_jaina_fosAI(pCreature); +}; + +CreatureAI* GetAI_npc_sylvanas_fosAI(Creature* pCreature) +{ + return new npc_sylvanas_fosAI(pCreature); +}; + +CreatureAI* GetAI_mob_spiteful_apparitionAI(Creature* pCreature) +{ + return new mob_spiteful_apparitionAI(pCreature); +} + +CreatureAI* GetAI_mob_spectral_wardenAI(Creature* pCreature) +{ + return new mob_spectral_wardenAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_watchmanAI(Creature* pCreature) +{ + return new mob_soulguard_watchmanAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_reaperAI(Creature* pCreature) +{ + return new mob_soulguard_reaperAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_bonecasterAI(Creature* pCreature) +{ + return new mob_soulguard_bonecasterAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_animatorAI(Creature* pCreature) +{ + return new mob_soulguard_animatorAI(pCreature); +} + +CreatureAI* GetAI_mob_soulguard_adeptAI(Creature* pCreature) +{ + return new mob_soulguard_adeptAI(pCreature); +} + +CreatureAI* GetAI_mob_soul_horrorAI(Creature* pCreature) +{ + return new mob_soul_horrorAI(pCreature); +} + +void AddSC_forge_of_souls() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sylvanas_fos"; + newscript->GetAI = &GetAI_npc_sylvanas_fosAI; + newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_fos"; + newscript->GetAI = &GetAI_npc_jaina_fosAI; + newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_spiteful_apparition"; + newscript->GetAI = &GetAI_mob_spiteful_apparitionAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_spectral_warden"; + newscript->GetAI = &GetAI_mob_spectral_wardenAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_watchman"; + newscript->GetAI = &GetAI_mob_soulguard_watchmanAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_reaper"; + newscript->GetAI = &GetAI_mob_soulguard_reaperAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_bonecaster"; + newscript->GetAI = &GetAI_mob_soulguard_bonecasterAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_animator"; + newscript->GetAI = &GetAI_mob_soulguard_animatorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soulguard_adept"; + newscript->GetAI = &GetAI_mob_soulguard_adeptAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_soul_horror"; + newscript->GetAI = &GetAI_mob_soul_horrorAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h new file mode 100644 index 00000000000..e0479eb4d2b --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/forge_of_souls.h @@ -0,0 +1,52 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_FORGE_OF_SOULS_H +#define DEF_FORGE_OF_SOULS_H + +enum Data +{ + DATA_BRONJAHM_EVENT, + DATA_DEVOURER_EVENT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_BRONJAHM, + DATA_DEVOURER, +}; + +enum Creatures +{ + CREATURE_BRONJAHM = 36497, + CREATURE_DEVOURER = 36502, + + NPC_SYLVANAS_PART1 = 37596, + NPC_SYLVANAS_PART2 = 38161, + NPC_JAINA_PART1 = 37597, + NPC_JAINA_PART2 = 38160, + NPC_KALIRA = 37583, + NPC_ELANDRA = 37774, + NPC_LORALEN = 37779, + NPC_KORELN = 37582, + NPC_CHAMPION_1_HORDE = 37584, + NPC_CHAMPION_2_HORDE = 37587, + NPC_CHAMPION_3_HORDE = 37588, + NPC_CHAMPION_1_ALLIANCE = 37496, + NPC_CHAMPION_2_ALLIANCE = 37497, +}; +#endif diff --git a/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp new file mode 100644 index 00000000000..67a6cdb4579 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/ForgeOfSouls/instance_forge_of_souls.cpp @@ -0,0 +1,168 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "forge_of_souls.h" + +#define MAX_ENCOUNTER 2 + +/* Forge of Souls encounters: +0- Bronjahm, The Godfather of Souls +1- The Devourer of Souls +*/ + +struct instance_forge_of_souls : public ScriptedInstance +{ + instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiBronjahm; + uint64 uiDevourer; + + uint32 uiEncounter[MAX_ENCOUNTER]; + uint32 uiTeamInInstance; + + void Initialize() + { + uiBronjahm = 0; + uiDevourer = 0; + + uiTeamInInstance = 0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + + if (!players.isEmpty()) + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + + switch(pCreature->GetEntry()) + { + case CREATURE_BRONJAHM: + uiBronjahm = pCreature->GetGUID(); + break; + case CREATURE_DEVOURER: + uiDevourer = pCreature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_BRONJAHM_EVENT: + uiEncounter[0] = data; + break; + case DATA_DEVOURER_EVENT: + uiEncounter[1] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_BRONJAHM_EVENT: return uiEncounter[0]; + case DATA_DEVOURER_EVENT: return uiEncounter[1]; + case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_BRONJAHM: return uiBronjahm; + case DATA_DEVOURER: return uiBronjahm; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "F S " << uiEncounter[0] << " " << uiEncounter[1]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; + + if (dataHead1 == 'F' && dataHead2 == 'S') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap) +{ + return new instance_forge_of_souls(pMap); +} + +void AddSC_instance_forge_of_souls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_forge_of_souls"; + newscript->GetInstanceData = &GetInstanceData_instance_forge_of_souls; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp new file mode 100644 index 00000000000..c9978faca6e --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_falric.cpp @@ -0,0 +1,142 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_AGGRO = -1668050, + SAY_SLAY_1 = -1668051, + SAY_SLAY_2 = -1668052, + SAY_DEATH = -1668053, + SAY_IMPENDING_DESPAIR = -1668054, + SAY_DEFILING_HORROR = -1668055, +}; + +enum Spells +{ + SPELL_QUIVERING_STRIKE = 72422, + SPELL_IMPENDING_DESPAIR = 72426, + SPELL_DEFILING_HORROR = 72435, + SPELL_HOPELESSNESS = 72395, + H_SPELL_HOPELESSNESS = 72390, // TODO: not in dbc. Add in DB. +}; + +enum Events +{ + EVENT_NONE, + EVENT_QUIVERING_STRIKE, + EVENT_IMPENDING_DESPAIR, + EVENT_DEFILING_HORROR, +}; + +struct boss_falricAI : public boss_horAI +{ + boss_falricAI(Creature *pCreature) : boss_horAI(pCreature) {} + + uint8 uiHopelessnessCount; + + void Reset() + { + boss_horAI::Reset(); + + uiHopelessnessCount = 0; + + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000); + events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000); + events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FALRIC_EVENT, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_QUIVERING_STRIKE: + DoCast(SPELL_QUIVERING_STRIKE); + events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000); + break; + case EVENT_IMPENDING_DESPAIR: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + { + DoScriptText(SAY_IMPENDING_DESPAIR, me); + DoCast(pTarget, SPELL_IMPENDING_DESPAIR); + } + events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000); + break; + case EVENT_DEFILING_HORROR: + DoCast(SPELL_DEFILING_HORROR); + events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. + break; + } + + if ((uiHopelessnessCount < 1 && HealthBelowPct(66)) + || (uiHopelessnessCount < 2 && HealthBelowPct(33)) + || (uiHopelessnessCount < 3 && HealthBelowPct(10))) + { + uiHopelessnessCount++; + DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS,H_SPELL_HOPELESSNESS)); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_falric(Creature* pCreature) +{ + return new boss_falricAI(pCreature); +} + +void AddSC_boss_falric() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_falric"; + newscript->GetAI = &GetAI_boss_falric; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp new file mode 100644 index 00000000000..95fb2737ce9 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/boss_marwyn.cpp @@ -0,0 +1,133 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_AGGRO = -1668060, + SAY_SLAY_1 = -1668061, + SAY_SLAY_2 = -1668062, + SAY_DEATH = -1668063, + SAY_CORRUPTED_FLESH_1 = -1668064, + SAY_CORRUPTED_FLESH_2 = -1668065, +}; + +enum Spells +{ + SPELL_OBLITERATE = 72360, + SPELL_WELL_OF_CORRUPTION = 72362, + SPELL_CORRUPTED_FLESH = 72363, + SPELL_SHARED_SUFFERING = 72368, +}; + +enum Events +{ + EVENT_NONE, + EVENT_OBLITERATE, + EVENT_WELL_OF_CORRUPTION, + EVENT_CORRUPTED_FLESH, + EVENT_SHARED_SUFFERING, +}; + +struct boss_marwynAI : public boss_horAI +{ + boss_marwynAI(Creature *pCreature) : boss_horAI(pCreature) {} + + void Reset() + { + boss_horAI::Reset(); + + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_OBLITERATE, 30000); // TODO Check timer + events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); + events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); + events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); // TODO Check timer + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MARWYN_EVENT, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + // Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch (events.ExecuteEvent()) + { + case EVENT_OBLITERATE: + DoCast(SPELL_OBLITERATE); + events.ScheduleEvent(EVENT_OBLITERATE, 30000); + break; + case EVENT_WELL_OF_CORRUPTION: + DoCast(SPELL_WELL_OF_CORRUPTION); + events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); + break; + case EVENT_CORRUPTED_FLESH: + DoScriptText(RAND(SAY_CORRUPTED_FLESH_1,SAY_CORRUPTED_FLESH_2), me); + DoCast(SPELL_CORRUPTED_FLESH); + events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); + break; + case EVENT_SHARED_SUFFERING: + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHARED_SUFFERING); + events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_marwyn(Creature* pCreature) +{ + return new boss_marwynAI(pCreature); +} + +void AddSC_boss_marwyn() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_marwyn"; + newscript->GetAI = &GetAI_boss_marwyn; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp new file mode 100644 index 00000000000..fb3d3d5d752 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -0,0 +1,1022 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +enum Yells +{ + SAY_JAINA_INTRO_1 = -1668001, + SAY_JAINA_INTRO_2 = -1668002, + SAY_JAINA_INTRO_3 = -1668003, + SAY_JAINA_INTRO_4 = -1668004, + SAY_UTHER_INTRO_A2_1 = -1668005, + SAY_JAINA_INTRO_5 = -1668006, + SAY_UTHER_INTRO_A2_2 = -1668007, + SAY_JAINA_INTRO_6 = -1668008, + SAY_UTHER_INTRO_A2_3 = -1668009, + SAY_JAINA_INTRO_7 = -1668010, + SAY_UTHER_INTRO_A2_4 = -1668011, + SAY_JAINA_INTRO_8 = -1668012, + SAY_UTHER_INTRO_A2_5 = -1668013, + SAY_JAINA_INTRO_9 = -1668014, + SAY_UTHER_INTRO_A2_6 = -1668015, + SAY_UTHER_INTRO_A2_7 = -1668016, + SAY_JAINA_INTRO_10 = -1668017, + SAY_UTHER_INTRO_A2_8 = -1668018, + SAY_JAINA_INTRO_11 = -1668019, + SAY_UTHER_INTRO_A2_9 = -1668020, + + SAY_SYLVANAS_INTRO_1 = -1668021, + SAY_SYLVANAS_INTRO_2 = -1668022, + SAY_SYLVANAS_INTRO_3 = -1668023, + SAY_UTHER_INTRO_H2_1 = -1668024, + SAY_SYLVANAS_INTRO_4 = -1668025, + SAY_UTHER_INTRO_H2_2 = -1668026, + SAY_SYLVANAS_INTRO_5 = -1668027, + SAY_UTHER_INTRO_H2_3 = -1668028, + SAY_SYLVANAS_INTRO_6 = -1668029, + SAY_UTHER_INTRO_H2_4 = -1668030, + SAY_SYLVANAS_INTRO_7 = -1668031, + SAY_UTHER_INTRO_H2_5 = -1668032, + SAY_UTHER_INTRO_H2_6 = -1668033, + SAY_SYLVANAS_INTRO_8 = -1668034, + SAY_UTHER_INTRO_H2_7 = -1668035, + + SAY_LK_INTRO_1 = -1668036, + SAY_LK_INTRO_2 = -1668037, + SAY_LK_INTRO_3 = -1668038, + SAY_FALRIC_INTRO_1 = -1668039, + SAY_MARWYN_INTRO_1 = -1668040, + SAY_FALRIC_INTRO_2 = -1668041, + + SAY_JAINA_INTRO_END = -1668042, + SAY_SYLVANAS_INTRO_END = -1668043, +}; + +enum Events +{ + EVENT_NONE, + + EVENT_START_INTRO, + EVENT_SKIP_INTRO, + + EVENT_INTRO_A2_1, + EVENT_INTRO_A2_2, + EVENT_INTRO_A2_3, + EVENT_INTRO_A2_4, + EVENT_INTRO_A2_5, + EVENT_INTRO_A2_6, + EVENT_INTRO_A2_7, + EVENT_INTRO_A2_8, + EVENT_INTRO_A2_9, + EVENT_INTRO_A2_10, + EVENT_INTRO_A2_11, + EVENT_INTRO_A2_12, + EVENT_INTRO_A2_13, + EVENT_INTRO_A2_14, + EVENT_INTRO_A2_15, + EVENT_INTRO_A2_16, + EVENT_INTRO_A2_17, + EVENT_INTRO_A2_18, + EVENT_INTRO_A2_19, + + EVENT_INTRO_H2_1, + EVENT_INTRO_H2_2, + EVENT_INTRO_H2_3, + EVENT_INTRO_H2_4, + EVENT_INTRO_H2_5, + EVENT_INTRO_H2_6, + EVENT_INTRO_H2_7, + EVENT_INTRO_H2_8, + EVENT_INTRO_H2_9, + EVENT_INTRO_H2_10, + EVENT_INTRO_H2_11, + EVENT_INTRO_H2_12, + EVENT_INTRO_H2_13, + EVENT_INTRO_H2_14, + EVENT_INTRO_H2_15, + + EVENT_INTRO_LK_1, + EVENT_INTRO_LK_2, + EVENT_INTRO_LK_3, + EVENT_INTRO_LK_4, + EVENT_INTRO_LK_5, + EVENT_INTRO_LK_6, + EVENT_INTRO_LK_7, + EVENT_INTRO_LK_8, + EVENT_INTRO_LK_9, + + EVENT_INTRO_END, +}; + +enum eEnum +{ + ACTION_START_INTRO, + ACTION_SKIP_INTRO, + + QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710, + QUEST_DELIVRANCE_FROM_THE_PIT_H2 = 24712, + QUEST_WRATH_OF_THE_LICH_KING_A2 = 24500, + QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802, +}; + +static Position HallsofReflectionLocs[]= +{ + {5283.234863, 1990.946777, 707.695679, 0.929097}, // 2 Loralen Follows + {5408.031250, 2102.918213, 707.695251, 0.792756}, // 9 Sylvanas Follows + {5401.866699, 2110.837402, 707.695251, 0.800610}, // 10 Loralen follows +}; + +static Position SpawnPos = {5262.540527, 1949.693726, 707.695007, 0.808736}; // Jaina/Sylvanas Beginning Position +static Position MoveThronePos = {5306.952148, 1998.499023, 709.341431, 1.277278}; // Jaina/Sylvanas walks to throne +static Position UtherSpawnPos = {5308.310059, 2003.857178, 709.341431, 4.650315}; +static Position LichKingSpawnPos = {5362.917480, 2062.307129, 707.695374, 3.945812}; +static Position LichKingMoveThronePos = {5312.080566, 2009.172119, 709.341431, 3.973301}; // Lich King walks to throne +static Position LichKingMoveAwayPos = {5400.069824, 2102.7131689, 707.69525, 0.843803}; // Lich King walks away + +// AI of Part1: handle the intro till start of gauntlet event. +struct npc_jaina_or_sylvanas_horAI : public ScriptedAI +{ + npc_jaina_or_sylvanas_horAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint64 uiUther; + uint64 uiLichKing; + + EventMap events; + + void Reset() + { + events.Reset(); + + uiUther = 0; + uiLichKing = 0; + + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetVisibility(VISIBILITY_ON); + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_START_INTRO: + events.ScheduleEvent(EVENT_START_INTRO, 0); + break; + case ACTION_SKIP_INTRO: + events.ScheduleEvent(EVENT_SKIP_INTRO, 0); + break; + } + } + + void UpdateAI(const uint32 diff) + { + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_START_INTRO: + me->GetMotionMaster()->MovePoint(0, MoveThronePos); + // Begining of intro is differents between factions as the speech sequence and timers are differents. + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + events.ScheduleEvent(EVENT_INTRO_A2_1, 0); + else + events.ScheduleEvent(EVENT_INTRO_H2_1, 0); + break; + + // A2 Intro Events + case EVENT_INTRO_A2_1: + DoScriptText(SAY_JAINA_INTRO_3, me); + events.ScheduleEvent(EVENT_INTRO_A2_2, 5000); + break; + case EVENT_INTRO_A2_2: + DoScriptText(SAY_JAINA_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_A2_3, 10000); + break; + case EVENT_INTRO_A2_3: + // TODO: she's doing some kind of spell casting emote + pInstance->HandleGameObject(pInstance->GetData64(DATA_FROSTMOURNE), true); + events.ScheduleEvent(EVENT_INTRO_A2_4, 10000); + break; + case EVENT_INTRO_A2_4: + // spawn UTHER during speach 2 + if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pUther->GetMotionMaster()->MoveIdle(); + pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas + uiUther = pUther->GetGUID(); + } + events.ScheduleEvent(EVENT_INTRO_A2_5, 2000); + break; + case EVENT_INTRO_A2_5: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_1, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_6, 3000); + break; + case EVENT_INTRO_A2_6: + DoScriptText(SAY_JAINA_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_A2_7, 6000); + break; + case EVENT_INTRO_A2_7: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_2, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_8, 6500); + break; + case EVENT_INTRO_A2_8: + DoScriptText(SAY_JAINA_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_A2_9, 2000); + break; + case EVENT_INTRO_A2_9: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_3, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_10, 9000); + break; + case EVENT_INTRO_A2_10: + DoScriptText(SAY_JAINA_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_A2_11, 5000); + break; + case EVENT_INTRO_A2_11: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_4, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_12, 11000); + break; + case EVENT_INTRO_A2_12: + DoScriptText(SAY_JAINA_INTRO_8, me); + events.ScheduleEvent(EVENT_INTRO_A2_13, 4000); + break; + case EVENT_INTRO_A2_13: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_5, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_14, 12500); + break; + case EVENT_INTRO_A2_14: + DoScriptText(SAY_JAINA_INTRO_9, me); + events.ScheduleEvent(EVENT_INTRO_A2_15, 10000); + break; + case EVENT_INTRO_A2_15: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_6, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_16, 22000); + break; + case EVENT_INTRO_A2_16: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_A2_7, pUther); + events.ScheduleEvent(EVENT_INTRO_A2_17, 4000); + break; + case EVENT_INTRO_A2_17: + DoScriptText(SAY_JAINA_INTRO_10, me); + events.ScheduleEvent(EVENT_INTRO_A2_18, 2000); + break; + case EVENT_INTRO_A2_18: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); + DoScriptText(SAY_UTHER_INTRO_A2_8, pUther); + } + events.ScheduleEvent(EVENT_INTRO_A2_19, 11000); + break; + case EVENT_INTRO_A2_19: + DoScriptText(SAY_JAINA_INTRO_11, me); + events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + break; + + // H2 Intro Events + case EVENT_INTRO_H2_1: + DoScriptText(SAY_SYLVANAS_INTRO_1, me); + events.ScheduleEvent(EVENT_INTRO_H2_2, 8000); + break; + case EVENT_INTRO_H2_2: + DoScriptText(SAY_SYLVANAS_INTRO_2, me); + events.ScheduleEvent(EVENT_INTRO_H2_3, 6000); + break; + case EVENT_INTRO_H2_3: + DoScriptText(SAY_SYLVANAS_INTRO_3, me); + // TODO: she's doing some kind of spell casting emote + events.ScheduleEvent(EVENT_INTRO_H2_4, 6000); + break; + case EVENT_INTRO_H2_4: + // spawn UTHER during speach 2 + if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pUther->GetMotionMaster()->MoveIdle(); + pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas + uiUther = pUther->GetGUID(); + } + events.ScheduleEvent(EVENT_INTRO_H2_5, 2000); + break; + case EVENT_INTRO_H2_5: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_1, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_6, 11000); + break; + case EVENT_INTRO_H2_6: + DoScriptText(SAY_SYLVANAS_INTRO_4, me); + events.ScheduleEvent(EVENT_INTRO_H2_7, 3000); + break; + case EVENT_INTRO_H2_7: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_2, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_8, 6000); + break; + case EVENT_INTRO_H2_8: + DoScriptText(SAY_SYLVANAS_INTRO_5, me); + events.ScheduleEvent(EVENT_INTRO_H2_9, 5000); + break; + case EVENT_INTRO_H2_9: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_3, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_10, 19000); + break; + case EVENT_INTRO_H2_10: + DoScriptText(SAY_SYLVANAS_INTRO_6, me); + events.ScheduleEvent(EVENT_INTRO_H2_11, 1500); + break; + case EVENT_INTRO_H2_11: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_4, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_12, 19500); + break; + case EVENT_INTRO_H2_12: + DoScriptText(SAY_SYLVANAS_INTRO_7, me); + events.ScheduleEvent(EVENT_INTRO_H2_13, 2000); + break; + case EVENT_INTRO_H2_13: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); + DoScriptText(SAY_UTHER_INTRO_H2_5, pUther); + } + events.ScheduleEvent(EVENT_INTRO_H2_14, 12000); + break; + case EVENT_INTRO_H2_14: + if (Creature* pUther = me->GetCreature(*me, uiUther)) + DoScriptText(SAY_UTHER_INTRO_H2_6, pUther); + events.ScheduleEvent(EVENT_INTRO_H2_15, 8000); + break; + case EVENT_INTRO_H2_15: + DoScriptText(SAY_SYLVANAS_INTRO_8, me); + events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); + break; + + // Remaining Intro Events common for both faction + case EVENT_INTRO_LK_1: + // Spawn LK in front of door, and make him move to the sword. + if (Creature* pLichKing = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pLichKing->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); + pLichKing->SetReactState(REACT_PASSIVE); + uiLichKing = pLichKing->GetGUID(); + } + + if (Creature* pUther = me->GetCreature(*me, uiUther)) + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + DoScriptText(SAY_UTHER_INTRO_A2_9, pUther); + else + DoScriptText(SAY_UTHER_INTRO_H2_7, pUther); + + events.ScheduleEvent(EVENT_INTRO_LK_2, 11000); + break; + + case EVENT_INTRO_LK_2: + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + DoScriptText(SAY_LK_INTRO_1, pLichKing); + events.ScheduleEvent(EVENT_INTRO_LK_3, 2000); + break; + + case EVENT_INTRO_LK_3: + // The Lich King banishes Uther to the abyss. + if (Creature* pUther = me->GetCreature(*me, uiUther)) + { + pUther->DisappearAndDie(); + uiUther = 0; + } + + // He steps forward and removes the runeblade from the heap of skulls. + + events.ScheduleEvent(EVENT_INTRO_LK_4, 4000); + break; + + case EVENT_INTRO_LK_4: + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + DoScriptText(SAY_LK_INTRO_2, pLichKing); + events.ScheduleEvent(EVENT_INTRO_LK_5, 10000); + break; + + case EVENT_INTRO_LK_5: + // summon Falric and Marwyn. then go back to the door + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + pFalric->SetVisibility(VISIBILITY_ON); + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + pMarwyn->SetVisibility(VISIBILITY_ON); + + if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) + { + pLichKing->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + DoScriptText(SAY_LK_INTRO_3, pLichKing); + } + + events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); + break; + + case EVENT_INTRO_LK_6: + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + DoScriptText(SAY_FALRIC_INTRO_1, pFalric); + + events.ScheduleEvent(EVENT_INTRO_LK_7, 2000); + break; + + case EVENT_INTRO_LK_7: + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + DoScriptText(SAY_MARWYN_INTRO_1, pMarwyn); + + events.ScheduleEvent(EVENT_INTRO_LK_8, 2000); + break; + + case EVENT_INTRO_LK_8: + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + DoScriptText(SAY_FALRIC_INTRO_2, pFalric); + + events.ScheduleEvent(EVENT_INTRO_LK_9, 5000); + break; + + case EVENT_INTRO_LK_9: + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) + DoScriptText(SAY_JAINA_INTRO_END, me); + else + DoScriptText(SAY_SYLVANAS_INTRO_END, me); + + me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + // TODO: Loralen/Koreln shall run also + events.ScheduleEvent(EVENT_INTRO_END, 10000); + break; + + case EVENT_INTRO_END: + if (pInstance) + pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave + + // Loralen or Koreln disappearAndDie() + me->DisappearAndDie(); + break; + + case EVENT_SKIP_INTRO: + // TODO: implement + + if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) + pFalric->SetVisibility(VISIBILITY_ON); + if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) + pMarwyn->SetVisibility(VISIBILITY_ON); + + me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); + // TODO: Loralen/Koreln shall run also + + events.ScheduleEvent(EVENT_INTRO_END, 15000); + break; + } + } +}; + +bool GossipHello_npc_sylvanas_hor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_H2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + // once last quest is completed, she offers this shortcut of the starting event + if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_H2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Dark Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + + return true; +} + +bool GossipHello_npc_jaina_hor(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_A2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + // once last quest of the series is completed, she offers this shortcut of the starting event + if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_A2) == QUEST_STATUS_COMPLETE) + pPlayer->ADD_GOSSIP_ITEM( 0, "My Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_or_sylvanas_hor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_START_INTRO); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + if (pCreature->AI()) + pCreature->AI()->DoAction(ACTION_SKIP_INTRO); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + } + + return true; +} + +enum TrashSpells +{ + // Ghostly Priest + SPELL_SHADOW_WORD_PAIN = 72318, + SPELL_CIRCLE_OF_DESTRUCTION = 72320, + SPELL_COWER_IN_FEAR = 72321, + SPELL_DARK_MENDING = 72322, + + // Phantom Mage + SPELL_FIREBALL = 72163, + SPELL_FLAMESTRIKE = 72169, + SPELL_FROSTBOLT = 72166, + SPELL_CHAINS_OF_ICE = 72121, + SPELL_HALLUCINATION = 72342, + + // Phantom Hallucination (same as phantom mage + HALLUCINATION_2 when dies) + SPELL_HALLUCINATION_2 = 72344, + + // Shadowy Mercenary + SPELL_SHADOW_STEP = 72326, + SPELL_DEADLY_POISON = 72329, + SPELL_ENVENOMED_DAGGER_THROW = 72333, + SPELL_KIDNEY_SHOT = 72335, + + // Spectral Footman + SPELL_SPECTRAL_STRIKE = 72198, + SPELL_SHIELD_BASH = 72194, + SPELL_TORTURED_ENRAGE = 72203, + + // Tortured Rifleman + SPELL_SHOOT = 72208, + SPELL_CURSED_ARROW = 72222, + SPELL_FROST_TRAP = 72215, + SPELL_ICE_SHOT = 72268, +}; + +enum TrashEvents +{ + EVENT_TRASH_NONE, + + // Ghostly Priest + EVENT_SHADOW_WORD_PAIN, + EVENT_CIRCLE_OF_DESTRUCTION, + EVENT_COWER_IN_FEAR, + EVENT_DARK_MENDING, + + // Phantom Mage + EVENT_FIREBALL, + EVENT_FLAMESTRIKE, + EVENT_FROSTBOLT, + EVENT_CHAINS_OF_ICE, + EVENT_HALLUCINATION, + + // Shadowy Mercenary + EVENT_SHADOW_STEP, + EVENT_DEADLY_POISON, + EVENT_ENVENOMED_DAGGER_THROW, + EVENT_KIDNEY_SHOT, + + // Spectral Footman + EVENT_SPECTRAL_STRIKE, + EVENT_SHIELD_BASH, + EVENT_TORTURED_ENRAGE, + + // Tortured Rifleman + EVENT_SHOOT, + EVENT_CURSED_ARROW, + EVENT_FROST_TRAP, + EVENT_ICE_SHOT, +}; + +struct npc_ghostly_priestAI: public ScriptedAI +{ + npc_ghostly_priestAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); // TODO: adjust timers + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_WORD_PAIN: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); + events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); + return; + case EVENT_CIRCLE_OF_DESTRUCTION: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CIRCLE_OF_DESTRUCTION); + events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); + return; + case EVENT_COWER_IN_FEAR: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_COWER_IN_FEAR); + events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); + return; + case EVENT_DARK_MENDING: + // find an ally with missing HP + if (Unit *pTarget = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000,50000))) + { + DoCast(pTarget, SPELL_DARK_MENDING); + events.ScheduleEvent(EVENT_DARK_MENDING, 20000); + } + else + { + // no friendly unit with missing hp. re-check in just 5 sec. + events.ScheduleEvent(EVENT_DARK_MENDING, 5000); + } + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_phantom_mageAI: public ScriptedAI +{ + npc_phantom_mageAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FIREBALL, 3000); // TODO: adjust timers + events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000); + events.ScheduleEvent(EVENT_FROSTBOLT, 9000); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000); + events.ScheduleEvent(EVENT_HALLUCINATION, 40000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FIREBALL: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_FIREBALL); + events.ScheduleEvent(EVENT_FIREBALL, 15000); + return; + case EVENT_FLAMESTRIKE: + DoCast(SPELL_FLAMESTRIKE); + events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); + return; + case EVENT_FROSTBOLT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_FROSTBOLT); + events.ScheduleEvent(EVENT_FROSTBOLT, 15000); + return; + case EVENT_CHAINS_OF_ICE: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CHAINS_OF_ICE); + events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); + return; + case EVENT_HALLUCINATION: + DoCast(SPELL_HALLUCINATION); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_phantom_hallucinationAI: public npc_phantom_mageAI +{ + npc_phantom_hallucinationAI(Creature *c) : npc_phantom_mageAI(c) + { + } + + void JustDied(Unit * /*pWho*/) + { + DoCast(SPELL_HALLUCINATION_2); + } +}; + +struct npc_shadowy_mercenaryAI: public ScriptedAI +{ + npc_shadowy_mercenaryAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); // TODO: adjust timers + events.ScheduleEvent(EVENT_DEADLY_POISON, 5000); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_STEP: + DoCast(SPELL_SHADOW_STEP); + events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); + return; + case EVENT_DEADLY_POISON: + DoCast(me->getVictim(), SPELL_DEADLY_POISON); + events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); + return; + case EVENT_ENVENOMED_DAGGER_THROW: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_ENVENOMED_DAGGER_THROW); + events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); + return; + case EVENT_KIDNEY_SHOT: + DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); + events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_spectral_footmanAI: public ScriptedAI +{ + npc_spectral_footmanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); // TODO: adjust timers + events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SPECTRAL_STRIKE: + DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); + events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); + return; + case EVENT_SHIELD_BASH: + DoCast(me->getVictim(), SPELL_SHIELD_BASH); + events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); + return; + case EVENT_TORTURED_ENRAGE: + DoCast(SPELL_TORTURED_ENRAGE); + events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct npc_tortured_riflemanAI : public ScriptedAI +{ + npc_tortured_riflemanAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHOOT, 2000); // TODO: adjust timers + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + events.ScheduleEvent(EVENT_FROST_TRAP, 1000); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHOOT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_SHOOT); + events.ScheduleEvent(EVENT_SHOOT, 2000); + return; + case EVENT_CURSED_ARROW: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_CURSED_ARROW); + events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); + return; + case EVENT_FROST_TRAP: + DoCast(SPELL_FROST_TRAP); + events.ScheduleEvent(EVENT_FROST_TRAP, 30000); + return; + case EVENT_ICE_SHOT: + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_ICE_SHOT); + events.ScheduleEvent(EVENT_ICE_SHOT, 15000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_jaina_or_sylvanas_horAI(Creature* pCreature) +{ + return new npc_jaina_or_sylvanas_horAI(pCreature); +} + +CreatureAI* GetAI_npc_ghostly_priestAI(Creature* pCreature) +{ + return new npc_ghostly_priestAI(pCreature); +} + +CreatureAI* GetAI_npc_phantom_mageAI(Creature* pCreature) +{ + return new npc_phantom_mageAI(pCreature); +} + +CreatureAI* GetAI_npc_phantom_hallucinationAI(Creature* pCreature) +{ + return new npc_phantom_hallucinationAI(pCreature); +} + +CreatureAI* GetAI_npc_shadowy_mercenaryAI(Creature* pCreature) +{ + return new npc_shadowy_mercenaryAI(pCreature); +} + +CreatureAI* GetAI_npc_spectral_footmanAI(Creature* pCreature) +{ + return new npc_spectral_footmanAI(pCreature); +} + +CreatureAI* GetAI_npc_tortured_riflemanAI(Creature* pCreature) +{ + return new npc_tortured_riflemanAI(pCreature); +} + +void AddSC_halls_of_reflection() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_sylvanas_hor_part1"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; + newscript->pGossipHello = &GossipHello_npc_sylvanas_hor; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_hor_part1"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; + newscript->pGossipHello = &GossipHello_npc_jaina_hor; + newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_ghostly_priest"; + newscript->GetAI = &GetAI_npc_ghostly_priestAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_phantom_mage"; + newscript->GetAI = &GetAI_npc_phantom_mageAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_phantom_hallucination"; + newscript->GetAI = &GetAI_npc_phantom_hallucinationAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_shadowy_mercenary"; + newscript->GetAI = &GetAI_npc_shadowy_mercenaryAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_spectral_footman"; + newscript->GetAI = &GetAI_npc_spectral_footmanAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tortured_rifleman"; + newscript->GetAI = &GetAI_npc_tortured_riflemanAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h new file mode 100644 index 00000000000..46ae0cb283c --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.h @@ -0,0 +1,156 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_HALLS_OF_REFLECTION_H +#define DEF_HALLS_OF_REFLECTION_H + +enum Data +{ + DATA_FALRIC_EVENT, + DATA_MARWYN_EVENT, + DATA_LICHKING_EVENT, + DATA_WAVE_COUNT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_FALRIC, + DATA_MARWYN, + DATA_LICHKING, + DATA_FROSTMOURNE, +}; + +enum Creatures +{ + NPC_FALRIC = 38112, + NPC_MARWYN = 38113, + NPC_LICH_KING_EVENT = 37226, + NPC_LICH_KING_BOSS = 36954, + + NPC_UTHER = 37225, + NPC_JAINA_PART1 = 37221, + NPC_JAINA_PART2 = 36955, + NPC_SYLVANAS_PART1 = 37223, + NPC_SYLVANAS_PART2 = 37554, + + NPC_WAVE_MERCENARY = 38177, + NPC_WAVE_FOOTMAN = 38173, + NPC_WAVE_RIFLEMAN = 38176, + NPC_WAVE_PRIEST = 38175, + NPC_WAVE_MAGE = 38172, +}; + +enum GameObjects +{ + GO_FROSTMOURNE = 202302, + GO_FROSTMOURNE_ALTAR = 202236, + GO_FRONT_DOOR = 201976, + GO_ARTHAS_DOOR = 197341, +}; + +enum HorWorldStates +{ + WORLD_STATE_HOR = 4884, + WORLD_STATE_HOR_WAVE_COUNT = 4882, +}; + +// Common actions from Instance Script to Boss Script +enum Actions +{ + ACTION_ENTER_COMBAT, +}; + +// Base class for FALRIC and MARWYN +// handled the summonList and the notification events to/from the InstanceData +struct boss_horAI : ScriptedAI +{ + boss_horAI(Creature *pCreature) : ScriptedAI(pCreature), summons(pCreature) + { + pInstance = me->GetInstanceData(); + } + + InstanceData* pInstance; + EventMap events; + SummonList summons; + + void Reset() + { + events.Reset(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_PASSIVE); + } + + void DamageTaken(Unit *pWho, uint32 &uiDamage) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + uiDamage = 0; + } + + void DoAction(const int32 actionID) + { + switch(actionID) + { + case ACTION_ENTER_COMBAT: // called by InstanceData when boss shall enter in combat. + // Just in case. Should have been done by InstanceData + me->SetVisibility(VISIBILITY_ON); + + // Reset flags + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetReactState(REACT_AGGRESSIVE); + + if (Unit *pUnit = me->SelectNearestTarget()) + AttackStart(pUnit); + + DoZoneInCombat(); + break; + } + } + + void JustSummoned(Creature *pSummoned) + { + summons.Summon(pSummoned); + + if (Unit *pUnit = pSummoned->SelectNearestTarget()) + { + if (pSummoned->AI()) + pSummoned->AI()->AttackStart(pUnit); + else + { + pSummoned->GetMotionMaster()->MoveChase(pUnit); + pSummoned->Attack(pUnit, true); + } + } + + if (pSummoned->AI()) + pSummoned->AI()->DoZoneInCombat(); + } + + void SummonedCreatureDespawn(Creature *pSummoned) + { + summons.Despawn(pSummoned); + if (summons.empty()) + { + if (pSummoned->isAlive()) + pInstance->SetData(DATA_WAVE_COUNT, NOT_STARTED); + else + pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); + } + } +}; + +#endif diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp new file mode 100644 index 00000000000..7a5d2479b7c --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/instance_halls_of_reflection.cpp @@ -0,0 +1,431 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "halls_of_reflection.h" + +#define MAX_ENCOUNTER 3 + +/* Halls of Reflection encounters: +0- Falric +1- Marwyn +2- The Lich King +*/ + +enum eEnum +{ + ENCOUNTER_WAVE_MERCENARY = 6, + ENCOUNTER_WAVE_FOOTMAN = 10, + ENCOUNTER_WAVE_RIFLEMAN = 6, + ENCOUNTER_WAVE_PRIEST = 6, + ENCOUNTER_WAVE_MAGE = 6, +}; + +enum Events +{ + EVENT_NONE, + EVENT_NEXT_WAVE, + EVENT_START_LICH_KING, +}; + +static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] = +{ + {5277.74,2016.88,707.778,5.96903}, + {5295.88,2040.34,707.778,5.07891}, + {5320.37,1980.13,707.778,2.00713}, + {5280.51,1997.84,707.778,0.296706}, + {5302.45,2042.22,707.778,4.90438}, + {5306.57,1977.47,707.778,1.50098}, +}; + +static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] = +{ + {5312.75,2037.12,707.778,4.59022}, + {5309.58,2042.67,707.778,4.69494}, + {5275.08,2008.72,707.778,6.21337}, + {5279.65,2004.66,707.778,0.069813}, + {5275.48,2001.14,707.778,0.174533}, + {5316.7,2041.55,707.778,4.50295}, +}; + +static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] = +{ + {5302.25,1972.41,707.778,1.37881}, + {5311.03,1972.23,707.778,1.64061}, + {5277.36,1993.23,707.778,0.401426}, + {5318.7,2036.11,707.778,4.2237}, + {5335.72,1996.86,707.778,2.74017}, + {5299.43,1979.01,707.778,1.23918}, +}; + +static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] = +{ + {5306.06,2037,707.778,4.81711}, + {5344.15,2007.17,707.778,3.15905}, + {5337.83,2010.06,707.778,3.22886}, + {5343.29,1999.38,707.778,2.9147}, + {5340.84,1992.46,707.778,2.75762}, + {5325.07,1977.6,707.778,2.07694}, + {5336.6,2017.28,707.778,3.47321}, + {5313.82,1978.15,707.778,1.74533}, + {5280.63,2012.16,707.778,6.05629}, + {5322.96,2040.29,707.778,4.34587}, +}; + +static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] = +{ + {5343.47,2015.95,707.778,3.49066}, + {5337.86,2003.4,707.778,2.98451}, + {5319.16,1974,707.778,1.91986}, + {5299.25,2036,707.778,5.02655}, + {5295.64,1973.76,707.778,1.18682}, + {5282.9,2019.6,707.778,5.88176}, +}; + +struct instance_halls_of_reflection : public ScriptedInstance +{ + instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiFalric; + uint64 uiMarwyn; + uint64 uiLichKingEvent; + uint64 uiJainaPart1; + uint64 uiSylvanasPart1; + + uint64 uiFrostmourne; + uint64 uiFrostmourneAltar; + uint64 uiArthasDoor; + uint64 uiFrontDoor; + + uint32 uiEncounter[MAX_ENCOUNTER]; + uint32 uiTeamInInstance; + uint32 uiWaveCount; + bool bIntroDone; + + EventMap events; + + void Initialize() + { + events.Reset(); + + uiFalric = 0; + uiMarwyn = 0; + uiLichKingEvent = 0; + uiJainaPart1 = 0; + uiSylvanasPart1 = 0; + + uiFrostmourne = 0; + uiFrostmourneAltar = 0; + uiArthasDoor = 0; + uiFrontDoor = 0; + uiTeamInInstance = 0; + uiWaveCount = 0; + bIntroDone = false; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + if (!add) + return; + + Map::PlayerList const &players = instance->GetPlayers(); + if (!players.isEmpty()) + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + + switch(pCreature->GetEntry()) + { + case NPC_FALRIC: + uiFalric = pCreature->GetGUID(); + break; + case NPC_MARWYN: + uiMarwyn = pCreature->GetGUID(); + break; + case NPC_LICH_KING_EVENT: + uiLichKingEvent = pCreature->GetGUID(); + break; + case NPC_JAINA_PART1: + uiJainaPart1 = pCreature->GetGUID(); + break; + case NPC_SYLVANAS_PART1: + uiSylvanasPart1 = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (!add) + return; + + // TODO: init state depending on encounters + switch(pGo->GetEntry()) + { + case GO_FROSTMOURNE: + uiFrostmourne = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, false, pGo); + break; + case GO_FROSTMOURNE_ALTAR: + uiFrostmourneAltar = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, true, pGo); + break; + case GO_FRONT_DOOR: + uiFrontDoor = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + HandleGameObject(0, true, pGo); + break; + case GO_ARTHAS_DOOR: + uiArthasDoor = pGo->GetGUID(); + pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + + if (uiEncounter[1] == DONE) + HandleGameObject(0, true, pGo); + else + HandleGameObject(0, false, pGo); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + if (type == DATA_WAVE_COUNT && data == SPECIAL) + { + bIntroDone = true; + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + return; + } + + + if (uiWaveCount && data == NOT_STARTED) + DoWipe(); + + switch(type) + { + case DATA_FALRIC_EVENT: + uiEncounter[0] = data; + if (data == DONE) + events.ScheduleEvent(EVENT_NEXT_WAVE, 60000); + break; + case DATA_MARWYN_EVENT: + uiEncounter[1] = data; + if (data == DONE) + HandleGameObject(uiArthasDoor, true); + break; + case DATA_LICHKING_EVENT: + uiEncounter[2] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_FALRIC_EVENT: return uiEncounter[0]; + case DATA_MARWYN_EVENT: return uiEncounter[1]; + case DATA_LICHKING_EVENT: return uiEncounter[2]; + case DATA_WAVE_COUNT: return uiWaveCount; + case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_FALRIC: return uiFalric; + case DATA_MARWYN: return uiMarwyn; + case DATA_LICHKING: return uiLichKingEvent; + case DATA_FROSTMOURNE: return uiFrostmourne; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H R 1 " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 version; + uint16 data0, data1, data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2; + + if (dataHead1 == 'H' && dataHead2 == 'R') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + uiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + if (uiEncounter[0] == DONE || uiEncounter[1] == DONE) + bIntroDone = true; + + OUT_LOAD_INST_DATA_COMPLETE; + } + + void AddWave() + { + DoUpdateWorldState(WORLD_STATE_HOR, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); + + switch(uiWaveCount) + { + case 1: + case 2: + case 3: + case 4: + if (Creature *pFalric = instance->GetCreature(uiFalric)) + SpawnWave(pFalric); + break; + case 5: + if (GetData(DATA_FALRIC_EVENT) == DONE) + events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); + else if (Creature *pFalric = instance->GetCreature(uiFalric)) + if (pFalric->AI()) + pFalric->AI()->DoAction(ACTION_ENTER_COMBAT); + break; + case 6: + case 7: + case 8: + case 9: + if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) + SpawnWave(pMarwyn); + break; + case 10: + if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit! + if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) + if (pMarwyn->AI()) + pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT); + break; + } + } + + // Wipe has been detected. Perform cleanup and reset. + void DoWipe() + { + uiWaveCount = 0; + events.Reset(); + DoUpdateWorldState(WORLD_STATE_HOR, 1); + DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); + HandleGameObject(uiFrontDoor, true); + + // TODO + // in case of wipe, the event is normally restarted by jumping into the center of the room. + // As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted. + if (Creature* pJaina = instance->GetCreature(uiJainaPart1)) + pJaina->Respawn(); + if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1)) + pSylvanas->Respawn(); + + if (Creature* pFalric = instance->GetCreature(uiFalric)) + pFalric->SetVisibility(VISIBILITY_OFF); + if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) + pMarwyn->SetVisibility(VISIBILITY_OFF); + } + + // spawn a wave on behalf of the summoner. + void SpawnWave(Creature *pSummoner) + { + uint32 index; + + pSummoner->SetVisibility(VISIBILITY_ON); + + // TODO: do composition at random. # of spawn also depends on uiWaveCount + // As of now, it is just one of each. + index = urand(0,ENCOUNTER_WAVE_MERCENARY-1); + pSummoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_FOOTMAN-1); + pSummoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_RIFLEMAN-1); + pSummoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_PRIEST-1); + pSummoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + + index = urand(0,ENCOUNTER_WAVE_MAGE-1); + pSummoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); + } + + void Update(uint32 diff) + { + if (!instance->HavePlayers()) + return; + + events.Update(diff); + + switch(uint32 eventId = events.ExecuteEvent()) + { + case EVENT_NEXT_WAVE: + uiWaveCount++; + AddWave(); + break; + case EVENT_START_LICH_KING: + // TODO + break; + } + } +}; + +InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap) +{ + return new instance_halls_of_reflection(pMap); +} + +void AddSC_instance_halls_of_reflection() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_reflection"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_reflection; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp new file mode 100644 index 00000000000..25c78c4a0d3 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_forgemaster_garfrost.cpp @@ -0,0 +1,209 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +enum Yells +{ + SAY_AGGRO = -1658001, + SAY_SLAY_1 = -1658002, + SAY_SLAY_2 = -1658003, + SAY_DEATH = -1658004, + SAY_PHASE2 = -1658005, + SAY_PHASE3 = -1658006, + + SAY_TYRANNUS_DEATH = -1659007, +}; + +enum eEvents +{ + EVENT_NONE, + EVENT_PERMAFROST, + EVENT_THROW_SARONITE, + EVENT_CHILLINGWAVE, + EVENT_DEEPFREEZE, +}; + +enum Spells +{ + SPELL_PERMAFROST = 70326, + SPELL_PERMAFROST_TRIGGER = 68786, // triggered by PERMAFROST. Used to check aura + SPELL_THROW_SARONITE = 68788, + SPELL_THUNDERING_STOMP = 68771, + SPELL_CHILLING_WAVE = 68778, + H_SPELL_CHILLING_WAVE = 70333, + SPELL_DEEP_FREEZE = 70381, + H_SPELL_DEEP_FREEZE = 72930, + SPELL_FORGE_MACE = 68785, + H_SPELL_FORGE_MACE = 70335, + SPELL_FORGE_BLADE = 68774, + H_SPELL_FORGE_BLADE = 70334, +}; + +enum eEnums +{ + EQUIP_ID_SWORD = 49345, + EQUIP_ID_MACE = 49344, + ACHIEV_DOESNT_GO_TO_ELEVEN = 4524, +}; + +struct boss_garfrostAI : public ScriptedAI +{ + boss_garfrostAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + bool phase2; + bool phase3; + bool bAchievement; + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + phase2 = false; + phase3 = false; + bAchievement = true; + + if (pInstance) + pInstance->SetData(DATA_GARFROST_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCast(me, SPELL_PERMAFROST); + + if (pInstance) + pInstance->SetData(DATA_GARFROST_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_THROW_SARONITE, 45000); + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32& /*uiDamage*/) + { + if (HealthBelowPct(66) && !phase2) + { + phase2 = true; + DoCast(me, SPELL_THUNDERING_STOMP); + // TODO: should go to a forge + DoCast(me, SPELL_FORGE_BLADE); + // TODO: should equip when spell completes + SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + events.ScheduleEvent(EVENT_CHILLINGWAVE, 10000); + } + + if (HealthBelowPct(33) && !phase3) + { + phase3 = true; + DoCast(me, SPELL_THUNDERING_STOMP); + // TODO: should go to a forge + DoCast(me, SPELL_FORGE_MACE); + // TODO: should equip when spell completes + SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); + me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + events.CancelEvent(EVENT_CHILLINGWAVE); // cast only in phase 2. + events.ScheduleEvent(EVENT_DEEPFREEZE, 10000); + } + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + { + if (Creature *pTyrannus = me->GetCreature(*me, pInstance->GetData64(DATA_TYRANNUS))) + DoScriptText(SAY_TYRANNUS_DEATH, pTyrannus); + + pInstance->SetData(DATA_GARFROST_EVENT, DONE); + if (IsHeroic() && bAchievement) + pInstance->DoCompleteAchievement(ACHIEV_DOESNT_GO_TO_ELEVEN); + } + } + + void SpellHitTarget(Unit* pTarget, const SpellEntry *spell) + { + if (spell->Id == SPELL_PERMAFROST_TRIGGER && bAchievement) + { + if (Aura *pAura = pTarget->GetAura(SPELL_PERMAFROST_TRIGGER)) + if (pAura->GetStackAmount() > 10) + bAchievement = false; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_THROW_SARONITE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_THROW_SARONITE); + events.RescheduleEvent(EVENT_THROW_SARONITE, 35000); + return; + case EVENT_DEEPFREEZE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DEEP_FREEZE); + events.RescheduleEvent(EVENT_DEEPFREEZE, 35000); + return; + case EVENT_CHILLINGWAVE: + DoCastAOE(SPELL_CHILLING_WAVE); + events.RescheduleEvent(EVENT_CHILLINGWAVE, 40000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_garfrost(Creature* pCreature) +{ + return new boss_garfrostAI (pCreature); +} + +void AddSC_boss_garfrost() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_garfrost"; + newscript->GetAI = &GetAI_boss_garfrost; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp new file mode 100644 index 00000000000..8b8b03a3d4e --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -0,0 +1,482 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/* + * SDComment: Spell Explosive barrage is not working. + */ + +enum Spells +{ + SPELL_PURSUED = 68987, + SPELL_CONFUSION = 69029, + SPELL_EXPLOSIVE_BARRAGE = 69263, + SPELL_MIGHTY_KICK = 69021, + SPELL_POISON_NOVA = 68989, + H_SPELL_POISON_NOVA = 70434, + SPELL_SHADOW_BOLT = 69028, + SPELL_TOXIC_WASTE = 69024, + H_SPELL_TOXIC_WASTE = 70436, +}; + +enum Yells +{ + // Krick + SAY_KRICK_AGGRO = -1658010, + SAY_KRICK_SLAY_1 = -1658011, + SAY_KRICK_SLAY_2 = -1658012, + SAY_KRICK_BARRAGE_1 = -1658013, + SAY_KRICK_BARRAGE_2 = -1658014, + SAY_KRICK_POISON_NOVA = -1658015, + SAY_KRICK_CHASE_1 = -1658016, + SAY_KRICK_CHASE_2 = -1658017, + SAY_KRICK_CHASE_3 = -1658018, + + // Ick + SAY_ICK_POISON_NOVA = -1658020, + SAY_ICK_CHASE_1 = -1658021, + + // OUTRO + SAY_KRICK_OUTRO_1 = -1658030, + SAY_JAYNA_OUTRO_2 = -1658031, + SAY_SYLVANAS_OUTRO_2 = -1658032, + SAY_KRICK_OUTRO_3 = -1658033, + SAY_JAYNA_OUTRO_4 = -1658034, + SAY_SYLVANAS_OUTRO_4 = -1658035, + SAY_KRICK_OUTRO_5 = -1658036, + SAY_TYRANNUS_OUTRO_7 = -1658037, + SAY_KRICK_OUTRO_8 = -1658038, + SAY_TYRANNUS_OUTRO_9 = -1658039, + SAY_JAYNA_OUTRO_10 = -1658040, + SAY_SYLVANAS_OUTRO_10 = -1658041, +}; + +enum Events +{ + EVENT_NONE, + EVENT_PURSUE, + EVENT_MIGHTY_KICK, + EVENT_POISON_NOVA, + EVENT_EXPLOSIVE_BARRAGE, + EVENT_END_EXPLOSIVE_BARRAGE, + + // Krick + EVENT_SHADOW_BOLT, + EVENT_TOXIC_WASTE, + + // Krick OUTRO + EVENT_OUTRO_1, + EVENT_OUTRO_2, + EVENT_OUTRO_3, + EVENT_OUTRO_4, + EVENT_OUTRO_5, + EVENT_OUTRO_6, + EVENT_OUTRO_7, + EVENT_OUTRO_8, + EVENT_OUTRO_9, + EVENT_OUTRO_10, + EVENT_OUTRO_11, + EVENT_OUTRO_12, + EVENT_OUTRO_END, +}; + +enum KrickPhase +{ + PHASE_COMBAT, + PHASE_OUTRO, +}; + +enum Actions +{ + ACTION_OUTRO, +}; + +enum Misc +{ + SEAT_KRICK = 0, + + // events GCD. Shall not be 0. + GCD_1 = 1, +}; + +// Krick is the Gnome. +// Ick is the Mount +// Common Events are handled/triggered by Ick that "drive" Krick through DoAction. + +struct boss_ickAI : public ScriptedAI +{ + boss_ickAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, NOT_STARTED); + } + + Creature* GetKrick() + { + return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_KRICK) : 0); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, IN_PROGRESS); + + Creature* pKrick = GetKrick(); + if (!pKrick) + pKrick = me->SummonCreature(CREATURE_KRICK, *me, TEMPSUMMON_MANUAL_DESPAWN); + + if (pKrick) + DoScriptText(SAY_KRICK_AGGRO, pKrick); + + events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000, GCD_1); + events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); + events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); + events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 35000); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + } + + void EnterEvadeMode() + { + me->GetMotionMaster()->Clear(); + ScriptedAI::EnterEvadeMode(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (Creature* pKrick = GetKrick()) + { + if (pKrick->AI()) + pKrick->AI()->DoAction(ACTION_OUTRO); + } + + if (pInstance) + pInstance->SetData(DATA_KRICKANDICK_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + return; + + if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) + { + EnterEvadeMode(); + return; + } + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + switch(events.ExecuteEvent()) + { + case EVENT_PURSUE: + if (Creature* pKrick = GetKrick()) + DoScriptText(RAND(SAY_KRICK_CHASE_1,SAY_KRICK_CHASE_2,SAY_KRICK_CHASE_3), pKrick); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->Attack(pTarget,false); + DoScriptText(SAY_ICK_CHASE_1, me, pTarget); + DoCast(pTarget, SPELL_PURSUED); + } + + DoCast(SPELL_CONFUSION); + events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); + return; + + case EVENT_MIGHTY_KICK: + DoCast(me->getVictim(), SPELL_MIGHTY_KICK); + events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000, GCD_1); + return; + + case EVENT_POISON_NOVA: + if (Creature* pKrick = GetKrick()) + DoScriptText(SAY_KRICK_POISON_NOVA, pKrick); + + DoScriptText(SAY_ICK_POISON_NOVA, me); + DoCastAOE(SPELL_POISON_NOVA); + events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); + return; + + case EVENT_TOXIC_WASTE: + DoCast(me->getVictim(), SPELL_TOXIC_WASTE); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); + return; + + case EVENT_SHADOW_BOLT: + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); + return; + + case EVENT_EXPLOSIVE_BARRAGE: + if (Creature *pKrick = GetKrick()) + { + DoScriptText(SAY_KRICK_BARRAGE_1, pKrick); + DoScriptText(SAY_KRICK_BARRAGE_2, pKrick); + } + + DoCastAOE(SPELL_EXPLOSIVE_BARRAGE); + me->GetMotionMaster()->MoveIdle(); + events.DelayEvents(20000, GCD_1); // 2 sec cast + 18 sec + events.ScheduleEvent(EVENT_END_EXPLOSIVE_BARRAGE, 20000); + return; + + case EVENT_END_EXPLOSIVE_BARRAGE: + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 25000); + break; + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_krickAI : public ScriptedAI +{ + boss_krickAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + KrickPhase phase; + uint64 uiNpcOutroDialog; + uint64 uiTyrannus; + + void Reset() + { + uiNpcOutroDialog = 0; + uiTyrannus = 0; + phase = PHASE_COMBAT; + + me->SetReactState(REACT_PASSIVE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetVisibility(VISIBILITY_OFF); + } + + Creature* GetIck() + { + return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ICK) : 0); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_KRICK_SLAY_1,SAY_KRICK_SLAY_2), me); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + // if killed whatever the reason, it breaks the outro + uiDamage = 0; + } + + void DoAction(const int32 actionId) + { + switch(actionId) + { + case ACTION_OUTRO: + { + Position pos; + if (Creature* pIck = GetIck()) + { + // TODO: tele on Ick then run some distance. + pIck->GetNearPosition(pos, 5.0f, 3.14); + me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0.0f); + } + me->SetVisibility(VISIBILITY_ON); + + Creature* pJainaOrSylvanas = me->GetCreature(*me, pInstance->GetData64(DATA_JAINA_SYLVANAS_1)); + if (pJainaOrSylvanas) { + Position pos; + me->GetNearPosition(pos, 5.0f, 0); + pJainaOrSylvanas->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), + pos.GetAngle(me->GetPositionX(), me->GetPositionY())); + } + else { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + pJainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); + else + pJainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); + } + + if (pJainaOrSylvanas) + { + pJainaOrSylvanas->SetOrientation(pJainaOrSylvanas->GetAngle(me->GetPositionX(), me->GetPositionY())); + me->SetOrientation(me->GetAngle(pJainaOrSylvanas->GetPositionX(), pJainaOrSylvanas->GetPositionY())); + uiNpcOutroDialog = pJainaOrSylvanas->GetGUID(); + } + + phase = PHASE_OUTRO; + events.Reset(); + events.ScheduleEvent(EVENT_OUTRO_1, 1000); + break; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (phase == PHASE_OUTRO) + { + if (!pInstance) + return; + + events.Update(diff); + switch(events.ExecuteEvent()) + { + case EVENT_OUTRO_1: + { + DoScriptText(SAY_KRICK_OUTRO_1, me); + events.ScheduleEvent(EVENT_OUTRO_2, 14000); + break; + } + case EVENT_OUTRO_2: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_2, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_2, pNpcDialog); + } + events.ScheduleEvent(EVENT_OUTRO_3, 8500); + break; + } + case EVENT_OUTRO_3: + DoScriptText(SAY_KRICK_OUTRO_3, me); + events.ScheduleEvent(EVENT_OUTRO_4, 12000); + break; + case EVENT_OUTRO_4: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_4, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_4, pNpcDialog); + } + events.ScheduleEvent(EVENT_OUTRO_5, 8000); + break; + } + case EVENT_OUTRO_5: + DoScriptText(SAY_KRICK_OUTRO_5, me); + events.ScheduleEvent(EVENT_OUTRO_6, 4000); + break; + case EVENT_OUTRO_6: + // TODO spawn Tyrannus at some distance and MovePoint near-by (flying on rimefang) + // store uiTyrannus + // Adjust timer so tyrannus has time to come + uiTyrannus = (pInstance ? pInstance->GetData64(DATA_TYRANNUS) : 0); + events.ScheduleEvent(EVENT_OUTRO_7, 1); + break; + case EVENT_OUTRO_7: + if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) + DoScriptText(SAY_TYRANNUS_OUTRO_7, pTyrannus); + events.ScheduleEvent(EVENT_OUTRO_8, 7000); + break; + case EVENT_OUTRO_8: + DoScriptText(SAY_KRICK_OUTRO_8, me); + // TODO: Tyrannus starts killing Krick. + // there shall be some visual spell effect + events.ScheduleEvent(EVENT_OUTRO_9, 6000); + break; + case EVENT_OUTRO_9: + // tyrannus kills krick + me->SetStandState(UNIT_STAND_STATE_DEAD); + me->SetHealth(0); + + if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) + DoScriptText(SAY_TYRANNUS_OUTRO_9, pTyrannus); + + events.ScheduleEvent(EVENT_OUTRO_10, 12000); + break; + case EVENT_OUTRO_10: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + { + if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) + DoScriptText(SAY_JAYNA_OUTRO_10, pNpcDialog); + else + DoScriptText(SAY_SYLVANAS_OUTRO_10, pNpcDialog); + } + + // End of OUTRO. for now... + events.ScheduleEvent(EVENT_OUTRO_END, 8000); + break; + } + case EVENT_OUTRO_END: + { + Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); + if (pNpcDialog) + pNpcDialog->DisappearAndDie(); + + me->DisappearAndDie(); + break; + } + } + return; + } + } +}; + +CreatureAI* GetAI_boss_ick(Creature* pCreature) +{ + return new boss_ickAI(pCreature); +} + +CreatureAI* GetAI_boss_krick(Creature* pCreature) +{ + return new boss_krickAI(pCreature); +} + +void AddSC_boss_ick() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ick"; + newscript->GetAI = &GetAI_boss_ick; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_krick"; + newscript->GetAI = &GetAI_boss_krick; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp new file mode 100644 index 00000000000..55ffa0b4e4b --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp @@ -0,0 +1,273 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/* + * SDComment: TODO: + * - implement aura for spell Overlord Brand. + * - Intro/Outro + * - improve script of Rimefang + */ + +enum Yells +{ + SAY_AMBUSH_1 = -1658050, + SAY_AMBUSH_2 = -1658051, + SAY_GAUNTLET_START = -1658052, + SAY_INTRO_1 = -1658053, + SAY_INTRO_2 = -1658054, + + SAY_AGGRO = -1658055, + SAY_SLAY_1 = -1658056, + SAY_SLAY_2 = -1658057, + SAY_DEATH = -1658058, + SAY_MARK_RIMEFANG_1 = -1658059, + SAY_MARK_RIMEFANG_2 = -1658060, + SAY_DARK_MIGHT_1 = -1658061, + SAY_DARK_MIGHT_2 = -1658062, + + SAY_GORKUN_OUTRO_1 = -1658063, + SAY_GORKUN_OUTRO_2 = -1658064, + SAY_JAYNA_OUTRO_3 = -1658065, + SAY_SYLVANAS_OUTRO_3 = -1658066, + SAY_JAYNA_OUTRO_4 = -1658067, + SAY_SYLVANAS_OUTRO_4 = -1658068, + SAY_JAYNA_OUTRO_5 = -1658069, +}; + +enum Spells +{ + SPELL_FORCEFUL_SMASH = 69155, + H_SPELL_FORCEFUL_SMASH = 69627, + SPELL_OVERLORDS_BRAND = 69172, + SPELL_DARK_MIGHT = 69167, + H_SPELL_DARK_MIGHT = 69629, + SPELL_HOARFROST = 69246, + SPELL_MARK_OF_RIMEFANG = 69275, + SPELL_ICY_BLAST = 69233, + H_SPELL_ICY_BLAST = 69646, + SPELL_ICY_BLAST_2 = 69238, + H_SPELL_ICY_BLAST_2 = 69628, +}; + +enum Events +{ + EVENT_NONE, + EVENT_FORCEFUL_SMASH, + EVENT_OVERLORDS_BRAND, + EVENT_DARK_MIGHT, + + // Rimefang + EVENT_MARK_OF_RIMEFANG, + EVENT_HOARFROST, + EVENT_ICY_BLAST, + EVENT_ICY_BLAST_2, +}; + +enum Misc +{ + SEAT_TYRANNUS = 0 +}; + +struct boss_tyrannusAI : public ScriptedAI +{ + boss_tyrannusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + events.Reset(); + + if (pInstance) + pInstance->SetData(DATA_TYRANNUS_EVENT, NOT_STARTED); + } + + Creature* GetRimefang() + { + return me->GetCreature(*me, pInstance->GetData64(DATA_RIMEFANG)); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + me->ExitVehicle(); + + // restore health if any damage done during intro + me->SetHealth(me->GetMaxHealth()); + + if (pInstance) + pInstance->SetData(DATA_TYRANNUS_EVENT, IN_PROGRESS); + + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); + events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 35000); + events.ScheduleEvent(EVENT_DARK_MIGHT, 40000); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_TYRANNUS_EVENT, DONE); + if (Creature* pRimefang = GetRimefang()) + pRimefang->ForcedDespawn(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FORCEFUL_SMASH: + DoCast(me->getVictim(), SPELL_FORCEFUL_SMASH); + events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); + return; + case EVENT_OVERLORDS_BRAND: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_OVERLORDS_BRAND); + events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 45000); + return; + case EVENT_DARK_MIGHT: + DoScriptText(SAY_DARK_MIGHT_1, me); + DoScriptText(SAY_DARK_MIGHT_2, me); + DoCast(me, SPELL_DARK_MIGHT); + events.ScheduleEvent(EVENT_DARK_MIGHT, 60000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct boss_rimefangAI : public ScriptedAI +{ + boss_rimefangAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + EventMap events; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + me->InterruptSpell(CURRENT_GENERIC_SPELL); + me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 25000); + events.ScheduleEvent(EVENT_ICY_BLAST, 35000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_MARK_OF_RIMEFANG: + DoScriptText(SAY_MARK_RIMEFANG_1, me); + DoScriptText(SAY_MARK_RIMEFANG_2, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MARK_OF_RIMEFANG); + events.ScheduleEvent(EVENT_HOARFROST, 5000); + return; + case EVENT_HOARFROST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_HOARFROST); + events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 20000); + return; + case EVENT_ICY_BLAST: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ICY_BLAST); + events.ScheduleEvent(EVENT_ICY_BLAST_2, 5000); + return; + case EVENT_ICY_BLAST_2: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget->getVictim(), SPELL_ICY_BLAST_2); + events.ScheduleEvent(EVENT_ICY_BLAST, 30000); + return; + } + } + } +}; + +CreatureAI* GetAI_boss_tyrannus(Creature* pCreature) +{ + return new boss_tyrannusAI(pCreature); +} + +CreatureAI* GetAI_boss_rimefang(Creature* pCreature) +{ + return new boss_rimefangAI(pCreature); +} + +void AddSC_boss_tyrannus() +{ + Script *newscript; + newscript = new Script; + newscript->Name="boss_tyrannus"; + newscript->GetAI = &GetAI_boss_tyrannus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="boss_rimefang"; + newscript->GetAI = &GetAI_boss_rimefang; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp new file mode 100644 index 00000000000..8512eca24c1 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/instance_pit_of_saron.cpp @@ -0,0 +1,236 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +#define MAX_ENCOUNTER 3 + +/* Pit of Saron encounters: +0- Forgemaster Garfrost +1- Krick and Ick +2- Scourgelord Tyrannus +*/ + +struct instance_pit_of_saron : public ScriptedInstance +{ + instance_pit_of_saron(Map* pMap) : ScriptedInstance(pMap) {}; + + uint64 uiKrick; + uint64 uiIck; + uint64 uiGarfrost; + uint64 uiTyrannus; + uint64 uiRimefang; + + uint64 uiJainaOrSylvanas1; + uint64 uiJainaOrSylvanas2; + + uint32 uiTeamInInstance; + uint32 uiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + uiEncounter[i] = NOT_STARTED; + + uiGarfrost = 0; + uiKrick = 0; + uiIck = 0; + uiTyrannus = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + uiTeamInInstance = pPlayer->GetTeam(); + } + + switch(pCreature->GetEntry()) + { + case CREATURE_KRICK: + uiKrick = pCreature->GetGUID(); + break; + + case CREATURE_ICK: + uiIck = pCreature->GetGUID(); + break; + + case CREATURE_GARFROST: + uiGarfrost = pCreature->GetGUID(); + break; + + case CREATURE_TYRANNUS: + uiTyrannus = pCreature->GetGUID(); + break; + + case CREATURE_RIMEFANG: + uiRimefang = pCreature->GetGUID(); + break; + + case NPC_SYLVANAS_PART1: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); + uiJainaOrSylvanas1 = pCreature->GetGUID(); + break; + case NPC_SYLVANAS_PART2: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); + uiJainaOrSylvanas2 = pCreature->GetGUID(); + break; + case NPC_KILARA: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_ELANDRA, ALLIANCE); + break; + case NPC_KORALEN: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_KORLAEN, ALLIANCE); + break; + case NPC_CHAMPION_1_HORDE: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_2_HORDE: + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? + if (uiTeamInInstance == ALLIANCE) + pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); + break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_GARFROST: return uiGarfrost; + case DATA_KRICK: return uiKrick; + case DATA_ICK: return uiIck; + case DATA_TYRANNUS: return uiTyrannus; + case DATA_RIMEFANG: return uiRimefang; + + case DATA_JAINA_SYLVANAS_1: return uiJainaOrSylvanas1; + case DATA_JAINA_SYLVANAS_2: return uiJainaOrSylvanas2; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_GARFROST_EVENT: + uiEncounter[0] = data; + break; + case DATA_TYRANNUS_EVENT: + uiEncounter[1] = data; + break; + case DATA_KRICKANDICK_EVENT: + uiEncounter[2] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_GARFROST_EVENT: return uiEncounter[0]; + case DATA_TYRANNUS_EVENT: return uiEncounter[1]; + case DATA_KRICKANDICK_EVENT: return uiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::string str_data; + + std::ostringstream saveStream; + saveStream << "P S " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; + + if (dataHead1 == 'P' && dataHead2 == 'S') + { + uiEncounter[0] = data0; + uiEncounter[1] = data1; + uiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (uiEncounter[i] == IN_PROGRESS) + uiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_pit_of_saron(Map* pMap) +{ + return new instance_pit_of_saron(pMap); +} + +void AddSC_instance_pit_of_saron() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_pit_of_saron"; + newscript->GetInstanceData = &GetInstanceData_instance_pit_of_saron; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp new file mode 100644 index 00000000000..bc53efc7033 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.cpp @@ -0,0 +1,1101 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "pit_of_saron.h" + +/***************************************SPELLS*************************************/ +// Ymirjar Wrathbringer +#define SPELL_BLIGHT DUNGEON_MODE(69603,70285) + +//Ymirjar Skycaller +#define SPELL_FROSTBLADE 70291 +#define SPELL_GLACIAL_STRIKE 70292 + +//Ymirjar Flamebearer +#define SPELL_FIREBALL DUNGEON_MODE(69583,70282) +#define SPELL_HELLFIRE DUNGEON_MODE(69586,70283) +#define SPELL_TACTICAL_BLINK 69584 + +//Ymirjar Deathbringer +#define SPELL_EMPOWERED_SHADOW_BOLT DUNGEON_MODE(69528,70281) +#define SPELL_SUMMON_UNDEAD 69516 + +//Wrathbone Laborer +#define SPELL_BLINDING_DIRT 70302 +#define SPELL_PUNCTURE_WOUND DUNGEON_MODE(70278,70279) +#define SPELL_SHOVELLED DUNGEON_MODE(69572,70280) + +//Wrathbone Coldwraith +#define SPELL_FREEZING_CIRCLE DUNGEON_MODE(69574,70276) +#define SPELL_FROSTBOLT DUNGEON_MODE(69573,70277) + +//Stonespine Gargoyle +#define SPELL_GARGOYLE_STRIKE DUNGEON_MODE(69520,70275) +#define SPELL_STONEFORM 69575 + +// Plagueborn Horror +#define SPELL_BLIGHT_BOMB 69582 +#define SPELL_PUSTULANT_FLESH DUNGEON_MODE(69581,70273) +#define SPELL_TOXIC_WASTE 70274 + +//Iceborn Proto-Drake +#define SPELL_FROST_BREATH DUNGEON_MODE(69527,70272) + +//Hungering Ghoul +#define SPELL_DEVOUR_FLESH 70393 + +//Fallen Warrior +#define SPELL_ARCING_SLICE 69579 +#define SPELL_DEMORALIZING_SHOUT 61044 +#define SPELL_SHIELD_BLOCK 69580 + +//Deathwhisper Torturer +#define SPELL_BLACK_BRAND 70392 +#define SPELL_CURSE_OF_AGONY 70391 + +//Deathwhisper Shadowcaster +#define SPELL_SHADOW_BOLT DUNGEON_MODE(70386,70387) + +//Deathwhisper Necrolyte +#define SPELL_CONVERSION_BEAM DUNGEON_MODE(69578,70269) +#define SPELL_SHADOW_BOLT_2 DUNGEON_MODE(69577,70270) + +//Wrathbone Sorcerer +#define SPELL_SHADOW_BOLT_3 DUNGEON_MODE(70386,70387) + +//Geist Ambusher +#define SPELL_LEAPING_FACE_MAUL DUNGEON_MODE(69504,70271) + +/****************************************EVENTS************************************/ +enum eEvents +{ + EVENT_NONE, + + // Ymirjar Wrathbringer + EVENT_BLIGHT, + + // Ymirjar Skycaller + EVENT_FROSTBLADE, + EVENT_GLACIAL_STRIKE, + + // Ymirjar Flamebearer + EVENT_FIREBALL, + EVENT_HELLFIRE, + EVENT_TACTICAL_BLINK, + + //Ymirjar Deathbringer + EVENT_EMPOWERED_SHADOW_BOLT, + EVENT_SUMMON_UNDEAD, + + //Wrathbone Laborer + EVENT_BLINDING_DIRT, + EVENT_PUNCTURE_WOUND, + EVENT_SHOVELLED, + + //Wrathbone Coldwraith + EVENT_FREEZING_CIRCLE, + EVENT_FROSTBOLT, + + //Stonespine Gargoyle + EVENT_GARGOYLE_STRIKE, + EVENT_STONEFORM, + + //Plagueborn Horror + EVENT_BLIGHT_BOMB, + EVENT_PUSTULANT_FLESH, + EVENT_TOXIC_WASTE, + + //Iceborn Proto-Drake + EVENT_FROST_BREATH, + + //Hungering Ghoul + EVENT_DEVOUR_FLESH, + + //Fallen Warrior + EVENT_ARCING_SLICE, + EVENT_DEMORALIZING_SHOUT, + EVENT_SHIELD_BLOCK, + + //Deathwhisper Torturer + EVENT_BLACK_BRAND, + EVENT_CURSE_OF_AGONY, + + //Deathwhisper Shadowcaster + EVENT_SHADOW_BOLT, + + //Deathwhisper Necrolyte + EVENT_CONVERSION_BEAM, + EVENT_SHADOW_BOLT_2, + + EVENT_SHADOW_BOLT_3, + + //Geist Ambusher + EVENT_LEAPING_FACE_MAUL, +}; + +/****************************************AI****************************************/ +struct mob_ymirjar_wrathbringerAI : public ScriptedAI +{ + mob_ymirjar_wrathbringerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLIGHT, 7000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLIGHT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLIGHT); + events.RescheduleEvent(EVENT_BLIGHT, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_skyCallerAI: public ScriptedAI +{ + mob_ymirjar_skyCallerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROSTBLADE, 1); + events.ScheduleEvent(EVENT_GLACIAL_STRIKE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_GLACIAL_STRIKE: + DoCast(me->getVictim(), SPELL_GLACIAL_STRIKE); + events.RescheduleEvent(EVENT_GLACIAL_STRIKE, 8000); + return; + case EVENT_FROSTBLADE: + DoCast(me, SPELL_FROSTBLADE); + events.CancelEvent(EVENT_FROSTBLADE); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_flamebearerAI: public ScriptedAI +{ + mob_ymirjar_flamebearerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FIREBALL, 4000); + events.ScheduleEvent(EVENT_HELLFIRE, 8000); + events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FIREBALL: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FIREBALL); + events.RescheduleEvent(EVENT_FIREBALL, 5000); + return; + case EVENT_HELLFIRE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_HELLFIRE); + events.RescheduleEvent(EVENT_HELLFIRE, 10000); + return; + case EVENT_TACTICAL_BLINK: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_TACTICAL_BLINK); + events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_ymirjar_deathbringerAI: public ScriptedAI +{ + mob_ymirjar_deathbringerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_EMPOWERED_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_EMPOWERED_SHADOW_BOLT); + events.RescheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_laborerAI: public ScriptedAI +{ + mob_wrathbone_laborerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); + events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + events.ScheduleEvent(EVENT_SHOVELLED, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLINDING_DIRT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLINDING_DIRT); + events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); + return; + case EVENT_PUNCTURE_WOUND: + DoCast(me->getVictim(), SPELL_PUNCTURE_WOUND); + events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); + return; + case EVENT_SHOVELLED: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHOVELLED); + events.RescheduleEvent(EVENT_SHOVELLED, 7000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_coldwraithAI: public ScriptedAI +{ + mob_wrathbone_coldwraithAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FREEZING_CIRCLE, 9000); + events.ScheduleEvent(EVENT_FROSTBOLT, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FREEZING_CIRCLE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FREEZING_CIRCLE); + events.RescheduleEvent(EVENT_FREEZING_CIRCLE, 9000); + return; + case EVENT_FROSTBOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_FROSTBOLT); + events.RescheduleEvent(EVENT_FROSTBOLT, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_stonespine_gargoyleAI: public ScriptedAI +{ + mob_stonespine_gargoyleAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_GARGOYLE_STRIKE, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_GARGOYLE_STRIKE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_GARGOYLE_STRIKE); + events.RescheduleEvent(EVENT_GARGOYLE_STRIKE, 6000); + return; + case EVENT_STONEFORM: + if (HealthBelowPct(10)) + DoCast(me, SPELL_STONEFORM); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_plagueborn_horrorAI: public ScriptedAI +{ + mob_plagueborn_horrorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLIGHT_BOMB, 999999); + events.ScheduleEvent(EVENT_PUSTULANT_FLESH, 5000); + events.ScheduleEvent(EVENT_TOXIC_WASTE, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLIGHT_BOMB: + if (HealthBelowPct(15)) + DoCast(me, SPELL_BLIGHT_BOMB); + return; + case EVENT_PUSTULANT_FLESH: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_PUSTULANT_FLESH); + events.RescheduleEvent(EVENT_PUSTULANT_FLESH, 10000); + return; + case EVENT_TOXIC_WASTE: + DoCast(me, SPELL_TOXIC_WASTE); + events.RescheduleEvent(EVENT_TOXIC_WASTE, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_iceborn_protodrakeAI: public ScriptedAI +{ + mob_iceborn_protodrakeAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_FROST_BREATH, 5000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_FROST_BREATH: + DoCast(me->getVictim(), SPELL_FROST_BREATH); + events.RescheduleEvent(EVENT_FROST_BREATH, 10000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_hungering_ghoulAI: public ScriptedAI +{ + mob_hungering_ghoulAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_DEVOUR_FLESH, 4000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_DEVOUR_FLESH: + DoCast(me->getVictim(), SPELL_DEVOUR_FLESH); + events.RescheduleEvent(EVENT_DEVOUR_FLESH, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_fallen_warriorAI: public ScriptedAI +{ + mob_fallen_warriorAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_ARCING_SLICE, 8000); + events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); + events.ScheduleEvent(EVENT_SHIELD_BLOCK, 8000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_ARCING_SLICE: + DoCast(me->getVictim(), SPELL_ARCING_SLICE); + events.RescheduleEvent(EVENT_ARCING_SLICE, 10000); + return; + case EVENT_DEMORALIZING_SHOUT: + DoCast(me, SPELL_DEMORALIZING_SHOUT); + events.RescheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); + return; + case EVENT_SHIELD_BLOCK: + DoCast(me->getVictim(), SPELL_SHIELD_BLOCK); + events.RescheduleEvent(EVENT_SHIELD_BLOCK, 8000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_torturerAI: public ScriptedAI +{ + mob_deathwhisper_torturerAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_BLACK_BRAND, 10000); + events.ScheduleEvent(EVENT_CURSE_OF_AGONY, 6000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_BLACK_BRAND: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLACK_BRAND); + events.RescheduleEvent(EVENT_BLACK_BRAND, 10000); + return; + case EVENT_CURSE_OF_AGONY: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CURSE_OF_AGONY); + events.RescheduleEvent(EVENT_CURSE_OF_AGONY, 13000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_shadowcasterAI: public ScriptedAI +{ + mob_deathwhisper_shadowcasterAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_BOLT, 3000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_BOLT: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT); + events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_deathwhisper_necrolyteAI: public ScriptedAI +{ + mob_deathwhisper_necrolyteAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_CONVERSION_BEAM, 12000); + events.ScheduleEvent(EVENT_SHADOW_BOLT_2, 4000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_CONVERSION_BEAM: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CONVERSION_BEAM); + events.RescheduleEvent(EVENT_CONVERSION_BEAM, 12000); + return; + case EVENT_SHADOW_BOLT_2: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT_2); + events.RescheduleEvent(EVENT_SHADOW_BOLT_2, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_wrathbone_sorcererAI: public ScriptedAI +{ + mob_wrathbone_sorcererAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + events.ScheduleEvent(EVENT_SHADOW_BOLT_3, 3000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + case EVENT_SHADOW_BOLT_3: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHADOW_BOLT_3); + events.RescheduleEvent(EVENT_SHADOW_BOLT_3, 5000); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_geist_ambusherAI: public ScriptedAI +{ + mob_geist_ambusherAI(Creature *c) : ScriptedAI(c) + { + } + + EventMap events; + + void Reset() + { + events.Reset(); + } + + void EnterCombat(Unit* /*who*/) + { + //Only here so when I figure out how to make it cast on an NPC i can do that. + events.ScheduleEvent(EVENT_LEAPING_FACE_MAUL, 99999); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + events.Update(diff); + + if (me->hasUnitState(UNIT_STAT_CASTING)) + return; + + while (uint32 eventId = events.ExecuteEvent()) + { + switch(eventId) + { + //Should only be used on NPCs + case EVENT_LEAPING_FACE_MAUL: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_LEAPING_FACE_MAUL); + events.CancelEvent(EVENT_LEAPING_FACE_MAUL); + return; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_ymirjar_wrathbringerAI(Creature* pCreature) +{ + return new mob_ymirjar_wrathbringerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_skyCallerAI(Creature* pCreature) +{ + return new mob_ymirjar_skyCallerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_flamebearerAI(Creature* pCreature) +{ + return new mob_ymirjar_flamebearerAI(pCreature); +} + +CreatureAI* GetAI_mob_ymirjar_deathbringerAI(Creature* pCreature) +{ + return new mob_ymirjar_deathbringerAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_laborerAI(Creature* pCreature) +{ + return new mob_wrathbone_laborerAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_coldwraithAI(Creature* pCreature) +{ + return new mob_wrathbone_coldwraithAI(pCreature); +} + +CreatureAI* GetAI_mob_stonespine_gargoyleAI(Creature* pCreature) +{ + return new mob_stonespine_gargoyleAI(pCreature); +} + +CreatureAI* GetAI_mob_plagueborn_horrorAI(Creature* pCreature) +{ + return new mob_plagueborn_horrorAI(pCreature); +} + +CreatureAI* GetAI_mob_iceborn_protodrakeAI(Creature* pCreature) +{ + return new mob_iceborn_protodrakeAI(pCreature); +} + +CreatureAI* GetAI_mob_hungering_ghoulAI(Creature* pCreature) +{ + return new mob_hungering_ghoulAI(pCreature); +} + +CreatureAI* GetAI_mob_fallen_warriorAI(Creature* pCreature) +{ + return new mob_fallen_warriorAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_torturerAI(Creature* pCreature) +{ + return new mob_deathwhisper_torturerAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_shadowcasterAI(Creature* pCreature) +{ + return new mob_deathwhisper_shadowcasterAI(pCreature); +} + +CreatureAI* GetAI_mob_deathwhisper_necrolyteAI(Creature* pCreature) +{ + return new mob_deathwhisper_necrolyteAI(pCreature); +} + +CreatureAI* GetAI_mob_wrathbone_sorcererAI(Creature* pCreature) +{ + return new mob_wrathbone_sorcererAI(pCreature); +} + +CreatureAI* GetAI_mob_geist_ambusherAI(Creature* pCreature) +{ + return new mob_geist_ambusherAI(pCreature); +} + +void AddSC_pit_of_saron() +{ + Script *newscript; + newscript = new Script; + newscript->Name="mob_ymirjar_wrathbringer"; + newscript->GetAI = &GetAI_mob_ymirjar_wrathbringerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_skycaller"; + newscript->GetAI = &GetAI_mob_ymirjar_skyCallerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_flamebearer"; + newscript->GetAI = &GetAI_mob_ymirjar_flamebearerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_ymirjar_deathbringer"; + newscript->GetAI = &GetAI_mob_ymirjar_deathbringerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_laborer"; + newscript->GetAI = &GetAI_mob_wrathbone_laborerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_coldwraith"; + newscript->GetAI = &GetAI_mob_wrathbone_coldwraithAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_stonespine_gargoyle"; + newscript->GetAI = &GetAI_mob_stonespine_gargoyleAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_plagueborn_horror"; + newscript->GetAI = &GetAI_mob_plagueborn_horrorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_iceborn_protodrake"; + newscript->GetAI = &GetAI_mob_iceborn_protodrakeAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_hungering_ghoul"; + newscript->GetAI = &GetAI_mob_hungering_ghoulAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_fallen_warrior"; + newscript->GetAI = &GetAI_mob_fallen_warriorAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_torturer"; + newscript->GetAI = &GetAI_mob_deathwhisper_torturerAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_shadowcaster"; + newscript->GetAI = &GetAI_mob_deathwhisper_shadowcasterAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_deathwhisper_necrolyte"; + newscript->GetAI = &GetAI_mob_deathwhisper_necrolyteAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_wrathbone_sorcerer"; + newscript->GetAI = &GetAI_mob_wrathbone_sorcererAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name="mob_geist_ambusher"; + newscript->GetAI = &GetAI_mob_geist_ambusherAI; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h new file mode 100644 index 00000000000..4a221d17518 --- /dev/null +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/pit_of_saron.h @@ -0,0 +1,63 @@ +/* Copyright (C) 2006 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_PIT_OF_SARON_H +#define DEF_PIT_OF_SARON_H + +enum Data +{ + DATA_GARFROST_EVENT, + DATA_KRICKANDICK_EVENT, + DATA_TYRANNUS_EVENT, + DATA_TEAM_IN_INSTANCE, +}; + +enum Data64 +{ + DATA_GARFROST, + DATA_KRICK, + DATA_ICK, + DATA_TYRANNUS, + DATA_RIMEFANG, + + DATA_JAINA_SYLVANAS_1, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. + DATA_JAINA_SYLVANAS_2, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. +}; + +enum Creatures +{ + CREATURE_GARFROST = 36494, + CREATURE_KRICK = 36477, + CREATURE_ICK = 36476, + CREATURE_TYRANNUS = 36658, + CREATURE_RIMEFANG = 36661, + + NPC_SYLVANAS_PART1 = 36990, + NPC_SYLVANAS_PART2 = 38189, + NPC_JAINA_PART1 = 36993, + NPC_JAINA_PART2 = 38188, + NPC_KILARA = 37583, + NPC_ELANDRA = 37774, + NPC_KORALEN = 37779, + NPC_KORLAEN = 37582, + NPC_CHAMPION_1_HORDE = 37584, + NPC_CHAMPION_2_HORDE = 37587, + NPC_CHAMPION_3_HORDE = 37588, + NPC_CHAMPION_1_ALLIANCE = 37496, + NPC_CHAMPION_2_ALLIANCE = 37497, +}; + +#endif diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp deleted file mode 100644 index 59db2842735..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_bronjahm.cpp +++ /dev/null @@ -1,263 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -/* - * TODO: - * - Fix Soul Storm spell and remove work around. - */ - -enum Yells -{ - SAY_AGGRO = -1632001, - SAY_SLAY_1 = -1632002, - SAY_SLAY_2 = -1632003, - SAY_DEATH = -1632004, - SAY_SOUL_STORM = -1632005, - SAY_CORRUPT_SOUL = -1632006, -}; - -enum Spells -{ - SPELL_MAGIC_S_BANE = 68793, - SPELL_CORRUPT_SOUL = 68839, - SPELL_CONSUME_SOUL = 68858, - SPELL_TELEPORT = 68988, - SPELL_FEAR = 68950, - SPELL_SOULSTORM = 68872, - SPELL_SOULSTORM_AURA = 68921, - SPELL_SHADOW_BOLT = 70043, -}; - -enum Events -{ - EVENT_NONE, - EVENT_SHADOW_BOLT, - EVENT_MAGIC_BANE, - EVENT_CORRUPT_SOUL, - EVENT_SOUL_STORM, - EVENT_SOUL_STORM_AURA, - EVENT_FEAR, -}; - -enum CombatPhases -{ - PHASE_1, - PHASE_2 -}; - -struct boss_bronjahmAI : public ScriptedAI -{ - boss_bronjahmAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - CombatPhases phase; - - void Reset() - { - phase = PHASE_1; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - - events.Reset(); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); - events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); - events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_BRONJAHM_EVENT, DONE); - } - - void KilledUnit(Unit * /*who*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - // Cast aura spell on all players farther than 10y - void ApplySoulStorm() - { - std::list targetList; - - SelectTargetList(targetList, 100, SELECT_TARGET_TOPAGGRO, -10.0f); - if (targetList.empty()) - return; - - for (std::list::const_iterator itr = targetList.begin(); itr != targetList.end(); ++itr) - { - Unit* pUnit = (*itr); - if (pUnit && pUnit->isAlive()) - me->CastSpell(pUnit, SPELL_SOULSTORM_AURA, true); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - if (phase == PHASE_1 && HealthBelowPct(30)) - { - phase = PHASE_2; - DoCast(me,SPELL_TELEPORT); - me->GetMotionMaster()->Clear(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - events.CancelEvent(EVENT_CORRUPT_SOUL); - events.ScheduleEvent(EVENT_SOUL_STORM, 1000); - events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); - return; - } - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CORRUPT_SOUL: - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - DoScriptText(SAY_CORRUPT_SOUL, me); - DoCast(pTarget,SPELL_CORRUPT_SOUL); - } - events.ScheduleEvent(EVENT_CORRUPT_SOUL, urand(25000,35000)); - break; - case EVENT_SOUL_STORM: - DoScriptText(SAY_SOUL_STORM, me); - // DoCast(me, SPELL_SOULSTORM); bug: put the aura without the limit of 10 yards. - events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); - break; - case EVENT_SOUL_STORM_AURA: - ApplySoulStorm(); - events.ScheduleEvent(EVENT_SOUL_STORM_AURA, 1000); - break; - case EVENT_FEAR: - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget,SPELL_FEAR); - events.ScheduleEvent(EVENT_FEAR, urand(8000,12000)); - break; - case EVENT_SHADOW_BOLT: - DoCastVictim(SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 2000); - break; - case EVENT_MAGIC_BANE: - DoCastVictim(SPELL_MAGIC_S_BANE); - events.ScheduleEvent(EVENT_MAGIC_BANE, urand(8000,15000)); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_bronjahm(Creature* pCreature) -{ - return new boss_bronjahmAI(pCreature); -} - -struct mob_corrupted_soul_fragmentAI : public ScriptedAI -{ - mob_corrupted_soul_fragmentAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCheckTimer; - - void Reset() - { - uiCheckTimer = 0; // first check is immediate - } - - void UpdateAI(const uint32 diff) - { - if (uiCheckTimer <= diff) - { - if (pInstance) - { - Creature* pBronjham = Unit::GetCreature(*me, pInstance->GetData64(DATA_BRONJAHM)); - if (pBronjham && pBronjham->isAlive()) - { - if (me->IsWithinMeleeRange(pBronjham)) - { - pBronjham->CastSpell(pBronjham, SPELL_CONSUME_SOUL, true); - me->ForcedDespawn(); - } - else - { - Position pos; - pBronjham->GetPosition(&pos); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, pos); - } - } - else - me->ForcedDespawn(); - } - uiCheckTimer = 500; - } - else - uiCheckTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_corrupted_soul_fragment(Creature* pCreature) -{ - return new mob_corrupted_soul_fragmentAI(pCreature); -} - -void AddSC_boss_bronjahm() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_bronjahm"; - newscript->GetAI = &GetAI_boss_bronjahm; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_corrupted_soul_fragment"; - newscript->GetAI = &GetAI_mob_corrupted_soul_fragment; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp deleted file mode 100644 index 6811ba953e2..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/boss_devourer_of_souls.cpp +++ /dev/null @@ -1,349 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -/* - * TODO: - * - Fix model id during unleash soul -> seems DB issue 36503 is missing (likewise 36504 is also missing). - * - Fix outro npc movement - */ - -#define PI 3.1415f - -enum Yells -{ - SAY_FACE_ANGER_AGGRO = -1632010, - SAY_FACE_DESIRE_AGGRO = -1632011, - SAY_FACE_ANGER_SLAY_1 = -1632012, - SAY_FACE_SORROW_SLAY_1 = -1632013, - SAY_FACE_DESIRE_SLAY_1 = -1632014, - SAY_FACE_ANGER_SLAY_2 = -1632015, - SAY_FACE_SORROW_SLAY_2 = -1632016, - SAY_FACE_DESIRE_SLAY_2 = -1632017, - SAY_FACE_SORROW_DEATH = -1632019, - SAY_FACE_DESIRE_DEATH = -1632020, - EMOTE_MIRRORED_SOUL = -1632021, - EMOTE_UNLEASH_SOUL = -1632022, - SAY_FACE_ANGER_UNLEASH_SOUL = -1632023, - SAY_FACE_SORROW_UNLEASH_SOUL = -1632024, - SAY_FACE_DESIRE_UNLEASH_SOUL = -1632025, - EMOTE_WAILING_SOUL = -1632026, - SAY_FACE_ANGER_WAILING_SOUL = -1632027, - SAY_FACE_DESIRE_WAILING_SOUL = -1632028, - - SAY_JAINA_OUTRO = -1632029, - SAY_SYLVANAS_OUTRO = -1632030, -}; - -enum Spells -{ - SPELL_PHANTOM_BLAST = 68982, - H_SPELL_PHANTOM_BLAST = 70322, - SPELL_MIRRORED_SOUL = 69051, - SPELL_WELL_OF_SOULS = 68820, - SPELL_WELL_OF_SOULS_VIS = 68854, - SPELL_UNLEASHED_SOULS = 68939, - SPELL_WAILING_SOULS_STARTING = 68912, // Initial spell cast at begining of wailing souls phase - SPELL_WAILING_SOULS_BEAM = 68875, // the beam visual - SPELL_WAILING_SOULS = 68873, // the actual spell - H_SPELL_WAILING_SOULS = 70324, -// 68871,68873,68875,68876,68899,68912,70324, -// 68899 trigger 68871 -}; - -enum Events -{ - EVENT_NONE, - EVENT_PHANTOM_BLAST, - EVENT_MIRRORED_SOUL, - EVENT_WELL_OF_SOULS, - EVENT_UNLEASHED_SOULS, - EVENT_WAILING_SOULS, - EVENT_WAILING_SOULS_TICK, - EVENT_FACE_ANGER, -}; - -enum eEnum -{ - ACHIEV_THREE_FACED = 4523, - DISPLAY_ANGER = 30148, - DISPLAY_SORROW = 30149, - DISPLAY_DESIRE = 30150, -}; - -struct -{ - uint32 entry[2]; - Position movePosition; -} outroPositions[] = -{ - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5590.47, 2427.79, 705.935, 0.802851 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5593.59, 2428.34, 705.935, 0.977384 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2429.31, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5600.81, 2421.12, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.43, 2426.53, 705.935, 0.890118 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5601.55, 2418.36, 705.935, 1.15192 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5598, 2429.14, 705.935, 1.0472 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5594.04, 2424.87, 705.935, 1.15192 } }, - { NPC_CHAMPION_1_ALLIANCE, NPC_CHAMPION_1_HORDE, { 5597.89, 2421.54, 705.935, 0.610865 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5598.57, 2434.62, 705.935, 1.13446 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5585.46, 2417.99, 705.935, 1.06465 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5605.81, 2428.42, 705.935, 0.820305 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5591.61, 2412.66, 705.935, 0.925025 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5593.9, 2410.64, 705.935, 0.872665 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_2_HORDE, { 5586.76, 2416.73, 705.935, 0.942478 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5592.23, 2419.14, 705.935, 0.855211 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5594.61, 2416.87, 705.935, 0.907571 } }, - { NPC_CHAMPION_2_ALLIANCE, NPC_CHAMPION_3_HORDE, { 5589.77, 2421.03, 705.935, 0.855211 } }, - - { NPC_KORELN, NPC_LORALEN, { 5602.58, 2435.95, 705.935, 0.959931 } }, - { NPC_ELANDRA, NPC_KALIRA, { 5606.13, 2433.16, 705.935, 0.785398 } }, - { NPC_JAINA_PART2, NPC_SYLVANAS_PART2, { 5606.12, 2436.6, 705.935, 0.890118 } }, - - { 0, 0, { 0, 0, 0, 0 } } -}; - -struct boss_devourer_of_soulsAI : public ScriptedAI -{ - boss_devourer_of_soulsAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - bool bThreeFaceAchievement; - - ScriptedInstance* pInstance; - EventMap events; - - // wailing soul event - float beamAngle; - float beamAngleDiff; - int8 wailingSoulTick; - - uint64 uiMirroredSoulTarget; - - void Reset() - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->SetDisplayId(DISPLAY_ANGER); - me->SetReactState(REACT_AGGRESSIVE); - - events.Reset(); - - bThreeFaceAchievement = true; - uiMirroredSoulTarget = 0; - - if (pInstance) - pInstance->SetData(DATA_DEVOURER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_DEVOURER_EVENT, IN_PROGRESS); - - DoScriptText(RAND(SAY_FACE_ANGER_AGGRO,SAY_FACE_DESIRE_AGGRO), me); - - events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); - events.ScheduleEvent(EVENT_MIRRORED_SOUL, 8000); - events.ScheduleEvent(EVENT_WELL_OF_SOULS, 30000); - events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 20000); - events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - if (uiMirroredSoulTarget && me->HasAura(SPELL_MIRRORED_SOUL)) - { - if (Player *pPlayer = Unit::GetPlayer(uiMirroredSoulTarget)) - { - if (Aura *pAura = pPlayer->GetAura(SPELL_MIRRORED_SOUL)) - { - int32 mirrorDamage = (uiDamage * 45)/100; - me->CastCustomSpell(pPlayer, 69034, &mirrorDamage, 0, 0, true); -// me->DealDamage(pPlayer, (uiDamage * 45)/100, 0, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW); - } - else - uiMirroredSoulTarget = 0; - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_FACE_ANGER_SLAY_1,SAY_FACE_SORROW_SLAY_1,SAY_FACE_DESIRE_SLAY_1, - SAY_FACE_ANGER_SLAY_2,SAY_FACE_SORROW_SLAY_2,SAY_FACE_DESIRE_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - Position spawnPoint = { 5618.139, 2451.873, 705.854 }; - - DoScriptText(RAND(SAY_FACE_SORROW_DEATH,SAY_FACE_DESIRE_DEATH), me); - - if (pInstance) - { - pInstance->SetData(DATA_DEVOURER_EVENT, DONE); - - if (bThreeFaceAchievement && IsHeroic()) - pInstance->DoCompleteAchievement(ACHIEV_THREE_FACED); - - int32 entryIndex; - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - entryIndex = 0; - else - entryIndex = 1; - - for (int8 i = 0; outroPositions[i].entry[entryIndex] != 0; ++i) - { - if (Creature *pSummon = me->SummonCreature(outroPositions[i].entry[entryIndex], spawnPoint, TEMPSUMMON_DEAD_DESPAWN)) - { - pSummon->GetMotionMaster()->MovePoint(0, outroPositions[i].movePosition); - - if (pSummon->GetEntry() == NPC_JAINA_PART2) - DoScriptText(SAY_JAINA_OUTRO, pSummon); - else if (pSummon->GetEntry() == NPC_SYLVANAS_PART2) - DoScriptText(SAY_SYLVANAS_OUTRO, pSummon); - } - } - } - } - - void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry *pSpell) - { - if (pSpell->Id == H_SPELL_PHANTOM_BLAST) - bThreeFaceAchievement = false; - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_PHANTOM_BLAST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0)) - DoCast(pTarget, SPELL_PHANTOM_BLAST); - events.ScheduleEvent(EVENT_PHANTOM_BLAST, 5000); - break; - case EVENT_MIRRORED_SOUL: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) - { - uiMirroredSoulTarget = pTarget->GetGUID(); - DoCast(pTarget, SPELL_MIRRORED_SOUL); - DoScriptText(EMOTE_MIRRORED_SOUL, me); - } - events.ScheduleEvent(EVENT_MIRRORED_SOUL, urand(15000,30000)); - break; - case EVENT_WELL_OF_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_WELL_OF_SOULS); - events.ScheduleEvent(EVENT_WELL_OF_SOULS, 20000); - break; - case EVENT_UNLEASHED_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_UNLEASHED_SOULS); - me->SetDisplayId(DISPLAY_SORROW); - DoScriptText(RAND(SAY_FACE_ANGER_UNLEASH_SOUL,SAY_FACE_SORROW_UNLEASH_SOUL,SAY_FACE_DESIRE_UNLEASH_SOUL), me); - DoScriptText(EMOTE_UNLEASH_SOUL, me); - events.ScheduleEvent(EVENT_UNLEASHED_SOULS, 30000); - events.ScheduleEvent(EVENT_FACE_ANGER, 5000); - break; - case EVENT_FACE_ANGER: - me->SetDisplayId(DISPLAY_ANGER); - break; - - case EVENT_WAILING_SOULS: - me->SetDisplayId(DISPLAY_DESIRE); - DoScriptText(RAND(SAY_FACE_ANGER_WAILING_SOUL,SAY_FACE_DESIRE_WAILING_SOUL), me); - DoScriptText(EMOTE_WAILING_SOUL, me); - DoCast(me, SPELL_WAILING_SOULS_STARTING); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->SetOrientation(me->GetAngle(pTarget)); - DoCast(me, SPELL_WAILING_SOULS_BEAM); - } - - beamAngle = me->GetOrientation(); - - beamAngleDiff = PI/30.0f; // PI/2 in 15 sec = PI/30 per tick - if (RAND(true,false)) - beamAngleDiff = -beamAngleDiff; - - me->InterruptNonMeleeSpells(false); - me->SetReactState(REACT_PASSIVE); - - //Remove any target - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - - me->GetMotionMaster()->Clear(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - - wailingSoulTick = 15; - events.DelayEvents(18000); // no other events during wailing souls - events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 3000); // first one after 3 secs. - break; - - case EVENT_WAILING_SOULS_TICK: - beamAngle += beamAngleDiff; - me->SetOrientation(beamAngle); - me->StopMoving(); - - DoCast(me, SPELL_WAILING_SOULS); - - if (--wailingSoulTick) - events.ScheduleEvent(EVENT_WAILING_SOULS_TICK, 1000); - else - { - me->SetReactState(REACT_AGGRESSIVE); - me->SetDisplayId(DISPLAY_ANGER); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE); - me->GetMotionMaster()->MoveChase(me->getVictim()); - events.ScheduleEvent(EVENT_WAILING_SOULS, urand(60000,70000)); - } - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_devourer_of_souls(Creature* pCreature) -{ - return new boss_devourer_of_soulsAI(pCreature); -} - -void AddSC_boss_devourer_of_souls() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_devourer_of_souls"; - newscript->GetAI = &GetAI_boss_devourer_of_souls; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp deleted file mode 100644 index 5c85da69898..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.cpp +++ /dev/null @@ -1,899 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -enum Spells -{ - //Spiteful Apparition - SPELL_SPITE = 68895, - H_SPELL_SPITE = 70212, - - //Spectral Warden - SPELL_VEIL_OF_SHADOWS = 69633, - SPELL_WAIL_OF_SOULS = 69148, - H_SPELL_WAIL_OF_SOULS = 70210, - - //Soulguard Watchman - SPELL_SHROUD_OF_RUNES = 69056, - SPELL_UNHOLY_RAGE = 69053, - - //Soulguard Reaper - SPELL_FROST_NOVA = 69060, - H_SPELL_FROST_NOVA = 70209, - SPELL_SHADOW_LANCE = 69058, - - //Soulguard Bonecaster - SPELL_BONE_VOLLEY = 69080, - H_SPELL_BONE_VOLLEY = 70206, - SPELL_RAISE_DEAD = 69562, - SPELL_SHIELD_OF_BONES = 69069, - H_SPELL_SHIELD_OF_BONES = 70207, - - //Soulguard Animator - // Raise dead 69562 - SPELL_SHADOW_BOLT = 69068, - H_SPELL_SHADOW_BOLT = 70208, - SPELL_SOUL_SICKNESS = 69131, - SPELL_SOUL_SIPHON = 69128, - - //Soulguard Adept - //Raise dead 69562 - //Shadow Bolt 69068/70208 - SPELL_DRAIN_LIFE = 69066, - H_SPELL_DRAIN_LIFE = 70213, - SPELL_SHADOW_MEND = 69564, - H_SPELL_SHADOW_MEND = 70205, - - //Soul Horror - SPELL_SOUL_STRIKE = 69088, - H_SPELL_SOUL_STRIKE = 70211, -}; - -enum Events -{ - EVENT_NONE, - - // Jaina/Sylvanas Intro - EVENT_INTRO_1, - EVENT_INTRO_2, - EVENT_INTRO_3, - EVENT_INTRO_4, - EVENT_INTRO_5, - EVENT_INTRO_6, - EVENT_INTRO_7, - EVENT_INTRO_8, - - //Spiteful Apparition - EVENT_SPITE, - - //Spectral Warden - EVENT_VEIL_OF_SHADOWS, - EVENT_WAIL_OF_SOULS, - - //Soulguard Watchman - EVENT_SHROUD_OF_RUNES, - EVENT_UNHOLY_RAGE, - - //Soulguard Reaper - EVENT_FROST_NOVA, - EVENT_SHADOW_LANCE, - - //Soulguard Bonecaster - EVENT_BONE_VOLLEY, - EVENT_RAISE_DEAD, - EVENT_SHIELD_OF_BONES, - - //Soulguard Animator - EVENT_SHADOW_BOLT, - EVENT_SOUL_SICKNESS, - EVENT_SOUL_SIPHON, - - //Soulguard Adept - EVENT_DRAIN_LIFE, - EVENT_SHADOW_MEND, - - //Soul Horror - EVENT_SOUL_STRIKE, -}; - -/****************************************SYLVANAS************************************/ -#define GOSSIP_SYLVANAS_ITEM "What would you have of me, Banshee Queen?" -#define GOSSIP_JAINA_ITEM "What would you have of me, my lady?" - -enum Yells -{ - SAY_JAINA_INTRO_1 = -1632040, - SAY_JAINA_INTRO_2 = -1632041, - SAY_JAINA_INTRO_3 = -1632042, - SAY_JAINA_INTRO_4 = -1632043, - SAY_JAINA_INTRO_5 = -1632044, - SAY_JAINA_INTRO_6 = -1632045, - SAY_JAINA_INTRO_7 = -1632046, - SAY_JAINA_INTRO_8 = -1632047, - - SAY_SYLVANAS_INTRO_1 = -1632050, - SAY_SYLVANAS_INTRO_2 = -1632051, - SAY_SYLVANAS_INTRO_3 = -1632052, - SAY_SYLVANAS_INTRO_4 = -1632053, - SAY_SYLVANAS_INTRO_5 = -1632054, - SAY_SYLVANAS_INTRO_6 = -1632055, -}; - -enum eSylvanas -{ - GOSSIP_SPEECHINTRO = 13525, - ACTION_INTRO, -}; - -enum Phase -{ - PHASE_NORMAL, - PHASE_INTRO, -}; - -struct npc_sylvanas_fosAI: public ScriptedAI -{ - npc_sylvanas_fosAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - ScriptedInstance* pInstance; - - EventMap events; - Phase phase; - - void Reset() - { - events.Reset(); - phase = PHASE_NORMAL; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_INTRO: - { - phase = PHASE_INTRO; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - events.Reset(); - events.ScheduleEvent(EVENT_INTRO_1, 1000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_INTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_INTRO_1: - DoScriptText(SAY_SYLVANAS_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_2, 11500); - break; - - case EVENT_INTRO_2: - DoScriptText(SAY_SYLVANAS_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_3, 10500); - break; - - case EVENT_INTRO_3: - DoScriptText(SAY_SYLVANAS_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_4, 9500); - break; - - case EVENT_INTRO_4: - DoScriptText(SAY_SYLVANAS_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_5, 10500); - break; - - case EVENT_INTRO_5: - DoScriptText(SAY_SYLVANAS_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_6, 9500); - break; - - case EVENT_INTRO_6: - DoScriptText(SAY_SYLVANAS_INTRO_6, me); - // End of Intro - phase = PHASE_NORMAL; - break; - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - //if (me->hasUnitState(UNIT_STAT_CASTING)) - // return; - - //while (uint32 eventId = events.ExecuteEvent()) - //{ - // switch(eventId) - // { - // } - //} - - DoMeleeAttackIfReady(); - } -}; - -struct npc_jaina_fosAI: public ScriptedAI -{ - npc_jaina_fosAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - } - - ScriptedInstance* pInstance; - - EventMap events; - Phase phase; - - void Reset() - { - events.Reset(); - phase = PHASE_NORMAL; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_INTRO: - { - phase = PHASE_INTRO; - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - events.Reset(); - events.ScheduleEvent(EVENT_INTRO_1, 1000); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_INTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_INTRO_1: - DoScriptText(SAY_JAINA_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_2, 8000); - break; - - case EVENT_INTRO_2: - DoScriptText(SAY_JAINA_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_3, 8500); - break; - - case EVENT_INTRO_3: - DoScriptText(SAY_JAINA_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_4, 8000); - break; - - case EVENT_INTRO_4: - DoScriptText(SAY_JAINA_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_5, 10000); - break; - - case EVENT_INTRO_5: - DoScriptText(SAY_JAINA_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_6, 8000); - break; - - case EVENT_INTRO_6: - DoScriptText(SAY_JAINA_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_7, 12000); - break; - - case EVENT_INTRO_7: - DoScriptText(SAY_JAINA_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_8, 8000); - break; - - case EVENT_INTRO_8: - DoScriptText(SAY_JAINA_INTRO_8, me); - // End of Intro - phase = PHASE_NORMAL; - break; - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - //if (me->hasUnitState(UNIT_STAT_CASTING)) - // return; - - //while (uint32 eventId = events.ExecuteEvent()) - //{ - // switch(eventId) - // { - // } - //} - - DoMeleeAttackIfReady(); - } -}; - -bool GossipHello_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->GetEntry() == NPC_JAINA_PART1) - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_JAINA_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - else - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SYLVANAS_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_or_slyvanas_fos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_INTRO); - break; - } - - return true; -} - -struct mob_spiteful_apparitionAI: public ScriptedAI -{ - mob_spiteful_apparitionAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SPITE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SPITE: - DoCast(me->getVictim(), SPELL_SPITE); - events.RescheduleEvent(EVENT_SPITE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_spectral_wardenAI: public ScriptedAI -{ - mob_spectral_wardenAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_VEIL_OF_SHADOWS, 5000); - events.ScheduleEvent(EVENT_WAIL_OF_SOULS, 10000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_VEIL_OF_SHADOWS: - DoCast(me->getVictim(), SPELL_VEIL_OF_SHADOWS); - events.RescheduleEvent(EVENT_VEIL_OF_SHADOWS, 10000); - return; - case EVENT_WAIL_OF_SOULS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_WAIL_OF_SOULS); - events.RescheduleEvent(EVENT_WAIL_OF_SOULS, 5000); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_watchmanAI: public ScriptedAI -{ - mob_soulguard_watchmanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHROUD_OF_RUNES, 1000); - events.ScheduleEvent(EVENT_UNHOLY_RAGE, 1000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHROUD_OF_RUNES: - DoCast(me, SPELL_SHROUD_OF_RUNES); - events.RescheduleEvent(EVENT_SHROUD_OF_RUNES, 5000); - return; - case EVENT_UNHOLY_RAGE: - DoCast(me, SPELL_UNHOLY_RAGE); - events.RescheduleEvent(EVENT_UNHOLY_RAGE, 99999); - return; - } - } - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_reaperAI: public ScriptedAI -{ - mob_soulguard_reaperAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_NOVA, 8000); - events.ScheduleEvent(EVENT_SHADOW_LANCE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROST_NOVA: - DoCast(me, SPELL_FROST_NOVA); - events.RescheduleEvent(EVENT_FROST_NOVA, 9600); - return; - case EVENT_SHADOW_LANCE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_LANCE); - events.RescheduleEvent(EVENT_SHADOW_LANCE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_bonecasterAI: public ScriptedAI -{ - mob_soulguard_bonecasterAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BONE_VOLLEY, 6000); - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHIELD_OF_BONES, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BONE_VOLLEY: - DoCastAOE(SPELL_BONE_VOLLEY); - events.RescheduleEvent(EVENT_BONE_VOLLEY, 7000); - return; - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHIELD_OF_BONES: - DoCast(me, SPELL_SHIELD_OF_BONES); - events.RescheduleEvent(EVENT_SHIELD_OF_BONES, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_animatorAI: public ScriptedAI -{ - mob_soulguard_animatorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 5000); - events.ScheduleEvent(EVENT_SOUL_SICKNESS, 8000); - events.ScheduleEvent(EVENT_SOUL_SIPHON, 10000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; - case EVENT_SOUL_SICKNESS: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SOUL_SICKNESS); - events.RescheduleEvent(EVENT_SOUL_SICKNESS, 10000); - return; - case EVENT_SOUL_SIPHON: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SOUL_SIPHON); - events.RescheduleEvent(EVENT_SOUL_SIPHON, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soulguard_adeptAI: public ScriptedAI -{ - mob_soulguard_adeptAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_RAISE_DEAD, 25000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 8000); - events.ScheduleEvent(EVENT_DRAIN_LIFE, 7000); - events.ScheduleEvent(EVENT_SHADOW_MEND, 35000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_RAISE_DEAD: - DoCast(me, SPELL_RAISE_DEAD); - events.RescheduleEvent(EVENT_RAISE_DEAD, 25000); - return; - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 4000); - return; - case EVENT_DRAIN_LIFE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DRAIN_LIFE); - events.RescheduleEvent(EVENT_DRAIN_LIFE, 9000); - return; - case EVENT_SHADOW_MEND: - DoCast(me, SPELL_SHADOW_MEND); - events.RescheduleEvent(EVENT_SHADOW_MEND, 20000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_soul_horrorAI: public ScriptedAI -{ - mob_soul_horrorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SOUL_STRIKE, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SOUL_STRIKE: - DoCast(me->getVictim(), SPELL_SOUL_STRIKE); - events.RescheduleEvent(EVENT_SOUL_STRIKE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_jaina_fosAI(Creature* pCreature) -{ - return new npc_jaina_fosAI(pCreature); -}; - -CreatureAI* GetAI_npc_sylvanas_fosAI(Creature* pCreature) -{ - return new npc_sylvanas_fosAI(pCreature); -}; - -CreatureAI* GetAI_mob_spiteful_apparitionAI(Creature* pCreature) -{ - return new mob_spiteful_apparitionAI(pCreature); -} - -CreatureAI* GetAI_mob_spectral_wardenAI(Creature* pCreature) -{ - return new mob_spectral_wardenAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_watchmanAI(Creature* pCreature) -{ - return new mob_soulguard_watchmanAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_reaperAI(Creature* pCreature) -{ - return new mob_soulguard_reaperAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_bonecasterAI(Creature* pCreature) -{ - return new mob_soulguard_bonecasterAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_animatorAI(Creature* pCreature) -{ - return new mob_soulguard_animatorAI(pCreature); -} - -CreatureAI* GetAI_mob_soulguard_adeptAI(Creature* pCreature) -{ - return new mob_soulguard_adeptAI(pCreature); -} - -CreatureAI* GetAI_mob_soul_horrorAI(Creature* pCreature) -{ - return new mob_soul_horrorAI(pCreature); -} - -void AddSC_forge_of_souls() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sylvanas_fos"; - newscript->GetAI = &GetAI_npc_sylvanas_fosAI; - newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jaina_fos"; - newscript->GetAI = &GetAI_npc_jaina_fosAI; - newscript->pGossipHello = &GossipHello_npc_jaina_or_slyvanas_fos; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_slyvanas_fos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_spiteful_apparition"; - newscript->GetAI = &GetAI_mob_spiteful_apparitionAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_spectral_warden"; - newscript->GetAI = &GetAI_mob_spectral_wardenAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_watchman"; - newscript->GetAI = &GetAI_mob_soulguard_watchmanAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_reaper"; - newscript->GetAI = &GetAI_mob_soulguard_reaperAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_bonecaster"; - newscript->GetAI = &GetAI_mob_soulguard_bonecasterAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_animator"; - newscript->GetAI = &GetAI_mob_soulguard_animatorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soulguard_adept"; - newscript->GetAI = &GetAI_mob_soulguard_adeptAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_soul_horror"; - newscript->GetAI = &GetAI_mob_soul_horrorAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h deleted file mode 100644 index e0479eb4d2b..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/forge_of_souls.h +++ /dev/null @@ -1,52 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_FORGE_OF_SOULS_H -#define DEF_FORGE_OF_SOULS_H - -enum Data -{ - DATA_BRONJAHM_EVENT, - DATA_DEVOURER_EVENT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_BRONJAHM, - DATA_DEVOURER, -}; - -enum Creatures -{ - CREATURE_BRONJAHM = 36497, - CREATURE_DEVOURER = 36502, - - NPC_SYLVANAS_PART1 = 37596, - NPC_SYLVANAS_PART2 = 38161, - NPC_JAINA_PART1 = 37597, - NPC_JAINA_PART2 = 38160, - NPC_KALIRA = 37583, - NPC_ELANDRA = 37774, - NPC_LORALEN = 37779, - NPC_KORELN = 37582, - NPC_CHAMPION_1_HORDE = 37584, - NPC_CHAMPION_2_HORDE = 37587, - NPC_CHAMPION_3_HORDE = 37588, - NPC_CHAMPION_1_ALLIANCE = 37496, - NPC_CHAMPION_2_ALLIANCE = 37497, -}; -#endif diff --git a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp b/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp deleted file mode 100644 index 67a6cdb4579..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/forge_of_souls/instance_forge_of_souls.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "forge_of_souls.h" - -#define MAX_ENCOUNTER 2 - -/* Forge of Souls encounters: -0- Bronjahm, The Godfather of Souls -1- The Devourer of Souls -*/ - -struct instance_forge_of_souls : public ScriptedInstance -{ - instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiBronjahm; - uint64 uiDevourer; - - uint32 uiEncounter[MAX_ENCOUNTER]; - uint32 uiTeamInInstance; - - void Initialize() - { - uiBronjahm = 0; - uiDevourer = 0; - - uiTeamInInstance = 0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - - if (!players.isEmpty()) - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - - switch(pCreature->GetEntry()) - { - case CREATURE_BRONJAHM: - uiBronjahm = pCreature->GetGUID(); - break; - case CREATURE_DEVOURER: - uiDevourer = pCreature->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_BRONJAHM_EVENT: - uiEncounter[0] = data; - break; - case DATA_DEVOURER_EVENT: - uiEncounter[1] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_BRONJAHM_EVENT: return uiEncounter[0]; - case DATA_DEVOURER_EVENT: return uiEncounter[1]; - case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_BRONJAHM: return uiBronjahm; - case DATA_DEVOURER: return uiBronjahm; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "F S " << uiEncounter[0] << " " << uiEncounter[1]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1; - - if (dataHead1 == 'F' && dataHead2 == 'S') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap) -{ - return new instance_forge_of_souls(pMap); -} - -void AddSC_instance_forge_of_souls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_forge_of_souls"; - newscript->GetInstanceData = &GetInstanceData_instance_forge_of_souls; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp deleted file mode 100644 index c9978faca6e..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_falric.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_AGGRO = -1668050, - SAY_SLAY_1 = -1668051, - SAY_SLAY_2 = -1668052, - SAY_DEATH = -1668053, - SAY_IMPENDING_DESPAIR = -1668054, - SAY_DEFILING_HORROR = -1668055, -}; - -enum Spells -{ - SPELL_QUIVERING_STRIKE = 72422, - SPELL_IMPENDING_DESPAIR = 72426, - SPELL_DEFILING_HORROR = 72435, - SPELL_HOPELESSNESS = 72395, - H_SPELL_HOPELESSNESS = 72390, // TODO: not in dbc. Add in DB. -}; - -enum Events -{ - EVENT_NONE, - EVENT_QUIVERING_STRIKE, - EVENT_IMPENDING_DESPAIR, - EVENT_DEFILING_HORROR, -}; - -struct boss_falricAI : public boss_horAI -{ - boss_falricAI(Creature *pCreature) : boss_horAI(pCreature) {} - - uint8 uiHopelessnessCount; - - void Reset() - { - boss_horAI::Reset(); - - uiHopelessnessCount = 0; - - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 23000); - events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 9000); - events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_FALRIC_EVENT, DONE); - } - - void KilledUnit(Unit *victim) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_QUIVERING_STRIKE: - DoCast(SPELL_QUIVERING_STRIKE); - events.ScheduleEvent(EVENT_QUIVERING_STRIKE, 10000); - break; - case EVENT_IMPENDING_DESPAIR: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - { - DoScriptText(SAY_IMPENDING_DESPAIR, me); - DoCast(pTarget, SPELL_IMPENDING_DESPAIR); - } - events.ScheduleEvent(EVENT_IMPENDING_DESPAIR, 13000); - break; - case EVENT_DEFILING_HORROR: - DoCast(SPELL_DEFILING_HORROR); - events.ScheduleEvent(EVENT_DEFILING_HORROR, urand(25000,45000)); // TODO adjust timer. - break; - } - - if ((uiHopelessnessCount < 1 && HealthBelowPct(66)) - || (uiHopelessnessCount < 2 && HealthBelowPct(33)) - || (uiHopelessnessCount < 3 && HealthBelowPct(10))) - { - uiHopelessnessCount++; - DoCast(DUNGEON_MODE(SPELL_HOPELESSNESS,H_SPELL_HOPELESSNESS)); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_falric(Creature* pCreature) -{ - return new boss_falricAI(pCreature); -} - -void AddSC_boss_falric() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_falric"; - newscript->GetAI = &GetAI_boss_falric; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp deleted file mode 100644 index 95fb2737ce9..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/boss_marwyn.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_AGGRO = -1668060, - SAY_SLAY_1 = -1668061, - SAY_SLAY_2 = -1668062, - SAY_DEATH = -1668063, - SAY_CORRUPTED_FLESH_1 = -1668064, - SAY_CORRUPTED_FLESH_2 = -1668065, -}; - -enum Spells -{ - SPELL_OBLITERATE = 72360, - SPELL_WELL_OF_CORRUPTION = 72362, - SPELL_CORRUPTED_FLESH = 72363, - SPELL_SHARED_SUFFERING = 72368, -}; - -enum Events -{ - EVENT_NONE, - EVENT_OBLITERATE, - EVENT_WELL_OF_CORRUPTION, - EVENT_CORRUPTED_FLESH, - EVENT_SHARED_SUFFERING, -}; - -struct boss_marwynAI : public boss_horAI -{ - boss_marwynAI(Creature *pCreature) : boss_horAI(pCreature) {} - - void Reset() - { - boss_horAI::Reset(); - - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_OBLITERATE, 30000); // TODO Check timer - events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); - events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); - events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); // TODO Check timer - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MARWYN_EVENT, DONE); - } - - void KilledUnit(Unit *victim) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - // Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch (events.ExecuteEvent()) - { - case EVENT_OBLITERATE: - DoCast(SPELL_OBLITERATE); - events.ScheduleEvent(EVENT_OBLITERATE, 30000); - break; - case EVENT_WELL_OF_CORRUPTION: - DoCast(SPELL_WELL_OF_CORRUPTION); - events.ScheduleEvent(EVENT_WELL_OF_CORRUPTION, 13000); - break; - case EVENT_CORRUPTED_FLESH: - DoScriptText(RAND(SAY_CORRUPTED_FLESH_1,SAY_CORRUPTED_FLESH_2), me); - DoCast(SPELL_CORRUPTED_FLESH); - events.ScheduleEvent(EVENT_CORRUPTED_FLESH, 20000); - break; - case EVENT_SHARED_SUFFERING: - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHARED_SUFFERING); - events.ScheduleEvent(EVENT_SHARED_SUFFERING, 20000); - break; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_marwyn(Creature* pCreature) -{ - return new boss_marwynAI(pCreature); -} - -void AddSC_boss_marwyn() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_marwyn"; - newscript->GetAI = &GetAI_boss_marwyn; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp deleted file mode 100644 index fb3d3d5d752..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -enum Yells -{ - SAY_JAINA_INTRO_1 = -1668001, - SAY_JAINA_INTRO_2 = -1668002, - SAY_JAINA_INTRO_3 = -1668003, - SAY_JAINA_INTRO_4 = -1668004, - SAY_UTHER_INTRO_A2_1 = -1668005, - SAY_JAINA_INTRO_5 = -1668006, - SAY_UTHER_INTRO_A2_2 = -1668007, - SAY_JAINA_INTRO_6 = -1668008, - SAY_UTHER_INTRO_A2_3 = -1668009, - SAY_JAINA_INTRO_7 = -1668010, - SAY_UTHER_INTRO_A2_4 = -1668011, - SAY_JAINA_INTRO_8 = -1668012, - SAY_UTHER_INTRO_A2_5 = -1668013, - SAY_JAINA_INTRO_9 = -1668014, - SAY_UTHER_INTRO_A2_6 = -1668015, - SAY_UTHER_INTRO_A2_7 = -1668016, - SAY_JAINA_INTRO_10 = -1668017, - SAY_UTHER_INTRO_A2_8 = -1668018, - SAY_JAINA_INTRO_11 = -1668019, - SAY_UTHER_INTRO_A2_9 = -1668020, - - SAY_SYLVANAS_INTRO_1 = -1668021, - SAY_SYLVANAS_INTRO_2 = -1668022, - SAY_SYLVANAS_INTRO_3 = -1668023, - SAY_UTHER_INTRO_H2_1 = -1668024, - SAY_SYLVANAS_INTRO_4 = -1668025, - SAY_UTHER_INTRO_H2_2 = -1668026, - SAY_SYLVANAS_INTRO_5 = -1668027, - SAY_UTHER_INTRO_H2_3 = -1668028, - SAY_SYLVANAS_INTRO_6 = -1668029, - SAY_UTHER_INTRO_H2_4 = -1668030, - SAY_SYLVANAS_INTRO_7 = -1668031, - SAY_UTHER_INTRO_H2_5 = -1668032, - SAY_UTHER_INTRO_H2_6 = -1668033, - SAY_SYLVANAS_INTRO_8 = -1668034, - SAY_UTHER_INTRO_H2_7 = -1668035, - - SAY_LK_INTRO_1 = -1668036, - SAY_LK_INTRO_2 = -1668037, - SAY_LK_INTRO_3 = -1668038, - SAY_FALRIC_INTRO_1 = -1668039, - SAY_MARWYN_INTRO_1 = -1668040, - SAY_FALRIC_INTRO_2 = -1668041, - - SAY_JAINA_INTRO_END = -1668042, - SAY_SYLVANAS_INTRO_END = -1668043, -}; - -enum Events -{ - EVENT_NONE, - - EVENT_START_INTRO, - EVENT_SKIP_INTRO, - - EVENT_INTRO_A2_1, - EVENT_INTRO_A2_2, - EVENT_INTRO_A2_3, - EVENT_INTRO_A2_4, - EVENT_INTRO_A2_5, - EVENT_INTRO_A2_6, - EVENT_INTRO_A2_7, - EVENT_INTRO_A2_8, - EVENT_INTRO_A2_9, - EVENT_INTRO_A2_10, - EVENT_INTRO_A2_11, - EVENT_INTRO_A2_12, - EVENT_INTRO_A2_13, - EVENT_INTRO_A2_14, - EVENT_INTRO_A2_15, - EVENT_INTRO_A2_16, - EVENT_INTRO_A2_17, - EVENT_INTRO_A2_18, - EVENT_INTRO_A2_19, - - EVENT_INTRO_H2_1, - EVENT_INTRO_H2_2, - EVENT_INTRO_H2_3, - EVENT_INTRO_H2_4, - EVENT_INTRO_H2_5, - EVENT_INTRO_H2_6, - EVENT_INTRO_H2_7, - EVENT_INTRO_H2_8, - EVENT_INTRO_H2_9, - EVENT_INTRO_H2_10, - EVENT_INTRO_H2_11, - EVENT_INTRO_H2_12, - EVENT_INTRO_H2_13, - EVENT_INTRO_H2_14, - EVENT_INTRO_H2_15, - - EVENT_INTRO_LK_1, - EVENT_INTRO_LK_2, - EVENT_INTRO_LK_3, - EVENT_INTRO_LK_4, - EVENT_INTRO_LK_5, - EVENT_INTRO_LK_6, - EVENT_INTRO_LK_7, - EVENT_INTRO_LK_8, - EVENT_INTRO_LK_9, - - EVENT_INTRO_END, -}; - -enum eEnum -{ - ACTION_START_INTRO, - ACTION_SKIP_INTRO, - - QUEST_DELIVRANCE_FROM_THE_PIT_A2 = 24710, - QUEST_DELIVRANCE_FROM_THE_PIT_H2 = 24712, - QUEST_WRATH_OF_THE_LICH_KING_A2 = 24500, - QUEST_WRATH_OF_THE_LICH_KING_H2 = 24802, -}; - -static Position HallsofReflectionLocs[]= -{ - {5283.234863, 1990.946777, 707.695679, 0.929097}, // 2 Loralen Follows - {5408.031250, 2102.918213, 707.695251, 0.792756}, // 9 Sylvanas Follows - {5401.866699, 2110.837402, 707.695251, 0.800610}, // 10 Loralen follows -}; - -static Position SpawnPos = {5262.540527, 1949.693726, 707.695007, 0.808736}; // Jaina/Sylvanas Beginning Position -static Position MoveThronePos = {5306.952148, 1998.499023, 709.341431, 1.277278}; // Jaina/Sylvanas walks to throne -static Position UtherSpawnPos = {5308.310059, 2003.857178, 709.341431, 4.650315}; -static Position LichKingSpawnPos = {5362.917480, 2062.307129, 707.695374, 3.945812}; -static Position LichKingMoveThronePos = {5312.080566, 2009.172119, 709.341431, 3.973301}; // Lich King walks to throne -static Position LichKingMoveAwayPos = {5400.069824, 2102.7131689, 707.69525, 0.843803}; // Lich King walks away - -// AI of Part1: handle the intro till start of gauntlet event. -struct npc_jaina_or_sylvanas_horAI : public ScriptedAI -{ - npc_jaina_or_sylvanas_horAI(Creature *pCreature) : ScriptedAI(pCreature) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint64 uiUther; - uint64 uiLichKing; - - EventMap events; - - void Reset() - { - events.Reset(); - - uiUther = 0; - uiLichKing = 0; - - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetVisibility(VISIBILITY_ON); - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_START_INTRO: - events.ScheduleEvent(EVENT_START_INTRO, 0); - break; - case ACTION_SKIP_INTRO: - events.ScheduleEvent(EVENT_SKIP_INTRO, 0); - break; - } - } - - void UpdateAI(const uint32 diff) - { - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_START_INTRO: - me->GetMotionMaster()->MovePoint(0, MoveThronePos); - // Begining of intro is differents between factions as the speech sequence and timers are differents. - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - events.ScheduleEvent(EVENT_INTRO_A2_1, 0); - else - events.ScheduleEvent(EVENT_INTRO_H2_1, 0); - break; - - // A2 Intro Events - case EVENT_INTRO_A2_1: - DoScriptText(SAY_JAINA_INTRO_3, me); - events.ScheduleEvent(EVENT_INTRO_A2_2, 5000); - break; - case EVENT_INTRO_A2_2: - DoScriptText(SAY_JAINA_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_A2_3, 10000); - break; - case EVENT_INTRO_A2_3: - // TODO: she's doing some kind of spell casting emote - pInstance->HandleGameObject(pInstance->GetData64(DATA_FROSTMOURNE), true); - events.ScheduleEvent(EVENT_INTRO_A2_4, 10000); - break; - case EVENT_INTRO_A2_4: - // spawn UTHER during speach 2 - if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pUther->GetMotionMaster()->MoveIdle(); - pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas - uiUther = pUther->GetGUID(); - } - events.ScheduleEvent(EVENT_INTRO_A2_5, 2000); - break; - case EVENT_INTRO_A2_5: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_1, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_6, 3000); - break; - case EVENT_INTRO_A2_6: - DoScriptText(SAY_JAINA_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_A2_7, 6000); - break; - case EVENT_INTRO_A2_7: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_2, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_8, 6500); - break; - case EVENT_INTRO_A2_8: - DoScriptText(SAY_JAINA_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_A2_9, 2000); - break; - case EVENT_INTRO_A2_9: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_3, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_10, 9000); - break; - case EVENT_INTRO_A2_10: - DoScriptText(SAY_JAINA_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_A2_11, 5000); - break; - case EVENT_INTRO_A2_11: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_4, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_12, 11000); - break; - case EVENT_INTRO_A2_12: - DoScriptText(SAY_JAINA_INTRO_8, me); - events.ScheduleEvent(EVENT_INTRO_A2_13, 4000); - break; - case EVENT_INTRO_A2_13: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_5, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_14, 12500); - break; - case EVENT_INTRO_A2_14: - DoScriptText(SAY_JAINA_INTRO_9, me); - events.ScheduleEvent(EVENT_INTRO_A2_15, 10000); - break; - case EVENT_INTRO_A2_15: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_6, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_16, 22000); - break; - case EVENT_INTRO_A2_16: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_A2_7, pUther); - events.ScheduleEvent(EVENT_INTRO_A2_17, 4000); - break; - case EVENT_INTRO_A2_17: - DoScriptText(SAY_JAINA_INTRO_10, me); - events.ScheduleEvent(EVENT_INTRO_A2_18, 2000); - break; - case EVENT_INTRO_A2_18: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); - DoScriptText(SAY_UTHER_INTRO_A2_8, pUther); - } - events.ScheduleEvent(EVENT_INTRO_A2_19, 11000); - break; - case EVENT_INTRO_A2_19: - DoScriptText(SAY_JAINA_INTRO_11, me); - events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); - break; - - // H2 Intro Events - case EVENT_INTRO_H2_1: - DoScriptText(SAY_SYLVANAS_INTRO_1, me); - events.ScheduleEvent(EVENT_INTRO_H2_2, 8000); - break; - case EVENT_INTRO_H2_2: - DoScriptText(SAY_SYLVANAS_INTRO_2, me); - events.ScheduleEvent(EVENT_INTRO_H2_3, 6000); - break; - case EVENT_INTRO_H2_3: - DoScriptText(SAY_SYLVANAS_INTRO_3, me); - // TODO: she's doing some kind of spell casting emote - events.ScheduleEvent(EVENT_INTRO_H2_4, 6000); - break; - case EVENT_INTRO_H2_4: - // spawn UTHER during speach 2 - if (Creature* pUther = me->SummonCreature(NPC_UTHER, UtherSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pUther->GetMotionMaster()->MoveIdle(); - pUther->SetReactState(REACT_PASSIVE); // be sure he will not aggro arthas - uiUther = pUther->GetGUID(); - } - events.ScheduleEvent(EVENT_INTRO_H2_5, 2000); - break; - case EVENT_INTRO_H2_5: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_1, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_6, 11000); - break; - case EVENT_INTRO_H2_6: - DoScriptText(SAY_SYLVANAS_INTRO_4, me); - events.ScheduleEvent(EVENT_INTRO_H2_7, 3000); - break; - case EVENT_INTRO_H2_7: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_2, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_8, 6000); - break; - case EVENT_INTRO_H2_8: - DoScriptText(SAY_SYLVANAS_INTRO_5, me); - events.ScheduleEvent(EVENT_INTRO_H2_9, 5000); - break; - case EVENT_INTRO_H2_9: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_3, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_10, 19000); - break; - case EVENT_INTRO_H2_10: - DoScriptText(SAY_SYLVANAS_INTRO_6, me); - events.ScheduleEvent(EVENT_INTRO_H2_11, 1500); - break; - case EVENT_INTRO_H2_11: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_4, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_12, 19500); - break; - case EVENT_INTRO_H2_12: - DoScriptText(SAY_SYLVANAS_INTRO_7, me); - events.ScheduleEvent(EVENT_INTRO_H2_13, 2000); - break; - case EVENT_INTRO_H2_13: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->HandleEmoteCommand(EMOTE_ONESHOT_NO); - DoScriptText(SAY_UTHER_INTRO_H2_5, pUther); - } - events.ScheduleEvent(EVENT_INTRO_H2_14, 12000); - break; - case EVENT_INTRO_H2_14: - if (Creature* pUther = me->GetCreature(*me, uiUther)) - DoScriptText(SAY_UTHER_INTRO_H2_6, pUther); - events.ScheduleEvent(EVENT_INTRO_H2_15, 8000); - break; - case EVENT_INTRO_H2_15: - DoScriptText(SAY_SYLVANAS_INTRO_8, me); - events.ScheduleEvent(EVENT_INTRO_LK_1, 2000); - break; - - // Remaining Intro Events common for both faction - case EVENT_INTRO_LK_1: - // Spawn LK in front of door, and make him move to the sword. - if (Creature* pLichKing = me->SummonCreature(NPC_LICH_KING_EVENT, LichKingSpawnPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pLichKing->GetMotionMaster()->MovePoint(0, LichKingMoveThronePos); - pLichKing->SetReactState(REACT_PASSIVE); - uiLichKing = pLichKing->GetGUID(); - } - - if (Creature* pUther = me->GetCreature(*me, uiUther)) - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - DoScriptText(SAY_UTHER_INTRO_A2_9, pUther); - else - DoScriptText(SAY_UTHER_INTRO_H2_7, pUther); - - events.ScheduleEvent(EVENT_INTRO_LK_2, 11000); - break; - - case EVENT_INTRO_LK_2: - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - DoScriptText(SAY_LK_INTRO_1, pLichKing); - events.ScheduleEvent(EVENT_INTRO_LK_3, 2000); - break; - - case EVENT_INTRO_LK_3: - // The Lich King banishes Uther to the abyss. - if (Creature* pUther = me->GetCreature(*me, uiUther)) - { - pUther->DisappearAndDie(); - uiUther = 0; - } - - // He steps forward and removes the runeblade from the heap of skulls. - - events.ScheduleEvent(EVENT_INTRO_LK_4, 4000); - break; - - case EVENT_INTRO_LK_4: - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - DoScriptText(SAY_LK_INTRO_2, pLichKing); - events.ScheduleEvent(EVENT_INTRO_LK_5, 10000); - break; - - case EVENT_INTRO_LK_5: - // summon Falric and Marwyn. then go back to the door - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - pFalric->SetVisibility(VISIBILITY_ON); - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - pMarwyn->SetVisibility(VISIBILITY_ON); - - if (Creature* pLichKing = me->GetCreature(*me, uiLichKing)) - { - pLichKing->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - DoScriptText(SAY_LK_INTRO_3, pLichKing); - } - - events.ScheduleEvent(EVENT_INTRO_LK_6, 8000); - break; - - case EVENT_INTRO_LK_6: - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - DoScriptText(SAY_FALRIC_INTRO_1, pFalric); - - events.ScheduleEvent(EVENT_INTRO_LK_7, 2000); - break; - - case EVENT_INTRO_LK_7: - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - DoScriptText(SAY_MARWYN_INTRO_1, pMarwyn); - - events.ScheduleEvent(EVENT_INTRO_LK_8, 2000); - break; - - case EVENT_INTRO_LK_8: - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - DoScriptText(SAY_FALRIC_INTRO_2, pFalric); - - events.ScheduleEvent(EVENT_INTRO_LK_9, 5000); - break; - - case EVENT_INTRO_LK_9: - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE) - DoScriptText(SAY_JAINA_INTRO_END, me); - else - DoScriptText(SAY_SYLVANAS_INTRO_END, me); - - me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - // TODO: Loralen/Koreln shall run also - events.ScheduleEvent(EVENT_INTRO_END, 10000); - break; - - case EVENT_INTRO_END: - if (pInstance) - pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); // start first wave - - // Loralen or Koreln disappearAndDie() - me->DisappearAndDie(); - break; - - case EVENT_SKIP_INTRO: - // TODO: implement - - if (Creature* pFalric = me->GetCreature(*me, pInstance->GetData64(DATA_FALRIC))) - pFalric->SetVisibility(VISIBILITY_ON); - if (Creature* pMarwyn = me->GetCreature(*me, pInstance->GetData64(DATA_MARWYN))) - pMarwyn->SetVisibility(VISIBILITY_ON); - - me->GetMotionMaster()->MovePoint(0, LichKingSpawnPos); - // TODO: Loralen/Koreln shall run also - - events.ScheduleEvent(EVENT_INTRO_END, 15000); - break; - } - } -}; - -bool GossipHello_npc_sylvanas_hor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_H2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - // once last quest is completed, she offers this shortcut of the starting event - if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_H2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Dark Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - - return true; -} - -bool GossipHello_npc_jaina_hor(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pPlayer->GetQuestStatus(QUEST_DELIVRANCE_FROM_THE_PIT_A2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Can you remove the sword?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - // once last quest of the series is completed, she offers this shortcut of the starting event - if (pPlayer->GetQuestStatus(QUEST_WRATH_OF_THE_LICH_KING_A2) == QUEST_STATUS_COMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "My Lady, I think I hear Arthas coming. Whatever you're going to do, do it quickly.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); - - pPlayer->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); - return true; -} - -bool GossipSelect_npc_jaina_or_sylvanas_hor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_START_INTRO); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->CLOSE_GOSSIP_MENU(); - if (pCreature->AI()) - pCreature->AI()->DoAction(ACTION_SKIP_INTRO); - pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - break; - } - - return true; -} - -enum TrashSpells -{ - // Ghostly Priest - SPELL_SHADOW_WORD_PAIN = 72318, - SPELL_CIRCLE_OF_DESTRUCTION = 72320, - SPELL_COWER_IN_FEAR = 72321, - SPELL_DARK_MENDING = 72322, - - // Phantom Mage - SPELL_FIREBALL = 72163, - SPELL_FLAMESTRIKE = 72169, - SPELL_FROSTBOLT = 72166, - SPELL_CHAINS_OF_ICE = 72121, - SPELL_HALLUCINATION = 72342, - - // Phantom Hallucination (same as phantom mage + HALLUCINATION_2 when dies) - SPELL_HALLUCINATION_2 = 72344, - - // Shadowy Mercenary - SPELL_SHADOW_STEP = 72326, - SPELL_DEADLY_POISON = 72329, - SPELL_ENVENOMED_DAGGER_THROW = 72333, - SPELL_KIDNEY_SHOT = 72335, - - // Spectral Footman - SPELL_SPECTRAL_STRIKE = 72198, - SPELL_SHIELD_BASH = 72194, - SPELL_TORTURED_ENRAGE = 72203, - - // Tortured Rifleman - SPELL_SHOOT = 72208, - SPELL_CURSED_ARROW = 72222, - SPELL_FROST_TRAP = 72215, - SPELL_ICE_SHOT = 72268, -}; - -enum TrashEvents -{ - EVENT_TRASH_NONE, - - // Ghostly Priest - EVENT_SHADOW_WORD_PAIN, - EVENT_CIRCLE_OF_DESTRUCTION, - EVENT_COWER_IN_FEAR, - EVENT_DARK_MENDING, - - // Phantom Mage - EVENT_FIREBALL, - EVENT_FLAMESTRIKE, - EVENT_FROSTBOLT, - EVENT_CHAINS_OF_ICE, - EVENT_HALLUCINATION, - - // Shadowy Mercenary - EVENT_SHADOW_STEP, - EVENT_DEADLY_POISON, - EVENT_ENVENOMED_DAGGER_THROW, - EVENT_KIDNEY_SHOT, - - // Spectral Footman - EVENT_SPECTRAL_STRIKE, - EVENT_SHIELD_BASH, - EVENT_TORTURED_ENRAGE, - - // Tortured Rifleman - EVENT_SHOOT, - EVENT_CURSED_ARROW, - EVENT_FROST_TRAP, - EVENT_ICE_SHOT, -}; - -struct npc_ghostly_priestAI: public ScriptedAI -{ - npc_ghostly_priestAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); // TODO: adjust timers - events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); - events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); - events.ScheduleEvent(EVENT_DARK_MENDING, 20000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_WORD_PAIN: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHADOW_WORD_PAIN); - events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 8000); - return; - case EVENT_CIRCLE_OF_DESTRUCTION: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CIRCLE_OF_DESTRUCTION); - events.ScheduleEvent(EVENT_CIRCLE_OF_DESTRUCTION, 12000); - return; - case EVENT_COWER_IN_FEAR: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_COWER_IN_FEAR); - events.ScheduleEvent(EVENT_COWER_IN_FEAR, 10000); - return; - case EVENT_DARK_MENDING: - // find an ally with missing HP - if (Unit *pTarget = DoSelectLowestHpFriendly(40, DUNGEON_MODE(30000,50000))) - { - DoCast(pTarget, SPELL_DARK_MENDING); - events.ScheduleEvent(EVENT_DARK_MENDING, 20000); - } - else - { - // no friendly unit with missing hp. re-check in just 5 sec. - events.ScheduleEvent(EVENT_DARK_MENDING, 5000); - } - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_phantom_mageAI: public ScriptedAI -{ - npc_phantom_mageAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FIREBALL, 3000); // TODO: adjust timers - events.ScheduleEvent(EVENT_FLAMESTRIKE, 6000); - events.ScheduleEvent(EVENT_FROSTBOLT, 9000); - events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 12000); - events.ScheduleEvent(EVENT_HALLUCINATION, 40000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FIREBALL: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_FIREBALL); - events.ScheduleEvent(EVENT_FIREBALL, 15000); - return; - case EVENT_FLAMESTRIKE: - DoCast(SPELL_FLAMESTRIKE); - events.ScheduleEvent(EVENT_FLAMESTRIKE, 15000); - return; - case EVENT_FROSTBOLT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_FROSTBOLT); - events.ScheduleEvent(EVENT_FROSTBOLT, 15000); - return; - case EVENT_CHAINS_OF_ICE: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CHAINS_OF_ICE); - events.ScheduleEvent(EVENT_CHAINS_OF_ICE, 15000); - return; - case EVENT_HALLUCINATION: - DoCast(SPELL_HALLUCINATION); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_phantom_hallucinationAI: public npc_phantom_mageAI -{ - npc_phantom_hallucinationAI(Creature *c) : npc_phantom_mageAI(c) - { - } - - void JustDied(Unit * /*pWho*/) - { - DoCast(SPELL_HALLUCINATION_2); - } -}; - -struct npc_shadowy_mercenaryAI: public ScriptedAI -{ - npc_shadowy_mercenaryAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); // TODO: adjust timers - events.ScheduleEvent(EVENT_DEADLY_POISON, 5000); - events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); - events.ScheduleEvent(EVENT_KIDNEY_SHOT, 12000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_STEP: - DoCast(SPELL_SHADOW_STEP); - events.ScheduleEvent(EVENT_SHADOW_STEP, 8000); - return; - case EVENT_DEADLY_POISON: - DoCast(me->getVictim(), SPELL_DEADLY_POISON); - events.ScheduleEvent(EVENT_DEADLY_POISON, 10000); - return; - case EVENT_ENVENOMED_DAGGER_THROW: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_ENVENOMED_DAGGER_THROW); - events.ScheduleEvent(EVENT_ENVENOMED_DAGGER_THROW, 10000); - return; - case EVENT_KIDNEY_SHOT: - DoCast(me->getVictim(), SPELL_KIDNEY_SHOT); - events.ScheduleEvent(EVENT_KIDNEY_SHOT, 10000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_spectral_footmanAI: public ScriptedAI -{ - npc_spectral_footmanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); // TODO: adjust timers - events.ScheduleEvent(EVENT_SHIELD_BASH, 10000); - events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SPECTRAL_STRIKE: - DoCast(me->getVictim(), SPELL_SPECTRAL_STRIKE); - events.ScheduleEvent(EVENT_SPECTRAL_STRIKE, 5000); - return; - case EVENT_SHIELD_BASH: - DoCast(me->getVictim(), SPELL_SHIELD_BASH); - events.ScheduleEvent(EVENT_SHIELD_BASH, 5000); - return; - case EVENT_TORTURED_ENRAGE: - DoCast(SPELL_TORTURED_ENRAGE); - events.ScheduleEvent(EVENT_TORTURED_ENRAGE, 15000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct npc_tortured_riflemanAI : public ScriptedAI -{ - npc_tortured_riflemanAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHOOT, 2000); // TODO: adjust timers - events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); - events.ScheduleEvent(EVENT_FROST_TRAP, 1000); - events.ScheduleEvent(EVENT_ICE_SHOT, 15000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHOOT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_SHOOT); - events.ScheduleEvent(EVENT_SHOOT, 2000); - return; - case EVENT_CURSED_ARROW: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_CURSED_ARROW); - events.ScheduleEvent(EVENT_CURSED_ARROW, 10000); - return; - case EVENT_FROST_TRAP: - DoCast(SPELL_FROST_TRAP); - events.ScheduleEvent(EVENT_FROST_TRAP, 30000); - return; - case EVENT_ICE_SHOT: - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_ICE_SHOT); - events.ScheduleEvent(EVENT_ICE_SHOT, 15000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_jaina_or_sylvanas_horAI(Creature* pCreature) -{ - return new npc_jaina_or_sylvanas_horAI(pCreature); -} - -CreatureAI* GetAI_npc_ghostly_priestAI(Creature* pCreature) -{ - return new npc_ghostly_priestAI(pCreature); -} - -CreatureAI* GetAI_npc_phantom_mageAI(Creature* pCreature) -{ - return new npc_phantom_mageAI(pCreature); -} - -CreatureAI* GetAI_npc_phantom_hallucinationAI(Creature* pCreature) -{ - return new npc_phantom_hallucinationAI(pCreature); -} - -CreatureAI* GetAI_npc_shadowy_mercenaryAI(Creature* pCreature) -{ - return new npc_shadowy_mercenaryAI(pCreature); -} - -CreatureAI* GetAI_npc_spectral_footmanAI(Creature* pCreature) -{ - return new npc_spectral_footmanAI(pCreature); -} - -CreatureAI* GetAI_npc_tortured_riflemanAI(Creature* pCreature) -{ - return new npc_tortured_riflemanAI(pCreature); -} - -void AddSC_halls_of_reflection() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_sylvanas_hor_part1"; - newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; - newscript->pGossipHello = &GossipHello_npc_sylvanas_hor; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_jaina_hor_part1"; - newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_horAI; - newscript->pGossipHello = &GossipHello_npc_jaina_hor; - newscript->pGossipSelect = &GossipSelect_npc_jaina_or_sylvanas_hor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_ghostly_priest"; - newscript->GetAI = &GetAI_npc_ghostly_priestAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_phantom_mage"; - newscript->GetAI = &GetAI_npc_phantom_mageAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_phantom_hallucination"; - newscript->GetAI = &GetAI_npc_phantom_hallucinationAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_shadowy_mercenary"; - newscript->GetAI = &GetAI_npc_shadowy_mercenaryAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_spectral_footman"; - newscript->GetAI = &GetAI_npc_spectral_footmanAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_tortured_rifleman"; - newscript->GetAI = &GetAI_npc_tortured_riflemanAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h deleted file mode 100644 index 46ae0cb283c..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/halls_of_reflection.h +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_HALLS_OF_REFLECTION_H -#define DEF_HALLS_OF_REFLECTION_H - -enum Data -{ - DATA_FALRIC_EVENT, - DATA_MARWYN_EVENT, - DATA_LICHKING_EVENT, - DATA_WAVE_COUNT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_FALRIC, - DATA_MARWYN, - DATA_LICHKING, - DATA_FROSTMOURNE, -}; - -enum Creatures -{ - NPC_FALRIC = 38112, - NPC_MARWYN = 38113, - NPC_LICH_KING_EVENT = 37226, - NPC_LICH_KING_BOSS = 36954, - - NPC_UTHER = 37225, - NPC_JAINA_PART1 = 37221, - NPC_JAINA_PART2 = 36955, - NPC_SYLVANAS_PART1 = 37223, - NPC_SYLVANAS_PART2 = 37554, - - NPC_WAVE_MERCENARY = 38177, - NPC_WAVE_FOOTMAN = 38173, - NPC_WAVE_RIFLEMAN = 38176, - NPC_WAVE_PRIEST = 38175, - NPC_WAVE_MAGE = 38172, -}; - -enum GameObjects -{ - GO_FROSTMOURNE = 202302, - GO_FROSTMOURNE_ALTAR = 202236, - GO_FRONT_DOOR = 201976, - GO_ARTHAS_DOOR = 197341, -}; - -enum HorWorldStates -{ - WORLD_STATE_HOR = 4884, - WORLD_STATE_HOR_WAVE_COUNT = 4882, -}; - -// Common actions from Instance Script to Boss Script -enum Actions -{ - ACTION_ENTER_COMBAT, -}; - -// Base class for FALRIC and MARWYN -// handled the summonList and the notification events to/from the InstanceData -struct boss_horAI : ScriptedAI -{ - boss_horAI(Creature *pCreature) : ScriptedAI(pCreature), summons(pCreature) - { - pInstance = me->GetInstanceData(); - } - - InstanceData* pInstance; - EventMap events; - SummonList summons; - - void Reset() - { - events.Reset(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_PASSIVE); - } - - void DamageTaken(Unit *pWho, uint32 &uiDamage) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - uiDamage = 0; - } - - void DoAction(const int32 actionID) - { - switch(actionID) - { - case ACTION_ENTER_COMBAT: // called by InstanceData when boss shall enter in combat. - // Just in case. Should have been done by InstanceData - me->SetVisibility(VISIBILITY_ON); - - // Reset flags - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetReactState(REACT_AGGRESSIVE); - - if (Unit *pUnit = me->SelectNearestTarget()) - AttackStart(pUnit); - - DoZoneInCombat(); - break; - } - } - - void JustSummoned(Creature *pSummoned) - { - summons.Summon(pSummoned); - - if (Unit *pUnit = pSummoned->SelectNearestTarget()) - { - if (pSummoned->AI()) - pSummoned->AI()->AttackStart(pUnit); - else - { - pSummoned->GetMotionMaster()->MoveChase(pUnit); - pSummoned->Attack(pUnit, true); - } - } - - if (pSummoned->AI()) - pSummoned->AI()->DoZoneInCombat(); - } - - void SummonedCreatureDespawn(Creature *pSummoned) - { - summons.Despawn(pSummoned); - if (summons.empty()) - { - if (pSummoned->isAlive()) - pInstance->SetData(DATA_WAVE_COUNT, NOT_STARTED); - else - pInstance->SetData(DATA_WAVE_COUNT, SPECIAL); - } - } -}; - -#endif diff --git a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp deleted file mode 100644 index 7a5d2479b7c..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/halls_of_reflection/instance_halls_of_reflection.cpp +++ /dev/null @@ -1,431 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "halls_of_reflection.h" - -#define MAX_ENCOUNTER 3 - -/* Halls of Reflection encounters: -0- Falric -1- Marwyn -2- The Lich King -*/ - -enum eEnum -{ - ENCOUNTER_WAVE_MERCENARY = 6, - ENCOUNTER_WAVE_FOOTMAN = 10, - ENCOUNTER_WAVE_RIFLEMAN = 6, - ENCOUNTER_WAVE_PRIEST = 6, - ENCOUNTER_WAVE_MAGE = 6, -}; - -enum Events -{ - EVENT_NONE, - EVENT_NEXT_WAVE, - EVENT_START_LICH_KING, -}; - -static Position PriestSpawnPos[ENCOUNTER_WAVE_PRIEST] = -{ - {5277.74,2016.88,707.778,5.96903}, - {5295.88,2040.34,707.778,5.07891}, - {5320.37,1980.13,707.778,2.00713}, - {5280.51,1997.84,707.778,0.296706}, - {5302.45,2042.22,707.778,4.90438}, - {5306.57,1977.47,707.778,1.50098}, -}; - -static Position MageSpawnPos[ENCOUNTER_WAVE_MAGE] = -{ - {5312.75,2037.12,707.778,4.59022}, - {5309.58,2042.67,707.778,4.69494}, - {5275.08,2008.72,707.778,6.21337}, - {5279.65,2004.66,707.778,0.069813}, - {5275.48,2001.14,707.778,0.174533}, - {5316.7,2041.55,707.778,4.50295}, -}; - -static Position MercenarySpawnPos[ENCOUNTER_WAVE_MERCENARY] = -{ - {5302.25,1972.41,707.778,1.37881}, - {5311.03,1972.23,707.778,1.64061}, - {5277.36,1993.23,707.778,0.401426}, - {5318.7,2036.11,707.778,4.2237}, - {5335.72,1996.86,707.778,2.74017}, - {5299.43,1979.01,707.778,1.23918}, -}; - -static Position FootmenSpawnPos[ENCOUNTER_WAVE_FOOTMAN] = -{ - {5306.06,2037,707.778,4.81711}, - {5344.15,2007.17,707.778,3.15905}, - {5337.83,2010.06,707.778,3.22886}, - {5343.29,1999.38,707.778,2.9147}, - {5340.84,1992.46,707.778,2.75762}, - {5325.07,1977.6,707.778,2.07694}, - {5336.6,2017.28,707.778,3.47321}, - {5313.82,1978.15,707.778,1.74533}, - {5280.63,2012.16,707.778,6.05629}, - {5322.96,2040.29,707.778,4.34587}, -}; - -static Position RiflemanSpawnPos[ENCOUNTER_WAVE_RIFLEMAN] = -{ - {5343.47,2015.95,707.778,3.49066}, - {5337.86,2003.4,707.778,2.98451}, - {5319.16,1974,707.778,1.91986}, - {5299.25,2036,707.778,5.02655}, - {5295.64,1973.76,707.778,1.18682}, - {5282.9,2019.6,707.778,5.88176}, -}; - -struct instance_halls_of_reflection : public ScriptedInstance -{ - instance_halls_of_reflection(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiFalric; - uint64 uiMarwyn; - uint64 uiLichKingEvent; - uint64 uiJainaPart1; - uint64 uiSylvanasPart1; - - uint64 uiFrostmourne; - uint64 uiFrostmourneAltar; - uint64 uiArthasDoor; - uint64 uiFrontDoor; - - uint32 uiEncounter[MAX_ENCOUNTER]; - uint32 uiTeamInInstance; - uint32 uiWaveCount; - bool bIntroDone; - - EventMap events; - - void Initialize() - { - events.Reset(); - - uiFalric = 0; - uiMarwyn = 0; - uiLichKingEvent = 0; - uiJainaPart1 = 0; - uiSylvanasPart1 = 0; - - uiFrostmourne = 0; - uiFrostmourneAltar = 0; - uiArthasDoor = 0; - uiFrontDoor = 0; - uiTeamInInstance = 0; - uiWaveCount = 0; - bIntroDone = false; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - if (!add) - return; - - Map::PlayerList const &players = instance->GetPlayers(); - if (!players.isEmpty()) - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - - switch(pCreature->GetEntry()) - { - case NPC_FALRIC: - uiFalric = pCreature->GetGUID(); - break; - case NPC_MARWYN: - uiMarwyn = pCreature->GetGUID(); - break; - case NPC_LICH_KING_EVENT: - uiLichKingEvent = pCreature->GetGUID(); - break; - case NPC_JAINA_PART1: - uiJainaPart1 = pCreature->GetGUID(); - break; - case NPC_SYLVANAS_PART1: - uiSylvanasPart1 = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if (!add) - return; - - // TODO: init state depending on encounters - switch(pGo->GetEntry()) - { - case GO_FROSTMOURNE: - uiFrostmourne = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, false, pGo); - break; - case GO_FROSTMOURNE_ALTAR: - uiFrostmourneAltar = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, true, pGo); - break; - case GO_FRONT_DOOR: - uiFrontDoor = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - HandleGameObject(0, true, pGo); - break; - case GO_ARTHAS_DOOR: - uiArthasDoor = pGo->GetGUID(); - pGo->SetFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - - if (uiEncounter[1] == DONE) - HandleGameObject(0, true, pGo); - else - HandleGameObject(0, false, pGo); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - if (type == DATA_WAVE_COUNT && data == SPECIAL) - { - bIntroDone = true; - events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); - return; - } - - - if (uiWaveCount && data == NOT_STARTED) - DoWipe(); - - switch(type) - { - case DATA_FALRIC_EVENT: - uiEncounter[0] = data; - if (data == DONE) - events.ScheduleEvent(EVENT_NEXT_WAVE, 60000); - break; - case DATA_MARWYN_EVENT: - uiEncounter[1] = data; - if (data == DONE) - HandleGameObject(uiArthasDoor, true); - break; - case DATA_LICHKING_EVENT: - uiEncounter[2] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_FALRIC_EVENT: return uiEncounter[0]; - case DATA_MARWYN_EVENT: return uiEncounter[1]; - case DATA_LICHKING_EVENT: return uiEncounter[2]; - case DATA_WAVE_COUNT: return uiWaveCount; - case DATA_TEAM_IN_INSTANCE: return uiTeamInInstance; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_FALRIC: return uiFalric; - case DATA_MARWYN: return uiMarwyn; - case DATA_LICHKING: return uiLichKingEvent; - case DATA_FROSTMOURNE: return uiFrostmourne; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H R 1 " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 version; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> version >> data0 >> data1 >> data2; - - if (dataHead1 == 'H' && dataHead2 == 'R') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - if (uiEncounter[0] == DONE || uiEncounter[1] == DONE) - bIntroDone = true; - - OUT_LOAD_INST_DATA_COMPLETE; - } - - void AddWave() - { - DoUpdateWorldState(WORLD_STATE_HOR, 1); - DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); - - switch(uiWaveCount) - { - case 1: - case 2: - case 3: - case 4: - if (Creature *pFalric = instance->GetCreature(uiFalric)) - SpawnWave(pFalric); - break; - case 5: - if (GetData(DATA_FALRIC_EVENT) == DONE) - events.ScheduleEvent(EVENT_NEXT_WAVE, 10000); - else if (Creature *pFalric = instance->GetCreature(uiFalric)) - if (pFalric->AI()) - pFalric->AI()->DoAction(ACTION_ENTER_COMBAT); - break; - case 6: - case 7: - case 8: - case 9: - if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) - SpawnWave(pMarwyn); - break; - case 10: - if (GetData(DATA_MARWYN_EVENT) != DONE) // wave should not have been started if DONE. Check anyway to avoid bug exploit! - if (Creature *pMarwyn = instance->GetCreature(uiMarwyn)) - if (pMarwyn->AI()) - pMarwyn->AI()->DoAction(ACTION_ENTER_COMBAT); - break; - } - } - - // Wipe has been detected. Perform cleanup and reset. - void DoWipe() - { - uiWaveCount = 0; - events.Reset(); - DoUpdateWorldState(WORLD_STATE_HOR, 1); - DoUpdateWorldState(WORLD_STATE_HOR_WAVE_COUNT, uiWaveCount); - HandleGameObject(uiFrontDoor, true); - - // TODO - // in case of wipe, the event is normally restarted by jumping into the center of the room. - // As I can't find a trigger area there, just respawn Jaina/Sylvanas so the event may be restarted. - if (Creature* pJaina = instance->GetCreature(uiJainaPart1)) - pJaina->Respawn(); - if (Creature* pSylvanas = instance->GetCreature(uiSylvanasPart1)) - pSylvanas->Respawn(); - - if (Creature* pFalric = instance->GetCreature(uiFalric)) - pFalric->SetVisibility(VISIBILITY_OFF); - if (Creature* pMarwyn = instance->GetCreature(uiMarwyn)) - pMarwyn->SetVisibility(VISIBILITY_OFF); - } - - // spawn a wave on behalf of the summoner. - void SpawnWave(Creature *pSummoner) - { - uint32 index; - - pSummoner->SetVisibility(VISIBILITY_ON); - - // TODO: do composition at random. # of spawn also depends on uiWaveCount - // As of now, it is just one of each. - index = urand(0,ENCOUNTER_WAVE_MERCENARY-1); - pSummoner->SummonCreature(NPC_WAVE_MERCENARY, MercenarySpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_FOOTMAN-1); - pSummoner->SummonCreature(NPC_WAVE_FOOTMAN, FootmenSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_RIFLEMAN-1); - pSummoner->SummonCreature(NPC_WAVE_RIFLEMAN, RiflemanSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_PRIEST-1); - pSummoner->SummonCreature(NPC_WAVE_PRIEST, PriestSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - - index = urand(0,ENCOUNTER_WAVE_MAGE-1); - pSummoner->SummonCreature(NPC_WAVE_MAGE, MageSpawnPos[index], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 0); - } - - void Update(uint32 diff) - { - if (!instance->HavePlayers()) - return; - - events.Update(diff); - - switch(uint32 eventId = events.ExecuteEvent()) - { - case EVENT_NEXT_WAVE: - uiWaveCount++; - AddWave(); - break; - case EVENT_START_LICH_KING: - // TODO - break; - } - } -}; - -InstanceData* GetInstanceData_instance_halls_of_reflection(Map* pMap) -{ - return new instance_halls_of_reflection(pMap); -} - -void AddSC_instance_halls_of_reflection() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_reflection"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_reflection; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp deleted file mode 100644 index 25c78c4a0d3..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_forgemaster_garfrost.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -enum Yells -{ - SAY_AGGRO = -1658001, - SAY_SLAY_1 = -1658002, - SAY_SLAY_2 = -1658003, - SAY_DEATH = -1658004, - SAY_PHASE2 = -1658005, - SAY_PHASE3 = -1658006, - - SAY_TYRANNUS_DEATH = -1659007, -}; - -enum eEvents -{ - EVENT_NONE, - EVENT_PERMAFROST, - EVENT_THROW_SARONITE, - EVENT_CHILLINGWAVE, - EVENT_DEEPFREEZE, -}; - -enum Spells -{ - SPELL_PERMAFROST = 70326, - SPELL_PERMAFROST_TRIGGER = 68786, // triggered by PERMAFROST. Used to check aura - SPELL_THROW_SARONITE = 68788, - SPELL_THUNDERING_STOMP = 68771, - SPELL_CHILLING_WAVE = 68778, - H_SPELL_CHILLING_WAVE = 70333, - SPELL_DEEP_FREEZE = 70381, - H_SPELL_DEEP_FREEZE = 72930, - SPELL_FORGE_MACE = 68785, - H_SPELL_FORGE_MACE = 70335, - SPELL_FORGE_BLADE = 68774, - H_SPELL_FORGE_BLADE = 70334, -}; - -enum eEnums -{ - EQUIP_ID_SWORD = 49345, - EQUIP_ID_MACE = 49344, - ACHIEV_DOESNT_GO_TO_ELEVEN = 4524, -}; - -struct boss_garfrostAI : public ScriptedAI -{ - boss_garfrostAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - bool phase2; - bool phase3; - bool bAchievement; - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - phase2 = false; - phase3 = false; - bAchievement = true; - - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCast(me, SPELL_PERMAFROST); - - if (pInstance) - pInstance->SetData(DATA_GARFROST_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_THROW_SARONITE, 45000); - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32& /*uiDamage*/) - { - if (HealthBelowPct(66) && !phase2) - { - phase2 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_BLADE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.ScheduleEvent(EVENT_CHILLINGWAVE, 10000); - } - - if (HealthBelowPct(33) && !phase3) - { - phase3 = true; - DoCast(me, SPELL_THUNDERING_STOMP); - // TODO: should go to a forge - DoCast(me, SPELL_FORGE_MACE); - // TODO: should equip when spell completes - SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); - me->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); - events.CancelEvent(EVENT_CHILLINGWAVE); // cast only in phase 2. - events.ScheduleEvent(EVENT_DEEPFREEZE, 10000); - } - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - { - if (Creature *pTyrannus = me->GetCreature(*me, pInstance->GetData64(DATA_TYRANNUS))) - DoScriptText(SAY_TYRANNUS_DEATH, pTyrannus); - - pInstance->SetData(DATA_GARFROST_EVENT, DONE); - if (IsHeroic() && bAchievement) - pInstance->DoCompleteAchievement(ACHIEV_DOESNT_GO_TO_ELEVEN); - } - } - - void SpellHitTarget(Unit* pTarget, const SpellEntry *spell) - { - if (spell->Id == SPELL_PERMAFROST_TRIGGER && bAchievement) - { - if (Aura *pAura = pTarget->GetAura(SPELL_PERMAFROST_TRIGGER)) - if (pAura->GetStackAmount() > 10) - bAchievement = false; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_THROW_SARONITE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_THROW_SARONITE); - events.RescheduleEvent(EVENT_THROW_SARONITE, 35000); - return; - case EVENT_DEEPFREEZE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_DEEP_FREEZE); - events.RescheduleEvent(EVENT_DEEPFREEZE, 35000); - return; - case EVENT_CHILLINGWAVE: - DoCastAOE(SPELL_CHILLING_WAVE); - events.RescheduleEvent(EVENT_CHILLINGWAVE, 40000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_garfrost(Creature* pCreature) -{ - return new boss_garfrostAI (pCreature); -} - -void AddSC_boss_garfrost() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_garfrost"; - newscript->GetAI = &GetAI_boss_garfrost; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp deleted file mode 100644 index 8b8b03a3d4e..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_krickandick.cpp +++ /dev/null @@ -1,482 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/* - * SDComment: Spell Explosive barrage is not working. - */ - -enum Spells -{ - SPELL_PURSUED = 68987, - SPELL_CONFUSION = 69029, - SPELL_EXPLOSIVE_BARRAGE = 69263, - SPELL_MIGHTY_KICK = 69021, - SPELL_POISON_NOVA = 68989, - H_SPELL_POISON_NOVA = 70434, - SPELL_SHADOW_BOLT = 69028, - SPELL_TOXIC_WASTE = 69024, - H_SPELL_TOXIC_WASTE = 70436, -}; - -enum Yells -{ - // Krick - SAY_KRICK_AGGRO = -1658010, - SAY_KRICK_SLAY_1 = -1658011, - SAY_KRICK_SLAY_2 = -1658012, - SAY_KRICK_BARRAGE_1 = -1658013, - SAY_KRICK_BARRAGE_2 = -1658014, - SAY_KRICK_POISON_NOVA = -1658015, - SAY_KRICK_CHASE_1 = -1658016, - SAY_KRICK_CHASE_2 = -1658017, - SAY_KRICK_CHASE_3 = -1658018, - - // Ick - SAY_ICK_POISON_NOVA = -1658020, - SAY_ICK_CHASE_1 = -1658021, - - // OUTRO - SAY_KRICK_OUTRO_1 = -1658030, - SAY_JAYNA_OUTRO_2 = -1658031, - SAY_SYLVANAS_OUTRO_2 = -1658032, - SAY_KRICK_OUTRO_3 = -1658033, - SAY_JAYNA_OUTRO_4 = -1658034, - SAY_SYLVANAS_OUTRO_4 = -1658035, - SAY_KRICK_OUTRO_5 = -1658036, - SAY_TYRANNUS_OUTRO_7 = -1658037, - SAY_KRICK_OUTRO_8 = -1658038, - SAY_TYRANNUS_OUTRO_9 = -1658039, - SAY_JAYNA_OUTRO_10 = -1658040, - SAY_SYLVANAS_OUTRO_10 = -1658041, -}; - -enum Events -{ - EVENT_NONE, - EVENT_PURSUE, - EVENT_MIGHTY_KICK, - EVENT_POISON_NOVA, - EVENT_EXPLOSIVE_BARRAGE, - EVENT_END_EXPLOSIVE_BARRAGE, - - // Krick - EVENT_SHADOW_BOLT, - EVENT_TOXIC_WASTE, - - // Krick OUTRO - EVENT_OUTRO_1, - EVENT_OUTRO_2, - EVENT_OUTRO_3, - EVENT_OUTRO_4, - EVENT_OUTRO_5, - EVENT_OUTRO_6, - EVENT_OUTRO_7, - EVENT_OUTRO_8, - EVENT_OUTRO_9, - EVENT_OUTRO_10, - EVENT_OUTRO_11, - EVENT_OUTRO_12, - EVENT_OUTRO_END, -}; - -enum KrickPhase -{ - PHASE_COMBAT, - PHASE_OUTRO, -}; - -enum Actions -{ - ACTION_OUTRO, -}; - -enum Misc -{ - SEAT_KRICK = 0, - - // events GCD. Shall not be 0. - GCD_1 = 1, -}; - -// Krick is the Gnome. -// Ick is the Mount -// Common Events are handled/triggered by Ick that "drive" Krick through DoAction. - -struct boss_ickAI : public ScriptedAI -{ - boss_ickAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, NOT_STARTED); - } - - Creature* GetKrick() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_KRICK) : 0); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, IN_PROGRESS); - - Creature* pKrick = GetKrick(); - if (!pKrick) - pKrick = me->SummonCreature(CREATURE_KRICK, *me, TEMPSUMMON_MANUAL_DESPAWN); - - if (pKrick) - DoScriptText(SAY_KRICK_AGGRO, pKrick); - - events.ScheduleEvent(EVENT_MIGHTY_KICK, 20000, GCD_1); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 35000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - } - - void EnterEvadeMode() - { - me->GetMotionMaster()->Clear(); - ScriptedAI::EnterEvadeMode(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (Creature* pKrick = GetKrick()) - { - if (pKrick->AI()) - pKrick->AI()->DoAction(ACTION_OUTRO); - } - - if (pInstance) - pInstance->SetData(DATA_KRICKANDICK_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - return; - - if (!me->getVictim() && me->getThreatManager().isThreatListEmpty()) - { - EnterEvadeMode(); - return; - } - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - switch(events.ExecuteEvent()) - { - case EVENT_PURSUE: - if (Creature* pKrick = GetKrick()) - DoScriptText(RAND(SAY_KRICK_CHASE_1,SAY_KRICK_CHASE_2,SAY_KRICK_CHASE_3), pKrick); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->Attack(pTarget,false); - DoScriptText(SAY_ICK_CHASE_1, me, pTarget); - DoCast(pTarget, SPELL_PURSUED); - } - - DoCast(SPELL_CONFUSION); - events.ScheduleEvent(EVENT_PURSUE, 30000, GCD_1); - return; - - case EVENT_MIGHTY_KICK: - DoCast(me->getVictim(), SPELL_MIGHTY_KICK); - events.ScheduleEvent(EVENT_MIGHTY_KICK, 25000, GCD_1); - return; - - case EVENT_POISON_NOVA: - if (Creature* pKrick = GetKrick()) - DoScriptText(SAY_KRICK_POISON_NOVA, pKrick); - - DoScriptText(SAY_ICK_POISON_NOVA, me); - DoCastAOE(SPELL_POISON_NOVA); - events.ScheduleEvent(EVENT_POISON_NOVA, 30000, GCD_1); - return; - - case EVENT_TOXIC_WASTE: - DoCast(me->getVictim(), SPELL_TOXIC_WASTE); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 5000); - return; - - case EVENT_SHADOW_BOLT: - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - events.ScheduleEvent(EVENT_SHADOW_BOLT, 15000); - return; - - case EVENT_EXPLOSIVE_BARRAGE: - if (Creature *pKrick = GetKrick()) - { - DoScriptText(SAY_KRICK_BARRAGE_1, pKrick); - DoScriptText(SAY_KRICK_BARRAGE_2, pKrick); - } - - DoCastAOE(SPELL_EXPLOSIVE_BARRAGE); - me->GetMotionMaster()->MoveIdle(); - events.DelayEvents(20000, GCD_1); // 2 sec cast + 18 sec - events.ScheduleEvent(EVENT_END_EXPLOSIVE_BARRAGE, 20000); - return; - - case EVENT_END_EXPLOSIVE_BARRAGE: - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - events.ScheduleEvent(EVENT_EXPLOSIVE_BARRAGE, 25000); - break; - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_krickAI : public ScriptedAI -{ - boss_krickAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - KrickPhase phase; - uint64 uiNpcOutroDialog; - uint64 uiTyrannus; - - void Reset() - { - uiNpcOutroDialog = 0; - uiTyrannus = 0; - phase = PHASE_COMBAT; - - me->SetReactState(REACT_PASSIVE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetVisibility(VISIBILITY_OFF); - } - - Creature* GetIck() - { - return me->GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ICK) : 0); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_KRICK_SLAY_1,SAY_KRICK_SLAY_2), me); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - // if killed whatever the reason, it breaks the outro - uiDamage = 0; - } - - void DoAction(const int32 actionId) - { - switch(actionId) - { - case ACTION_OUTRO: - { - Position pos; - if (Creature* pIck = GetIck()) - { - // TODO: tele on Ick then run some distance. - pIck->GetNearPosition(pos, 5.0f, 3.14); - me->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), 0.0f); - } - me->SetVisibility(VISIBILITY_ON); - - Creature* pJainaOrSylvanas = me->GetCreature(*me, pInstance->GetData64(DATA_JAINA_SYLVANAS_1)); - if (pJainaOrSylvanas) { - Position pos; - me->GetNearPosition(pos, 5.0f, 0); - pJainaOrSylvanas->NearTeleportTo(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), - pos.GetAngle(me->GetPositionX(), me->GetPositionY())); - } - else { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - pJainaOrSylvanas = me->SummonCreature(NPC_SYLVANAS_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - else - pJainaOrSylvanas = me->SummonCreature(NPC_JAINA_PART1, *me, TEMPSUMMON_MANUAL_DESPAWN); - } - - if (pJainaOrSylvanas) - { - pJainaOrSylvanas->SetOrientation(pJainaOrSylvanas->GetAngle(me->GetPositionX(), me->GetPositionY())); - me->SetOrientation(me->GetAngle(pJainaOrSylvanas->GetPositionX(), pJainaOrSylvanas->GetPositionY())); - uiNpcOutroDialog = pJainaOrSylvanas->GetGUID(); - } - - phase = PHASE_OUTRO; - events.Reset(); - events.ScheduleEvent(EVENT_OUTRO_1, 1000); - break; - } - } - } - - void UpdateAI(const uint32 diff) - { - if (phase == PHASE_OUTRO) - { - if (!pInstance) - return; - - events.Update(diff); - switch(events.ExecuteEvent()) - { - case EVENT_OUTRO_1: - { - DoScriptText(SAY_KRICK_OUTRO_1, me); - events.ScheduleEvent(EVENT_OUTRO_2, 14000); - break; - } - case EVENT_OUTRO_2: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_2, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_2, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_3, 8500); - break; - } - case EVENT_OUTRO_3: - DoScriptText(SAY_KRICK_OUTRO_3, me); - events.ScheduleEvent(EVENT_OUTRO_4, 12000); - break; - case EVENT_OUTRO_4: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_4, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_4, pNpcDialog); - } - events.ScheduleEvent(EVENT_OUTRO_5, 8000); - break; - } - case EVENT_OUTRO_5: - DoScriptText(SAY_KRICK_OUTRO_5, me); - events.ScheduleEvent(EVENT_OUTRO_6, 4000); - break; - case EVENT_OUTRO_6: - // TODO spawn Tyrannus at some distance and MovePoint near-by (flying on rimefang) - // store uiTyrannus - // Adjust timer so tyrannus has time to come - uiTyrannus = (pInstance ? pInstance->GetData64(DATA_TYRANNUS) : 0); - events.ScheduleEvent(EVENT_OUTRO_7, 1); - break; - case EVENT_OUTRO_7: - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_7, pTyrannus); - events.ScheduleEvent(EVENT_OUTRO_8, 7000); - break; - case EVENT_OUTRO_8: - DoScriptText(SAY_KRICK_OUTRO_8, me); - // TODO: Tyrannus starts killing Krick. - // there shall be some visual spell effect - events.ScheduleEvent(EVENT_OUTRO_9, 6000); - break; - case EVENT_OUTRO_9: - // tyrannus kills krick - me->SetStandState(UNIT_STAND_STATE_DEAD); - me->SetHealth(0); - - if (Creature *pTyrannus = me->GetCreature(*me, uiTyrannus)) - DoScriptText(SAY_TYRANNUS_OUTRO_9, pTyrannus); - - events.ScheduleEvent(EVENT_OUTRO_10, 12000); - break; - case EVENT_OUTRO_10: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - { - if (pInstance->GetData(DATA_TEAM_IN_INSTANCE) == TEAM_ALLIANCE) - DoScriptText(SAY_JAYNA_OUTRO_10, pNpcDialog); - else - DoScriptText(SAY_SYLVANAS_OUTRO_10, pNpcDialog); - } - - // End of OUTRO. for now... - events.ScheduleEvent(EVENT_OUTRO_END, 8000); - break; - } - case EVENT_OUTRO_END: - { - Creature* pNpcDialog = me->GetCreature(*me, uiNpcOutroDialog); - if (pNpcDialog) - pNpcDialog->DisappearAndDie(); - - me->DisappearAndDie(); - break; - } - } - return; - } - } -}; - -CreatureAI* GetAI_boss_ick(Creature* pCreature) -{ - return new boss_ickAI(pCreature); -} - -CreatureAI* GetAI_boss_krick(Creature* pCreature) -{ - return new boss_krickAI(pCreature); -} - -void AddSC_boss_ick() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ick"; - newscript->GetAI = &GetAI_boss_ick; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_krick"; - newscript->GetAI = &GetAI_boss_krick; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp deleted file mode 100644 index 55ffa0b4e4b..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/boss_scourgelord_tyrannus.cpp +++ /dev/null @@ -1,273 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/* - * SDComment: TODO: - * - implement aura for spell Overlord Brand. - * - Intro/Outro - * - improve script of Rimefang - */ - -enum Yells -{ - SAY_AMBUSH_1 = -1658050, - SAY_AMBUSH_2 = -1658051, - SAY_GAUNTLET_START = -1658052, - SAY_INTRO_1 = -1658053, - SAY_INTRO_2 = -1658054, - - SAY_AGGRO = -1658055, - SAY_SLAY_1 = -1658056, - SAY_SLAY_2 = -1658057, - SAY_DEATH = -1658058, - SAY_MARK_RIMEFANG_1 = -1658059, - SAY_MARK_RIMEFANG_2 = -1658060, - SAY_DARK_MIGHT_1 = -1658061, - SAY_DARK_MIGHT_2 = -1658062, - - SAY_GORKUN_OUTRO_1 = -1658063, - SAY_GORKUN_OUTRO_2 = -1658064, - SAY_JAYNA_OUTRO_3 = -1658065, - SAY_SYLVANAS_OUTRO_3 = -1658066, - SAY_JAYNA_OUTRO_4 = -1658067, - SAY_SYLVANAS_OUTRO_4 = -1658068, - SAY_JAYNA_OUTRO_5 = -1658069, -}; - -enum Spells -{ - SPELL_FORCEFUL_SMASH = 69155, - H_SPELL_FORCEFUL_SMASH = 69627, - SPELL_OVERLORDS_BRAND = 69172, - SPELL_DARK_MIGHT = 69167, - H_SPELL_DARK_MIGHT = 69629, - SPELL_HOARFROST = 69246, - SPELL_MARK_OF_RIMEFANG = 69275, - SPELL_ICY_BLAST = 69233, - H_SPELL_ICY_BLAST = 69646, - SPELL_ICY_BLAST_2 = 69238, - H_SPELL_ICY_BLAST_2 = 69628, -}; - -enum Events -{ - EVENT_NONE, - EVENT_FORCEFUL_SMASH, - EVENT_OVERLORDS_BRAND, - EVENT_DARK_MIGHT, - - // Rimefang - EVENT_MARK_OF_RIMEFANG, - EVENT_HOARFROST, - EVENT_ICY_BLAST, - EVENT_ICY_BLAST_2, -}; - -enum Misc -{ - SEAT_TYRANNUS = 0 -}; - -struct boss_tyrannusAI : public ScriptedAI -{ - boss_tyrannusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - events.Reset(); - - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, NOT_STARTED); - } - - Creature* GetRimefang() - { - return me->GetCreature(*me, pInstance->GetData64(DATA_RIMEFANG)); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - me->ExitVehicle(); - - // restore health if any damage done during intro - me->SetHealth(me->GetMaxHealth()); - - if (pInstance) - pInstance->SetData(DATA_TYRANNUS_EVENT, IN_PROGRESS); - - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 35000); - events.ScheduleEvent(EVENT_DARK_MIGHT, 40000); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_TYRANNUS_EVENT, DONE); - if (Creature* pRimefang = GetRimefang()) - pRimefang->ForcedDespawn(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FORCEFUL_SMASH: - DoCast(me->getVictim(), SPELL_FORCEFUL_SMASH); - events.ScheduleEvent(EVENT_FORCEFUL_SMASH, 10000); - return; - case EVENT_OVERLORDS_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_OVERLORDS_BRAND); - events.ScheduleEvent(EVENT_OVERLORDS_BRAND, 45000); - return; - case EVENT_DARK_MIGHT: - DoScriptText(SAY_DARK_MIGHT_1, me); - DoScriptText(SAY_DARK_MIGHT_2, me); - DoCast(me, SPELL_DARK_MIGHT); - events.ScheduleEvent(EVENT_DARK_MIGHT, 60000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct boss_rimefangAI : public ScriptedAI -{ - boss_rimefangAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - EventMap events; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - me->InterruptSpell(CURRENT_GENERIC_SPELL); - me->HandleEmoteCommand(EMOTE_ONESHOT_LIFTOFF); - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 25000); - events.ScheduleEvent(EVENT_ICY_BLAST, 35000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_MARK_OF_RIMEFANG: - DoScriptText(SAY_MARK_RIMEFANG_1, me); - DoScriptText(SAY_MARK_RIMEFANG_2, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_MARK_OF_RIMEFANG); - events.ScheduleEvent(EVENT_HOARFROST, 5000); - return; - case EVENT_HOARFROST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HOARFROST); - events.ScheduleEvent(EVENT_MARK_OF_RIMEFANG, 20000); - return; - case EVENT_ICY_BLAST: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ICY_BLAST); - events.ScheduleEvent(EVENT_ICY_BLAST_2, 5000); - return; - case EVENT_ICY_BLAST_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget->getVictim(), SPELL_ICY_BLAST_2); - events.ScheduleEvent(EVENT_ICY_BLAST, 30000); - return; - } - } - } -}; - -CreatureAI* GetAI_boss_tyrannus(Creature* pCreature) -{ - return new boss_tyrannusAI(pCreature); -} - -CreatureAI* GetAI_boss_rimefang(Creature* pCreature) -{ - return new boss_rimefangAI(pCreature); -} - -void AddSC_boss_tyrannus() -{ - Script *newscript; - newscript = new Script; - newscript->Name="boss_tyrannus"; - newscript->GetAI = &GetAI_boss_tyrannus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="boss_rimefang"; - newscript->GetAI = &GetAI_boss_rimefang; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp deleted file mode 100644 index 8512eca24c1..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/instance_pit_of_saron.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -#define MAX_ENCOUNTER 3 - -/* Pit of Saron encounters: -0- Forgemaster Garfrost -1- Krick and Ick -2- Scourgelord Tyrannus -*/ - -struct instance_pit_of_saron : public ScriptedInstance -{ - instance_pit_of_saron(Map* pMap) : ScriptedInstance(pMap) {}; - - uint64 uiKrick; - uint64 uiIck; - uint64 uiGarfrost; - uint64 uiTyrannus; - uint64 uiRimefang; - - uint64 uiJainaOrSylvanas1; - uint64 uiJainaOrSylvanas2; - - uint32 uiTeamInInstance; - uint32 uiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - uiEncounter[i] = NOT_STARTED; - - uiGarfrost = 0; - uiKrick = 0; - uiIck = 0; - uiTyrannus = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - uiTeamInInstance = pPlayer->GetTeam(); - } - - switch(pCreature->GetEntry()) - { - case CREATURE_KRICK: - uiKrick = pCreature->GetGUID(); - break; - - case CREATURE_ICK: - uiIck = pCreature->GetGUID(); - break; - - case CREATURE_GARFROST: - uiGarfrost = pCreature->GetGUID(); - break; - - case CREATURE_TYRANNUS: - uiTyrannus = pCreature->GetGUID(); - break; - - case CREATURE_RIMEFANG: - uiRimefang = pCreature->GetGUID(); - break; - - case NPC_SYLVANAS_PART1: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_JAINA_PART1, ALLIANCE); - uiJainaOrSylvanas1 = pCreature->GetGUID(); - break; - case NPC_SYLVANAS_PART2: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_JAINA_PART2, ALLIANCE); - uiJainaOrSylvanas2 = pCreature->GetGUID(); - break; - case NPC_KILARA: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_ELANDRA, ALLIANCE); - break; - case NPC_KORALEN: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_KORLAEN, ALLIANCE); - break; - case NPC_CHAMPION_1_HORDE: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_1_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_2_HORDE: - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - case NPC_CHAMPION_3_HORDE: // No 3rd set for Alliance? - if (uiTeamInInstance == ALLIANCE) - pCreature->UpdateEntry(NPC_CHAMPION_2_ALLIANCE, ALLIANCE); - break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_GARFROST: return uiGarfrost; - case DATA_KRICK: return uiKrick; - case DATA_ICK: return uiIck; - case DATA_TYRANNUS: return uiTyrannus; - case DATA_RIMEFANG: return uiRimefang; - - case DATA_JAINA_SYLVANAS_1: return uiJainaOrSylvanas1; - case DATA_JAINA_SYLVANAS_2: return uiJainaOrSylvanas2; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_GARFROST_EVENT: - uiEncounter[0] = data; - break; - case DATA_TYRANNUS_EVENT: - uiEncounter[1] = data; - break; - case DATA_KRICKANDICK_EVENT: - uiEncounter[2] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_GARFROST_EVENT: return uiEncounter[0]; - case DATA_TYRANNUS_EVENT: return uiEncounter[1]; - case DATA_KRICKANDICK_EVENT: return uiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::string str_data; - - std::ostringstream saveStream; - saveStream << "P S " << uiEncounter[0] << " " << uiEncounter[1] << " " << uiEncounter[2]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2; - - if (dataHead1 == 'P' && dataHead2 == 'S') - { - uiEncounter[0] = data0; - uiEncounter[1] = data1; - uiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (uiEncounter[i] == IN_PROGRESS) - uiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_pit_of_saron(Map* pMap) -{ - return new instance_pit_of_saron(pMap); -} - -void AddSC_instance_pit_of_saron() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_pit_of_saron"; - newscript->GetInstanceData = &GetInstanceData_instance_pit_of_saron; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp deleted file mode 100644 index bc53efc7033..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.cpp +++ /dev/null @@ -1,1101 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "pit_of_saron.h" - -/***************************************SPELLS*************************************/ -// Ymirjar Wrathbringer -#define SPELL_BLIGHT DUNGEON_MODE(69603,70285) - -//Ymirjar Skycaller -#define SPELL_FROSTBLADE 70291 -#define SPELL_GLACIAL_STRIKE 70292 - -//Ymirjar Flamebearer -#define SPELL_FIREBALL DUNGEON_MODE(69583,70282) -#define SPELL_HELLFIRE DUNGEON_MODE(69586,70283) -#define SPELL_TACTICAL_BLINK 69584 - -//Ymirjar Deathbringer -#define SPELL_EMPOWERED_SHADOW_BOLT DUNGEON_MODE(69528,70281) -#define SPELL_SUMMON_UNDEAD 69516 - -//Wrathbone Laborer -#define SPELL_BLINDING_DIRT 70302 -#define SPELL_PUNCTURE_WOUND DUNGEON_MODE(70278,70279) -#define SPELL_SHOVELLED DUNGEON_MODE(69572,70280) - -//Wrathbone Coldwraith -#define SPELL_FREEZING_CIRCLE DUNGEON_MODE(69574,70276) -#define SPELL_FROSTBOLT DUNGEON_MODE(69573,70277) - -//Stonespine Gargoyle -#define SPELL_GARGOYLE_STRIKE DUNGEON_MODE(69520,70275) -#define SPELL_STONEFORM 69575 - -// Plagueborn Horror -#define SPELL_BLIGHT_BOMB 69582 -#define SPELL_PUSTULANT_FLESH DUNGEON_MODE(69581,70273) -#define SPELL_TOXIC_WASTE 70274 - -//Iceborn Proto-Drake -#define SPELL_FROST_BREATH DUNGEON_MODE(69527,70272) - -//Hungering Ghoul -#define SPELL_DEVOUR_FLESH 70393 - -//Fallen Warrior -#define SPELL_ARCING_SLICE 69579 -#define SPELL_DEMORALIZING_SHOUT 61044 -#define SPELL_SHIELD_BLOCK 69580 - -//Deathwhisper Torturer -#define SPELL_BLACK_BRAND 70392 -#define SPELL_CURSE_OF_AGONY 70391 - -//Deathwhisper Shadowcaster -#define SPELL_SHADOW_BOLT DUNGEON_MODE(70386,70387) - -//Deathwhisper Necrolyte -#define SPELL_CONVERSION_BEAM DUNGEON_MODE(69578,70269) -#define SPELL_SHADOW_BOLT_2 DUNGEON_MODE(69577,70270) - -//Wrathbone Sorcerer -#define SPELL_SHADOW_BOLT_3 DUNGEON_MODE(70386,70387) - -//Geist Ambusher -#define SPELL_LEAPING_FACE_MAUL DUNGEON_MODE(69504,70271) - -/****************************************EVENTS************************************/ -enum eEvents -{ - EVENT_NONE, - - // Ymirjar Wrathbringer - EVENT_BLIGHT, - - // Ymirjar Skycaller - EVENT_FROSTBLADE, - EVENT_GLACIAL_STRIKE, - - // Ymirjar Flamebearer - EVENT_FIREBALL, - EVENT_HELLFIRE, - EVENT_TACTICAL_BLINK, - - //Ymirjar Deathbringer - EVENT_EMPOWERED_SHADOW_BOLT, - EVENT_SUMMON_UNDEAD, - - //Wrathbone Laborer - EVENT_BLINDING_DIRT, - EVENT_PUNCTURE_WOUND, - EVENT_SHOVELLED, - - //Wrathbone Coldwraith - EVENT_FREEZING_CIRCLE, - EVENT_FROSTBOLT, - - //Stonespine Gargoyle - EVENT_GARGOYLE_STRIKE, - EVENT_STONEFORM, - - //Plagueborn Horror - EVENT_BLIGHT_BOMB, - EVENT_PUSTULANT_FLESH, - EVENT_TOXIC_WASTE, - - //Iceborn Proto-Drake - EVENT_FROST_BREATH, - - //Hungering Ghoul - EVENT_DEVOUR_FLESH, - - //Fallen Warrior - EVENT_ARCING_SLICE, - EVENT_DEMORALIZING_SHOUT, - EVENT_SHIELD_BLOCK, - - //Deathwhisper Torturer - EVENT_BLACK_BRAND, - EVENT_CURSE_OF_AGONY, - - //Deathwhisper Shadowcaster - EVENT_SHADOW_BOLT, - - //Deathwhisper Necrolyte - EVENT_CONVERSION_BEAM, - EVENT_SHADOW_BOLT_2, - - EVENT_SHADOW_BOLT_3, - - //Geist Ambusher - EVENT_LEAPING_FACE_MAUL, -}; - -/****************************************AI****************************************/ -struct mob_ymirjar_wrathbringerAI : public ScriptedAI -{ - mob_ymirjar_wrathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT, 7000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLIGHT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLIGHT); - events.RescheduleEvent(EVENT_BLIGHT, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_skyCallerAI: public ScriptedAI -{ - mob_ymirjar_skyCallerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROSTBLADE, 1); - events.ScheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_GLACIAL_STRIKE: - DoCast(me->getVictim(), SPELL_GLACIAL_STRIKE); - events.RescheduleEvent(EVENT_GLACIAL_STRIKE, 8000); - return; - case EVENT_FROSTBLADE: - DoCast(me, SPELL_FROSTBLADE); - events.CancelEvent(EVENT_FROSTBLADE); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_flamebearerAI: public ScriptedAI -{ - mob_ymirjar_flamebearerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FIREBALL, 4000); - events.ScheduleEvent(EVENT_HELLFIRE, 8000); - events.ScheduleEvent(EVENT_TACTICAL_BLINK, 15000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FIREBALL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FIREBALL); - events.RescheduleEvent(EVENT_FIREBALL, 5000); - return; - case EVENT_HELLFIRE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_HELLFIRE); - events.RescheduleEvent(EVENT_HELLFIRE, 10000); - return; - case EVENT_TACTICAL_BLINK: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_TACTICAL_BLINK); - events.RescheduleEvent(EVENT_TACTICAL_BLINK, 12000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_ymirjar_deathbringerAI: public ScriptedAI -{ - mob_ymirjar_deathbringerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_EMPOWERED_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_EMPOWERED_SHADOW_BOLT); - events.RescheduleEvent(EVENT_EMPOWERED_SHADOW_BOLT, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_laborerAI: public ScriptedAI -{ - mob_wrathbone_laborerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLINDING_DIRT, 8000); - events.ScheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - events.ScheduleEvent(EVENT_SHOVELLED, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLINDING_DIRT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLINDING_DIRT); - events.RescheduleEvent(EVENT_BLINDING_DIRT, 10000); - return; - case EVENT_PUNCTURE_WOUND: - DoCast(me->getVictim(), SPELL_PUNCTURE_WOUND); - events.RescheduleEvent(EVENT_PUNCTURE_WOUND, 9000); - return; - case EVENT_SHOVELLED: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHOVELLED); - events.RescheduleEvent(EVENT_SHOVELLED, 7000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_coldwraithAI: public ScriptedAI -{ - mob_wrathbone_coldwraithAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - events.ScheduleEvent(EVENT_FROSTBOLT, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FREEZING_CIRCLE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FREEZING_CIRCLE); - events.RescheduleEvent(EVENT_FREEZING_CIRCLE, 9000); - return; - case EVENT_FROSTBOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_FROSTBOLT); - events.RescheduleEvent(EVENT_FROSTBOLT, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_stonespine_gargoyleAI: public ScriptedAI -{ - mob_stonespine_gargoyleAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_GARGOYLE_STRIKE, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_GARGOYLE_STRIKE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_GARGOYLE_STRIKE); - events.RescheduleEvent(EVENT_GARGOYLE_STRIKE, 6000); - return; - case EVENT_STONEFORM: - if (HealthBelowPct(10)) - DoCast(me, SPELL_STONEFORM); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_plagueborn_horrorAI: public ScriptedAI -{ - mob_plagueborn_horrorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLIGHT_BOMB, 999999); - events.ScheduleEvent(EVENT_PUSTULANT_FLESH, 5000); - events.ScheduleEvent(EVENT_TOXIC_WASTE, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLIGHT_BOMB: - if (HealthBelowPct(15)) - DoCast(me, SPELL_BLIGHT_BOMB); - return; - case EVENT_PUSTULANT_FLESH: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_PUSTULANT_FLESH); - events.RescheduleEvent(EVENT_PUSTULANT_FLESH, 10000); - return; - case EVENT_TOXIC_WASTE: - DoCast(me, SPELL_TOXIC_WASTE); - events.RescheduleEvent(EVENT_TOXIC_WASTE, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_iceborn_protodrakeAI: public ScriptedAI -{ - mob_iceborn_protodrakeAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_FROST_BREATH, 5000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_FROST_BREATH: - DoCast(me->getVictim(), SPELL_FROST_BREATH); - events.RescheduleEvent(EVENT_FROST_BREATH, 10000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_hungering_ghoulAI: public ScriptedAI -{ - mob_hungering_ghoulAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_DEVOUR_FLESH, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_DEVOUR_FLESH: - DoCast(me->getVictim(), SPELL_DEVOUR_FLESH); - events.RescheduleEvent(EVENT_DEVOUR_FLESH, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_fallen_warriorAI: public ScriptedAI -{ - mob_fallen_warriorAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_ARCING_SLICE, 8000); - events.ScheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - events.ScheduleEvent(EVENT_SHIELD_BLOCK, 8000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_ARCING_SLICE: - DoCast(me->getVictim(), SPELL_ARCING_SLICE); - events.RescheduleEvent(EVENT_ARCING_SLICE, 10000); - return; - case EVENT_DEMORALIZING_SHOUT: - DoCast(me, SPELL_DEMORALIZING_SHOUT); - events.RescheduleEvent(EVENT_DEMORALIZING_SHOUT, 20000); - return; - case EVENT_SHIELD_BLOCK: - DoCast(me->getVictim(), SPELL_SHIELD_BLOCK); - events.RescheduleEvent(EVENT_SHIELD_BLOCK, 8000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_torturerAI: public ScriptedAI -{ - mob_deathwhisper_torturerAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_BLACK_BRAND, 10000); - events.ScheduleEvent(EVENT_CURSE_OF_AGONY, 6000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_BLACK_BRAND: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BLACK_BRAND); - events.RescheduleEvent(EVENT_BLACK_BRAND, 10000); - return; - case EVENT_CURSE_OF_AGONY: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CURSE_OF_AGONY); - events.RescheduleEvent(EVENT_CURSE_OF_AGONY, 13000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_shadowcasterAI: public ScriptedAI -{ - mob_deathwhisper_shadowcasterAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_BOLT: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT); - events.RescheduleEvent(EVENT_SHADOW_BOLT, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_deathwhisper_necrolyteAI: public ScriptedAI -{ - mob_deathwhisper_necrolyteAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_CONVERSION_BEAM, 12000); - events.ScheduleEvent(EVENT_SHADOW_BOLT_2, 4000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_CONVERSION_BEAM: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CONVERSION_BEAM); - events.RescheduleEvent(EVENT_CONVERSION_BEAM, 12000); - return; - case EVENT_SHADOW_BOLT_2: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_2); - events.RescheduleEvent(EVENT_SHADOW_BOLT_2, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_wrathbone_sorcererAI: public ScriptedAI -{ - mob_wrathbone_sorcererAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - events.ScheduleEvent(EVENT_SHADOW_BOLT_3, 3000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - case EVENT_SHADOW_BOLT_3: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SHADOW_BOLT_3); - events.RescheduleEvent(EVENT_SHADOW_BOLT_3, 5000); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_geist_ambusherAI: public ScriptedAI -{ - mob_geist_ambusherAI(Creature *c) : ScriptedAI(c) - { - } - - EventMap events; - - void Reset() - { - events.Reset(); - } - - void EnterCombat(Unit* /*who*/) - { - //Only here so when I figure out how to make it cast on an NPC i can do that. - events.ScheduleEvent(EVENT_LEAPING_FACE_MAUL, 99999); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - events.Update(diff); - - if (me->hasUnitState(UNIT_STAT_CASTING)) - return; - - while (uint32 eventId = events.ExecuteEvent()) - { - switch(eventId) - { - //Should only be used on NPCs - case EVENT_LEAPING_FACE_MAUL: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_LEAPING_FACE_MAUL); - events.CancelEvent(EVENT_LEAPING_FACE_MAUL); - return; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_ymirjar_wrathbringerAI(Creature* pCreature) -{ - return new mob_ymirjar_wrathbringerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_skyCallerAI(Creature* pCreature) -{ - return new mob_ymirjar_skyCallerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_flamebearerAI(Creature* pCreature) -{ - return new mob_ymirjar_flamebearerAI(pCreature); -} - -CreatureAI* GetAI_mob_ymirjar_deathbringerAI(Creature* pCreature) -{ - return new mob_ymirjar_deathbringerAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_laborerAI(Creature* pCreature) -{ - return new mob_wrathbone_laborerAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_coldwraithAI(Creature* pCreature) -{ - return new mob_wrathbone_coldwraithAI(pCreature); -} - -CreatureAI* GetAI_mob_stonespine_gargoyleAI(Creature* pCreature) -{ - return new mob_stonespine_gargoyleAI(pCreature); -} - -CreatureAI* GetAI_mob_plagueborn_horrorAI(Creature* pCreature) -{ - return new mob_plagueborn_horrorAI(pCreature); -} - -CreatureAI* GetAI_mob_iceborn_protodrakeAI(Creature* pCreature) -{ - return new mob_iceborn_protodrakeAI(pCreature); -} - -CreatureAI* GetAI_mob_hungering_ghoulAI(Creature* pCreature) -{ - return new mob_hungering_ghoulAI(pCreature); -} - -CreatureAI* GetAI_mob_fallen_warriorAI(Creature* pCreature) -{ - return new mob_fallen_warriorAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_torturerAI(Creature* pCreature) -{ - return new mob_deathwhisper_torturerAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_shadowcasterAI(Creature* pCreature) -{ - return new mob_deathwhisper_shadowcasterAI(pCreature); -} - -CreatureAI* GetAI_mob_deathwhisper_necrolyteAI(Creature* pCreature) -{ - return new mob_deathwhisper_necrolyteAI(pCreature); -} - -CreatureAI* GetAI_mob_wrathbone_sorcererAI(Creature* pCreature) -{ - return new mob_wrathbone_sorcererAI(pCreature); -} - -CreatureAI* GetAI_mob_geist_ambusherAI(Creature* pCreature) -{ - return new mob_geist_ambusherAI(pCreature); -} - -void AddSC_pit_of_saron() -{ - Script *newscript; - newscript = new Script; - newscript->Name="mob_ymirjar_wrathbringer"; - newscript->GetAI = &GetAI_mob_ymirjar_wrathbringerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_skycaller"; - newscript->GetAI = &GetAI_mob_ymirjar_skyCallerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_flamebearer"; - newscript->GetAI = &GetAI_mob_ymirjar_flamebearerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_ymirjar_deathbringer"; - newscript->GetAI = &GetAI_mob_ymirjar_deathbringerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_laborer"; - newscript->GetAI = &GetAI_mob_wrathbone_laborerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_coldwraith"; - newscript->GetAI = &GetAI_mob_wrathbone_coldwraithAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_stonespine_gargoyle"; - newscript->GetAI = &GetAI_mob_stonespine_gargoyleAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_plagueborn_horror"; - newscript->GetAI = &GetAI_mob_plagueborn_horrorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_iceborn_protodrake"; - newscript->GetAI = &GetAI_mob_iceborn_protodrakeAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_hungering_ghoul"; - newscript->GetAI = &GetAI_mob_hungering_ghoulAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_fallen_warrior"; - newscript->GetAI = &GetAI_mob_fallen_warriorAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_torturer"; - newscript->GetAI = &GetAI_mob_deathwhisper_torturerAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_shadowcaster"; - newscript->GetAI = &GetAI_mob_deathwhisper_shadowcasterAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_deathwhisper_necrolyte"; - newscript->GetAI = &GetAI_mob_deathwhisper_necrolyteAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_wrathbone_sorcerer"; - newscript->GetAI = &GetAI_mob_wrathbone_sorcererAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name="mob_geist_ambusher"; - newscript->GetAI = &GetAI_mob_geist_ambusherAI; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h b/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h deleted file mode 100644 index 4a221d17518..00000000000 --- a/src/server/scripts/Northrend/FrozenHalls/pit_of_saron/pit_of_saron.h +++ /dev/null @@ -1,63 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_PIT_OF_SARON_H -#define DEF_PIT_OF_SARON_H - -enum Data -{ - DATA_GARFROST_EVENT, - DATA_KRICKANDICK_EVENT, - DATA_TYRANNUS_EVENT, - DATA_TEAM_IN_INSTANCE, -}; - -enum Data64 -{ - DATA_GARFROST, - DATA_KRICK, - DATA_ICK, - DATA_TYRANNUS, - DATA_RIMEFANG, - - DATA_JAINA_SYLVANAS_1, // GUID of either Jaina or Sylvanas part 1, depending on team, as it's the same spawn. - DATA_JAINA_SYLVANAS_2, // GUID of either Jaina or Sylvanas part 2, depending on team, as it's the same spawn. -}; - -enum Creatures -{ - CREATURE_GARFROST = 36494, - CREATURE_KRICK = 36477, - CREATURE_ICK = 36476, - CREATURE_TYRANNUS = 36658, - CREATURE_RIMEFANG = 36661, - - NPC_SYLVANAS_PART1 = 36990, - NPC_SYLVANAS_PART2 = 38189, - NPC_JAINA_PART1 = 36993, - NPC_JAINA_PART2 = 38188, - NPC_KILARA = 37583, - NPC_ELANDRA = 37774, - NPC_KORALEN = 37779, - NPC_KORLAEN = 37582, - NPC_CHAMPION_1_HORDE = 37584, - NPC_CHAMPION_2_HORDE = 37587, - NPC_CHAMPION_3_HORDE = 37588, - NPC_CHAMPION_1_ALLIANCE = 37496, - NPC_CHAMPION_2_ALLIANCE = 37497, -}; - -#endif diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp new file mode 100644 index 00000000000..bbb1df2731d --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -0,0 +1,175 @@ +/* Script Data Start +SDName: Boss malygos +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = '' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +//Spells +#define SPELL_ARCANE_BREATH_N 56272 +#define SPELL_ARCANE_BREATH_H 60072 +#define SPELL_ARCANE_PULSE 57432 +#define SPELL_ARCANE_STORM_1 57459 +#define SPELL_ARCANE_STORM_2 61693 +#define SPELL_ARCANE_STORM_3 61694 +#define SPELL_STATIC_FIELD 57430 +#define SPELL_SURGE_OF_POWER_1 56505 +#define SPELL_SURGE_OF_POWER_2 57407 +#define SPELL_SURGE_OF_POWER_3 60936 +#define SPELL_VORTEX 56105 + +//Dragon "mounts" spells in Phase3 +//they use Rugelike energy +#define SPELL_DMOUNT_FLAME_SPIKE 56091 //maybe not accurate +#define SPELL_DMOUNT_ENGULF_IN_FLAMES 61621 +#define SPELL_DMOUNT_REVIVIFY 57090 +#define SPELL_DMOUNT_LIFE_BURST 57143 +#define SPELL_DMOUNT_FLAME_SHIELD 57108 +//#define SPELL_DMOUNT_UNKNOWN XYZ //Increases your drake's flight speed by 500%. + +//not in db +//Yell +//-->Other +#define SAY_ANTI_MAGIC_SHELL -1616000 +#define SAY_BREATH_ATTACK -1616001 +#define SAY_HIGH_DAMAGE_MODE -1616002 +#define SAY_MAGIC_BLAST -1616003 +//--> Generic Spells +#define SAY_GENERIC_SPELL_1 -1616004 +#define SAY_GENERIC_SPELL_2 -1616005 +#define SAY_GENERIC_SPELL_3 -1616006 +#define SAY_DEATH -1616007 +//--> Prefight +#define SAY_PREFIGHT_1 -1616008 +#define SAY_PREFIGHT_2 -1616009 +#define SAY_PREFIGHT_3 -1616010 +#define SAY_PREFIGHT_4 -1616011 +#define SAY_PREFIGHT_5 -1616012 +//--> Phase1 +#define SAY_PHASE1_AGGRO -1616013 +#define SAY_PHASE1_END -1616014 +#define SAY_PHASE1_SLAY_1 -1616015 +#define SAY_PHASE1_SLAY_2 -1616016 +#define SAY_PHASE1_SLAY_3 -1616017 + +//--> Phase2 at 50% HP, + +/*Malygos himself is not targetable during this phase, it will end when the adds he spawns are all killed. However, he does continue to play a part in the encounter. +During this phase he drops anti-magic zones onto the ground the raid MUST stand inside of, it reduces magical damage taken by 50%. They shrink over time, so it's important that your raid moves to each new one he drops. +Throughout the phase, he will deep breath doing ~4k damage per second, unless you are standing inside of the anti-magic zone. +The way the fight works during this phase is there are NPCs riding around on disks in the room. There are two types of mobs, Lords and Scions. +The Lords will move down onto the group, and need to be tanked (They will one-shot a non-tank). After they die, they drop a disk that a raid member can mount onto, which allows them to fly, to attack the Scions that do not come down to the ground. +It is recommended to let melee take the first disks, then ranged. As those mobs die, they also drop disks, which allows the rest of your dps to get onto them. +The Scions will continually cast Arcane Blast on random targets on the floor, which is mitigated by the anti-magic zones. While mounted on a disk, you will not take damage. +After all of the NPCs riding on the disks die, the players on the disks need to dismount as Phase 3 is about to begin.*/ + +//not in db +#define SAY_PHASE2_AGGRO -1616018 +#define SAY_PHASE2_END -1616019 +#define SAY_PHASE2_SLAY_1 -1616020 +#define SAY_PHASE2_SLAY_2 -1616021 +#define SAY_PHASE2_SLAY_3 -1616022 +//--> Phase3 Malygos destroys the floor, encounter continues on dragon "mounts" +#define SAY_PHASE3_INTRO -1616023 +#define SAY_PHASE3_AGGRO -1616024 +#define SAY_PHASE3_SLAY_1 -1616025 +#define SAY_PHASE3_SLAY_2 -1616026 +#define SAY_PHASE3_SLAY_3 -1616027 +#define SAY_PHASE3_BIG_ATTACK -1616028 + +enum +{ + ACHIEV_TIMED_START_EVENT = 20387, +}; + +struct boss_malygosAI : public ScriptedAI +{ + boss_malygosAI(Creature *c) : ScriptedAI(c) + { + instance = me->GetInstanceData(); + } + + InstanceData *instance; + + uint32 phase; + uint32 enrage; + + void Reset() + { + phase = 1; + enrage = 615000; //Source Deadly Boss Mod + + if (instance) + instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + void EnterCombat(Unit* /*who*/) + { + if (phase == 1) + { + DoScriptText(SAY_PHASE1_AGGRO, me); + if (instance) + instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + if (phase == 2) + DoScriptText(SAY_PHASE1_AGGRO, me); + if (phase == 3) + DoScriptText(SAY_PHASE1_AGGRO, me); + } + + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (phase == 1 && HealthBelowPct(50)) { + phase = 2; + //spawn adds + //set malygos unatackable untill all adds spawned dead + //start phase3 + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + if (phase == 1) + DoScriptText(RAND(SAY_PHASE1_SLAY_1,SAY_PHASE1_SLAY_2,SAY_PHASE1_SLAY_3), me); + if (phase == 2) + DoScriptText(RAND(SAY_PHASE2_SLAY_1,SAY_PHASE2_SLAY_2,SAY_PHASE2_SLAY_3), me); + if (phase == 3) + DoScriptText(RAND(SAY_PHASE3_SLAY_1,SAY_PHASE3_SLAY_2,SAY_PHASE3_SLAY_3), me); + } +}; + +CreatureAI* GetAI_boss_malygos(Creature* pCreature) +{ + return new boss_malygosAI (pCreature); +} + +void AddSC_boss_malygos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_malygos"; + newscript->GetAI = &GetAI_boss_malygos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h new file mode 100644 index 00000000000..caa82a92e95 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/eye_of_eternity.h @@ -0,0 +1,4 @@ +#ifndef DEF_EYE_OF_ETERNITY_H +#define DEF_EYE_OF_ETERNITY_H + +#endif diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp new file mode 100644 index 00000000000..d93ec415b42 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -0,0 +1,21 @@ +#include "ScriptedPch.h" +#include "eye_of_eternity.h" + +struct instance_eye_of_eternity : public ScriptedInstance +{ + instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; +}; + +InstanceData* GetInstanceData_instance_eye_of_eternity(Map* pMap) +{ + return new instance_eye_of_eternity(pMap); +} + +void AddSC_instance_eye_of_eternity() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_eye_of_eternity"; + newscript->GetInstanceData = &GetInstanceData_instance_eye_of_eternity; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp new file mode 100644 index 00000000000..02c39dc1232 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_anomalus.cpp @@ -0,0 +1,253 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + //Spells + SPELL_SPARK = 47751, + H_SPELL_SPARK = 57062, + SPELL_RIFT_SHIELD = 47748, + SPELL_CHARGE_RIFT = 47747, //Works wrong (affect players, not rifts) + SPELL_CREATE_RIFT = 47743, //Don't work, using WA + SPELL_ARCANE_ATTRACTION = 57063, //No idea, when it's used +}; + +enum Adds +{ + MOB_CRAZED_MANA_WRAITH = 26746, + MOB_CHAOTIC_RIFT = 26918 +}; +enum Yells +{ + //Yell + SAY_AGGRO = -1576010, + SAY_DEATH = -1576011, + SAY_RIFT = -1576012, + SAY_SHIELD = -1576013 +}; + +enum Achievs +{ + ACHIEV_CHAOS_THEORY = 2037 +}; + +const Position RiftLocation[6] = +{ + {652.64, -273.70, -8.75}, + {634.45, -265.94, -8.44}, + {620.73, -281.17, -9.02}, + {626.10, -304.67, -9.44}, + {639.87, -314.11, -9.49}, + {651.72, -297.44, -9.37} +}; + +struct boss_anomalusAI : public ScriptedAI +{ + boss_anomalusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint8 Phase; + uint32 uiSparkTimer; + uint32 uiCreateRiftTimer; + uint64 uiChaoticRiftGUID; + + bool bDeadChaoticRift; // needed for achievement: Chaos Theory(2037) + + void Reset() + { + Phase = 0; + uiSparkTimer = 5*IN_MILISECONDS; + uiChaoticRiftGUID = 0; + + bDeadChaoticRift = false; + + if (pInstance) + pInstance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && !bDeadChaoticRift) + pInstance->DoCompleteAchievement(ACHIEV_CHAOS_THEORY); + pInstance->SetData(DATA_ANOMALUS_EVENT, DONE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (me->GetDistance(me->GetHomePosition()) > 60.0f) + { + //Not blizzlike, hack to avoid an exploit + EnterEvadeMode(); + return; + } + + if (me->HasAura(SPELL_RIFT_SHIELD)) + { + if (uiChaoticRiftGUID) + { + Unit* Rift = Unit::GetUnit((*me), uiChaoticRiftGUID); + if (Rift && Rift->isDead()) + { + me->RemoveAurasDueToSpell(SPELL_RIFT_SHIELD); + uiChaoticRiftGUID = 0; + } + return; + } + } else + uiChaoticRiftGUID = 0; + + if ((Phase == 0) && HealthBelowPct(50)) + { + Phase = 1; + DoScriptText(SAY_SHIELD, me); + DoCast(me, SPELL_RIFT_SHIELD); + Creature* Rift = me->SummonCreature(MOB_CHAOTIC_RIFT, RiftLocation[urand(0,5)], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); + if (Rift) + { + //DoCast(Rift, SPELL_CHARGE_RIFT); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Rift->AI()->AttackStart(pTarget); + uiChaoticRiftGUID = Rift->GetGUID(); + DoScriptText(SAY_RIFT , me); + } + } + + + if (uiSparkTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SPARK); + uiSparkTimer = 5*IN_MILISECONDS; + } else uiSparkTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_anomalus(Creature* pCreature) +{ + return new boss_anomalusAI (pCreature); +} + +enum RiftSpells +{ + SPELL_CHAOTIC_ENERGY_BURST = 47688, + SPELL_CHARGED_CHAOTIC_ENERGY_BURST = 47737, + SPELL_ARCANEFORM = 48019 //Chaotic Rift visual +}; + +struct mob_chaotic_riftAI : public Scripted_NoMovementAI +{ + mob_chaotic_riftAI(Creature *c) : Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiChaoticEnergyBurstTimer; + uint32 uiSummonCrazedManaWraithTimer; + + void Reset() + { + uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; + uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; + //me->SetDisplayId(25206); //For some reason in DB models for ally and horde are different. + //Model for ally (1126) does not show auras. Horde model works perfect. + //Set model to horde number + DoCast(me, SPELL_ARCANEFORM, false); + } + + void JustDied(Unit * /*killer*/) + { + if (Creature* pAnomalus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0)) + CAST_AI(boss_anomalusAI,pAnomalus->AI())->bDeadChaoticRift = true; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiChaoticEnergyBurstTimer <= diff) + { + Unit* pAnomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + if (pAnomalus && pAnomalus->HasAura(SPELL_RIFT_SHIELD)) + DoCast(pTarget, SPELL_CHARGED_CHAOTIC_ENERGY_BURST); + else + DoCast(pTarget, SPELL_CHAOTIC_ENERGY_BURST); + uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; + } else uiChaoticEnergyBurstTimer -= diff; + + if (uiSummonCrazedManaWraithTimer <= diff) + { + Creature* Wraith = me->SummonCreature(MOB_CRAZED_MANA_WRAITH, me->GetPositionX()+1, me->GetPositionY()+1, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); + if (Wraith) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Wraith->AI()->AttackStart(pTarget); + Unit* Anomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); + if (Anomalus && Anomalus->HasAura(SPELL_RIFT_SHIELD)) + uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; + else + uiSummonCrazedManaWraithTimer = 10*IN_MILISECONDS; + } else uiSummonCrazedManaWraithTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_chaotic_rift(Creature* pCreature) +{ + return new mob_chaotic_riftAI (pCreature); +} + +void AddSC_boss_anomalus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_anomalus"; + newscript->GetAI = &GetAI_boss_anomalus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_chaotic_rift"; + newscript->GetAI = &GetAI_mob_chaotic_rift; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp new file mode 100644 index 00000000000..ff633c55eac --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_keristrasza.cpp @@ -0,0 +1,247 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + //Spells + SPELL_FROZEN_PRISON = 47854, + SPELL_TAIL_SWEEP = 50155, + SPELL_CRYSTAL_CHAINS = 50997, + SPELL_ENRAGE = 8599, + SPELL_CRYSTALFIRE_BREATH = 48096, + H_SPELL_CRYSTALFIRE_BREATH = 57091, + SPELL_CRYSTALIZE = 48179, + SPELL_INTENSE_COLD = 48094, + SPELL_INTENSE_COLD_TRIGGERED = 48095 +}; +enum Yells +{ + //Yell + SAY_AGGRO = -1576040, + SAY_SLAY = -1576041, + SAY_ENRAGE = -1576042, + SAY_DEATH = -1576043, + SAY_CRYSTAL_NOVA = -1576044 +}; +enum Achievements +{ + ACHIEV_INTENSE_COLD = 2036 +}; +enum Misc +{ + DATA_CONTAINMENT_SPHERES = 3 +}; + +struct boss_keristraszaAI : public ScriptedAI +{ + boss_keristraszaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCrystalfireBreathTimer; + uint32 uiCrystalChainsCrystalizeTimer; + uint32 uiTailSweepTimer; + bool bEnrage; + + uint64 auiContainmentSphereGUIDs[DATA_CONTAINMENT_SPHERES]; + + uint32 uiCheckIntenseColdTimer; + bool bMoreThanTwoIntenseCold; // needed for achievement: Intense Cold(2036) + + void Reset() + { + uiCrystalfireBreathTimer = 14*IN_MILISECONDS; + uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); + uiTailSweepTimer = 5*IN_MILISECONDS; + bEnrage = false; + + uiCheckIntenseColdTimer = 2*IN_MILISECONDS; + bMoreThanTwoIntenseCold = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + + RemovePrison(CheckContainmentSpheres()); + + if (pInstance) + pInstance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoCastAOE(SPELL_INTENSE_COLD); + + if (pInstance) + pInstance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && !bMoreThanTwoIntenseCold) + pInstance->DoCompleteAchievement(ACHIEV_INTENSE_COLD); + pInstance->SetData(DATA_KERISTRASZA_EVENT, DONE); + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_SLAY, me); + } + + bool CheckContainmentSpheres(bool remove_prison = false) + { + if (!pInstance) + return false; + + auiContainmentSphereGUIDs[0] = pInstance->GetData64(ANOMALUS_CONTAINMET_SPHERE); + auiContainmentSphereGUIDs[1] = pInstance->GetData64(ORMOROKS_CONTAINMET_SPHERE); + auiContainmentSphereGUIDs[2] = pInstance->GetData64(TELESTRAS_CONTAINMET_SPHERE); + + GameObject *ContainmentSpheres[DATA_CONTAINMENT_SPHERES]; + + for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i) + { + ContainmentSpheres[i] = pInstance->instance->GetGameObject(auiContainmentSphereGUIDs[i]); + if (!ContainmentSpheres[i]) + return false; + if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE) + return false; + } + if (remove_prison) + RemovePrison(true); + return true; + } + + void RemovePrison(bool remove) + { + if (remove) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (me->HasAura(SPELL_FROZEN_PRISON)) + me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON); + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(me, SPELL_FROZEN_PRISON, false); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (uiCheckIntenseColdTimer < diff && !bMoreThanTwoIntenseCold) + { + std::list ThreatList = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER) + continue; + + Aura *AuraIntenseCold = pTarget->GetAura(SPELL_INTENSE_COLD_TRIGGERED); + if (AuraIntenseCold && AuraIntenseCold->GetStackAmount() > 2) + { + bMoreThanTwoIntenseCold = true; + break; + } + } + uiCheckIntenseColdTimer = 2*IN_MILISECONDS; + } else uiCheckIntenseColdTimer -= diff; + + if (!bEnrage && HealthBelowPct(25)) + { + DoScriptText(SAY_ENRAGE, me); + DoCast(me, SPELL_ENRAGE); + bEnrage = true; + } + + if (uiCrystalfireBreathTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CRYSTALFIRE_BREATH); + uiCrystalfireBreathTimer = 14*IN_MILISECONDS; + } else uiCrystalfireBreathTimer -= diff; + + if (uiTailSweepTimer <= diff) + { + DoCast(me, SPELL_TAIL_SWEEP); + uiTailSweepTimer = 5*IN_MILISECONDS; + } else uiTailSweepTimer -= diff; + + if (uiCrystalChainsCrystalizeTimer <= diff) + { + DoScriptText(SAY_CRYSTAL_NOVA, me); + if (IsHeroic()) + DoCast(me, SPELL_CRYSTALIZE); + else if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CRYSTAL_CHAINS); + uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); + } else uiCrystalChainsCrystalizeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_keristrasza(Creature* pCreature) +{ + return new boss_keristraszaAI (pCreature); +} + +bool GOHello_containment_sphere(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + + Creature *pKeristrasza = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_KERISTRASZA) : 0); + if (pKeristrasza && pKeristrasza->isAlive()) + { + // maybe these are hacks :( + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + CAST_AI(boss_keristraszaAI, pKeristrasza->AI())->CheckContainmentSpheres(true); + } + return true; +} + +void AddSC_boss_keristrasza() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_keristrasza"; + newscript->GetAI = &GetAI_boss_keristrasza; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "containment_sphere"; + newscript->pGOHello = &GOHello_containment_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp new file mode 100644 index 00000000000..0bf9fb07bb7 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_magus_telestra.cpp @@ -0,0 +1,327 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + SPELL_ICE_NOVA = 47772, + H_SPELL_ICE_NOVA = 56935, + SPELL_FIREBOMB = 47773, + H_SPELL_FIREBOMB = 56934, + SPELL_GRAVITY_WELL = 47756, + SPELL_TELESTRA_BACK = 47714, + + SPELL_FIRE_MAGUS_VISUAL = 47705, + SPELL_FROST_MAGUS_VISUAL = 47706, + SPELL_ARCANE_MAGUS_VISUAL = 47704 +}; +enum Creatures +{ + MOB_FIRE_MAGUS = 26928, + MOB_FROST_MAGUS = 26930, + MOB_ARCANE_MAGUS = 26929 +}; +enum Yells +{ + SAY_AGGRO = -1576000, + SAY_KILL = -1576001, + SAY_DEATH = -1576002, + SAY_MERGE = -1576003, + SAY_SPLIT_1 = -1576004, + SAY_SPLIT_2 = -1576005, +}; +enum Achievements +{ + ACHIEV_SPLIT_PERSONALITY = 2150, + ACHIEV_TIMER = 5*IN_MILISECONDS +}; + +const Position CenterOfRoom = {504.80, 89.07, -16.12, 6.27}; + +struct boss_magus_telestraAI : public ScriptedAI +{ + boss_magus_telestraAI(Creature* c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 uiFireMagusGUID; + uint64 uiFrostMagusGUID; + uint64 uiArcaneMagusGUID; + + bool bFireMagusDead; + bool bFrostMagusDead; + bool bArcaneMagusDead; + bool bIsWaitingToAppear; + bool bIsAchievementTimerRunning; + + uint32 uiIsWaitingToAppearTimer; + uint32 uiIceNovaTimer; + uint32 uiFireBombTimer; + uint32 uiGravityWellTimer; + uint32 uiCooldown; + uint32 uiAchievementTimer; + + uint8 Phase; + uint8 uiAchievementProgress; + + void Reset() + { + Phase = 0; + //These times are probably wrong + uiIceNovaTimer = 7*IN_MILISECONDS; + uiFireBombTimer = 0; + uiGravityWellTimer = 15*IN_MILISECONDS; + uiCooldown = 0; + + uiFireMagusGUID = 0; + uiFrostMagusGUID = 0; + uiArcaneMagusGUID = 0; + + uiAchievementProgress = 0; + uiAchievementTimer = 0; + + bIsAchievementTimerRunning = false; + bIsWaitingToAppear = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + if (pInstance) + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + if (IsHeroic() && uiAchievementProgress == 2) + pInstance->DoCompleteAchievement(ACHIEV_SPLIT_PERSONALITY); + pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE); + } + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + uint64 SplitPersonality(uint32 entry) + { + if (Creature* Summoned = me->SummonCreature(entry, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS)) + { + switch (entry) + { + case MOB_FIRE_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_FIRE_MAGUS_VISUAL, false); + break; + } + case MOB_FROST_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_FROST_MAGUS_VISUAL, false); + break; + } + case MOB_ARCANE_MAGUS: + { + Summoned->CastSpell(Summoned, SPELL_ARCANE_MAGUS_VISUAL, false); + break; + } + } + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Summoned->AI()->AttackStart(pTarget); + return Summoned->GetGUID(); + } + return 0; + } + + void SummonedCreatureDespawn(Creature *summon) + { + if (summon->isAlive()) + return; + + if (summon->GetGUID() == uiFireMagusGUID) + { + bFireMagusDead = true; + bIsAchievementTimerRunning = true; + } + else if (summon->GetGUID() == uiFrostMagusGUID) + { + bFrostMagusDead = true; + bIsAchievementTimerRunning = true; + } + else if (summon->GetGUID() == uiArcaneMagusGUID) + { + bArcaneMagusDead = true; + bIsAchievementTimerRunning = true; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (bIsWaitingToAppear) + { + me->StopMoving(); + me->AttackStop(); + if (uiIsWaitingToAppearTimer <= diff) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + bIsWaitingToAppear = false; + } else uiIsWaitingToAppearTimer -= diff; + return; + } + + if ((Phase == 1) ||(Phase == 3)) + { + if (bIsAchievementTimerRunning) + uiAchievementTimer += diff; + if (bFireMagusDead && bFrostMagusDead && bArcaneMagusDead) + { + if (uiAchievementTimer <= ACHIEV_TIMER) + uiAchievementProgress +=1; + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, CenterOfRoom.GetPositionX(), CenterOfRoom.GetPositionY(), CenterOfRoom.GetPositionZ(), CenterOfRoom.GetOrientation()); + DoCast(me, SPELL_TELESTRA_BACK); + me->SetVisibility(VISIBILITY_ON); + if (Phase == 1) + Phase = 2; + if (Phase == 3) + Phase = 4; + uiFireMagusGUID = 0; + uiFrostMagusGUID = 0; + uiArcaneMagusGUID = 0; + bIsWaitingToAppear = true; + uiIsWaitingToAppearTimer = 4*IN_MILISECONDS; + DoScriptText(SAY_MERGE, me); + bIsAchievementTimerRunning = false; + uiAchievementTimer = 0; + } + else + return; + } + + if ((Phase == 0) && HealthBelowPct(50)) + { + Phase = 1; + me->CastStop(); + me->RemoveAllAuras(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); + uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); + uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); + bFireMagusDead = false; + bFrostMagusDead = false; + bArcaneMagusDead = false; + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + return; + } + + if (IsHeroic() && (Phase == 2) && HealthBelowPct(10)) + { + Phase = 3; + me->CastStop(); + me->RemoveAllAuras(); + me->SetVisibility(VISIBILITY_OFF); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); + uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); + uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); + bFireMagusDead = false; + bFrostMagusDead = false; + bArcaneMagusDead = false; + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + return; + } + + if (uiCooldown) + { + if (uiCooldown <= diff) + uiCooldown = 0; + else + { + uiCooldown -= diff; + return; + } + } + + if (uiIceNovaTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_ICE_NOVA, false); + uiCooldown = 1.5*IN_MILISECONDS; + } + uiIceNovaTimer = 15*IN_MILISECONDS; + } else uiIceNovaTimer -= diff; + + if (uiGravityWellTimer <= diff) + { + if (Unit *pTarget = me->getVictim()) + { + DoCast(pTarget, SPELL_GRAVITY_WELL); + uiCooldown = 6*IN_MILISECONDS; + } + uiGravityWellTimer = 15*IN_MILISECONDS; + } else uiGravityWellTimer -= diff; + + if (uiFireBombTimer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_FIREBOMB, false); + uiCooldown = 2*IN_MILISECONDS; + } + uiFireBombTimer = 2*IN_MILISECONDS; + } else uiFireBombTimer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_magus_telestra(Creature* pCreature) +{ + return new boss_magus_telestraAI (pCreature); +} + +void AddSC_boss_magus_telestra() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_magus_telestra"; + newscript->GetAI = &GetAI_boss_magus_telestra; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp new file mode 100644 index 00000000000..1304f95c7ac --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Nexus/boss_ormorok.cpp @@ -0,0 +1,298 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +enum Spells +{ + SPELL_CRYSTAL_SPIKES = 47958, //Don't work, using walkaround + H_SPELL_CRYSTAL_SPIKES = 57082, //Don't work, using walkaround + SPELL_CRYSTALL_SPIKE_DAMAGE = 47944, + H_SPELL_CRYSTALL_SPIKE_DAMAGE = 57067, + SPELL_CRYSTAL_SPIKE_PREVISUAL = 50442, + MOB_CRYSTAL_SPIKE = 27099, + SPELL_SPELL_REFLECTION = 47981, + SPELL_TRAMPLE = 48016, + H_SPELL_TRAMPLE = 57066, + SPELL_FRENZY = 48017, + SPELL_SUMMON_CRYSTALLINE_TANGLER = 61564, //summons npc 32665 + SPELL_ROOTS = 28858 //proper spell id is unknown +}; +enum Yells +{ + SAY_AGGRO = -1576020, + SAY_DEATH = -1576021, + SAY_REFLECT = -1576022, + SAY_CRYSTAL_SPIKES = -1576023, + SAY_KILL = -1576024 +}; +enum Creatures +{ + MOB_CRYSTALLINE_TANGLER = 32665 +}; + +#define SPIKE_DISTANCE 5.0f + +struct boss_ormorokAI : public ScriptedAI +{ + boss_ormorokAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bFrenzy; + bool bCrystalSpikes; + uint8 uiCrystalSpikesCount; + float fBaseX; + float fBaseY; + float fBaseZ; + float fBaseO; + float fSpikeXY[4][2]; + + uint32 uiCrystalSpikesTimer; + uint32 uiCrystalSpikesTimer2; + uint32 uiTrampleTimer; + uint32 uiFrenzyTimer; + uint32 uiSpellReflectionTimer; + uint32 uiSummonCrystallineTanglerTimer; + + void Reset() + { + uiCrystalSpikesTimer = 12*IN_MILISECONDS; + uiTrampleTimer = 10*IN_MILISECONDS; + uiSpellReflectionTimer = 30*IN_MILISECONDS; + uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; + bFrenzy = false; + bCrystalSpikes = false; + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_ORMOROK_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(SAY_KILL, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + return; + } + if (bCrystalSpikes) + if (uiCrystalSpikesTimer2 <= diff) + { + fSpikeXY[0][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); + fSpikeXY[0][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); + fSpikeXY[1][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); + fSpikeXY[1][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); + fSpikeXY[2][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); + fSpikeXY[2][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); + fSpikeXY[3][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); + fSpikeXY[3][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); + for (uint8 i = 0; i < 4; ++i) + me->SummonCreature(MOB_CRYSTAL_SPIKE, fSpikeXY[i][0], fSpikeXY[i][1], fBaseZ, 0, TEMPSUMMON_TIMED_DESPAWN, 7*IN_MILISECONDS); + if (++uiCrystalSpikesCount >= 13) + bCrystalSpikes = false; + uiCrystalSpikesTimer2 = 200; + } else uiCrystalSpikesTimer2 -= diff; + + if (!bFrenzy && (me->GetHealth() < me->GetMaxHealth() * 0.25)) + { + DoCast(me, SPELL_FRENZY); + bFrenzy = true; + } + + if (uiTrampleTimer <= diff) + { + DoCast(me, SPELL_TRAMPLE); + uiTrampleTimer = 10*IN_MILISECONDS; + } else uiTrampleTimer -= diff; + + if (uiSpellReflectionTimer <= diff) + { + DoScriptText(SAY_REFLECT, me); + DoCast(me, SPELL_SPELL_REFLECTION); + uiSpellReflectionTimer = 30*IN_MILISECONDS; + } else uiSpellReflectionTimer -= diff; + + if (uiCrystalSpikesTimer <= diff) + { + DoScriptText(SAY_CRYSTAL_SPIKES, me); + bCrystalSpikes = true; + uiCrystalSpikesCount = 1; + uiCrystalSpikesTimer2 = 0; + fBaseX = me->GetPositionX(); + fBaseY = me->GetPositionY(); + fBaseZ = me->GetPositionZ(); + fBaseO = me->GetOrientation(); + uiCrystalSpikesTimer = 20*IN_MILISECONDS; + } else uiCrystalSpikesTimer -= diff; + + if (IsHeroic() && (uiSummonCrystallineTanglerTimer <= diff)) + { + Creature* Crystalline_Tangler = me->SummonCreature(MOB_CRYSTALLINE_TANGLER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); + if (Crystalline_Tangler) + { + Unit *pTarget = NULL; + uint8 Healer = 0; + for (uint8 j = 1; j <= 4; j++) + { + switch (j) + { + case 1: Healer = CLASS_PRIEST; break; + case 2: Healer = CLASS_PALADIN; break; + case 3: Healer = CLASS_DRUID; break; + case 4: Healer = CLASS_SHAMAN; break; + } + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + for (; i != me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pTemp = Unit::GetUnit((*me),(*i)->getUnitGuid()); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && pTemp->getClass() == Healer) + { + pTarget = pTemp; + break; + } + } + if (pTarget) + break; + } + if (!pTarget) + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Crystalline_Tangler->AI()->AttackStart(pTarget); + Crystalline_Tangler->getThreatManager().addThreat(pTarget, 1000000000.0f); + } + } + uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; + } else uiSummonCrystallineTanglerTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_crystal_spikeAI : public Scripted_NoMovementAI +{ + mob_crystal_spikeAI(Creature *c) : Scripted_NoMovementAI(c) + { + } + + uint32 SpellCrystalSpikeDamageTimer; + uint32 SpellCrystalSpikePrevisualTimer; + + void Reset() + { + SpellCrystalSpikeDamageTimer = 3.7*IN_MILISECONDS; + SpellCrystalSpikePrevisualTimer = 1*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (SpellCrystalSpikePrevisualTimer <= diff) + { + DoCast(me, SPELL_CRYSTAL_SPIKE_PREVISUAL); + SpellCrystalSpikePrevisualTimer = 10*IN_MILISECONDS; + } else SpellCrystalSpikePrevisualTimer -= diff; + + if (SpellCrystalSpikeDamageTimer <= diff) + { + DoCast(me, SPELL_CRYSTALL_SPIKE_DAMAGE); + SpellCrystalSpikeDamageTimer = 10*IN_MILISECONDS; + } else SpellCrystalSpikeDamageTimer -= diff; + } +}; + +struct mob_crystalline_tanglerAI : public ScriptedAI +{ + mob_crystalline_tanglerAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiRootsTimer; + + void Reset() + { + uiRootsTimer = 1*IN_MILISECONDS; + } + + void UpdateAI(const uint32 diff) + { + if (uiRootsTimer <= diff) + { + if (me->IsWithinDist(me->getVictim(), 5.0f, false)) + { + DoCast(me->getVictim(), SPELL_ROOTS); + uiRootsTimer = 15*IN_MILISECONDS; + } + } else uiRootsTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_crystal_spike(Creature* pCreature) +{ + return new mob_crystal_spikeAI (pCreature); +} + +CreatureAI* GetAI_mob_crystalline_tangler(Creature* pCreature) +{ + return new mob_crystalline_tanglerAI (pCreature); +} + +CreatureAI* GetAI_boss_ormorok(Creature* pCreature) +{ + return new boss_ormorokAI (pCreature); +} + +void AddSC_boss_ormorok() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ormorok"; + newscript->GetAI = &GetAI_boss_ormorok; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crystal_spike"; + newscript->GetAI = &GetAI_mob_crystal_spike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crystalline_tangler"; + newscript->GetAI = &GetAI_mob_crystalline_tangler; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp b/src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp new file mode 100644 index 00000000000..4bd9f55a013 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Nexus/commander_kolurg.cpp @@ -0,0 +1,58 @@ +/* Script Data Start +SDName: Boss Commander Kolurg +SDAuthor: LordVanMartin +SD%Complete: +SDComment: Only Alliance Heroic +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_commander_kolurg' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +#define SPELL_BATTLE_SHOUT 31403 +#define SPELL_CHARGE 60067 +#define SPELL_FRIGHTENING_SHOUT 19134 +#define SPELL_WHIRLWIND_1 38619 +#define SPELL_WHIRLWIND_2 38618 + +//not used +//Yell +#define SAY_AGGRO -1576024 +#define SAY_KILL -1576025 +#define SAY_DEATH -1576026 + +struct boss_commander_kolurgAI : public ScriptedAI +{ + boss_commander_kolurgAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) {} +}; + +CreatureAI* GetAI_boss_commander_kolurg(Creature* pCreature) +{ + return new boss_commander_kolurgAI (pCreature); +} + +void AddSC_boss_commander_kolurg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_commander_kolurg"; + newscript->GetAI = &GetAI_boss_commander_kolurg; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp b/src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp new file mode 100644 index 00000000000..ef02baa38e6 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Nexus/commander_stoutbeard.cpp @@ -0,0 +1,64 @@ +/* Script Data Start +SDName: Boss Commander Stoutbeard +SDAuthor: LordVanMartin +SD%Complete: +SDComment: Only Horde Heroic +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_commander_stoutbeard' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" + +#define SPELL_BATTLE_SHOUT 31403 +#define SPELL_CHARGE 60067 +#define SPELL_FRIGHTENING_SHOUT 19134 +#define SPELL_WHIRLWIND_1 38619 +#define SPELL_WHIRLWIND_2 38618 + +//not used +//Yell +#define SAY_AGGRO -1576021 +#define SAY_KILL -1576022 +#define SAY_DEATH -1576023 + +struct boss_commander_stoutbeardAI : public ScriptedAI +{ + boss_commander_stoutbeardAI(Creature *c) : ScriptedAI(c) {} + + void Reset() {} + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + } +}; + +CreatureAI* GetAI_boss_commander_stoutbeard(Creature* pCreature) +{ + return new boss_commander_stoutbeardAI (pCreature); +} + +void AddSC_boss_commander_stoutbeard() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_commander_stoutbeard"; + newscript->GetAI = &GetAI_boss_commander_stoutbeard; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp new file mode 100644 index 00000000000..db70245e3a4 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Nexus/instance_nexus.cpp @@ -0,0 +1,259 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "nexus.h" + +#define NUMBER_OF_ENCOUNTERS 4 + +enum Factions +{ + FACTION_HOSTILE_FOR_ALL = 16 +}; + +struct instance_nexus : public ScriptedInstance +{ + instance_nexus(Map *pMap) : ScriptedInstance(pMap) { Initialize(); } + + uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS]; + + uint64 Anomalus; + uint64 Keristrasza; + + uint64 AnomalusContainmentSphere; + uint64 OrmoroksContainmentSphere; + uint64 TelestrasContainmentSphere; + + std::string strInstData; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Anomalus = 0; + Keristrasza = 0; + } + + void OnCreatureCreate(Creature *pCreature, bool /*bAdd*/) + { + Map::PlayerList const &players = instance->GetPlayers(); + uint32 TeamInInstance = 0; + + if (!players.isEmpty()) + { + if (Player* pPlayer = players.begin()->getSource()) + TeamInInstance = pPlayer->GetTeam(); + } + switch (pCreature->GetEntry()) + { + case 26763: + Anomalus = pCreature->GetGUID(); + break; + case 26723: + Keristrasza = pCreature->GetGUID(); + break; + // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. + case 26800: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26799, HORDE); + break; + } + case 26802: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26801, HORDE); + break; + } + case 26805: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26803, HORDE); + break; + } + case 27949: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(27947, HORDE); + break; + } + case 26796: + { + if (ServerAllowsTwoSideGroups()) + pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); + if (TeamInInstance == ALLIANCE) + pCreature->UpdateEntry(26798, HORDE); + break; + } + } + } + + void OnGameObjectCreate(GameObject *pGo, bool /*bAdd*/) + { + switch (pGo->GetEntry()) + { + case 188527: + { + AnomalusContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + case 188528: + { + OrmoroksContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + case 188526: + { + TelestrasContainmentSphere = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + break; + } + } + } + + uint32 GetData(uint32 identifier) + { + switch(identifier) + { + case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0]; + case DATA_ANOMALUS_EVENT: return m_auiEncounter[1]; + case DATA_ORMOROK_EVENT: return m_auiEncounter[2]; + case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3]; + } + return 0; + } + + void SetData(uint32 identifier, uint32 data) + { + switch (identifier) + { + case DATA_MAGUS_TELESTRA_EVENT: + { + if (data == DONE) + { + GameObject *Sphere = instance->GetGameObject(TelestrasContainmentSphere); + if (Sphere) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[0] = data; + break; + } + case DATA_ANOMALUS_EVENT: + { + if (data == DONE) + { + if (GameObject *Sphere = instance->GetGameObject(AnomalusContainmentSphere)) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[1] = data; + break; + } + case DATA_ORMOROK_EVENT: + { + if (data == DONE) + { + if (GameObject *Sphere = instance->GetGameObject(OrmoroksContainmentSphere)) + Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + m_auiEncounter[2] = data; + break; + } + case DATA_KERISTRASZA_EVENT: + m_auiEncounter[3] = data; + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3]; + + strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint64 GetData64(uint32 uiIdentifier) + { + switch(uiIdentifier) + { + case DATA_ANOMALUS: return Anomalus; + case DATA_KERISTRASZA: return Keristrasza; + case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere; + case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere; + case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere; + } + return 0; + } + + std::string GetSaveData() + { + return strInstData; + } + + void Load(const char *chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + + for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData *GetInstanceData_instance_nexus(Map *pMap) +{ + return new instance_nexus(pMap); +} + +void AddSC_instance_nexus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_nexus"; + newscript->GetInstanceData = &GetInstanceData_instance_nexus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Nexus/nexus.h b/src/server/scripts/Northrend/Nexus/Nexus/nexus.h new file mode 100644 index 00000000000..66902bece30 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Nexus/nexus.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_NEXUS_H +#define DEF_NEXUS_H + +enum eTypes +{ + DATA_MAGUS_TELESTRA_EVENT, + DATA_ANOMALUS_EVENT, + DATA_ORMOROK_EVENT, + DATA_KERISTRASZA_EVENT, + + DATA_ANOMALUS, + DATA_KERISTRASZA, + + ANOMALUS_CONTAINMET_SPHERE, + ORMOROKS_CONTAINMET_SPHERE, + TELESTRAS_CONTAINMET_SPHERE +}; + +#endif diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp new file mode 100644 index 00000000000..7d276206339 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_drakos.cpp @@ -0,0 +1,218 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + SPELL_MAGIC_PULL = 51336, + SPELL_MAGIC_PULL_EFFECT = 50770, + SPELL_THUNDERING_STOMP = 50774, + SPELL_THUNDERING_STOMP_H = 59370, + SPELL_UNSTABLE_SPHERE_PASSIVE = 50756, + SPELL_UNSTABLE_SPHERE_PULSE = 50757, + SPELL_UNSTABLE_SPHERE_TIMER = 50758, + NPC_UNSTABLE_SPHERE = 28166, +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1578000, + SAY_KILL_1 = -1578001, + SAY_KILL_2 = -1578002, + SAY_KILL_3 = -1578003, + SAY_DEATH = -1578004, + SAY_PULL_1 = -1578005, + SAY_PULL_2 = -1578006, + SAY_PULL_3 = -1578007, + SAY_PULL_4 = -1578008, + SAY_STOMP_1 = -1578009, + SAY_STOMP_2 = -1578010, + SAY_STOMP_3 = -1578011 +}; + +enum +{ + ACHIEV_TIMED_START_EVENT = 18153, +}; + +struct boss_drakosAI : public ScriptedAI +{ + boss_drakosAI(Creature* pCreature) : ScriptedAI(pCreature), lSummons(me) + { + pInstance = pCreature->GetInstanceData(); + } + + uint32 uiMagicPullTimer; + uint32 uiStompTimer; + uint32 uiBombSummonTimer; + + bool bPostPull; + + ScriptedInstance* pInstance; + SummonList lSummons; + + void Reset() + { + lSummons.DespawnAll(); + uiMagicPullTimer = 15000; + uiStompTimer = 17000; + uiBombSummonTimer = 2000; + + bPostPull = false; + + if (pInstance) + pInstance->SetData(DATA_DRAKOS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_DRAKOS_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature* pSummon) + { + lSummons.Summon(pSummon); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBombSummonTimer <= uiDiff) + { + Position pPosition; + me->GetPosition(&pPosition); + + if (bPostPull) + { + for (uint8 uiI = 0; uiI >= 3; uiI++) + { + me->GetRandomNearPosition(pPosition, float(urand(0,10))); + me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); + } + } + else + { + me->GetRandomNearPosition(pPosition, float(urand(0,10))); + me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); + } + + uiBombSummonTimer = 2000; + } else uiBombSummonTimer -= uiDiff; + + if (uiMagicPullTimer <= uiDiff) + { + DoCast(SPELL_MAGIC_PULL); + + bPostPull = true; + + uiMagicPullTimer = 15000; + } else uiMagicPullTimer -= uiDiff; + + if (uiStompTimer <= uiDiff) + { + DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2,SAY_STOMP_3), me); + DoCast(SPELL_THUNDERING_STOMP); + uiStompTimer = 17000; + } else uiStompTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + { + pInstance->SetData(DATA_DRAKOS_EVENT, DONE); + // start achievement timer (kill Eregos within 20 min) + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + + lSummons.DespawnAll(); + } + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); + } +}; + +CreatureAI* GetAI_boss_drakos(Creature* pCreature) +{ + return new boss_drakosAI (pCreature); +} + +struct npc_unstable_sphereAI : public ScriptedAI +{ + npc_unstable_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 uiPulseTimer; + uint32 uiDeathTimer; + + void Reset() + { + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MoveRandom(40.0f); + + me->AddAura(SPELL_UNSTABLE_SPHERE_PASSIVE, me); + me->AddAura(SPELL_UNSTABLE_SPHERE_TIMER, me); + + uiPulseTimer = 3000; + uiDeathTimer = 19000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (uiPulseTimer <= uiDiff) + { + DoCast(SPELL_UNSTABLE_SPHERE_PULSE); + uiPulseTimer = 3*IN_MILISECONDS; + } else uiPulseTimer -= uiDiff; + + if (uiDeathTimer <= uiDiff) + me->DisappearAndDie(); + else uiDeathTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_unstable_sphere(Creature* pCreature) +{ + return new npc_unstable_sphereAI (pCreature); +} + +void AddSC_boss_drakos() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_drakos"; + newscript->GetAI = &GetAI_boss_drakos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_unstable_sphere"; + newscript->GetAI = &GetAI_npc_unstable_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp new file mode 100644 index 00000000000..94fb90ab206 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_eregos.cpp @@ -0,0 +1,129 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +//Types of drake mounts: Ruby(Tank), Amber(DPS), Emerald(Healer) +//Two Repeating phases + +enum Spells +{ + SPELL_ARCANE_BARRAGE = 50804, + H_SPELL_ARCANE_BARRAGE = 59381, + SPELL_ARCANE_VOLLEY = 51153, + H_SPELL_ARCANE_VOLLEY = 59382, + SPELL_ENRAGED_ASSAULT = 51170, + SPELL_PLANAR_ANOMALIES = 57959, + SPELL_PLANAR_SHIFT = 51162, +}; +/*Ruby Drake , +(npc 27756) (item 37860) +(summoned by spell Ruby Essence = 37860 ---> Call Amber Drake == 49462 ---> Summon 27756) +*/ +enum RubyDrake +{ + NPC_RUBY_DRAKE_VEHICLE = 27756, + SPELL_RIDE_RUBY_DRAKE_QUE = 49463, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49464 + SPELL_RUBY_DRAKE_SADDLE = 49464, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_RUBY_SEARING_WRATH = 50232, //(60 yds) - Instant - Breathes a stream of fire at an enemy dragon, dealing 6800 to 9200 Fire damage and then jumping to additional dragons within 30 yards. Each jump increases the damage by 50%. Affects up to 5 total targets + SPELL_RUBY_EVASIVE_AURA = 50248, //Instant - Allows the Ruby Drake to generate Evasive Charges when hit by hostile attacks and spells. + SPELL_RUBY_EVASIVE_MANEUVERS = 50240, //Instant - 5 sec. cooldown - Allows your drake to dodge all incoming attacks and spells. Requires Evasive Charges to use. Each attack or spell dodged while this ability is active burns one Evasive Charge. Lasts 30 sec. or until all charges are exhausted. + //you do not have acces to until you kill Mage-Lord Urom + SPELL_RUBY_MARTYR = 50253 //Instant - 10 sec. cooldown - Redirect all harmful spells cast at friendly drakes to yourself for 10 sec. +}; +/*Amber Drake, +(npc 27755) (item 37859) +(summoned by spell Amber Essence = 37859 ---> Call Amber Drake == 49461 ---> Summon 27755) +*/ +enum AmberDrake +{ + NPC_AMBER_DRAKE_VEHICLE = 27755, + SPELL_RIDE_AMBER_DRAKE_QUE = 49459, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49460 + SPELL_AMBER_DRAKE_SADDLE = 49460, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_AMBER_SHOCK_LANCE = 49840, //(60 yds) - Instant - Deals 4822 to 5602 Arcane damage and detonates all Shock Charges on an enemy dragon. Damage is increased by 6525 for each detonated. +// SPELL_AMBER_STOP_TIME //Instant - 1 min cooldown - Halts the passage of time, freezing all enemy dragons in place for 10 sec. This attack applies 5 Shock Charges to each affected target. + //you do not have access to until you kill the Mage-Lord Urom. + SPELL_AMBER_TEMPORAL_RIFT = 49592 //(60 yds) - Channeled - Channels a temporal rift on an enemy dragon for 10 sec. While trapped in the rift, all damage done to the target is increased by 100%. In addition, for every 15,000 damage done to a target affected by Temporal Rift, 1 Shock Charge is generated. +}; +/*Emerald Drake, +(npc 27692) (item 37815), + (summoned by spell Emerald Essence = 37815 ---> Call Emerald Drake == 49345 ---> Summon 27692) +*/ +enum EmeraldDrake +{ + NPC_EMERALD_DRAKE_VEHICLE = 27692, + SPELL_RIDE_EMERALD_DRAKE_QUE = 49427, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49346 + SPELL_EMERALD_DRAKE_SADDLE = 49346, //Allows you to ride on the back of an Amber Drake. ---> Dummy + SPELL_EMERALD_LEECHING_POISON = 50328, //(60 yds) - Instant - Poisons the enemy dragon, leeching 1300 to the caster every 2 sec. for 12 sec. Stacks up to 3 times. + SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, //(60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25,000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec. + // you do not have access to until you kill the Mage-Lord Urom + SPELL_EMERALD_DREAM_FUNNEL = 50344 //(60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels. +}; + +struct boss_eregosAI : public ScriptedAI +{ + boss_eregosAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, IN_PROGRESS); + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_EREGOS_EVENT, DONE); + } +}; + +CreatureAI* GetAI_boss_eregos(Creature* pCreature) +{ + return new boss_eregosAI (pCreature); +} + +void AddSC_boss_eregos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_eregos"; + newscript->GetAI = &GetAI_boss_eregos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp new file mode 100644 index 00000000000..29435441d00 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp @@ -0,0 +1,356 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Urom +SD%Complete: 80 +SDComment: Is not working SPELL_ARCANE_SHIELD. SPELL_FROSTBOMB has some issues, the damage aura should not stack. +SDCategory: Instance Script +EndScriptData */ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + + SPELL_ARCANE_SHIELD = 53813, //Dummy --> Channeled, shields the caster from damage. + SPELL_EMPOWERED_ARCANE_EXPLOSION = 51110, + SPELL_EMPOWERED_ARCANE_EXPLOSION_2 = 59377, + SPELL_FROSTBOMB = 51103, //Urom throws a bomb, hitting its target with the highest aggro which inflict directly 650 frost damage and drops a frost zone on the ground. This zone deals 650 frost damage per second and reduce the movement speed by 35%. Lasts 1 minute. + SPELL_SUMMON_MENAGERIE = 50476, //Summons an assortment of creatures and teleports the caster to safety. + SPELL_SUMMON_MENAGERIE_2 = 50495, + SPELL_SUMMON_MENAGERIE_3 = 50496, + SPELL_TELEPORT = 51112, //Teleports to the center of Oculus + SPELL_TIME_BOMB = 51121, //Deals arcane damage to a random player, and after 6 seconds, deals zone damage to nearby equal to the health missing of the target afflicted by the debuff. + SPELL_TIME_BOMB_2 = 59376 +}; + +enum Yells +{ + SAY_AGGRO_1 = -1578000, + SAY_AGGRO_2 = -1578001, + SAY_AGGRO_3 = -1578002, + SAY_AGGRO_4 = -1578003, + SAY_TELEPORT = -1578004, +}; + +enum eCreature +{ + NPC_PHANTASMAL_CLOUDSCRAPER = 27645, + NPC_PHANTASMAL_MAMMOTH = 27642, + NPC_PHANTASMAL_WOLF = 27644, + + NPC_PHANTASMAL_AIR = 27650, + NPC_PHANTASMAL_FIRE = 27651, + NPC_PHANTASMAL_WATER = 27653, + + NPC_PHANTASMAL_MURLOC = 27649, + NPC_PHANTASMAL_NAGAL = 27648, + NPC_PHANTASMAL_OGRE = 27647 +}; + +struct Summons +{ + uint32 uiEntry[4]; +}; + +static Summons Group[]= +{ + {NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_MAMMOTH,NPC_PHANTASMAL_WOLF}, + {NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_WATER,NPC_PHANTASMAL_FIRE}, + {NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_NAGAL,NPC_PHANTASMAL_MURLOC} +}; + +static uint32 TeleportSpells[]= +{ + SPELL_SUMMON_MENAGERIE,SPELL_SUMMON_MENAGERIE_2,SPELL_SUMMON_MENAGERIE_3 +}; + +static int32 SayAggro[]= +{ + SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4 +}; + +struct boss_uromAI : public ScriptedAI +{ + boss_uromAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + float x,y; + + bool bCanCast; + bool bCanGoBack; + + uint8 uiGroup[3]; + + uint32 uiTeleportTimer; + uint32 uiArcaneExplosionTimer; + uint32 uiCastArcaneExplosionTimer; + uint32 uiFrostBombTimer; + uint32 uiTimeBombTimer; + + void Reset() + { + if (pInstance && pInstance->GetData(DATA_VAROS_EVENT) != DONE) + DoCast(SPELL_ARCANE_SHIELD); + + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, NOT_STARTED); + + if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) == 0) + { + uiGroup[0] = 0; + uiGroup[1] = 0; + uiGroup[2] = 0; + } + + x,y = 0.0f; + bCanCast = false; + bCanGoBack = false; + + me->GetMotionMaster()->MoveIdle(); + + uiTeleportTimer = urand(30000,35000); + uiArcaneExplosionTimer = 9000; + uiCastArcaneExplosionTimer = 2000; + uiFrostBombTimer = urand(5000,8000); + uiTimeBombTimer = urand(20000,25000); + } + + void EnterCombat(Unit* pWho) + { + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, IN_PROGRESS); + + SetGroups(); + SummonGroups(); + CastTeleport(); + + if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) != 3) + pInstance->SetData(DATA_UROM_PLATAFORM,pInstance->GetData(DATA_UROM_PLATAFORM)+1); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (me->GetPositionZ() > 518.63) + DoStartNoMovement(pWho); + + if (me->GetPositionZ() < 518.63) + { + if (me->Attack(pWho, true)) + { + DoScriptText(SayAggro[3],me); + + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(pWho, 0,0); + } + } + } + + void SetGroups() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) != 0) + return; + + while (uiGroup[0] == uiGroup[1] || uiGroup[0] == uiGroup[2] || uiGroup[1] == uiGroup[2]) + { + uiGroup[0] = urand(0,2); + uiGroup[1] = urand(0,2); + uiGroup[2] = urand(0,2); + } + } + + void SetPosition(uint8 uiI) + { + switch(uiI) + { + case 0: + x = me->GetPositionX() + 4; + y = me->GetPositionY() - 4; + break; + case 1: + x = me->GetPositionX() + 4; + y = me->GetPositionY() + 4; + break; + case 2: + x = me->GetPositionX() - 4; + y = me->GetPositionY() + 4; + break; + case 3: + x = me->GetPositionX() - 4; + y = me->GetPositionY() - 4; + break; + default: + break; + } + } + + void SummonGroups() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) + return; + + for (uint8 uiI = 0; uiI < 4 ; uiI++) + { + SetPosition(uiI); + me->SummonCreature(Group[uiGroup[pInstance->GetData(DATA_UROM_PLATAFORM)]].uiEntry[uiI],x,y,me->GetPositionZ(),me->GetOrientation()); + } + } + + void CastTeleport() + { + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) + return; + + DoScriptText(SayAggro[pInstance->GetData(DATA_UROM_PLATAFORM)],me); + DoCast(TeleportSpells[pInstance->GetData(DATA_UROM_PLATAFORM)]); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) < 2) + return; + + if (uiTeleportTimer <= uiDiff) + { + me->InterruptNonMeleeSpells(false); + DoScriptText(SAY_TELEPORT,me); + me->GetMotionMaster()->MoveIdle(); + DoCast(SPELL_TELEPORT); + uiTeleportTimer = urand(30000,35000); + + } else uiTeleportTimer -= uiDiff; + + if (bCanCast && !me->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION)) + { + if (uiCastArcaneExplosionTimer <= uiDiff) + { + bCanCast = false; + bCanGoBack = true; + DoCastAOE(SPELL_EMPOWERED_ARCANE_EXPLOSION); + uiCastArcaneExplosionTimer = 2000; + }else uiCastArcaneExplosionTimer -= uiDiff; + } + + if (bCanGoBack) + { + if (uiArcaneExplosionTimer <= uiDiff) + { + Position pPos; + me->getVictim()->GetPosition(&pPos); + + me->NearTeleportTo(pPos.GetPositionX(),pPos.GetPositionY(),pPos.GetPositionZ(),pPos.GetOrientation()); + me->GetMotionMaster()->MoveChase(me->getVictim(),0,0); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + + bCanCast = false; + bCanGoBack = false; + uiArcaneExplosionTimer = 9000; + } else uiArcaneExplosionTimer -= uiDiff; + } + + if (!me->IsNonMeleeSpellCasted(false, true, true)) + { + if (uiFrostBombTimer <= uiDiff) + { + DoCastVictim(SPELL_FROSTBOMB); + uiFrostBombTimer = urand(5000,8000); + } else uiFrostBombTimer -= uiDiff; + + if (uiTimeBombTimer <= uiDiff) + { + if (Unit* pUnit = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pUnit,SPELL_TIME_BOMB); + + uiTimeBombTimer = urand(20000,25000); + } else uiTimeBombTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + pInstance->SetData(DATA_UROM_EVENT, DONE); + } + + void JustSummoned(Creature* pSummon) + { + pSummon->SetInCombatWithZone(); + } + + void LeaveCombat() + { + me->RemoveAllAuras(); + me->CombatStop(false); + me->DeleteThreatList(); + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + switch(pSpell->Id) + { + case SPELL_SUMMON_MENAGERIE: + me->SetHomePosition(968.66,1042.53,527.32,0.077); + LeaveCombat(); + break; + case SPELL_SUMMON_MENAGERIE_2: + me->SetHomePosition(1164.02,1170.85,527.321,3.66); + LeaveCombat(); + break; + case SPELL_SUMMON_MENAGERIE_3: + me->SetHomePosition(1118.31,1080.377,508.361,4.25); + LeaveCombat(); + break; + case SPELL_TELEPORT: + me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE); // with out it the npc will fall down while is casting + bCanCast = true; + break; + default: + break; + } + } +}; + +CreatureAI* GetAI_boss_urom(Creature* pCreature) +{ + return new boss_uromAI (pCreature); +} + +void AddSC_boss_urom() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_urom"; + newscript->GetAI = &GetAI_boss_urom; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp new file mode 100644 index 00000000000..79034250a43 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_varos.cpp @@ -0,0 +1,105 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +enum Spells +{ + SPELL_ENERGIZE_CORES = 50785, //Damage 5938 to 6562, effec2 Triggers 54069, effect3 Triggers 56251 + SPELL_ENERGIZE_CORES_TRIGGER_1 = 54069, + SPELL_ENERGIZE_CORES_TRIGGER_2 = 56251, + SPELL_ENERGIZE_CORES_2 = 59372, //Damage 9025 to 9975, effect2 Triggers 54069, effect 56251 + SPELL_CALL_AZURE_RING_CAPTAIN = 51002, //Effect Send Event (12229) + SPELL_CALL_AZURE_RING_CAPTAIN_2 = 51006, //Effect Send Event (10665) + SPELL_CALL_AZURE_RING_CAPTAIN_3 = 51007, //Effect Send Event (18454) + SPELL_CALL_AZURE_RING_CAPTAIN_4 = 51008, //Effect Send Event (18455) + SPELL_CALL_AMPLIFY_MAGIC = 51054, + SPELL_CALL_AMPLIFY_MAGIC_2 = 59371 +}; +//not in db +enum Yells +{ + SAY_AGGRO = -1578022, + SAY_KILL_1 = -1578023, + SAY_KILL_2 = -1578024, + SAY_DEATH = -1578025, + SAY_STRIKE_1 = -1578026, + SAY_STRIKE_2 = -1578027, + SAY_STRIKE_3 = -1578028, + SAY_SPAWN = -1578029 +}; + +struct boss_varosAI : public ScriptedAI +{ + boss_varosAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, NOT_STARTED); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, IN_PROGRESS); + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_VAROS_EVENT, DONE); + } + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } +}; + +CreatureAI* GetAI_boss_varos(Creature* pCreature) +{ + return new boss_varosAI (pCreature); +} + +void AddSC_boss_varos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_varos"; + newscript->GetAI = &GetAI_boss_varos; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp new file mode 100644 index 00000000000..49be2385a3c --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Oculus/instance_oculus.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2008 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +#define MAX_ENCOUNTER 4 + +/* The Occulus encounters: +0 - Drakos the Interrogator +1 - Varos Cloudstrider +2 - Mage-Lord Urom +3 - Ley-Guardian Eregos */ + +struct instance_oculus : public ScriptedInstance +{ + instance_oculus(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiDrakos; + uint64 uiVaros; + uint64 uiUrom; + uint64 uiEregos; + + uint8 uiPlataformUrom; + + uint8 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + std::list GameObjectList; + + void Initialize() + { + uiPlataformUrom = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case CREATURE_DRAKOS: + uiDrakos = pCreature->GetGUID(); + break; + case CREATURE_VAROS: + uiVaros = pCreature->GetGUID(); + break; + case CREATURE_UROM: + uiUrom = pCreature->GetGUID(); + break; + case CREATURE_EREGOS: + uiEregos = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGO, bool bAdd) + { + if (pGO->GetEntry() == GO_DRAGON_CAGE_DOOR) + { + if (DATA_DRAKOS_EVENT == DONE) + pGO->SetGoState(GO_STATE_ACTIVE); + else + pGO->SetGoState(GO_STATE_READY); + + GameObjectList.push_back(pGO->GetGUID()); + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_DRAKOS_EVENT: + m_auiEncounter[0] = data; + if (data == DONE) + OpenCageDoors(); + break; + case DATA_VAROS_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_UROM_EVENT: + m_auiEncounter[2] = data; + break; + case DATA_EREGOS_EVENT: + m_auiEncounter[3] = data; + break; + case DATA_UROM_PLATAFORM: + uiPlataformUrom = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_DRAKOS_EVENT: return m_auiEncounter[0]; + case DATA_VAROS_EVENT: return m_auiEncounter[1]; + case DATA_UROM_EVENT: return m_auiEncounter[2]; + case DATA_EREGOS_EVENT: return m_auiEncounter[3]; + case DATA_UROM_PLATAFORM: return uiPlataformUrom; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_DRAKOS: return uiDrakos; + case DATA_VAROS: return uiVaros; + case DATA_UROM: return uiUrom; + case DATA_EREGOS: return uiEregos; + } + + return 0; + } + + void OpenCageDoors() + { + if (GameObjectList.empty()) + return; + + for (std::list::const_iterator itr = GameObjectList.begin(); itr != GameObjectList.end(); ++itr) + { + if (GameObject* pGO = instance->GetGameObject(*itr)) + pGO->SetGoState(GO_STATE_ACTIVE); + } + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "T O " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'T' && dataHead2 == 'O') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_oculus(Map* pMap) +{ + return new instance_oculus(pMap); +} + +void AddSC_instance_oculus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_oculus"; + newscript->GetInstanceData = &GetInstanceData_instance_oculus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp new file mode 100644 index 00000000000..685583532d5 --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2006 - 2010 TrinityCore +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "ScriptedPch.h" +#include "oculus.h" + +#define GOSSIP_ITEM_DRAKES "So where do we go from here?" +#define GOSSIP_ITEM_BELGARISTRASZ1 "I want to fly on the wings of the Red Flight" +#define GOSSIP_ITEM_BELGARISTRASZ2 "What abilities do Ruby Drakes have?" +#define GOSSIP_ITEM_VERDISA1 "I want to fly on the wings of the Green Flight" +#define GOSSIP_ITEM_VERDISA2 "What abilities do Emerald Drakes have?" +#define GOSSIP_ITEM_ETERNOS1 "I want to fly on the wings of the Bronze Flight" +#define GOSSIP_ITEM_ETERNOS2 "What abilities do Amber Drakes have?" + +#define HAS_ESSENCE(a) ((a)->HasItemCount(ITEM_EMERALD_ESSENCE,1) || (a)->HasItemCount(ITEM_AMBER_ESSENCE,1) || (a)->HasItemCount(ITEM_RUBY_ESSENCE,1)) + +enum Drakes +{ + GOSSIP_TEXTID_DRAKES = 13267, + GOSSIP_TEXTID_BELGARISTRASZ1 = 12916, + GOSSIP_TEXTID_BELGARISTRASZ2 = 13466, + GOSSIP_TEXTID_BELGARISTRASZ3 = 13254, + GOSSIP_TEXTID_VERDISA1 = 1, + GOSSIP_TEXTID_VERDISA2 = 1, + GOSSIP_TEXTID_VERDISA3 = 1, + GOSSIP_TEXTID_ETERNOS1 = 1, + GOSSIP_TEXTID_ETERNOS2 = 1, + GOSSIP_TEXTID_ETERNOS3 = 13256, + + ITEM_EMERALD_ESSENCE = 37815, + ITEM_AMBER_ESSENCE = 37859, + ITEM_RUBY_ESSENCE = 37860, + + NPC_VERDISA = 27657, + NPC_BELGARISTRASZ = 27658, + NPC_ETERNOS = 27659 +}; + +bool GossipHello_npc_oculus_drake(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pCreature->GetInstanceData()->GetData(DATA_DRAKOS_EVENT) == DONE) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DRAKES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DRAKES, pCreature->GetGUID()); + } + + return true; +} + +bool GossipSelect_npc_oculus_drake(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + switch(pCreature->GetEntry()) + { + case NPC_VERDISA: //Verdisa + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_EMERALD_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_EMERALD_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA3, pCreature->GetGUID()); + break; + } + break; + case NPC_BELGARISTRASZ: //Belgaristrasz + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_RUBY_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_RUBY_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ3, pCreature->GetGUID()); + break; + } + break; + case NPC_ETERNOS: //Eternos + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (!HAS_ESSENCE(pPlayer)) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS1, pCreature->GetGUID()); + } + else + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS2, pCreature->GetGUID()); + } + break; + case GOSSIP_ACTION_INFO_DEF + 2: + { + ItemPosCountVec dest; + uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_AMBER_ESSENCE, 1); + if (msg == EQUIP_ERR_OK) + pPlayer->StoreNewItem(dest, ITEM_AMBER_ESSENCE, true); + pPlayer->CLOSE_GOSSIP_MENU(); + break; + } + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS3, pCreature->GetGUID()); + break; + } + break; + } + + return true; +} + +void AddSC_oculus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_oculus_drake"; + newscript->pGossipHello = &GossipHello_npc_oculus_drake; + newscript->pGossipSelect = &GossipSelect_npc_oculus_drake; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.h b/src/server/scripts/Northrend/Nexus/Oculus/oculus.h new file mode 100644 index 00000000000..b212c9b8b6a --- /dev/null +++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.h @@ -0,0 +1,34 @@ +#ifndef DEF_OCULUS_H +#define DEF_OCULUS_H + +enum Data +{ + DATA_DRAKOS_EVENT, + DATA_VAROS_EVENT, + DATA_UROM_EVENT, + DATA_EREGOS_EVENT, + DATA_UROM_PLATAFORM +}; + +enum Data64 +{ + DATA_DRAKOS, + DATA_VAROS, + DATA_UROM, + DATA_EREGOS +}; + +enum Bosses +{ + CREATURE_DRAKOS = 27654, + CREATURE_VAROS = 27447, + CREATURE_UROM = 27655, + CREATURE_EREGOS = 27656 +}; + +enum GameObjects +{ + GO_DRAGON_CAGE_DOOR = 193995 +}; + +#endif diff --git a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp deleted file mode 100644 index bbb1df2731d..00000000000 --- a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/boss_malygos.cpp +++ /dev/null @@ -1,175 +0,0 @@ -/* Script Data Start -SDName: Boss malygos -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = '' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -//Spells -#define SPELL_ARCANE_BREATH_N 56272 -#define SPELL_ARCANE_BREATH_H 60072 -#define SPELL_ARCANE_PULSE 57432 -#define SPELL_ARCANE_STORM_1 57459 -#define SPELL_ARCANE_STORM_2 61693 -#define SPELL_ARCANE_STORM_3 61694 -#define SPELL_STATIC_FIELD 57430 -#define SPELL_SURGE_OF_POWER_1 56505 -#define SPELL_SURGE_OF_POWER_2 57407 -#define SPELL_SURGE_OF_POWER_3 60936 -#define SPELL_VORTEX 56105 - -//Dragon "mounts" spells in Phase3 -//they use Rugelike energy -#define SPELL_DMOUNT_FLAME_SPIKE 56091 //maybe not accurate -#define SPELL_DMOUNT_ENGULF_IN_FLAMES 61621 -#define SPELL_DMOUNT_REVIVIFY 57090 -#define SPELL_DMOUNT_LIFE_BURST 57143 -#define SPELL_DMOUNT_FLAME_SHIELD 57108 -//#define SPELL_DMOUNT_UNKNOWN XYZ //Increases your drake's flight speed by 500%. - -//not in db -//Yell -//-->Other -#define SAY_ANTI_MAGIC_SHELL -1616000 -#define SAY_BREATH_ATTACK -1616001 -#define SAY_HIGH_DAMAGE_MODE -1616002 -#define SAY_MAGIC_BLAST -1616003 -//--> Generic Spells -#define SAY_GENERIC_SPELL_1 -1616004 -#define SAY_GENERIC_SPELL_2 -1616005 -#define SAY_GENERIC_SPELL_3 -1616006 -#define SAY_DEATH -1616007 -//--> Prefight -#define SAY_PREFIGHT_1 -1616008 -#define SAY_PREFIGHT_2 -1616009 -#define SAY_PREFIGHT_3 -1616010 -#define SAY_PREFIGHT_4 -1616011 -#define SAY_PREFIGHT_5 -1616012 -//--> Phase1 -#define SAY_PHASE1_AGGRO -1616013 -#define SAY_PHASE1_END -1616014 -#define SAY_PHASE1_SLAY_1 -1616015 -#define SAY_PHASE1_SLAY_2 -1616016 -#define SAY_PHASE1_SLAY_3 -1616017 - -//--> Phase2 at 50% HP, - -/*Malygos himself is not targetable during this phase, it will end when the adds he spawns are all killed. However, he does continue to play a part in the encounter. -During this phase he drops anti-magic zones onto the ground the raid MUST stand inside of, it reduces magical damage taken by 50%. They shrink over time, so it's important that your raid moves to each new one he drops. -Throughout the phase, he will deep breath doing ~4k damage per second, unless you are standing inside of the anti-magic zone. -The way the fight works during this phase is there are NPCs riding around on disks in the room. There are two types of mobs, Lords and Scions. -The Lords will move down onto the group, and need to be tanked (They will one-shot a non-tank). After they die, they drop a disk that a raid member can mount onto, which allows them to fly, to attack the Scions that do not come down to the ground. -It is recommended to let melee take the first disks, then ranged. As those mobs die, they also drop disks, which allows the rest of your dps to get onto them. -The Scions will continually cast Arcane Blast on random targets on the floor, which is mitigated by the anti-magic zones. While mounted on a disk, you will not take damage. -After all of the NPCs riding on the disks die, the players on the disks need to dismount as Phase 3 is about to begin.*/ - -//not in db -#define SAY_PHASE2_AGGRO -1616018 -#define SAY_PHASE2_END -1616019 -#define SAY_PHASE2_SLAY_1 -1616020 -#define SAY_PHASE2_SLAY_2 -1616021 -#define SAY_PHASE2_SLAY_3 -1616022 -//--> Phase3 Malygos destroys the floor, encounter continues on dragon "mounts" -#define SAY_PHASE3_INTRO -1616023 -#define SAY_PHASE3_AGGRO -1616024 -#define SAY_PHASE3_SLAY_1 -1616025 -#define SAY_PHASE3_SLAY_2 -1616026 -#define SAY_PHASE3_SLAY_3 -1616027 -#define SAY_PHASE3_BIG_ATTACK -1616028 - -enum -{ - ACHIEV_TIMED_START_EVENT = 20387, -}; - -struct boss_malygosAI : public ScriptedAI -{ - boss_malygosAI(Creature *c) : ScriptedAI(c) - { - instance = me->GetInstanceData(); - } - - InstanceData *instance; - - uint32 phase; - uint32 enrage; - - void Reset() - { - phase = 1; - enrage = 615000; //Source Deadly Boss Mod - - if (instance) - instance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - void EnterCombat(Unit* /*who*/) - { - if (phase == 1) - { - DoScriptText(SAY_PHASE1_AGGRO, me); - if (instance) - instance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - if (phase == 2) - DoScriptText(SAY_PHASE1_AGGRO, me); - if (phase == 3) - DoScriptText(SAY_PHASE1_AGGRO, me); - } - - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (phase == 1 && HealthBelowPct(50)) { - phase = 2; - //spawn adds - //set malygos unatackable untill all adds spawned dead - //start phase3 - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - if (phase == 1) - DoScriptText(RAND(SAY_PHASE1_SLAY_1,SAY_PHASE1_SLAY_2,SAY_PHASE1_SLAY_3), me); - if (phase == 2) - DoScriptText(RAND(SAY_PHASE2_SLAY_1,SAY_PHASE2_SLAY_2,SAY_PHASE2_SLAY_3), me); - if (phase == 3) - DoScriptText(RAND(SAY_PHASE3_SLAY_1,SAY_PHASE3_SLAY_2,SAY_PHASE3_SLAY_3), me); - } -}; - -CreatureAI* GetAI_boss_malygos(Creature* pCreature) -{ - return new boss_malygosAI (pCreature); -} - -void AddSC_boss_malygos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_malygos"; - newscript->GetAI = &GetAI_boss_malygos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h deleted file mode 100644 index caa82a92e95..00000000000 --- a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/eye_of_eternity.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef DEF_EYE_OF_ETERNITY_H -#define DEF_EYE_OF_ETERNITY_H - -#endif diff --git a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp deleted file mode 100644 index d93ec415b42..00000000000 --- a/src/server/scripts/Northrend/TheNexus/eye_of_eternity/instance_eye_of_eternity.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "ScriptedPch.h" -#include "eye_of_eternity.h" - -struct instance_eye_of_eternity : public ScriptedInstance -{ - instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; -}; - -InstanceData* GetInstanceData_instance_eye_of_eternity(Map* pMap) -{ - return new instance_eye_of_eternity(pMap); -} - -void AddSC_instance_eye_of_eternity() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_eye_of_eternity"; - newscript->GetInstanceData = &GetInstanceData_instance_eye_of_eternity; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp b/src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp deleted file mode 100644 index 02c39dc1232..00000000000 --- a/src/server/scripts/Northrend/TheNexus/nexus/boss_anomalus.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - //Spells - SPELL_SPARK = 47751, - H_SPELL_SPARK = 57062, - SPELL_RIFT_SHIELD = 47748, - SPELL_CHARGE_RIFT = 47747, //Works wrong (affect players, not rifts) - SPELL_CREATE_RIFT = 47743, //Don't work, using WA - SPELL_ARCANE_ATTRACTION = 57063, //No idea, when it's used -}; - -enum Adds -{ - MOB_CRAZED_MANA_WRAITH = 26746, - MOB_CHAOTIC_RIFT = 26918 -}; -enum Yells -{ - //Yell - SAY_AGGRO = -1576010, - SAY_DEATH = -1576011, - SAY_RIFT = -1576012, - SAY_SHIELD = -1576013 -}; - -enum Achievs -{ - ACHIEV_CHAOS_THEORY = 2037 -}; - -const Position RiftLocation[6] = -{ - {652.64, -273.70, -8.75}, - {634.45, -265.94, -8.44}, - {620.73, -281.17, -9.02}, - {626.10, -304.67, -9.44}, - {639.87, -314.11, -9.49}, - {651.72, -297.44, -9.37} -}; - -struct boss_anomalusAI : public ScriptedAI -{ - boss_anomalusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint8 Phase; - uint32 uiSparkTimer; - uint32 uiCreateRiftTimer; - uint64 uiChaoticRiftGUID; - - bool bDeadChaoticRift; // needed for achievement: Chaos Theory(2037) - - void Reset() - { - Phase = 0; - uiSparkTimer = 5*IN_MILISECONDS; - uiChaoticRiftGUID = 0; - - bDeadChaoticRift = false; - - if (pInstance) - pInstance->SetData(DATA_ANOMALUS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_ANOMALUS_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && !bDeadChaoticRift) - pInstance->DoCompleteAchievement(ACHIEV_CHAOS_THEORY); - pInstance->SetData(DATA_ANOMALUS_EVENT, DONE); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (me->GetDistance(me->GetHomePosition()) > 60.0f) - { - //Not blizzlike, hack to avoid an exploit - EnterEvadeMode(); - return; - } - - if (me->HasAura(SPELL_RIFT_SHIELD)) - { - if (uiChaoticRiftGUID) - { - Unit* Rift = Unit::GetUnit((*me), uiChaoticRiftGUID); - if (Rift && Rift->isDead()) - { - me->RemoveAurasDueToSpell(SPELL_RIFT_SHIELD); - uiChaoticRiftGUID = 0; - } - return; - } - } else - uiChaoticRiftGUID = 0; - - if ((Phase == 0) && HealthBelowPct(50)) - { - Phase = 1; - DoScriptText(SAY_SHIELD, me); - DoCast(me, SPELL_RIFT_SHIELD); - Creature* Rift = me->SummonCreature(MOB_CHAOTIC_RIFT, RiftLocation[urand(0,5)], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); - if (Rift) - { - //DoCast(Rift, SPELL_CHARGE_RIFT); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Rift->AI()->AttackStart(pTarget); - uiChaoticRiftGUID = Rift->GetGUID(); - DoScriptText(SAY_RIFT , me); - } - } - - - if (uiSparkTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_SPARK); - uiSparkTimer = 5*IN_MILISECONDS; - } else uiSparkTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_anomalus(Creature* pCreature) -{ - return new boss_anomalusAI (pCreature); -} - -enum RiftSpells -{ - SPELL_CHAOTIC_ENERGY_BURST = 47688, - SPELL_CHARGED_CHAOTIC_ENERGY_BURST = 47737, - SPELL_ARCANEFORM = 48019 //Chaotic Rift visual -}; - -struct mob_chaotic_riftAI : public Scripted_NoMovementAI -{ - mob_chaotic_riftAI(Creature *c) : Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiChaoticEnergyBurstTimer; - uint32 uiSummonCrazedManaWraithTimer; - - void Reset() - { - uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; - uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; - //me->SetDisplayId(25206); //For some reason in DB models for ally and horde are different. - //Model for ally (1126) does not show auras. Horde model works perfect. - //Set model to horde number - DoCast(me, SPELL_ARCANEFORM, false); - } - - void JustDied(Unit * /*killer*/) - { - if (Creature* pAnomalus = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0)) - CAST_AI(boss_anomalusAI,pAnomalus->AI())->bDeadChaoticRift = true; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiChaoticEnergyBurstTimer <= diff) - { - Unit* pAnomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - if (pAnomalus && pAnomalus->HasAura(SPELL_RIFT_SHIELD)) - DoCast(pTarget, SPELL_CHARGED_CHAOTIC_ENERGY_BURST); - else - DoCast(pTarget, SPELL_CHAOTIC_ENERGY_BURST); - uiChaoticEnergyBurstTimer = 1*IN_MILISECONDS; - } else uiChaoticEnergyBurstTimer -= diff; - - if (uiSummonCrazedManaWraithTimer <= diff) - { - Creature* Wraith = me->SummonCreature(MOB_CRAZED_MANA_WRAITH, me->GetPositionX()+1, me->GetPositionY()+1, me->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS); - if (Wraith) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Wraith->AI()->AttackStart(pTarget); - Unit* Anomalus = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_ANOMALUS) : 0); - if (Anomalus && Anomalus->HasAura(SPELL_RIFT_SHIELD)) - uiSummonCrazedManaWraithTimer = 5*IN_MILISECONDS; - else - uiSummonCrazedManaWraithTimer = 10*IN_MILISECONDS; - } else uiSummonCrazedManaWraithTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_chaotic_rift(Creature* pCreature) -{ - return new mob_chaotic_riftAI (pCreature); -} - -void AddSC_boss_anomalus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_anomalus"; - newscript->GetAI = &GetAI_boss_anomalus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_chaotic_rift"; - newscript->GetAI = &GetAI_mob_chaotic_rift; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp b/src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp deleted file mode 100644 index ff633c55eac..00000000000 --- a/src/server/scripts/Northrend/TheNexus/nexus/boss_keristrasza.cpp +++ /dev/null @@ -1,247 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - //Spells - SPELL_FROZEN_PRISON = 47854, - SPELL_TAIL_SWEEP = 50155, - SPELL_CRYSTAL_CHAINS = 50997, - SPELL_ENRAGE = 8599, - SPELL_CRYSTALFIRE_BREATH = 48096, - H_SPELL_CRYSTALFIRE_BREATH = 57091, - SPELL_CRYSTALIZE = 48179, - SPELL_INTENSE_COLD = 48094, - SPELL_INTENSE_COLD_TRIGGERED = 48095 -}; -enum Yells -{ - //Yell - SAY_AGGRO = -1576040, - SAY_SLAY = -1576041, - SAY_ENRAGE = -1576042, - SAY_DEATH = -1576043, - SAY_CRYSTAL_NOVA = -1576044 -}; -enum Achievements -{ - ACHIEV_INTENSE_COLD = 2036 -}; -enum Misc -{ - DATA_CONTAINMENT_SPHERES = 3 -}; - -struct boss_keristraszaAI : public ScriptedAI -{ - boss_keristraszaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCrystalfireBreathTimer; - uint32 uiCrystalChainsCrystalizeTimer; - uint32 uiTailSweepTimer; - bool bEnrage; - - uint64 auiContainmentSphereGUIDs[DATA_CONTAINMENT_SPHERES]; - - uint32 uiCheckIntenseColdTimer; - bool bMoreThanTwoIntenseCold; // needed for achievement: Intense Cold(2036) - - void Reset() - { - uiCrystalfireBreathTimer = 14*IN_MILISECONDS; - uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); - uiTailSweepTimer = 5*IN_MILISECONDS; - bEnrage = false; - - uiCheckIntenseColdTimer = 2*IN_MILISECONDS; - bMoreThanTwoIntenseCold = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - - RemovePrison(CheckContainmentSpheres()); - - if (pInstance) - pInstance->SetData(DATA_KERISTRASZA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoCastAOE(SPELL_INTENSE_COLD); - - if (pInstance) - pInstance->SetData(DATA_KERISTRASZA_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && !bMoreThanTwoIntenseCold) - pInstance->DoCompleteAchievement(ACHIEV_INTENSE_COLD); - pInstance->SetData(DATA_KERISTRASZA_EVENT, DONE); - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_SLAY, me); - } - - bool CheckContainmentSpheres(bool remove_prison = false) - { - if (!pInstance) - return false; - - auiContainmentSphereGUIDs[0] = pInstance->GetData64(ANOMALUS_CONTAINMET_SPHERE); - auiContainmentSphereGUIDs[1] = pInstance->GetData64(ORMOROKS_CONTAINMET_SPHERE); - auiContainmentSphereGUIDs[2] = pInstance->GetData64(TELESTRAS_CONTAINMET_SPHERE); - - GameObject *ContainmentSpheres[DATA_CONTAINMENT_SPHERES]; - - for (uint8 i = 0; i < DATA_CONTAINMENT_SPHERES; ++i) - { - ContainmentSpheres[i] = pInstance->instance->GetGameObject(auiContainmentSphereGUIDs[i]); - if (!ContainmentSpheres[i]) - return false; - if (ContainmentSpheres[i]->GetGoState() != GO_STATE_ACTIVE) - return false; - } - if (remove_prison) - RemovePrison(true); - return true; - } - - void RemovePrison(bool remove) - { - if (remove) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (me->HasAura(SPELL_FROZEN_PRISON)) - me->RemoveAurasDueToSpell(SPELL_FROZEN_PRISON); - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoCast(me, SPELL_FROZEN_PRISON, false); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (uiCheckIntenseColdTimer < diff && !bMoreThanTwoIntenseCold) - { - std::list ThreatList = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER) - continue; - - Aura *AuraIntenseCold = pTarget->GetAura(SPELL_INTENSE_COLD_TRIGGERED); - if (AuraIntenseCold && AuraIntenseCold->GetStackAmount() > 2) - { - bMoreThanTwoIntenseCold = true; - break; - } - } - uiCheckIntenseColdTimer = 2*IN_MILISECONDS; - } else uiCheckIntenseColdTimer -= diff; - - if (!bEnrage && HealthBelowPct(25)) - { - DoScriptText(SAY_ENRAGE, me); - DoCast(me, SPELL_ENRAGE); - bEnrage = true; - } - - if (uiCrystalfireBreathTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CRYSTALFIRE_BREATH); - uiCrystalfireBreathTimer = 14*IN_MILISECONDS; - } else uiCrystalfireBreathTimer -= diff; - - if (uiTailSweepTimer <= diff) - { - DoCast(me, SPELL_TAIL_SWEEP); - uiTailSweepTimer = 5*IN_MILISECONDS; - } else uiTailSweepTimer -= diff; - - if (uiCrystalChainsCrystalizeTimer <= diff) - { - DoScriptText(SAY_CRYSTAL_NOVA, me); - if (IsHeroic()) - DoCast(me, SPELL_CRYSTALIZE); - else if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CRYSTAL_CHAINS); - uiCrystalChainsCrystalizeTimer = DUNGEON_MODE(30*IN_MILISECONDS,11*IN_MILISECONDS); - } else uiCrystalChainsCrystalizeTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_keristrasza(Creature* pCreature) -{ - return new boss_keristraszaAI (pCreature); -} - -bool GOHello_containment_sphere(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - - Creature *pKeristrasza = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_KERISTRASZA) : 0); - if (pKeristrasza && pKeristrasza->isAlive()) - { - // maybe these are hacks :( - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - CAST_AI(boss_keristraszaAI, pKeristrasza->AI())->CheckContainmentSpheres(true); - } - return true; -} - -void AddSC_boss_keristrasza() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_keristrasza"; - newscript->GetAI = &GetAI_boss_keristrasza; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "containment_sphere"; - newscript->pGOHello = &GOHello_containment_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp b/src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp deleted file mode 100644 index 0bf9fb07bb7..00000000000 --- a/src/server/scripts/Northrend/TheNexus/nexus/boss_magus_telestra.cpp +++ /dev/null @@ -1,327 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - SPELL_ICE_NOVA = 47772, - H_SPELL_ICE_NOVA = 56935, - SPELL_FIREBOMB = 47773, - H_SPELL_FIREBOMB = 56934, - SPELL_GRAVITY_WELL = 47756, - SPELL_TELESTRA_BACK = 47714, - - SPELL_FIRE_MAGUS_VISUAL = 47705, - SPELL_FROST_MAGUS_VISUAL = 47706, - SPELL_ARCANE_MAGUS_VISUAL = 47704 -}; -enum Creatures -{ - MOB_FIRE_MAGUS = 26928, - MOB_FROST_MAGUS = 26930, - MOB_ARCANE_MAGUS = 26929 -}; -enum Yells -{ - SAY_AGGRO = -1576000, - SAY_KILL = -1576001, - SAY_DEATH = -1576002, - SAY_MERGE = -1576003, - SAY_SPLIT_1 = -1576004, - SAY_SPLIT_2 = -1576005, -}; -enum Achievements -{ - ACHIEV_SPLIT_PERSONALITY = 2150, - ACHIEV_TIMER = 5*IN_MILISECONDS -}; - -const Position CenterOfRoom = {504.80, 89.07, -16.12, 6.27}; - -struct boss_magus_telestraAI : public ScriptedAI -{ - boss_magus_telestraAI(Creature* c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 uiFireMagusGUID; - uint64 uiFrostMagusGUID; - uint64 uiArcaneMagusGUID; - - bool bFireMagusDead; - bool bFrostMagusDead; - bool bArcaneMagusDead; - bool bIsWaitingToAppear; - bool bIsAchievementTimerRunning; - - uint32 uiIsWaitingToAppearTimer; - uint32 uiIceNovaTimer; - uint32 uiFireBombTimer; - uint32 uiGravityWellTimer; - uint32 uiCooldown; - uint32 uiAchievementTimer; - - uint8 Phase; - uint8 uiAchievementProgress; - - void Reset() - { - Phase = 0; - //These times are probably wrong - uiIceNovaTimer = 7*IN_MILISECONDS; - uiFireBombTimer = 0; - uiGravityWellTimer = 15*IN_MILISECONDS; - uiCooldown = 0; - - uiFireMagusGUID = 0; - uiFrostMagusGUID = 0; - uiArcaneMagusGUID = 0; - - uiAchievementProgress = 0; - uiAchievementTimer = 0; - - bIsAchievementTimerRunning = false; - bIsWaitingToAppear = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - if (pInstance) - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - if (IsHeroic() && uiAchievementProgress == 2) - pInstance->DoCompleteAchievement(ACHIEV_SPLIT_PERSONALITY); - pInstance->SetData(DATA_MAGUS_TELESTRA_EVENT, DONE); - } - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - uint64 SplitPersonality(uint32 entry) - { - if (Creature* Summoned = me->SummonCreature(entry, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1*IN_MILISECONDS)) - { - switch (entry) - { - case MOB_FIRE_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_FIRE_MAGUS_VISUAL, false); - break; - } - case MOB_FROST_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_FROST_MAGUS_VISUAL, false); - break; - } - case MOB_ARCANE_MAGUS: - { - Summoned->CastSpell(Summoned, SPELL_ARCANE_MAGUS_VISUAL, false); - break; - } - } - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Summoned->AI()->AttackStart(pTarget); - return Summoned->GetGUID(); - } - return 0; - } - - void SummonedCreatureDespawn(Creature *summon) - { - if (summon->isAlive()) - return; - - if (summon->GetGUID() == uiFireMagusGUID) - { - bFireMagusDead = true; - bIsAchievementTimerRunning = true; - } - else if (summon->GetGUID() == uiFrostMagusGUID) - { - bFrostMagusDead = true; - bIsAchievementTimerRunning = true; - } - else if (summon->GetGUID() == uiArcaneMagusGUID) - { - bArcaneMagusDead = true; - bIsAchievementTimerRunning = true; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (bIsWaitingToAppear) - { - me->StopMoving(); - me->AttackStop(); - if (uiIsWaitingToAppearTimer <= diff) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - bIsWaitingToAppear = false; - } else uiIsWaitingToAppearTimer -= diff; - return; - } - - if ((Phase == 1) ||(Phase == 3)) - { - if (bIsAchievementTimerRunning) - uiAchievementTimer += diff; - if (bFireMagusDead && bFrostMagusDead && bArcaneMagusDead) - { - if (uiAchievementTimer <= ACHIEV_TIMER) - uiAchievementProgress +=1; - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, CenterOfRoom.GetPositionX(), CenterOfRoom.GetPositionY(), CenterOfRoom.GetPositionZ(), CenterOfRoom.GetOrientation()); - DoCast(me, SPELL_TELESTRA_BACK); - me->SetVisibility(VISIBILITY_ON); - if (Phase == 1) - Phase = 2; - if (Phase == 3) - Phase = 4; - uiFireMagusGUID = 0; - uiFrostMagusGUID = 0; - uiArcaneMagusGUID = 0; - bIsWaitingToAppear = true; - uiIsWaitingToAppearTimer = 4*IN_MILISECONDS; - DoScriptText(SAY_MERGE, me); - bIsAchievementTimerRunning = false; - uiAchievementTimer = 0; - } - else - return; - } - - if ((Phase == 0) && HealthBelowPct(50)) - { - Phase = 1; - me->CastStop(); - me->RemoveAllAuras(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); - uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); - uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); - bFireMagusDead = false; - bFrostMagusDead = false; - bArcaneMagusDead = false; - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - return; - } - - if (IsHeroic() && (Phase == 2) && HealthBelowPct(10)) - { - Phase = 3; - me->CastStop(); - me->RemoveAllAuras(); - me->SetVisibility(VISIBILITY_OFF); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - uiFireMagusGUID = SplitPersonality(MOB_FIRE_MAGUS); - uiFrostMagusGUID = SplitPersonality(MOB_FROST_MAGUS); - uiArcaneMagusGUID = SplitPersonality(MOB_ARCANE_MAGUS); - bFireMagusDead = false; - bFrostMagusDead = false; - bArcaneMagusDead = false; - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - return; - } - - if (uiCooldown) - { - if (uiCooldown <= diff) - uiCooldown = 0; - else - { - uiCooldown -= diff; - return; - } - } - - if (uiIceNovaTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_ICE_NOVA, false); - uiCooldown = 1.5*IN_MILISECONDS; - } - uiIceNovaTimer = 15*IN_MILISECONDS; - } else uiIceNovaTimer -= diff; - - if (uiGravityWellTimer <= diff) - { - if (Unit *pTarget = me->getVictim()) - { - DoCast(pTarget, SPELL_GRAVITY_WELL); - uiCooldown = 6*IN_MILISECONDS; - } - uiGravityWellTimer = 15*IN_MILISECONDS; - } else uiGravityWellTimer -= diff; - - if (uiFireBombTimer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_FIREBOMB, false); - uiCooldown = 2*IN_MILISECONDS; - } - uiFireBombTimer = 2*IN_MILISECONDS; - } else uiFireBombTimer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_magus_telestra(Creature* pCreature) -{ - return new boss_magus_telestraAI (pCreature); -} - -void AddSC_boss_magus_telestra() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_magus_telestra"; - newscript->GetAI = &GetAI_boss_magus_telestra; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp b/src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp deleted file mode 100644 index 1304f95c7ac..00000000000 --- a/src/server/scripts/Northrend/TheNexus/nexus/boss_ormorok.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -enum Spells -{ - SPELL_CRYSTAL_SPIKES = 47958, //Don't work, using walkaround - H_SPELL_CRYSTAL_SPIKES = 57082, //Don't work, using walkaround - SPELL_CRYSTALL_SPIKE_DAMAGE = 47944, - H_SPELL_CRYSTALL_SPIKE_DAMAGE = 57067, - SPELL_CRYSTAL_SPIKE_PREVISUAL = 50442, - MOB_CRYSTAL_SPIKE = 27099, - SPELL_SPELL_REFLECTION = 47981, - SPELL_TRAMPLE = 48016, - H_SPELL_TRAMPLE = 57066, - SPELL_FRENZY = 48017, - SPELL_SUMMON_CRYSTALLINE_TANGLER = 61564, //summons npc 32665 - SPELL_ROOTS = 28858 //proper spell id is unknown -}; -enum Yells -{ - SAY_AGGRO = -1576020, - SAY_DEATH = -1576021, - SAY_REFLECT = -1576022, - SAY_CRYSTAL_SPIKES = -1576023, - SAY_KILL = -1576024 -}; -enum Creatures -{ - MOB_CRYSTALLINE_TANGLER = 32665 -}; - -#define SPIKE_DISTANCE 5.0f - -struct boss_ormorokAI : public ScriptedAI -{ - boss_ormorokAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bFrenzy; - bool bCrystalSpikes; - uint8 uiCrystalSpikesCount; - float fBaseX; - float fBaseY; - float fBaseZ; - float fBaseO; - float fSpikeXY[4][2]; - - uint32 uiCrystalSpikesTimer; - uint32 uiCrystalSpikesTimer2; - uint32 uiTrampleTimer; - uint32 uiFrenzyTimer; - uint32 uiSpellReflectionTimer; - uint32 uiSummonCrystallineTanglerTimer; - - void Reset() - { - uiCrystalSpikesTimer = 12*IN_MILISECONDS; - uiTrampleTimer = 10*IN_MILISECONDS; - uiSpellReflectionTimer = 30*IN_MILISECONDS; - uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; - bFrenzy = false; - bCrystalSpikes = false; - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_ORMOROK_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(SAY_KILL, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - return; - } - if (bCrystalSpikes) - if (uiCrystalSpikesTimer2 <= diff) - { - fSpikeXY[0][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); - fSpikeXY[0][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); - fSpikeXY[1][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO)); - fSpikeXY[1][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO)); - fSpikeXY[2][0] = fBaseX+(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); - fSpikeXY[2][1] = fBaseY+(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); - fSpikeXY[3][0] = fBaseX-(SPIKE_DISTANCE*uiCrystalSpikesCount*cos(fBaseO-(M_PI/2))); - fSpikeXY[3][1] = fBaseY-(SPIKE_DISTANCE*uiCrystalSpikesCount*sin(fBaseO-(M_PI/2))); - for (uint8 i = 0; i < 4; ++i) - me->SummonCreature(MOB_CRYSTAL_SPIKE, fSpikeXY[i][0], fSpikeXY[i][1], fBaseZ, 0, TEMPSUMMON_TIMED_DESPAWN, 7*IN_MILISECONDS); - if (++uiCrystalSpikesCount >= 13) - bCrystalSpikes = false; - uiCrystalSpikesTimer2 = 200; - } else uiCrystalSpikesTimer2 -= diff; - - if (!bFrenzy && (me->GetHealth() < me->GetMaxHealth() * 0.25)) - { - DoCast(me, SPELL_FRENZY); - bFrenzy = true; - } - - if (uiTrampleTimer <= diff) - { - DoCast(me, SPELL_TRAMPLE); - uiTrampleTimer = 10*IN_MILISECONDS; - } else uiTrampleTimer -= diff; - - if (uiSpellReflectionTimer <= diff) - { - DoScriptText(SAY_REFLECT, me); - DoCast(me, SPELL_SPELL_REFLECTION); - uiSpellReflectionTimer = 30*IN_MILISECONDS; - } else uiSpellReflectionTimer -= diff; - - if (uiCrystalSpikesTimer <= diff) - { - DoScriptText(SAY_CRYSTAL_SPIKES, me); - bCrystalSpikes = true; - uiCrystalSpikesCount = 1; - uiCrystalSpikesTimer2 = 0; - fBaseX = me->GetPositionX(); - fBaseY = me->GetPositionY(); - fBaseZ = me->GetPositionZ(); - fBaseO = me->GetOrientation(); - uiCrystalSpikesTimer = 20*IN_MILISECONDS; - } else uiCrystalSpikesTimer -= diff; - - if (IsHeroic() && (uiSummonCrystallineTanglerTimer <= diff)) - { - Creature* Crystalline_Tangler = me->SummonCreature(MOB_CRYSTALLINE_TANGLER, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000); - if (Crystalline_Tangler) - { - Unit *pTarget = NULL; - uint8 Healer = 0; - for (uint8 j = 1; j <= 4; j++) - { - switch (j) - { - case 1: Healer = CLASS_PRIEST; break; - case 2: Healer = CLASS_PALADIN; break; - case 3: Healer = CLASS_DRUID; break; - case 4: Healer = CLASS_SHAMAN; break; - } - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pTemp = Unit::GetUnit((*me),(*i)->getUnitGuid()); - if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && pTemp->getClass() == Healer) - { - pTarget = pTemp; - break; - } - } - if (pTarget) - break; - } - if (!pTarget) - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Crystalline_Tangler->AI()->AttackStart(pTarget); - Crystalline_Tangler->getThreatManager().addThreat(pTarget, 1000000000.0f); - } - } - uiSummonCrystallineTanglerTimer = 17*IN_MILISECONDS; - } else uiSummonCrystallineTanglerTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_crystal_spikeAI : public Scripted_NoMovementAI -{ - mob_crystal_spikeAI(Creature *c) : Scripted_NoMovementAI(c) - { - } - - uint32 SpellCrystalSpikeDamageTimer; - uint32 SpellCrystalSpikePrevisualTimer; - - void Reset() - { - SpellCrystalSpikeDamageTimer = 3.7*IN_MILISECONDS; - SpellCrystalSpikePrevisualTimer = 1*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (SpellCrystalSpikePrevisualTimer <= diff) - { - DoCast(me, SPELL_CRYSTAL_SPIKE_PREVISUAL); - SpellCrystalSpikePrevisualTimer = 10*IN_MILISECONDS; - } else SpellCrystalSpikePrevisualTimer -= diff; - - if (SpellCrystalSpikeDamageTimer <= diff) - { - DoCast(me, SPELL_CRYSTALL_SPIKE_DAMAGE); - SpellCrystalSpikeDamageTimer = 10*IN_MILISECONDS; - } else SpellCrystalSpikeDamageTimer -= diff; - } -}; - -struct mob_crystalline_tanglerAI : public ScriptedAI -{ - mob_crystalline_tanglerAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiRootsTimer; - - void Reset() - { - uiRootsTimer = 1*IN_MILISECONDS; - } - - void UpdateAI(const uint32 diff) - { - if (uiRootsTimer <= diff) - { - if (me->IsWithinDist(me->getVictim(), 5.0f, false)) - { - DoCast(me->getVictim(), SPELL_ROOTS); - uiRootsTimer = 15*IN_MILISECONDS; - } - } else uiRootsTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_crystal_spike(Creature* pCreature) -{ - return new mob_crystal_spikeAI (pCreature); -} - -CreatureAI* GetAI_mob_crystalline_tangler(Creature* pCreature) -{ - return new mob_crystalline_tanglerAI (pCreature); -} - -CreatureAI* GetAI_boss_ormorok(Creature* pCreature) -{ - return new boss_ormorokAI (pCreature); -} - -void AddSC_boss_ormorok() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ormorok"; - newscript->GetAI = &GetAI_boss_ormorok; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crystal_spike"; - newscript->GetAI = &GetAI_mob_crystal_spike; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_crystalline_tangler"; - newscript->GetAI = &GetAI_mob_crystalline_tangler; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp b/src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp deleted file mode 100644 index 4bd9f55a013..00000000000 --- a/src/server/scripts/Northrend/TheNexus/nexus/commander_kolurg.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* Script Data Start -SDName: Boss Commander Kolurg -SDAuthor: LordVanMartin -SD%Complete: -SDComment: Only Alliance Heroic -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_commander_kolurg' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -#define SPELL_BATTLE_SHOUT 31403 -#define SPELL_CHARGE 60067 -#define SPELL_FRIGHTENING_SHOUT 19134 -#define SPELL_WHIRLWIND_1 38619 -#define SPELL_WHIRLWIND_2 38618 - -//not used -//Yell -#define SAY_AGGRO -1576024 -#define SAY_KILL -1576025 -#define SAY_DEATH -1576026 - -struct boss_commander_kolurgAI : public ScriptedAI -{ - boss_commander_kolurgAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) {} -}; - -CreatureAI* GetAI_boss_commander_kolurg(Creature* pCreature) -{ - return new boss_commander_kolurgAI (pCreature); -} - -void AddSC_boss_commander_kolurg() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_commander_kolurg"; - newscript->GetAI = &GetAI_boss_commander_kolurg; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp b/src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp deleted file mode 100644 index ef02baa38e6..00000000000 --- a/src/server/scripts/Northrend/TheNexus/nexus/commander_stoutbeard.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* Script Data Start -SDName: Boss Commander Stoutbeard -SDAuthor: LordVanMartin -SD%Complete: -SDComment: Only Horde Heroic -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_commander_stoutbeard' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" - -#define SPELL_BATTLE_SHOUT 31403 -#define SPELL_CHARGE 60067 -#define SPELL_FRIGHTENING_SHOUT 19134 -#define SPELL_WHIRLWIND_1 38619 -#define SPELL_WHIRLWIND_2 38618 - -//not used -//Yell -#define SAY_AGGRO -1576021 -#define SAY_KILL -1576022 -#define SAY_DEATH -1576023 - -struct boss_commander_stoutbeardAI : public ScriptedAI -{ - boss_commander_stoutbeardAI(Creature *c) : ScriptedAI(c) {} - - void Reset() {} - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - } -}; - -CreatureAI* GetAI_boss_commander_stoutbeard(Creature* pCreature) -{ - return new boss_commander_stoutbeardAI (pCreature); -} - -void AddSC_boss_commander_stoutbeard() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_commander_stoutbeard"; - newscript->GetAI = &GetAI_boss_commander_stoutbeard; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp b/src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp deleted file mode 100644 index db70245e3a4..00000000000 --- a/src/server/scripts/Northrend/TheNexus/nexus/instance_nexus.cpp +++ /dev/null @@ -1,259 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "nexus.h" - -#define NUMBER_OF_ENCOUNTERS 4 - -enum Factions -{ - FACTION_HOSTILE_FOR_ALL = 16 -}; - -struct instance_nexus : public ScriptedInstance -{ - instance_nexus(Map *pMap) : ScriptedInstance(pMap) { Initialize(); } - - uint32 m_auiEncounter[NUMBER_OF_ENCOUNTERS]; - - uint64 Anomalus; - uint64 Keristrasza; - - uint64 AnomalusContainmentSphere; - uint64 OrmoroksContainmentSphere; - uint64 TelestrasContainmentSphere; - - std::string strInstData; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Anomalus = 0; - Keristrasza = 0; - } - - void OnCreatureCreate(Creature *pCreature, bool /*bAdd*/) - { - Map::PlayerList const &players = instance->GetPlayers(); - uint32 TeamInInstance = 0; - - if (!players.isEmpty()) - { - if (Player* pPlayer = players.begin()->getSource()) - TeamInInstance = pPlayer->GetTeam(); - } - switch (pCreature->GetEntry()) - { - case 26763: - Anomalus = pCreature->GetGUID(); - break; - case 26723: - Keristrasza = pCreature->GetGUID(); - break; - // Alliance npcs are spawned by default, if you are alliance, you will fight against horde npcs. - case 26800: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26799, HORDE); - break; - } - case 26802: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26801, HORDE); - break; - } - case 26805: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26803, HORDE); - break; - } - case 27949: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(27947, HORDE); - break; - } - case 26796: - { - if (ServerAllowsTwoSideGroups()) - pCreature->setFaction(FACTION_HOSTILE_FOR_ALL); - if (TeamInInstance == ALLIANCE) - pCreature->UpdateEntry(26798, HORDE); - break; - } - } - } - - void OnGameObjectCreate(GameObject *pGo, bool /*bAdd*/) - { - switch (pGo->GetEntry()) - { - case 188527: - { - AnomalusContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - case 188528: - { - OrmoroksContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - case 188526: - { - TelestrasContainmentSphere = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - break; - } - } - } - - uint32 GetData(uint32 identifier) - { - switch(identifier) - { - case DATA_MAGUS_TELESTRA_EVENT: return m_auiEncounter[0]; - case DATA_ANOMALUS_EVENT: return m_auiEncounter[1]; - case DATA_ORMOROK_EVENT: return m_auiEncounter[2]; - case DATA_KERISTRASZA_EVENT: return m_auiEncounter[3]; - } - return 0; - } - - void SetData(uint32 identifier, uint32 data) - { - switch (identifier) - { - case DATA_MAGUS_TELESTRA_EVENT: - { - if (data == DONE) - { - GameObject *Sphere = instance->GetGameObject(TelestrasContainmentSphere); - if (Sphere) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[0] = data; - break; - } - case DATA_ANOMALUS_EVENT: - { - if (data == DONE) - { - if (GameObject *Sphere = instance->GetGameObject(AnomalusContainmentSphere)) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[1] = data; - break; - } - case DATA_ORMOROK_EVENT: - { - if (data == DONE) - { - if (GameObject *Sphere = instance->GetGameObject(OrmoroksContainmentSphere)) - Sphere->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - m_auiEncounter[2] = data; - break; - } - case DATA_KERISTRASZA_EVENT: - m_auiEncounter[3] = data; - break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3]; - - strInstData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint64 GetData64(uint32 uiIdentifier) - { - switch(uiIdentifier) - { - case DATA_ANOMALUS: return Anomalus; - case DATA_KERISTRASZA: return Keristrasza; - case ANOMALUS_CONTAINMET_SPHERE: return AnomalusContainmentSphere; - case ORMOROKS_CONTAINMET_SPHERE: return OrmoroksContainmentSphere; - case TELESTRAS_CONTAINMET_SPHERE: return TelestrasContainmentSphere; - } - return 0; - } - - std::string GetSaveData() - { - return strInstData; - } - - void Load(const char *chrIn) - { - if (!chrIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(chrIn); - - std::istringstream loadStream(chrIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - - for (uint8 i = 0; i < NUMBER_OF_ENCOUNTERS; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData *GetInstanceData_instance_nexus(Map *pMap) -{ - return new instance_nexus(pMap); -} - -void AddSC_instance_nexus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_nexus"; - newscript->GetInstanceData = &GetInstanceData_instance_nexus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/nexus/nexus.h b/src/server/scripts/Northrend/TheNexus/nexus/nexus.h deleted file mode 100644 index 66902bece30..00000000000 --- a/src/server/scripts/Northrend/TheNexus/nexus/nexus.h +++ /dev/null @@ -1,35 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_NEXUS_H -#define DEF_NEXUS_H - -enum eTypes -{ - DATA_MAGUS_TELESTRA_EVENT, - DATA_ANOMALUS_EVENT, - DATA_ORMOROK_EVENT, - DATA_KERISTRASZA_EVENT, - - DATA_ANOMALUS, - DATA_KERISTRASZA, - - ANOMALUS_CONTAINMET_SPHERE, - ORMOROKS_CONTAINMET_SPHERE, - TELESTRAS_CONTAINMET_SPHERE -}; - -#endif diff --git a/src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp b/src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp deleted file mode 100644 index 7d276206339..00000000000 --- a/src/server/scripts/Northrend/TheNexus/oculus/boss_drakos.cpp +++ /dev/null @@ -1,218 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - SPELL_MAGIC_PULL = 51336, - SPELL_MAGIC_PULL_EFFECT = 50770, - SPELL_THUNDERING_STOMP = 50774, - SPELL_THUNDERING_STOMP_H = 59370, - SPELL_UNSTABLE_SPHERE_PASSIVE = 50756, - SPELL_UNSTABLE_SPHERE_PULSE = 50757, - SPELL_UNSTABLE_SPHERE_TIMER = 50758, - NPC_UNSTABLE_SPHERE = 28166, -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1578000, - SAY_KILL_1 = -1578001, - SAY_KILL_2 = -1578002, - SAY_KILL_3 = -1578003, - SAY_DEATH = -1578004, - SAY_PULL_1 = -1578005, - SAY_PULL_2 = -1578006, - SAY_PULL_3 = -1578007, - SAY_PULL_4 = -1578008, - SAY_STOMP_1 = -1578009, - SAY_STOMP_2 = -1578010, - SAY_STOMP_3 = -1578011 -}; - -enum -{ - ACHIEV_TIMED_START_EVENT = 18153, -}; - -struct boss_drakosAI : public ScriptedAI -{ - boss_drakosAI(Creature* pCreature) : ScriptedAI(pCreature), lSummons(me) - { - pInstance = pCreature->GetInstanceData(); - } - - uint32 uiMagicPullTimer; - uint32 uiStompTimer; - uint32 uiBombSummonTimer; - - bool bPostPull; - - ScriptedInstance* pInstance; - SummonList lSummons; - - void Reset() - { - lSummons.DespawnAll(); - uiMagicPullTimer = 15000; - uiStompTimer = 17000; - uiBombSummonTimer = 2000; - - bPostPull = false; - - if (pInstance) - pInstance->SetData(DATA_DRAKOS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_DRAKOS_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature* pSummon) - { - lSummons.Summon(pSummon); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBombSummonTimer <= uiDiff) - { - Position pPosition; - me->GetPosition(&pPosition); - - if (bPostPull) - { - for (uint8 uiI = 0; uiI >= 3; uiI++) - { - me->GetRandomNearPosition(pPosition, float(urand(0,10))); - me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); - } - } - else - { - me->GetRandomNearPosition(pPosition, float(urand(0,10))); - me->SummonCreature(NPC_UNSTABLE_SPHERE, pPosition); - } - - uiBombSummonTimer = 2000; - } else uiBombSummonTimer -= uiDiff; - - if (uiMagicPullTimer <= uiDiff) - { - DoCast(SPELL_MAGIC_PULL); - - bPostPull = true; - - uiMagicPullTimer = 15000; - } else uiMagicPullTimer -= uiDiff; - - if (uiStompTimer <= uiDiff) - { - DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2,SAY_STOMP_3), me); - DoCast(SPELL_THUNDERING_STOMP); - uiStompTimer = 17000; - } else uiStompTimer -= uiDiff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - { - pInstance->SetData(DATA_DRAKOS_EVENT, DONE); - // start achievement timer (kill Eregos within 20 min) - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - - lSummons.DespawnAll(); - } - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2,SAY_KILL_3), me); - } -}; - -CreatureAI* GetAI_boss_drakos(Creature* pCreature) -{ - return new boss_drakosAI (pCreature); -} - -struct npc_unstable_sphereAI : public ScriptedAI -{ - npc_unstable_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 uiPulseTimer; - uint32 uiDeathTimer; - - void Reset() - { - me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveRandom(40.0f); - - me->AddAura(SPELL_UNSTABLE_SPHERE_PASSIVE, me); - me->AddAura(SPELL_UNSTABLE_SPHERE_TIMER, me); - - uiPulseTimer = 3000; - uiDeathTimer = 19000; - } - - void UpdateAI(const uint32 uiDiff) - { - if (uiPulseTimer <= uiDiff) - { - DoCast(SPELL_UNSTABLE_SPHERE_PULSE); - uiPulseTimer = 3*IN_MILISECONDS; - } else uiPulseTimer -= uiDiff; - - if (uiDeathTimer <= uiDiff) - me->DisappearAndDie(); - else uiDeathTimer -= uiDiff; - } -}; - -CreatureAI* GetAI_npc_unstable_sphere(Creature* pCreature) -{ - return new npc_unstable_sphereAI (pCreature); -} - -void AddSC_boss_drakos() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_drakos"; - newscript->GetAI = &GetAI_boss_drakos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_unstable_sphere"; - newscript->GetAI = &GetAI_npc_unstable_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp b/src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp deleted file mode 100644 index 94fb90ab206..00000000000 --- a/src/server/scripts/Northrend/TheNexus/oculus/boss_eregos.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -//Types of drake mounts: Ruby(Tank), Amber(DPS), Emerald(Healer) -//Two Repeating phases - -enum Spells -{ - SPELL_ARCANE_BARRAGE = 50804, - H_SPELL_ARCANE_BARRAGE = 59381, - SPELL_ARCANE_VOLLEY = 51153, - H_SPELL_ARCANE_VOLLEY = 59382, - SPELL_ENRAGED_ASSAULT = 51170, - SPELL_PLANAR_ANOMALIES = 57959, - SPELL_PLANAR_SHIFT = 51162, -}; -/*Ruby Drake , -(npc 27756) (item 37860) -(summoned by spell Ruby Essence = 37860 ---> Call Amber Drake == 49462 ---> Summon 27756) -*/ -enum RubyDrake -{ - NPC_RUBY_DRAKE_VEHICLE = 27756, - SPELL_RIDE_RUBY_DRAKE_QUE = 49463, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49464 - SPELL_RUBY_DRAKE_SADDLE = 49464, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_RUBY_SEARING_WRATH = 50232, //(60 yds) - Instant - Breathes a stream of fire at an enemy dragon, dealing 6800 to 9200 Fire damage and then jumping to additional dragons within 30 yards. Each jump increases the damage by 50%. Affects up to 5 total targets - SPELL_RUBY_EVASIVE_AURA = 50248, //Instant - Allows the Ruby Drake to generate Evasive Charges when hit by hostile attacks and spells. - SPELL_RUBY_EVASIVE_MANEUVERS = 50240, //Instant - 5 sec. cooldown - Allows your drake to dodge all incoming attacks and spells. Requires Evasive Charges to use. Each attack or spell dodged while this ability is active burns one Evasive Charge. Lasts 30 sec. or until all charges are exhausted. - //you do not have acces to until you kill Mage-Lord Urom - SPELL_RUBY_MARTYR = 50253 //Instant - 10 sec. cooldown - Redirect all harmful spells cast at friendly drakes to yourself for 10 sec. -}; -/*Amber Drake, -(npc 27755) (item 37859) -(summoned by spell Amber Essence = 37859 ---> Call Amber Drake == 49461 ---> Summon 27755) -*/ -enum AmberDrake -{ - NPC_AMBER_DRAKE_VEHICLE = 27755, - SPELL_RIDE_AMBER_DRAKE_QUE = 49459, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49460 - SPELL_AMBER_DRAKE_SADDLE = 49460, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_AMBER_SHOCK_LANCE = 49840, //(60 yds) - Instant - Deals 4822 to 5602 Arcane damage and detonates all Shock Charges on an enemy dragon. Damage is increased by 6525 for each detonated. -// SPELL_AMBER_STOP_TIME //Instant - 1 min cooldown - Halts the passage of time, freezing all enemy dragons in place for 10 sec. This attack applies 5 Shock Charges to each affected target. - //you do not have access to until you kill the Mage-Lord Urom. - SPELL_AMBER_TEMPORAL_RIFT = 49592 //(60 yds) - Channeled - Channels a temporal rift on an enemy dragon for 10 sec. While trapped in the rift, all damage done to the target is increased by 100%. In addition, for every 15,000 damage done to a target affected by Temporal Rift, 1 Shock Charge is generated. -}; -/*Emerald Drake, -(npc 27692) (item 37815), - (summoned by spell Emerald Essence = 37815 ---> Call Emerald Drake == 49345 ---> Summon 27692) -*/ -enum EmeraldDrake -{ - NPC_EMERALD_DRAKE_VEHICLE = 27692, - SPELL_RIDE_EMERALD_DRAKE_QUE = 49427, //Apply Aura: Periodic Trigger, Interval: 3 seconds ---> 49346 - SPELL_EMERALD_DRAKE_SADDLE = 49346, //Allows you to ride on the back of an Amber Drake. ---> Dummy - SPELL_EMERALD_LEECHING_POISON = 50328, //(60 yds) - Instant - Poisons the enemy dragon, leeching 1300 to the caster every 2 sec. for 12 sec. Stacks up to 3 times. - SPELL_EMERALD_TOUCH_THE_NIGHTMARE = 50341, //(60 yds) - Instant - Consumes 30% of the caster's max health to inflict 25,000 nature damage to an enemy dragon and reduce the damage it deals by 25% for 30 sec. - // you do not have access to until you kill the Mage-Lord Urom - SPELL_EMERALD_DREAM_FUNNEL = 50344 //(60 yds) - Channeled - Transfers 5% of the caster's max health to a friendly drake every second for 10 seconds as long as the caster channels. -}; - -struct boss_eregosAI : public ScriptedAI -{ - boss_eregosAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, IN_PROGRESS); - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_EREGOS_EVENT, DONE); - } -}; - -CreatureAI* GetAI_boss_eregos(Creature* pCreature) -{ - return new boss_eregosAI (pCreature); -} - -void AddSC_boss_eregos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_eregos"; - newscript->GetAI = &GetAI_boss_eregos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp b/src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp deleted file mode 100644 index 29435441d00..00000000000 --- a/src/server/scripts/Northrend/TheNexus/oculus/boss_urom.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Urom -SD%Complete: 80 -SDComment: Is not working SPELL_ARCANE_SHIELD. SPELL_FROSTBOMB has some issues, the damage aura should not stack. -SDCategory: Instance Script -EndScriptData */ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - - SPELL_ARCANE_SHIELD = 53813, //Dummy --> Channeled, shields the caster from damage. - SPELL_EMPOWERED_ARCANE_EXPLOSION = 51110, - SPELL_EMPOWERED_ARCANE_EXPLOSION_2 = 59377, - SPELL_FROSTBOMB = 51103, //Urom throws a bomb, hitting its target with the highest aggro which inflict directly 650 frost damage and drops a frost zone on the ground. This zone deals 650 frost damage per second and reduce the movement speed by 35%. Lasts 1 minute. - SPELL_SUMMON_MENAGERIE = 50476, //Summons an assortment of creatures and teleports the caster to safety. - SPELL_SUMMON_MENAGERIE_2 = 50495, - SPELL_SUMMON_MENAGERIE_3 = 50496, - SPELL_TELEPORT = 51112, //Teleports to the center of Oculus - SPELL_TIME_BOMB = 51121, //Deals arcane damage to a random player, and after 6 seconds, deals zone damage to nearby equal to the health missing of the target afflicted by the debuff. - SPELL_TIME_BOMB_2 = 59376 -}; - -enum Yells -{ - SAY_AGGRO_1 = -1578000, - SAY_AGGRO_2 = -1578001, - SAY_AGGRO_3 = -1578002, - SAY_AGGRO_4 = -1578003, - SAY_TELEPORT = -1578004, -}; - -enum eCreature -{ - NPC_PHANTASMAL_CLOUDSCRAPER = 27645, - NPC_PHANTASMAL_MAMMOTH = 27642, - NPC_PHANTASMAL_WOLF = 27644, - - NPC_PHANTASMAL_AIR = 27650, - NPC_PHANTASMAL_FIRE = 27651, - NPC_PHANTASMAL_WATER = 27653, - - NPC_PHANTASMAL_MURLOC = 27649, - NPC_PHANTASMAL_NAGAL = 27648, - NPC_PHANTASMAL_OGRE = 27647 -}; - -struct Summons -{ - uint32 uiEntry[4]; -}; - -static Summons Group[]= -{ - {NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_CLOUDSCRAPER,NPC_PHANTASMAL_MAMMOTH,NPC_PHANTASMAL_WOLF}, - {NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_AIR,NPC_PHANTASMAL_WATER,NPC_PHANTASMAL_FIRE}, - {NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_OGRE,NPC_PHANTASMAL_NAGAL,NPC_PHANTASMAL_MURLOC} -}; - -static uint32 TeleportSpells[]= -{ - SPELL_SUMMON_MENAGERIE,SPELL_SUMMON_MENAGERIE_2,SPELL_SUMMON_MENAGERIE_3 -}; - -static int32 SayAggro[]= -{ - SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3,SAY_AGGRO_4 -}; - -struct boss_uromAI : public ScriptedAI -{ - boss_uromAI(Creature* pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - float x,y; - - bool bCanCast; - bool bCanGoBack; - - uint8 uiGroup[3]; - - uint32 uiTeleportTimer; - uint32 uiArcaneExplosionTimer; - uint32 uiCastArcaneExplosionTimer; - uint32 uiFrostBombTimer; - uint32 uiTimeBombTimer; - - void Reset() - { - if (pInstance && pInstance->GetData(DATA_VAROS_EVENT) != DONE) - DoCast(SPELL_ARCANE_SHIELD); - - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, NOT_STARTED); - - if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) == 0) - { - uiGroup[0] = 0; - uiGroup[1] = 0; - uiGroup[2] = 0; - } - - x,y = 0.0f; - bCanCast = false; - bCanGoBack = false; - - me->GetMotionMaster()->MoveIdle(); - - uiTeleportTimer = urand(30000,35000); - uiArcaneExplosionTimer = 9000; - uiCastArcaneExplosionTimer = 2000; - uiFrostBombTimer = urand(5000,8000); - uiTimeBombTimer = urand(20000,25000); - } - - void EnterCombat(Unit* pWho) - { - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, IN_PROGRESS); - - SetGroups(); - SummonGroups(); - CastTeleport(); - - if (pInstance && pInstance->GetData(DATA_UROM_PLATAFORM) != 3) - pInstance->SetData(DATA_UROM_PLATAFORM,pInstance->GetData(DATA_UROM_PLATAFORM)+1); - } - - void AttackStart(Unit* pWho) - { - if (!pWho) - return; - - if (me->GetPositionZ() > 518.63) - DoStartNoMovement(pWho); - - if (me->GetPositionZ() < 518.63) - { - if (me->Attack(pWho, true)) - { - DoScriptText(SayAggro[3],me); - - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(pWho, 0,0); - } - } - } - - void SetGroups() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) != 0) - return; - - while (uiGroup[0] == uiGroup[1] || uiGroup[0] == uiGroup[2] || uiGroup[1] == uiGroup[2]) - { - uiGroup[0] = urand(0,2); - uiGroup[1] = urand(0,2); - uiGroup[2] = urand(0,2); - } - } - - void SetPosition(uint8 uiI) - { - switch(uiI) - { - case 0: - x = me->GetPositionX() + 4; - y = me->GetPositionY() - 4; - break; - case 1: - x = me->GetPositionX() + 4; - y = me->GetPositionY() + 4; - break; - case 2: - x = me->GetPositionX() - 4; - y = me->GetPositionY() + 4; - break; - case 3: - x = me->GetPositionX() - 4; - y = me->GetPositionY() - 4; - break; - default: - break; - } - } - - void SummonGroups() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) - return; - - for (uint8 uiI = 0; uiI < 4 ; uiI++) - { - SetPosition(uiI); - me->SummonCreature(Group[uiGroup[pInstance->GetData(DATA_UROM_PLATAFORM)]].uiEntry[uiI],x,y,me->GetPositionZ(),me->GetOrientation()); - } - } - - void CastTeleport() - { - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) > 2) - return; - - DoScriptText(SayAggro[pInstance->GetData(DATA_UROM_PLATAFORM)],me); - DoCast(TeleportSpells[pInstance->GetData(DATA_UROM_PLATAFORM)]); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!pInstance || pInstance->GetData(DATA_UROM_PLATAFORM) < 2) - return; - - if (uiTeleportTimer <= uiDiff) - { - me->InterruptNonMeleeSpells(false); - DoScriptText(SAY_TELEPORT,me); - me->GetMotionMaster()->MoveIdle(); - DoCast(SPELL_TELEPORT); - uiTeleportTimer = urand(30000,35000); - - } else uiTeleportTimer -= uiDiff; - - if (bCanCast && !me->FindCurrentSpellBySpellId(SPELL_EMPOWERED_ARCANE_EXPLOSION)) - { - if (uiCastArcaneExplosionTimer <= uiDiff) - { - bCanCast = false; - bCanGoBack = true; - DoCastAOE(SPELL_EMPOWERED_ARCANE_EXPLOSION); - uiCastArcaneExplosionTimer = 2000; - }else uiCastArcaneExplosionTimer -= uiDiff; - } - - if (bCanGoBack) - { - if (uiArcaneExplosionTimer <= uiDiff) - { - Position pPos; - me->getVictim()->GetPosition(&pPos); - - me->NearTeleportTo(pPos.GetPositionX(),pPos.GetPositionY(),pPos.GetPositionZ(),pPos.GetOrientation()); - me->GetMotionMaster()->MoveChase(me->getVictim(),0,0); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - - bCanCast = false; - bCanGoBack = false; - uiArcaneExplosionTimer = 9000; - } else uiArcaneExplosionTimer -= uiDiff; - } - - if (!me->IsNonMeleeSpellCasted(false, true, true)) - { - if (uiFrostBombTimer <= uiDiff) - { - DoCastVictim(SPELL_FROSTBOMB); - uiFrostBombTimer = urand(5000,8000); - } else uiFrostBombTimer -= uiDiff; - - if (uiTimeBombTimer <= uiDiff) - { - if (Unit* pUnit = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pUnit,SPELL_TIME_BOMB); - - uiTimeBombTimer = urand(20000,25000); - } else uiTimeBombTimer -= uiDiff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - pInstance->SetData(DATA_UROM_EVENT, DONE); - } - - void JustSummoned(Creature* pSummon) - { - pSummon->SetInCombatWithZone(); - } - - void LeaveCombat() - { - me->RemoveAllAuras(); - me->CombatStop(false); - me->DeleteThreatList(); - } - - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - switch(pSpell->Id) - { - case SPELL_SUMMON_MENAGERIE: - me->SetHomePosition(968.66,1042.53,527.32,0.077); - LeaveCombat(); - break; - case SPELL_SUMMON_MENAGERIE_2: - me->SetHomePosition(1164.02,1170.85,527.321,3.66); - LeaveCombat(); - break; - case SPELL_SUMMON_MENAGERIE_3: - me->SetHomePosition(1118.31,1080.377,508.361,4.25); - LeaveCombat(); - break; - case SPELL_TELEPORT: - me->AddUnitMovementFlag(MOVEMENTFLAG_FLY_MODE); // with out it the npc will fall down while is casting - bCanCast = true; - break; - default: - break; - } - } -}; - -CreatureAI* GetAI_boss_urom(Creature* pCreature) -{ - return new boss_uromAI (pCreature); -} - -void AddSC_boss_urom() -{ - Script* newscript; - - newscript = new Script; - newscript->Name = "boss_urom"; - newscript->GetAI = &GetAI_boss_urom; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp b/src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp deleted file mode 100644 index 79034250a43..00000000000 --- a/src/server/scripts/Northrend/TheNexus/oculus/boss_varos.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -enum Spells -{ - SPELL_ENERGIZE_CORES = 50785, //Damage 5938 to 6562, effec2 Triggers 54069, effect3 Triggers 56251 - SPELL_ENERGIZE_CORES_TRIGGER_1 = 54069, - SPELL_ENERGIZE_CORES_TRIGGER_2 = 56251, - SPELL_ENERGIZE_CORES_2 = 59372, //Damage 9025 to 9975, effect2 Triggers 54069, effect 56251 - SPELL_CALL_AZURE_RING_CAPTAIN = 51002, //Effect Send Event (12229) - SPELL_CALL_AZURE_RING_CAPTAIN_2 = 51006, //Effect Send Event (10665) - SPELL_CALL_AZURE_RING_CAPTAIN_3 = 51007, //Effect Send Event (18454) - SPELL_CALL_AZURE_RING_CAPTAIN_4 = 51008, //Effect Send Event (18455) - SPELL_CALL_AMPLIFY_MAGIC = 51054, - SPELL_CALL_AMPLIFY_MAGIC_2 = 59371 -}; -//not in db -enum Yells -{ - SAY_AGGRO = -1578022, - SAY_KILL_1 = -1578023, - SAY_KILL_2 = -1578024, - SAY_DEATH = -1578025, - SAY_STRIKE_1 = -1578026, - SAY_STRIKE_2 = -1578027, - SAY_STRIKE_3 = -1578028, - SAY_SPAWN = -1578029 -}; - -struct boss_varosAI : public ScriptedAI -{ - boss_varosAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, NOT_STARTED); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, IN_PROGRESS); - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_VAROS_EVENT, DONE); - } - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } -}; - -CreatureAI* GetAI_boss_varos(Creature* pCreature) -{ - return new boss_varosAI (pCreature); -} - -void AddSC_boss_varos() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_varos"; - newscript->GetAI = &GetAI_boss_varos; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp b/src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp deleted file mode 100644 index 49be2385a3c..00000000000 --- a/src/server/scripts/Northrend/TheNexus/oculus/instance_oculus.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -#define MAX_ENCOUNTER 4 - -/* The Occulus encounters: -0 - Drakos the Interrogator -1 - Varos Cloudstrider -2 - Mage-Lord Urom -3 - Ley-Guardian Eregos */ - -struct instance_oculus : public ScriptedInstance -{ - instance_oculus(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiDrakos; - uint64 uiVaros; - uint64 uiUrom; - uint64 uiEregos; - - uint8 uiPlataformUrom; - - uint8 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - std::list GameObjectList; - - void Initialize() - { - uiPlataformUrom = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case CREATURE_DRAKOS: - uiDrakos = pCreature->GetGUID(); - break; - case CREATURE_VAROS: - uiVaros = pCreature->GetGUID(); - break; - case CREATURE_UROM: - uiUrom = pCreature->GetGUID(); - break; - case CREATURE_EREGOS: - uiEregos = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGO, bool bAdd) - { - if (pGO->GetEntry() == GO_DRAGON_CAGE_DOOR) - { - if (DATA_DRAKOS_EVENT == DONE) - pGO->SetGoState(GO_STATE_ACTIVE); - else - pGO->SetGoState(GO_STATE_READY); - - GameObjectList.push_back(pGO->GetGUID()); - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_DRAKOS_EVENT: - m_auiEncounter[0] = data; - if (data == DONE) - OpenCageDoors(); - break; - case DATA_VAROS_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_UROM_EVENT: - m_auiEncounter[2] = data; - break; - case DATA_EREGOS_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_UROM_PLATAFORM: - uiPlataformUrom = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_DRAKOS_EVENT: return m_auiEncounter[0]; - case DATA_VAROS_EVENT: return m_auiEncounter[1]; - case DATA_UROM_EVENT: return m_auiEncounter[2]; - case DATA_EREGOS_EVENT: return m_auiEncounter[3]; - case DATA_UROM_PLATAFORM: return uiPlataformUrom; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_DRAKOS: return uiDrakos; - case DATA_VAROS: return uiVaros; - case DATA_UROM: return uiUrom; - case DATA_EREGOS: return uiEregos; - } - - return 0; - } - - void OpenCageDoors() - { - if (GameObjectList.empty()) - return; - - for (std::list::const_iterator itr = GameObjectList.begin(); itr != GameObjectList.end(); ++itr) - { - if (GameObject* pGO = instance->GetGameObject(*itr)) - pGO->SetGoState(GO_STATE_ACTIVE); - } - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "T O " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'T' && dataHead2 == 'O') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_oculus(Map* pMap) -{ - return new instance_oculus(pMap); -} - -void AddSC_instance_oculus() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_oculus"; - newscript->GetInstanceData = &GetInstanceData_instance_oculus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp b/src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp deleted file mode 100644 index 685583532d5..00000000000 --- a/src/server/scripts/Northrend/TheNexus/oculus/oculus.cpp +++ /dev/null @@ -1,174 +0,0 @@ -/* Copyright (C) 2006 - 2010 TrinityCore -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "ScriptedPch.h" -#include "oculus.h" - -#define GOSSIP_ITEM_DRAKES "So where do we go from here?" -#define GOSSIP_ITEM_BELGARISTRASZ1 "I want to fly on the wings of the Red Flight" -#define GOSSIP_ITEM_BELGARISTRASZ2 "What abilities do Ruby Drakes have?" -#define GOSSIP_ITEM_VERDISA1 "I want to fly on the wings of the Green Flight" -#define GOSSIP_ITEM_VERDISA2 "What abilities do Emerald Drakes have?" -#define GOSSIP_ITEM_ETERNOS1 "I want to fly on the wings of the Bronze Flight" -#define GOSSIP_ITEM_ETERNOS2 "What abilities do Amber Drakes have?" - -#define HAS_ESSENCE(a) ((a)->HasItemCount(ITEM_EMERALD_ESSENCE,1) || (a)->HasItemCount(ITEM_AMBER_ESSENCE,1) || (a)->HasItemCount(ITEM_RUBY_ESSENCE,1)) - -enum Drakes -{ - GOSSIP_TEXTID_DRAKES = 13267, - GOSSIP_TEXTID_BELGARISTRASZ1 = 12916, - GOSSIP_TEXTID_BELGARISTRASZ2 = 13466, - GOSSIP_TEXTID_BELGARISTRASZ3 = 13254, - GOSSIP_TEXTID_VERDISA1 = 1, - GOSSIP_TEXTID_VERDISA2 = 1, - GOSSIP_TEXTID_VERDISA3 = 1, - GOSSIP_TEXTID_ETERNOS1 = 1, - GOSSIP_TEXTID_ETERNOS2 = 1, - GOSSIP_TEXTID_ETERNOS3 = 13256, - - ITEM_EMERALD_ESSENCE = 37815, - ITEM_AMBER_ESSENCE = 37859, - ITEM_RUBY_ESSENCE = 37860, - - NPC_VERDISA = 27657, - NPC_BELGARISTRASZ = 27658, - NPC_ETERNOS = 27659 -}; - -bool GossipHello_npc_oculus_drake(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - if (pCreature->GetInstanceData()->GetData(DATA_DRAKOS_EVENT) == DONE) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DRAKES, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DRAKES, pCreature->GetGUID()); - } - - return true; -} - -bool GossipSelect_npc_oculus_drake(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - switch(pCreature->GetEntry()) - { - case NPC_VERDISA: //Verdisa - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VERDISA2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_EMERALD_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_EMERALD_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_VERDISA3, pCreature->GetGUID()); - break; - } - break; - case NPC_BELGARISTRASZ: //Belgaristrasz - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BELGARISTRASZ2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_RUBY_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_RUBY_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_BELGARISTRASZ3, pCreature->GetGUID()); - break; - } - break; - case NPC_ETERNOS: //Eternos - switch(uiAction) - { - case GOSSIP_ACTION_INFO_DEF + 1: - if (!HAS_ESSENCE(pPlayer)) - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS1, pCreature->GetGUID()); - } - else - { - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ETERNOS2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS2, pCreature->GetGUID()); - } - break; - case GOSSIP_ACTION_INFO_DEF + 2: - { - ItemPosCountVec dest; - uint8 msg = pPlayer->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, ITEM_AMBER_ESSENCE, 1); - if (msg == EQUIP_ERR_OK) - pPlayer->StoreNewItem(dest, ITEM_AMBER_ESSENCE, true); - pPlayer->CLOSE_GOSSIP_MENU(); - break; - } - case GOSSIP_ACTION_INFO_DEF + 3: - pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_ETERNOS3, pCreature->GetGUID()); - break; - } - break; - } - - return true; -} - -void AddSC_oculus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_oculus_drake"; - newscript->pGossipHello = &GossipHello_npc_oculus_drake; - newscript->pGossipSelect = &GossipSelect_npc_oculus_drake; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/TheNexus/oculus/oculus.h b/src/server/scripts/Northrend/TheNexus/oculus/oculus.h deleted file mode 100644 index b212c9b8b6a..00000000000 --- a/src/server/scripts/Northrend/TheNexus/oculus/oculus.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef DEF_OCULUS_H -#define DEF_OCULUS_H - -enum Data -{ - DATA_DRAKOS_EVENT, - DATA_VAROS_EVENT, - DATA_UROM_EVENT, - DATA_EREGOS_EVENT, - DATA_UROM_PLATAFORM -}; - -enum Data64 -{ - DATA_DRAKOS, - DATA_VAROS, - DATA_UROM, - DATA_EREGOS -}; - -enum Bosses -{ - CREATURE_DRAKOS = 27654, - CREATURE_VAROS = 27447, - CREATURE_UROM = 27655, - CREATURE_EREGOS = 27656 -}; - -enum GameObjects -{ - GO_DRAGON_CAGE_DOOR = 193995 -}; - -#endif diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp new file mode 100644 index 00000000000..c2da2a24e71 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_bjarngrim.cpp @@ -0,0 +1,432 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss General Bjarngrim +SD%Complete: 70% +SDComment: Waypoint needed, we expect boss to always have 2x Stormforged Lieutenant following +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + //Yell + SAY_AGGRO = -1602000, + SAY_SLAY_1 = -1602001, + SAY_SLAY_2 = -1602002, + SAY_SLAY_3 = -1602003, + SAY_DEATH = -1602004, + SAY_BATTLE_STANCE = -1602005, + EMOTE_BATTLE_STANCE = -1602006, + SAY_BERSEKER_STANCE = -1602007, + EMOTE_BERSEKER_STANCE = -1602008, + SAY_DEFENSIVE_STANCE = -1602009, + EMOTE_DEFENSIVE_STANCE = -1602010, + + SPELL_DEFENSIVE_STANCE = 53790, + //SPELL_DEFENSIVE_AURA = 41105, + SPELL_SPELL_REFLECTION = 36096, + SPELL_PUMMEL = 12555, + SPELL_KNOCK_AWAY = 52029, + SPELL_IRONFORM = 52022, + + SPELL_BERSEKER_STANCE = 53791, + //SPELL_BERSEKER_AURA = 41107, + SPELL_INTERCEPT = 58769, + SPELL_WHIRLWIND = 52027, + SPELL_CLEAVE = 15284, + + SPELL_BATTLE_STANCE = 53792, + //SPELL_BATTLE_AURA = 41106, + SPELL_MORTAL_STRIKE = 16856, + SPELL_SLAM = 52026, + + //OTHER SPELLS + //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other + //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above + + NPC_STORMFORGED_LIEUTENANT = 29240, + SPELL_ARC_WELD = 59085, + SPELL_RENEW_STEEL_N = 52774, + SPELL_RENEW_STEEL_H = 59160, + + EQUIP_SWORD = 37871, + EQUIP_SHIELD = 35642, + EQUIP_MACE = 43623, + + STANCE_DEFENSIVE = 0, + STANCE_BERSERKER = 1, + STANCE_BATTLE = 2 +}; + +/*###### +## boss_bjarngrim +######*/ + +struct boss_bjarngrimAI : public ScriptedAI +{ + boss_bjarngrimAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + m_uiStance = STANCE_DEFENSIVE; + memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID)); + } + + ScriptedInstance* m_pInstance; + + bool m_bIsChangingStance; + + uint8 m_uiChargingStatus; + uint8 m_uiStance; + + uint32 m_uiCharge_Timer; + uint32 m_uiChangeStance_Timer; + + uint32 m_uiReflection_Timer; + uint32 m_uiKnockAway_Timer; + uint32 m_uiPummel_Timer; + uint32 m_uiIronform_Timer; + + uint32 m_uiIntercept_Timer; + uint32 m_uiWhirlwind_Timer; + uint32 m_uiCleave_Timer; + + uint32 m_uiMortalStrike_Timer; + uint32 m_uiSlam_Timer; + + uint64 m_auiStormforgedLieutenantGUID[2]; + + void Reset() + { + m_bIsChangingStance = false; + + m_uiChargingStatus = 0; + m_uiCharge_Timer = 1000; + + m_uiChangeStance_Timer = 20000 + rand()%5000; + + m_uiReflection_Timer = 8000; + m_uiKnockAway_Timer = 20000; + m_uiPummel_Timer = 10000; + m_uiIronform_Timer = 25000; + + m_uiIntercept_Timer = 5000; + m_uiWhirlwind_Timer = 10000; + m_uiCleave_Timer = 8000; + + m_uiMortalStrike_Timer = 8000; + m_uiSlam_Timer = 10000; + + for (uint8 i = 0; i < 2; ++i) + { + if (Creature* pStormforgedLieutenant = (Unit::GetCreature((*me), m_auiStormforgedLieutenantGUID[i]))) + { + if (!pStormforgedLieutenant->isAlive()) + pStormforgedLieutenant->Respawn(); + } + } + + if (m_uiStance != STANCE_DEFENSIVE) + { + DoRemoveStanceAura(m_uiStance); + DoCast(me, SPELL_DEFENSIVE_STANCE); + m_uiStance = STANCE_DEFENSIVE; + } + + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + //must get both lieutenants here and make sure they are with him + me->CallForHelp(30.0f); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_BJARNGRIM, DONE); + } + + //TODO: remove when removal is done by the core + void DoRemoveStanceAura(uint8 uiStance) + { + switch(uiStance) + { + case STANCE_DEFENSIVE: + me->RemoveAurasDueToSpell(SPELL_DEFENSIVE_STANCE); + break; + case STANCE_BERSERKER: + me->RemoveAurasDueToSpell(SPELL_BERSEKER_STANCE); + break; + case STANCE_BATTLE: + me->RemoveAurasDueToSpell(SPELL_BATTLE_STANCE); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // Change stance + if (m_uiChangeStance_Timer <= uiDiff) + { + //wait for current spell to finish before change stance + if (me->IsNonMeleeSpellCasted(false)) + return; + + DoRemoveStanceAura(m_uiStance); + + int uiTempStance = rand()%(3-1); + + if (uiTempStance >= m_uiStance) + ++uiTempStance; + + m_uiStance = uiTempStance; + + switch(m_uiStance) + { + case STANCE_DEFENSIVE: + DoScriptText(SAY_DEFENSIVE_STANCE, me); + DoScriptText(EMOTE_DEFENSIVE_STANCE, me); + DoCast(me, SPELL_DEFENSIVE_STANCE); + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); + break; + case STANCE_BERSERKER: + DoScriptText(SAY_BERSEKER_STANCE, me); + DoScriptText(EMOTE_BERSEKER_STANCE, me); + DoCast(me, SPELL_BERSEKER_STANCE); + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); + break; + case STANCE_BATTLE: + DoScriptText(SAY_BATTLE_STANCE, me); + DoScriptText(EMOTE_BATTLE_STANCE, me); + DoCast(me, SPELL_BATTLE_STANCE); + SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); + break; + } + + m_uiChangeStance_Timer = 20000 + rand()%5000; + return; + } + else + m_uiChangeStance_Timer -= uiDiff; + + switch(m_uiStance) + { + case STANCE_DEFENSIVE: + { + if (m_uiReflection_Timer <= uiDiff) + { + DoCast(me, SPELL_SPELL_REFLECTION); + m_uiReflection_Timer = 8000 + rand()%1000; + } + else + m_uiReflection_Timer -= uiDiff; + + if (m_uiKnockAway_Timer <= uiDiff) + { + DoCast(me, SPELL_KNOCK_AWAY); + m_uiKnockAway_Timer = 20000 + rand()%1000; + } + else + m_uiKnockAway_Timer -= uiDiff; + + if (m_uiPummel_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_PUMMEL); + m_uiPummel_Timer = 10000 + rand()%1000; + } + else + m_uiPummel_Timer -= uiDiff; + + if (m_uiIronform_Timer <= uiDiff) + { + DoCast(me, SPELL_IRONFORM); + m_uiIronform_Timer = 25000 + rand()%1000; + } + else + m_uiIronform_Timer -= uiDiff; + + break; + } + case STANCE_BERSERKER: + { + if (m_uiIntercept_Timer <= uiDiff) + { + //not much point is this, better random target and more often? + DoCast(me->getVictim(), SPELL_INTERCEPT); + m_uiIntercept_Timer = 45000 + rand()%1000; + } + else + m_uiIntercept_Timer -= uiDiff; + + if (m_uiWhirlwind_Timer <= uiDiff) + { + DoCast(me, SPELL_WHIRLWIND); + m_uiWhirlwind_Timer = 10000 + rand()%1000; + } + else + m_uiWhirlwind_Timer -= uiDiff; + + if (m_uiCleave_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + m_uiCleave_Timer = 8000 + rand()%1000; + } + else + m_uiCleave_Timer -= uiDiff; + + break; + } + case STANCE_BATTLE: + { + if (m_uiMortalStrike_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + m_uiMortalStrike_Timer = 20000 + rand()%1000; + } + else + m_uiMortalStrike_Timer -= uiDiff; + + if (m_uiSlam_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_SLAM); + m_uiSlam_Timer = 15000 + rand()%1000; + } + else + m_uiSlam_Timer -= uiDiff; + + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## mob_stormforged_lieutenant +######*/ + +struct mob_stormforged_lieutenantAI : public ScriptedAI +{ + mob_stormforged_lieutenantAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiArcWeld_Timer; + uint32 m_uiRenewSteel_Timer; + + void Reset() + { + m_uiArcWeld_Timer = 20000 + rand()%1000; + m_uiRenewSteel_Timer = 10000 + rand()%1000; + } + + void EnterCombat(Unit* pWho) + { + if (m_pInstance) + { + if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) + { + if (pBjarngrim->isAlive() && !pBjarngrim->getVictim()) + pBjarngrim->AI()->AttackStart(pWho); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_uiArcWeld_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_ARC_WELD); + m_uiArcWeld_Timer = 20000 + rand()%1000; + } + else + m_uiArcWeld_Timer -= uiDiff; + + if (m_uiRenewSteel_Timer <= uiDiff) + { + if (m_pInstance) + { + if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) + { + if (pBjarngrim->isAlive()) + DoCast(pBjarngrim, SPELL_RENEW_STEEL_N); + } + } + m_uiRenewSteel_Timer = 10000 + rand()%4000; + } + else + m_uiRenewSteel_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_bjarngrim(Creature* pCreature) +{ + return new boss_bjarngrimAI(pCreature); +} + +CreatureAI* GetAI_mob_stormforged_lieutenant(Creature* pCreature) +{ + return new mob_stormforged_lieutenantAI(pCreature); +} + +void AddSC_boss_bjarngrim() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_bjarngrim"; + newscript->GetAI = &GetAI_boss_bjarngrim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stormforged_lieutenant"; + newscript->GetAI = &GetAI_mob_stormforged_lieutenant; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp new file mode 100644 index 00000000000..ecf61188b3e --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp @@ -0,0 +1,388 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* + * Comment: Timer check pending + */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum Spells +{ + SPELL_BALL_LIGHTNING = 52780, + H_SPELL_BALL_LIGHTNING = 59800, + SPELL_STATIC_OVERLOAD = 52658, + H_SPELL_STATIC_OVERLOAD = 59795, + + SPELL_DISPERSE = 52770, + SPELL_SUMMON_SPARK = 52746, + SPELL_SPARK_DESPAWN = 52776, + + //Spark of Ionar + SPELL_SPARK_VISUAL_TRIGGER = 52667, + H_SPELL_SPARK_VISUAL_TRIGGER = 59833 +}; + +enum Yells +{ + SAY_AGGRO = -1602011, + SAY_SLAY_1 = -1602012, + SAY_SLAY_2 = -1602013, + SAY_SLAY_3 = -1602014, + SAY_DEATH = -1602015, + SAY_SPLIT_1 = -1602016, + SAY_SPLIT_2 = -1602017 +}; + +enum Creatures +{ + NPC_SPARK_OF_IONAR = 28926 +}; + +enum Misc +{ + DATA_MAX_SPARKS = 5, + DATA_MAX_SPARK_DISTANCE = 90, // Distance to boss - prevent runs through the whole instance + DATA_POINT_CALLBACK = 0 +}; + +/*###### +## Boss Ionar +######*/ + +struct boss_ionarAI : public ScriptedAI +{ + boss_ionarAI(Creature *pCreature) : ScriptedAI(pCreature), lSparkList(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + SummonList lSparkList; + + bool bIsSplitPhase; + bool bHasDispersed; + + uint32 uiSplitTimer; + + uint32 uiStaticOverloadTimer; + uint32 uiBallLightningTimer; + + uint32 uiDisperseHealth; + + void Reset() + { + lSparkList.DespawnAll(); + + bIsSplitPhase = true; + bHasDispersed = false; + + uiSplitTimer = 25*IN_MILISECONDS; + + uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); + uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); + + uiDisperseHealth = 45 + urand(0,10); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + if (me->GetVisibility() == VISIBILITY_OFF) + me->SetVisibility(VISIBILITY_ON); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + lSparkList.DespawnAll(); + + if (pInstance) + pInstance->SetData(TYPE_IONAR, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + //make sparks come back + void CallBackSparks() + { + //should never be empty here, but check + if (lSparkList.empty()) + return; + + Position pos; + me->GetPosition(&pos); + + for (std::list::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) + { + if (Creature* pSpark = Unit::GetCreature(*me, *itr)) + { + if (pSpark->isAlive()) + { + pSpark->SetSpeed(MOVE_RUN, 2.0f); + pSpark->GetMotionMaster()->Clear(); + pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); + } + else + pSpark->ForcedDespawn(); + } + } + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + if (me->GetVisibility() == VISIBILITY_OFF) + uiDamage = 0; + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) + { + lSparkList.Summon(pSummoned); + + pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER,H_SPELL_SPARK_VISUAL_TRIGGER), true); + + Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + pSummoned->SetInCombatWith(pTarget); + pSummoned->GetMotionMaster()->Clear(); + pSummoned->GetMotionMaster()->MoveFollow(pTarget, 0.0f, 0.0f); + } + } + } + + void SummonedCreatureDespawn(Creature *pSummoned) + { + if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) + lSparkList.Despawn(pSummoned); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + // Splitted + if (me->GetVisibility() == VISIBILITY_OFF) + { + if (uiSplitTimer <= uiDiff) + { + uiSplitTimer = 2.5*IN_MILISECONDS; + + // Return sparks to where Ionar splitted + if (bIsSplitPhase) + { + CallBackSparks(); + bIsSplitPhase = false; + } + // Lightning effect and restore Ionar + else if (lSparkList.empty()) + { + me->SetVisibility(VISIBILITY_ON); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + DoCast(me, SPELL_SPARK_DESPAWN, false); + + uiSplitTimer = 25*IN_MILISECONDS; + bIsSplitPhase = true; + + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + } + else + uiSplitTimer -= uiDiff; + + return; + } + + if (uiStaticOverloadTimer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_STATIC_OVERLOAD); + + uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); + } + else + uiStaticOverloadTimer -= uiDiff; + + if (uiBallLightningTimer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); + uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); + } + else + uiBallLightningTimer -= uiDiff; + + // Health check + if (!bHasDispersed && HealthBelowPct(uiDisperseHealth)) + { + bHasDispersed = true; + + DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me, SPELL_DISPERSE, true); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ionar(Creature* pCreature) +{ + return new boss_ionarAI(pCreature); +} + +bool EffectDummyCreature_boss_ionar(Unit* /*pCaster*/, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_DISPERSE && uiEffIndex == 0) + { + if (pCreatureTarget->GetEntry() != NPC_IONAR) + return true; + + for (uint8 i = 0; i < DATA_MAX_SPARKS; ++i) + pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true); + + pCreatureTarget->AttackStop(); + pCreatureTarget->SetVisibility(VISIBILITY_OFF); + pCreatureTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); + + pCreatureTarget->GetMotionMaster()->Clear(); + pCreatureTarget->GetMotionMaster()->MoveIdle(); + + //always return true when we are handling this spell and effect + return true; + } + return false; +} + +/*###### +## mob_spark_of_ionar +######*/ + +struct mob_spark_of_ionarAI : public ScriptedAI +{ + mob_spark_of_ionarAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 uiCheckTimer; + + void Reset() + { + uiCheckTimer = 2*IN_MILISECONDS; + me->SetReactState(REACT_PASSIVE); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE || !pInstance) + return; + + if (uiPointId == DATA_POINT_CALLBACK) + me->ForcedDespawn(); + } + + void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) + { + uiDamage = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + // Despawn if the encounter is not running + if (pInstance && pInstance->GetData(TYPE_IONAR) != IN_PROGRESS) + { + me->ForcedDespawn(); + return; + } + + // Prevent them to follow players through the whole instance + if (uiCheckTimer <= uiDiff) + { + if (pInstance) + { + Creature* pIonar = pInstance->instance->GetCreature(pInstance->GetData64(DATA_IONAR)); + if (pIonar && pIonar->isAlive()) + { + if (me->GetDistance(pIonar) > DATA_MAX_SPARK_DISTANCE) + { + Position pos; + pIonar->GetPosition(&pos); + + me->SetSpeed(MOVE_RUN, 2.0f); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); + } + } + else + me->ForcedDespawn(); + } + uiCheckTimer = 2*IN_MILISECONDS; + } + else + uiCheckTimer -= uiDiff; + + // No melee attack at all! + } +}; + +CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature) +{ + return new mob_spark_of_ionarAI(pCreature); +} + +void AddSC_boss_ionar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ionar"; + newscript->GetAI = &GetAI_boss_ionar; + newscript->pEffectDummyCreature = &EffectDummyCreature_boss_ionar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_spark_of_ionar"; + newscript->GetAI = &GetAI_mob_spark_of_ionar; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp new file mode 100644 index 00000000000..f08c19efca2 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_loken.cpp @@ -0,0 +1,222 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Loken +SD%Complete: 60% +SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414) +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + ACHIEV_TIMELY_DEATH_START_EVENT = 20384, + + SAY_AGGRO = -1602018, + SAY_INTRO_1 = -1602019, + SAY_INTRO_2 = -1602020, + SAY_SLAY_1 = -1602021, + SAY_SLAY_2 = -1602022, + SAY_SLAY_3 = -1602023, + SAY_DEATH = -1602024, + SAY_NOVA_1 = -1602025, + SAY_NOVA_2 = -1602026, + SAY_NOVA_3 = -1602027, + SAY_75HEALTH = -1602028, + SAY_50HEALTH = -1602029, + SAY_25HEALTH = -1602030, + EMOTE_NOVA = -1602031, + + SPELL_ARC_LIGHTNING = 52921, + SPELL_LIGHTNING_NOVA_N = 52960, + SPELL_LIGHTNING_NOVA_H = 59835, + + SPELL_PULSING_SHOCKWAVE_N = 52961, + SPELL_PULSING_SHOCKWAVE_H = 59836, + SPELL_PULSING_SHOCKWAVE_AURA = 59414 +}; + +/*###### +## Boss Loken +######*/ + +struct boss_lokenAI : public ScriptedAI +{ + boss_lokenAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + bool m_bIsAura; + + uint32 m_uiArcLightning_Timer; + uint32 m_uiLightningNova_Timer; + uint32 m_uiPulsingShockwave_Timer; + uint32 m_uiResumePulsingShockwave_Timer; + + uint32 m_uiHealthAmountModifier; + + void Reset() + { + m_bIsAura = false; + + m_uiArcLightning_Timer = 15000; + m_uiLightningNova_Timer = 20000; + m_uiPulsingShockwave_Timer = 2000; + m_uiResumePulsingShockwave_Timer = 15000; + + m_uiHealthAmountModifier = 1; + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); + } + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + if (m_pInstance) + { + m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS); + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); + } + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_LOKEN, DONE); + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_bIsAura) + { + // workaround for PULSING_SHOCKWAVE + if (m_uiPulsingShockwave_Timer <= uiDiff) + { + Map* pMap = me->GetMap(); + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack()) + { + int32 dmg; + float m_fDist = me->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()); + + dmg = DUNGEON_MODE(100, 150); // need to correct damage + if (m_fDist > 1.0f) // Further from 1 yard + dmg *= m_fDist; + + me->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false); + } + } + m_uiPulsingShockwave_Timer = 2000; + } else m_uiPulsingShockwave_Timer -= uiDiff; + } + else + { + if (m_uiResumePulsingShockwave_Timer <= uiDiff) + { + //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement? + DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); + + DoCast(me, SPELL_PULSING_SHOCKWAVE_N); // need core support + m_bIsAura = true; + m_uiResumePulsingShockwave_Timer = 0; + } + else + m_uiResumePulsingShockwave_Timer -= uiDiff; + } + + if (m_uiArcLightning_Timer <= uiDiff) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_ARC_LIGHTNING); + + m_uiArcLightning_Timer = 15000 + rand()%1000; + } + else + m_uiArcLightning_Timer -= uiDiff; + + if (m_uiLightningNova_Timer <= uiDiff) + { + DoScriptText(RAND(SAY_NOVA_1,SAY_NOVA_2,SAY_NOVA_3), me); + DoScriptText(EMOTE_NOVA, me); + DoCast(me, SPELL_LIGHTNING_NOVA_N); + + m_bIsAura = false; + m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura + m_uiLightningNova_Timer = 20000 + rand()%1000; + } + else + m_uiLightningNova_Timer -= uiDiff; + + // Health check + if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(25*m_uiHealthAmountModifier))) + { + switch(m_uiHealthAmountModifier) + { + case 1: DoScriptText(SAY_75HEALTH, me); break; + case 2: DoScriptText(SAY_50HEALTH, me); break; + case 3: DoScriptText(SAY_25HEALTH, me); break; + } + + ++m_uiHealthAmountModifier; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_loken(Creature* pCreature) +{ + return new boss_lokenAI(pCreature); +} + +void AddSC_boss_loken() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_loken"; + newscript->GetAI = &GetAI_boss_loken; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp new file mode 100644 index 00000000000..184050e3103 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -0,0 +1,478 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss Volkhan +SD%Complete: 60% +SDComment: Not considered complete. Some events may fail and need further development +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +enum eEnums +{ + SAY_AGGRO = -1602032, + SAY_SLAY_1 = -1602033, + SAY_SLAY_2 = -1602034, + SAY_SLAY_3 = -1602035, + SAY_DEATH = -1602036, + SAY_STOMP_1 = -1602037, + SAY_STOMP_2 = -1602038, + SAY_FORGE_1 = -1602039, + SAY_FORGE_2 = -1602040, + EMOTE_TO_ANVIL = -1602041, + EMOTE_SHATTER = -1602042, + + SPELL_HEAT_N = 52387, + SPELL_HEAT_H = 59528, + SPELL_SHATTERING_STOMP_N = 52237, + SPELL_SHATTERING_STOMP_H = 59529, + + //unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on: + SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil + SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss + + //SPELL_TEMPER_VISUAL = 52661, //summons GO + + SPELL_SUMMON_MOLTEN_GOLEM = 52405, + + //Molten Golem + SPELL_BLAST_WAVE = 23113, + SPELL_IMMOLATION_STRIKE_N = 52433, + SPELL_IMMOLATION_STRIKE_H = 59530, + SPELL_SHATTER_N = 52429, + SPELL_SHATTER_H = 59527, + + NPC_VOLKHAN_ANVIL = 28823, + NPC_MOLTEN_GOLEM = 28695, + NPC_BRITTLE_GOLEM = 28681, + + POINT_ID_ANVIL = 0, + MAX_GOLEM = 2, + + ACHIEVEMENT_SHATTER_RESISTANT = 2042 +}; + +/*###### +## Boss Volkhan +######*/ + +struct boss_volkhanAI : public ScriptedAI +{ + boss_volkhanAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + std::list m_lGolemGUIDList; + + bool m_bHasTemper; + bool m_bIsStriking; + bool m_bCanShatterGolem; + + uint8 GolemsShattered; + uint32 m_uiPause_Timer; + uint32 m_uiShatteringStomp_Timer; + uint32 m_uiShatter_Timer; + + uint32 m_uiHealthAmountModifier; + + void Reset() + { + m_bIsStriking = false; + m_bHasTemper = false; + m_bCanShatterGolem = false; + + m_uiPause_Timer = 3500; + m_uiShatteringStomp_Timer = 0; + m_uiShatter_Timer = 5000; + GolemsShattered = 0; + + m_uiHealthAmountModifier = 1; + + DespawnGolem(); + m_lGolemGUIDList.clear(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); + } + + void EnterCombat(Unit* /*pWho*/) + { + DoScriptText(SAY_AGGRO, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); + } + + void AttackStart(Unit* pWho) + { + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + if (!m_bHasTemper) + me->GetMotionMaster()->MoveChase(pWho); + } + } + + void JustDied(Unit* /*pKiller*/) + { + DoScriptText(SAY_DEATH, me); + DespawnGolem(); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VOLKHAN, DONE); + + if (IsHeroic() && GolemsShattered < 5) + { + AchievementEntry const *AchievShatterResistant = GetAchievementStore()->LookupEntry(ACHIEVEMENT_SHATTER_RESISTANT); + if (AchievShatterResistant) + { + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievShatterResistant); + } + } + } + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void DespawnGolem() + { + if (m_lGolemGUIDList.empty()) + return; + + for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + } + + m_lGolemGUIDList.clear(); + } + + void ShatterGolem() + { + if (m_lGolemGUIDList.empty()) + return; + + for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) + { + if (Creature* pTemp = Unit::GetCreature(*me, *itr)) + { + // only shatter brittle golems + if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM) + { + pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false); + GolemsShattered += 1; + } + } + } + } + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_TEMPER_DUMMY) + m_bIsStriking = true; + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_MOLTEN_GOLEM) + { + m_lGolemGUIDList.push_back(pSummoned->GetGUID()); + + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + + //why healing when just summoned? + pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, me->GetGUID()); + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_bIsStriking) + { + if (m_uiPause_Timer <= uiDiff) + { + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) + { + if (me->getVictim()) + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + + m_bHasTemper = false; + m_bIsStriking = false; + m_uiPause_Timer = 3500; + } + else + m_uiPause_Timer -= uiDiff; + + return; + } + + // When to start shatter? After 60, 40 or 20% hp? + if (!m_bHasTemper && m_uiHealthAmountModifier >= 3) + { + if (m_uiShatteringStomp_Timer <= uiDiff) + { + //should he stomp even if he has no brittle golem to shatter? + + DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2), me); + + DoCast(me, SPELL_SHATTERING_STOMP_N); + + DoScriptText(EMOTE_SHATTER, me); + + m_uiShatteringStomp_Timer = 30000; + m_bCanShatterGolem = true; + } + else + m_uiShatteringStomp_Timer -= uiDiff; + } + + // Shatter Golems 3 seconds after Shattering Stomp + if (m_bCanShatterGolem) + { + if (m_uiShatter_Timer <= uiDiff) + { + ShatterGolem(); + m_uiShatter_Timer = 3000; + m_bCanShatterGolem = false; + } + else + m_uiShatter_Timer -= uiDiff; + } + + // Health check + if (!m_bCanShatterGolem && (me->GetHealth()*100 / me->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier))) + { + ++m_uiHealthAmountModifier; + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoScriptText(RAND(SAY_FORGE_1,SAY_FORGE_2), me); + + m_bHasTemper = true; + + DoCast(me, SPELL_TEMPER, false); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_volkhan(Creature* pCreature) +{ + return new boss_volkhanAI(pCreature); +} + +bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_TEMPER_DUMMY && uiEffIndex == 0) + { + if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN) + return true; + + for (uint8 i = 0; i < MAX_GOLEM; ++i) + { + pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true); + } + + //always return true when we are handling this spell and effect + return true; + } + + return false; +} + +/*###### +## npc_volkhan_anvil +######*/ + +bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) +{ + //always check spellid and effectindex + if (uiSpellId == SPELL_TEMPER && uiEffIndex == 0) + { + if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL) + return true; + + Creature *cre = CAST_CRE(pCaster); + + DoScriptText(EMOTE_TO_ANVIL, pCaster); + + float fX, fY, fZ; + pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE); + + pCaster->AttackStop(); + + if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + pCaster->GetMotionMaster()->MovementExpired(); + + cre->GetMap()->CreatureRelocation(cre, fX, fY, fZ, pCreatureTarget->GetOrientation()); + cre->SendMonsterMove(fX, fY, fZ, 0, cre->GetUnitMovementFlags(), 1); + + pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); + + //always return true when we are handling this spell and effect + return true; + } + + return false; +} + +/*###### +## mob_molten_golem +######*/ + +struct mob_molten_golemAI : public ScriptedAI +{ + mob_molten_golemAI(Creature *pCreature) : ScriptedAI(pCreature) + { + } + + bool m_bIsFrozen; + + uint32 m_uiBlast_Timer; + uint32 m_uiDeathDelay_Timer; + uint32 m_uiImmolation_Timer; + + void Reset() + { + m_bIsFrozen = false; + + m_uiBlast_Timer = 20000; + m_uiDeathDelay_Timer = 0; + m_uiImmolation_Timer = 5000; + } + + void AttackStart(Unit* pWho) + { + if (me->Attack(pWho, true)) + { + me->AddThreat(pWho, 0.0f); + me->SetInCombatWith(pWho); + pWho->SetInCombatWith(me); + + if (!m_bIsFrozen) + me->GetMotionMaster()->MoveChase(pWho); + } + } + + void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) + { + if (uiDamage > me->GetHealth()) + { + me->UpdateEntry(NPC_BRITTLE_GOLEM); + me->SetHealth(1); + uiDamage = 0; + me->RemoveAllAuras(); + me->AttackStop(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + m_bIsFrozen = true; + } + } + + void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) + { + //this is the dummy effect of the spells + if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H) + { + if (me->GetEntry() == NPC_BRITTLE_GOLEM) + me->ForcedDespawn(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target or if we are frozen + if (!UpdateVictim() || m_bIsFrozen) + return; + + if (m_uiBlast_Timer <= uiDiff) + { + DoCast(me, SPELL_BLAST_WAVE); + m_uiBlast_Timer = 20000; + } + else + m_uiBlast_Timer -= uiDiff; + + if (m_uiImmolation_Timer <= uiDiff) + { + DoCast(me->getVictim(), SPELL_IMMOLATION_STRIKE_N); + m_uiImmolation_Timer = 5000; + } + else + m_uiImmolation_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_molten_golem(Creature* pCreature) +{ + return new mob_molten_golemAI(pCreature); +} + +void AddSC_boss_volkhan() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_volkhan"; + newscript->GetAI = &GetAI_boss_volkhan; + newscript->pEffectDummyCreature = &EffectDummyCreature_boss_volkhan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_volkhan_anvil"; + newscript->pEffectDummyCreature = &EffectDummyCreature_npc_volkhan_anvil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_molten_golem"; + newscript->GetAI = &GetAI_mob_molten_golem; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h new file mode 100644 index 00000000000..d9739fdf888 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/halls_of_lightning.h @@ -0,0 +1,34 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_HALLS_OF_LIGHTNING_H +#define DEF_HALLS_OF_LIGHTNING_H + +enum eTypes +{ + MAX_ENCOUNTER = 4, + + DATA_BJARNGRIM = 1, + DATA_IONAR = 2, + DATA_LOKEN = 3, + DATA_VOLKHAN = 4, + + TYPE_BJARNGRIM = 10, + TYPE_IONAR = 11, + TYPE_LOKEN = 12, + TYPE_VOLKHAN = 13, + + NPC_BJARNGRIM = 28586, + NPC_VOLKHAN = 28587, + NPC_IONAR = 28546, + NPC_LOKEN = 28923, + + GO_BJARNGRIM_DOOR = 191416, //_doors10 + GO_VOLKHAN_DOOR = 191325, //_doors07 + GO_IONAR_DOOR = 191326, //_doors05 + GO_LOKEN_DOOR = 191324, //_doors02 + GO_LOKEN_THRONE = 192654 +}; + +#endif diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp new file mode 100644 index 00000000000..46cd5c9cccc --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/instance_halls_of_lightning.cpp @@ -0,0 +1,248 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Halls_of_Lightning +SD%Complete: 90% +SDComment: All ready. +SDCategory: Halls of Lightning +EndScriptData */ + +#include "ScriptedPch.h" +#include "halls_of_lightning.h" + +/* Halls of Lightning encounters: +0 - General Bjarngrim +1 - Volkhan +2 - Ionar +3 - Loken +*/ + +struct instance_halls_of_lightning : public ScriptedInstance +{ + instance_halls_of_lightning(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 m_uiGeneralBjarngrimGUID; + uint64 m_uiIonarGUID; + uint64 m_uiLokenGUID; + uint64 m_uiVolkhanGUID; + + uint64 m_uiBjarngrimDoorGUID; + uint64 m_uiVolkhanDoorGUID; + uint64 m_uiIonarDoorGUID; + uint64 m_uiLokenDoorGUID; + uint64 m_uiLokenGlobeGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiGeneralBjarngrimGUID = 0; + m_uiVolkhanGUID = 0; + m_uiIonarGUID = 0; + m_uiLokenGUID = 0; + + m_uiBjarngrimDoorGUID = 0; + m_uiVolkhanDoorGUID = 0; + m_uiIonarDoorGUID = 0; + m_uiLokenDoorGUID = 0; + m_uiLokenGlobeGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case NPC_BJARNGRIM: + m_uiGeneralBjarngrimGUID = pCreature->GetGUID(); + break; + case NPC_VOLKHAN: + m_uiVolkhanGUID = pCreature->GetGUID(); + break; + case NPC_IONAR: + m_uiIonarGUID = pCreature->GetGUID(); + break; + case NPC_LOKEN: + m_uiLokenGUID = pCreature->GetGUID(); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_BJARNGRIM_DOOR: + m_uiBjarngrimDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_VOLKHAN_DOOR: + m_uiVolkhanDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_IONAR_DOOR: + m_uiIonarDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_LOKEN_DOOR: + m_uiLokenDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_LOKEN_THRONE: + m_uiLokenGlobeGUID = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_BJARNGRIM: + if (uiData == DONE) + DoUseDoorOrButton(m_uiBjarngrimDoorGUID); + m_auiEncounter[0] = uiData; + break; + case TYPE_VOLKHAN: + if (uiData == DONE) + DoUseDoorOrButton(m_uiVolkhanDoorGUID); + m_auiEncounter[1] = uiData; + break; + case TYPE_IONAR: + if (uiData == DONE) + DoUseDoorOrButton(m_uiIonarDoorGUID); + m_auiEncounter[2] = uiData; + break; + case TYPE_LOKEN: + if (uiData == DONE) + { + DoUseDoorOrButton(m_uiLokenDoorGUID); + + //Appears to be type 5 GO with animation. Need to figure out how this work, code below only placeholder + if (GameObject* pGlobe = instance->GetGameObject(m_uiLokenGlobeGUID)) + pGlobe->SetGoState(GO_STATE_ACTIVE); + } + m_auiEncounter[3] = uiData; + break; + } + + if (uiData == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_BJARNGRIM: + return m_auiEncounter[0]; + case TYPE_VOLKHAN: + return m_auiEncounter[1]; + case TYPE_IONAR: + return m_auiEncounter[2]; + case TYPE_LOKEN: + return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_BJARNGRIM: + return m_uiGeneralBjarngrimGUID; + case DATA_VOLKHAN: + return m_uiVolkhanGUID; + case DATA_IONAR: + return m_uiIonarGUID; + case DATA_LOKEN: + return m_uiLokenGUID; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H L " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + OUT_SAVE_INST_DATA_COMPLETE; + return saveStream.str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'H' && dataHead2 == 'L') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_halls_of_lightning(Map* pMap) +{ + return new instance_halls_of_lightning(pMap); +} + +void AddSC_instance_halls_of_lightning() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_lightning"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_lightning; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp new file mode 100644 index 00000000000..0674b7c79eb --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_krystallus.cpp @@ -0,0 +1,148 @@ +/* Script Data Start +SDName: Boss krystallus +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_krystallus' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_BOULDER_TOSS = 50843, + H_SPELL_BOULDER_TOSS = 59742, + SPELL_GROUND_SPIKE = 59750, + SPELL_GROUND_SLAM = 50827, + SPELL_SHATTER = 50810, + H_SPELL_SHATTER = 61546, + SPELL_STOMP = 48131, + H_SPELL_STOMP = 59744 +}; + +enum Yells +{ + SAY_AGGRO = -1599007, + SAY_KILL = -1599008, + SAY_DEATH = -1599009, + SAY_SHATTER = -1599010 +}; + +struct boss_krystallusAI : public ScriptedAI +{ + boss_krystallusAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiBoulderTossTimer; + uint32 uiGroundSpikeTimer; + uint32 uiGroundSlamTimer; + uint32 uiShatterTimer; + uint32 uiStompTimer; + + bool bIsSlam; + + ScriptedInstance* pInstance; + + void Reset() + { + bIsSlam = false; + + uiBoulderTossTimer = 3000 + rand()%6000; + uiGroundSpikeTimer = 9000 + rand()%5000; + uiGroundSlamTimer = 15000 + rand()%3000; + uiStompTimer = 20000 + rand()%9000; + uiShatterTimer = 0; + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, NOT_STARTED); + } + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiBoulderTossTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_BOULDER_TOSS); + uiBoulderTossTimer = 9000 + rand()%6000; + } else uiBoulderTossTimer -= diff; + + if (uiGroundSpikeTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_GROUND_SPIKE); + uiGroundSpikeTimer = 12000 + rand()%5000; + } else uiGroundSpikeTimer -= diff; + + if (uiStompTimer <= diff) + { + DoCast(me, SPELL_STOMP); + uiStompTimer = 20000 + rand()%9000; + } else uiStompTimer -= diff; + + if (uiGroundSlamTimer <= diff) + { + DoCast(me, SPELL_GROUND_SLAM); + bIsSlam = true; + uiShatterTimer = 10000; + uiGroundSlamTimer = 15000 + rand()%3000; + } else uiGroundSlamTimer -= diff; + + if (bIsSlam) + { + if (uiShatterTimer <= diff) + { + DoCast(me, SPELL_SHATTER); + bIsSlam = false; + } else uiShatterTimer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_KRYSTALLUS_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(SAY_KILL, me); + } +}; + +CreatureAI* GetAI_boss_krystallus(Creature* pCreature) +{ + return new boss_krystallusAI (pCreature); +} + +void AddSC_boss_krystallus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_krystallus"; + newscript->GetAI = &GetAI_boss_krystallus; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp new file mode 100644 index 00000000000..b3c3c675347 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp @@ -0,0 +1,166 @@ +/* Script Data Start +SDName: Boss maiden_of_grief +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_maiden_of_grief' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_PARTING_SORROW = 59723, + SPELL_STORM_OF_GRIEF_N = 50752, + SPELL_STORM_OF_GRIEF_H = 59772, + SPELL_SHOCK_OF_SORROW_N = 50760, + SPELL_SHOCK_OF_SORROW_H = 59726, + SPELL_PILLAR_OF_WOE_N = 50761, + SPELL_PILLAR_OF_WOE_H = 59727 +}; + +enum Yells +{ + SAY_AGGRO = -1599000, + SAY_SLAY_1 = -1599001, + SAY_SLAY_2 = -1599002, + SAY_SLAY_3 = -1599003, + SAY_SLAY_4 = -1599004, + SAY_DEATH = -1599005, + SAY_STUN = -1599006 +}; + +enum Achievements +{ + ACHIEV_GOOD_GRIEF_START_EVENT = 20383, +}; + +struct boss_maiden_of_griefAI : public ScriptedAI +{ + boss_maiden_of_griefAI(Creature *c) : ScriptedAI(c) + { + pInstance = me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 PartingSorrowTimer; + uint32 StormOfGriefTimer; + uint32 ShockOfSorrowTimer; + uint32 PillarOfWoeTimer; + + void Reset() + { + PartingSorrowTimer = 25000 + rand()%5000; + StormOfGriefTimer = 10000; + ShockOfSorrowTimer = 20000+rand()%5000; + PillarOfWoeTimer = 5000 + rand()%10000; + + if (pInstance) + { + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, NOT_STARTED); + pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAIDEN_DOOR))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, IN_PROGRESS); + pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (IsHeroic()) + { + if (PartingSorrowTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget) + DoCast(pTarget, SPELL_PARTING_SORROW); + + PartingSorrowTimer = 30000 + rand()%10000; + } else PartingSorrowTimer -= diff; + } + + if (StormOfGriefTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STORM_OF_GRIEF_N, true); + StormOfGriefTimer = 15000 + rand()%5000; + } else StormOfGriefTimer -= diff; + + if (ShockOfSorrowTimer <= diff) + { + DoResetThreat(); + DoScriptText(SAY_STUN, me); + DoCast(me, SPELL_SHOCK_OF_SORROW_N); + ShockOfSorrowTimer = 20000 + rand()%10000; + } else ShockOfSorrowTimer -= diff; + + if (PillarOfWoeTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + + if (pTarget) + DoCast(pTarget, SPELL_PILLAR_OF_WOE_N); + else + DoCast(me->getVictim(), SPELL_PILLAR_OF_WOE_N); + + PillarOfWoeTimer = 5000 + rand()%20000; + } else PillarOfWoeTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, DONE); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } +}; + +CreatureAI* GetAI_boss_maiden_of_grief(Creature* pCreature) +{ + return new boss_maiden_of_griefAI (pCreature); +} + +void AddSC_boss_maiden_of_grief() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_maiden_of_grief"; + newscript->GetAI = &GetAI_boss_maiden_of_grief; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp new file mode 100644 index 00000000000..68c3e34e6bf --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_sjonnir.cpp @@ -0,0 +1,300 @@ +/* Script Data Start +SDName: Boss sjonnir +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_sjonnir' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +enum Spells +{ + SPELL_LIGHTING_RING = 51849, //Periodic Trigger (interval 2s) spell = 50841 + H_SPELL_LIGHTING_RING = 59861, //Periodic Trigger (interval 2s) spell = 59849 + SPELL_LIGHTING_RING_1 = 50840, //Periodic Trigger (interval 2s) spell = 50841 + H_SPELL_LIGHTING_RING_1 = 59848, //Periodic Trigger (interval 2s) spell = 59849 + SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835 + H_SPELL_STATIC_CHARGE = 59846, //Periodic Trigger 2s interval, spell =50847 + SPELL_CHAIN_LIGHTING = 50830, + H_SPELL_CHAIN_LIGHTING = 59844, + SPELL_LIGHTING_SHIELD = 50831, + H_SPELL_LIGHTING_SHIELD = 59845, + SPELL_FRENZY = 28747 +}; + +enum Yells +{ + SAY_AGGRO = -1599011, + SAY_SLAY_1 = -1599012, + SAY_SLAY_2 = -1599013, + SAY_SLAY_3 = -1599014, + SAY_DEATH = -1599015 +}; + +#define EMOTE_GENERIC_FRENZY -1000002 + +enum SjonnirCreatures +{ + CREATURE_FORGED_IRON_TROGG = 27979, + CREATURE_MALFORMED_OOZE = 27981, + CREATURE_FORGED_IRON_DWARF = 27982, + CREATURE_IRON_SLUDGE = 28165 +}; + +enum Misc +{ + DATA_TIME_BEFORE_OOZE = 150000, //2min 30 secs + ACHIEV_ABUSE_THE_OOZE = 2155 +}; + +struct Locations +{ + float x, y, z; +}; + +static Locations PipeLocations[] = +{ + {1295.44, 734.07, 200.3}, //left + {1297.7, 595.6, 199.9} //right +}; + +static Locations CenterPoint = {1295.21, 667.157, 189.691}; + +struct boss_sjonnirAI : public ScriptedAI +{ + boss_sjonnirAI(Creature *c) : ScriptedAI(c), lSummons(me) + { + pInstance = c->GetInstanceData(); + } + + bool bIsFrenzy; + + uint32 uiChainLightningTimer; + uint32 uiLightningShieldTimer; + uint32 uiStaticChargeTimer; + uint32 uiLightningRingTimer; + uint32 uiSummonTimer; + uint32 uiFrenzyTimer; + uint32 uiEncounterTimer; + uint32 uiKilledIronSludges; + + SummonList lSummons; + + ScriptedInstance* pInstance; + + void Reset() + { + bIsFrenzy = false; + + uiEncounterTimer = 0; + uiChainLightningTimer = 3000 + rand()%5000; + uiLightningShieldTimer = 20000 + rand()%5000; + uiStaticChargeTimer = 20000 + rand()%5000; + uiLightningRingTimer = 30000 + rand()%5000; + uiSummonTimer = 5000; + uiFrenzyTimer = 300000; //5 minutes + uiKilledIronSludges = 0; + + lSummons.DespawnAll(); + + if (pInstance) + pInstance->SetData(DATA_SJONNIR_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + uiEncounterTimer = 0; + + if (pInstance) + { + if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SJONNIR_DOOR))) + if (pDoor->GetGoState() == GO_STATE_READY) + { + EnterEvadeMode(); + return; + } + + pInstance->SetData(DATA_SJONNIR_EVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiChainLightningTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_CHAIN_LIGHTING); + uiChainLightningTimer = 10000 + rand()%5000; + } else uiChainLightningTimer -= diff; + + if (uiLightningShieldTimer <= diff) + { + DoCast(me, SPELL_LIGHTING_SHIELD); + uiLightningShieldTimer -= diff; + } + + if (uiStaticChargeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STATIC_CHARGE); + uiStaticChargeTimer = 20000 + rand()%5000; + } uiStaticChargeTimer -= diff; + + if (uiLightningRingTimer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_LIGHTING_RING); + uiLightningRingTimer = 30000 + rand()%5000; + } else uiLightningRingTimer -= diff; + + if (uiSummonTimer <= diff) + { + uint32 uiSummonPipe = rand()%2; + me->SummonCreature(uiEncounterTimer > DATA_TIME_BEFORE_OOZE ? CREATURE_MALFORMED_OOZE : + RAND(CREATURE_FORGED_IRON_DWARF,CREATURE_FORGED_IRON_TROGG), + PipeLocations[uiSummonPipe].x, PipeLocations[uiSummonPipe].y, PipeLocations[uiSummonPipe].z, 0.0f, + TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + uiSummonTimer = 20000; + } else uiSummonTimer -= diff; + + if (!bIsFrenzy) + { + if (uiFrenzyTimer <= diff) + { + DoCast(me, SPELL_FRENZY); + bIsFrenzy = true; + } + else uiFrenzyTimer -= diff; + } + + uiEncounterTimer +=diff; + + DoMeleeAttackIfReady(); + } + + void JustSummoned(Creature* summon) + { + summon->GetMotionMaster()->MovePoint(0, CenterPoint.x, CenterPoint.y, CenterPoint.z); + /*if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + summon->AI()->AttackStart(pTarget);*/ + lSummons.Summon(summon); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + lSummons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_SJONNIR_EVENT, DONE); + if (IsHeroic() && uiKilledIronSludges > 4) + pInstance->DoCompleteAchievement(ACHIEV_ABUSE_THE_OOZE); + } + } + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void KilledIronSludge() + { + ++uiKilledIronSludges; + } +}; + +CreatureAI* GetAI_boss_sjonnir(Creature* pCreature) +{ + return new boss_sjonnirAI (pCreature); +} + +struct mob_malformed_oozeAI : public ScriptedAI +{ + mob_malformed_oozeAI(Creature *c) : ScriptedAI(c) {} + + uint32 uiMergeTimer; + + void Reset() + { + uiMergeTimer = 10000; + } + + void UpdateAI(const uint32 diff) + { + if (uiMergeTimer <= diff) + { + if (Creature* pTemp = me->FindNearestCreature(CREATURE_MALFORMED_OOZE, 3.0f, true)) + { + DoSpawnCreature(CREATURE_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); + pTemp->DisappearAndDie(); + me->DisappearAndDie(); + } + uiMergeTimer = 3000; + } else uiMergeTimer -= diff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_malformed_ooze(Creature* pCreature) +{ + return new mob_malformed_oozeAI(pCreature); +} + +struct mob_iron_sludgeAI : public ScriptedAI +{ + mob_iron_sludgeAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void JustDied(Unit* /*pKiller*/) + { + if (pInstance) + if (Creature* pSjonnir = Unit::GetCreature(*me, pInstance->GetData64(DATA_SJONNIR))) + CAST_AI(boss_sjonnirAI, pSjonnir->AI())->KilledIronSludge(); + } +}; + +CreatureAI* GetAI_mob_iron_sludge(Creature* pCreature) +{ + return new mob_iron_sludgeAI(pCreature); +} + +void AddSC_boss_sjonnir() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sjonnir"; + newscript->GetAI = &GetAI_boss_sjonnir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_malformed_ooze"; + newscript->GetAI = &GetAI_mob_malformed_ooze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_iron_sludge"; + newscript->GetAI = &GetAI_mob_iron_sludge; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp new file mode 100644 index 00000000000..8febdaab879 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp @@ -0,0 +1,724 @@ +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "halls_of_stone.h" + +enum Texts +{ + SAY_KILL_1 = -1599016, + SAY_KILL_2 = -1599017, + SAY_KILL_3 = -1599018, + SAY_LOW_HEALTH = -1599019, + SAY_DEATH = -1599020, + SAY_PLAYER_DEATH_1 = -1599021, + SAY_PLAYER_DEATH_2 = -1599022, + SAY_PLAYER_DEATH_3 = -1599023, + SAY_ESCORT_START = -1599024, + + SAY_SPAWN_DWARF = -1599025, + SAY_SPAWN_TROGG = -1599026, + SAY_SPAWN_OOZE = -1599027, + SAY_SPAWN_EARTHEN = -1599028, + + SAY_EVENT_INTRO_1 = -1599029, + SAY_EVENT_INTRO_2 = -1599030, + SAY_EVENT_INTRO_3_ABED = -1599031, + + SAY_EVENT_A_1 = -1599032, + SAY_EVENT_A_2_KADD = -1599033, + SAY_EVENT_A_3 = -1599034, + + SAY_EVENT_B_1 = -1599035, + SAY_EVENT_B_2_MARN = -1599036, + SAY_EVENT_B_3 = -1599037, + + SAY_EVENT_C_1 = -1599038, + SAY_EVENT_C_2_ABED = -1599039, + SAY_EVENT_C_3 = -1599040, + + SAY_EVENT_D_1 = -1599041, + SAY_EVENT_D_2_ABED = -1599042, + SAY_EVENT_D_3 = -1599043, + SAY_EVENT_D_4_ABED = -1599044, + + SAY_EVENT_END_01 = -1599045, + SAY_EVENT_END_02 = -1599046, + SAY_EVENT_END_03_ABED = -1599047, + SAY_EVENT_END_04 = -1599048, + SAY_EVENT_END_05_ABED = -1599049, + SAY_EVENT_END_06 = -1599050, + SAY_EVENT_END_07_ABED = -1599051, + SAY_EVENT_END_08 = -1599052, + SAY_EVENT_END_09_KADD = -1599053, + SAY_EVENT_END_10 = -1599054, + SAY_EVENT_END_11_KADD = -1599055, + SAY_EVENT_END_12 = -1599056, + SAY_EVENT_END_13_KADD = -1599057, + SAY_EVENT_END_14 = -1599058, + SAY_EVENT_END_15_MARN = -1599059, + SAY_EVENT_END_16 = -1599060, + SAY_EVENT_END_17_MARN = -1599061, + SAY_EVENT_END_18 = -1599062, + SAY_EVENT_END_19_MARN = -1599063, + SAY_EVENT_END_20 = -1599064, + SAY_EVENT_END_21_ABED = -1599065, + + SAY_VICTORY_SJONNIR_1 = -1599066, + SAY_VICTORY_SJONNIR_2 = -1599067, + + SAY_ENTRANCE_MEET = -1599068, + + TEXT_ID_START = 13100, + TEXT_ID_PROGRESS = 13101 +}; + +enum BrannCreatures +{ + CREATURE_TRIBUNAL_OF_THE_AGES = 28234, + CREATURE_BRANN_BRONZEBEARD = 28070, + CREATURE_DARK_MATTER_TARGET = 28237, + CREATURE_SEARING_GAZE_TARGET = 28265, + CREATURE_DARK_RUNE_PROTECTOR = 27983, + CREATURE_DARK_RUNE_STORMCALLER = 27984, + CREATURE_IRON_GOLEM_CUSTODIAN = 27985, +}; + +enum Spells +{ + SPELL_STEALTH = 58506, + //Kadrak + SPELL_GLARE_OF_THE_TRIBUNAL = 50988, + H_SPELL_GLARE_OF_THE_TRIBUNAL = 59868, + //Marnak + SPELL_DARK_MATTER = 51012, + H_SPELL_DARK_MATTER = 59868, + //Abedneum + SPELL_SEARING_GAZE = 51136, + H_SPELL_SEARING_GAZE = 59867 +}; + +enum Quests +{ + QUEST_HALLS_OF_STONE = 13207 +}; + +enum Achievements +{ + ACHIEV_BRANN_SPANKIN_NEW = 2154 +}; + +#define GOSSIP_ITEM_START "Brann, it would be our honor!" +#define GOSSIP_ITEM_PROGRESS "Let's move Brann, enough of the history lessons!" + +static Position SpawnLocations[]= +{ + {946.992, 397.016, 208.374}, + {960.748, 382.944, 208.374}, +}; + +struct mob_tribuna_controllerAI : public ScriptedAI +{ + mob_tribuna_controllerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + SetCombatMovement(false); + } + + ScriptedInstance* pInstance; + + uint32 uiKaddrakEncounterTimer; + uint32 uiMarnakEncounterTimer; + uint32 uiAbedneumEncounterTimer; + + bool bKaddrakActivated; + bool bMarnakActivated; + bool bAbedneumActivated; + + std::list KaddrakGUIDList; + + void Reset() + { + uiKaddrakEncounterTimer = 1500; + uiMarnakEncounterTimer = 10000; + uiAbedneumEncounterTimer = 10000; + + bKaddrakActivated = false; + bMarnakActivated = false; + bAbedneumActivated = false; + + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); + } + + KaddrakGUIDList.clear(); + } + + void UpdateFacesList() + { + /*GetCreatureListWithEntryInGrid(lKaddrakGUIDList, me, CREATURE_KADDRAK, 50.0f); + if (!lKaddrakGUIDList.empty()) + { + uint32 uiPositionCounter = 0; + for (std::list::const_iterator itr = lKaddrakGUIDList.begin(); itr != lKaddrakGUIDList.end(); ++itr) + { + if ((*itr)->isAlive()) + { + if (uiPositionCounter == 0) + { + (*itr)->GetMap()->CreatureRelocation((*itr), 927.265, 333.200, 218.780, (*itr)->GetOrientation()); + (*itr)->SendMonsterMove(927.265, 333.200, 218.780, 0, (*itr)->GetMovementFlags(), 1); + } + else + { + (*itr)->GetMap()->CreatureRelocation((*itr), 921.745, 328.076, 218.780, (*itr)->GetOrientation()); + (*itr)->SendMonsterMove(921.745, 328.076, 218.780, 0, (*itr)->GetMovementFlags(), 1); + } + } + ++uiPositionCounter; + } + }*/ + } + + void UpdateAI(const uint32 diff) + { + if (bKaddrakActivated) + { + if (uiKaddrakEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (!KaddrakGUIDList.empty()) + for (std::list::const_iterator itr = KaddrakGUIDList.begin(); itr != KaddrakGUIDList.end(); ++itr) + { + if (Creature *pKaddrak = Unit::GetCreature(*me, *itr)) + { + if (pKaddrak->isAlive()) + pKaddrak->CastSpell(pTarget, DUNGEON_MODE(SPELL_GLARE_OF_THE_TRIBUNAL, H_SPELL_GLARE_OF_THE_TRIBUNAL), true); + } + } + uiKaddrakEncounterTimer = 1500; + } else uiKaddrakEncounterTimer -= diff; + } + if (bMarnakActivated) + { + if (uiMarnakEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature* pSummon = me->SummonCreature(CREATURE_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) + { + pSummon->SetDisplayId(11686); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_DARK_MATTER, H_SPELL_DARK_MATTER), true); + } + } + uiMarnakEncounterTimer = 30000 + rand()%1000; + } else uiMarnakEncounterTimer -= diff; + } + if (bAbedneumActivated) + { + if (uiAbedneumEncounterTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + if (Creature* pSummon = me->SummonCreature(CREATURE_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) + { + pSummon->SetDisplayId(11686); + pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_SEARING_GAZE, H_SPELL_SEARING_GAZE), true); + } + } + uiAbedneumEncounterTimer = 30000 + rand()%1000; + } else uiAbedneumEncounterTimer -= diff; + } + } +}; + +struct npc_brann_hosAI : public npc_escortAI +{ + npc_brann_hosAI(Creature *c) : npc_escortAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiStep; + uint32 uiPhaseTimer; + + uint64 uiControllerGUID; + std::list lDwarfGUIDList; + + ScriptedInstance* pInstance; + + bool bIsBattle; + bool bIsLowHP; + bool bHasBeenDamaged; + + void Reset() + { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + bIsLowHP = false; + bIsBattle = false; + bHasBeenDamaged = false; + uiStep = 0; + uiPhaseTimer = 0; + uiControllerGUID = 0; + + DespawnDwarf(); + + if (pInstance) + pInstance->SetData(DATA_BRANN_EVENT, NOT_STARTED); + } + } + + void DespawnDwarf() + { + if (lDwarfGUIDList.empty()) + return; + for (std::list::const_iterator itr = lDwarfGUIDList.begin(); itr != lDwarfGUIDList.end(); ++itr) + { + Creature* pTemp = Unit::GetCreature(*me, pInstance ? (*itr) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + lDwarfGUIDList.clear(); + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 7: + if (Creature* pCreature = GetClosestCreatureWithEntry(me, CREATURE_TRIBUNAL_OF_THE_AGES, 100.0f)) + { + if (!pCreature->isAlive()) + pCreature->Respawn(); + CAST_AI(mob_tribuna_controllerAI, pCreature->AI())->UpdateFacesList(); + uiControllerGUID = pCreature->GetGUID(); + } + break; + case 13: + DoScriptText(SAY_EVENT_INTRO_1, me); + SetEscortPaused(true); + JumpToNextStep(20000); + break; + case 17: + DoScriptText(SAY_EVENT_INTRO_2, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_TRIBUNAL_CONSOLE),true); + me->SetStandState(UNIT_STAND_STATE_KNEEL); + SetEscortPaused(true); + JumpToNextStep(8500); + break; + case 18: + SetEscortPaused(true); + break; + } + } + + void SpawnDwarf(uint32 uiType) + { + switch(uiType) + { + case 1: + { + uint32 uiSpawnNumber = DUNGEON_MODE(2,3); + for (uint8 i = 0; i < uiSpawnNumber; ++i) + me->SummonCreature(CREATURE_DARK_RUNE_PROTECTOR, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + } + case 2: + for (uint8 i = 0; i < 2; ++i) + me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + case 3: + me->SummonCreature(CREATURE_IRON_GOLEM_CUSTODIAN, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + lDwarfGUIDList.push_back(pSummoned->GetGUID()); + pSummoned->AddThreat(me, 0.0f); + pSummoned->AI()->AttackStart(me); + } + + void JumpToNextStep(uint32 uiTimer) + { + uiPhaseTimer = uiTimer; + ++uiStep; + } + + void StartWP() + { + me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetEscortPaused(false); + uiStep = 1; + Start(); + } + + void DamageTaken(Unit* /*done_by*/, uint32 & /*damage*/) + { + if (!bHasBeenDamaged) + bHasBeenDamaged = true; + } + + void UpdateEscortAI(const uint32 uiDiff) + { + if (uiPhaseTimer <= uiDiff) + { + switch(uiStep) + { + case 1: + if (pInstance) + { + if (pInstance->GetData(DATA_BRANN_EVENT) != NOT_STARTED) + return; + pInstance->SetData(DATA_BRANN_EVENT, IN_PROGRESS); + } + bIsBattle = false; + DoScriptText(SAY_ESCORT_START, me); + SetRun(true); + JumpToNextStep(0); + break; + case 3: + SetEscortPaused(false); + JumpToNextStep(0); + break; + case 5: + if (pInstance) + if (Creature* pTemp = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM)))) + DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp); + JumpToNextStep(8500); + break; + case 6: + DoScriptText(SAY_EVENT_A_1, me); + JumpToNextStep(6500); + break; + case 7: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_A_2_KADD, pTemp); + JumpToNextStep(12500); + break; + case 8: + DoScriptText(SAY_EVENT_A_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bKaddrakActivated = true; + JumpToNextStep(5000); + break; + case 9: + me->SetReactState(REACT_PASSIVE); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 10: + DoScriptText(SAY_EVENT_B_1, me); + JumpToNextStep(6000); + break; + case 11: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_B_2_MARN, pTemp); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 12: + DoScriptText(SAY_EVENT_B_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bMarnakActivated = true; + JumpToNextStep(10000); + break; + case 13: + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 14: + SpawnDwarf(2); + JumpToNextStep(20000); + break; + case 15: + DoScriptText(SAY_EVENT_C_1, me); + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 16: + SpawnDwarf(2); + JumpToNextStep(20000); + break; + case 17: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_C_2_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 18: + DoScriptText(SAY_EVENT_C_3, me); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bAbedneumActivated = true; + JumpToNextStep(5000); + break; + case 19: + SpawnDwarf(2); + JumpToNextStep(10000); + break; + case 20: + SpawnDwarf(1); + JumpToNextStep(15000); + break; + case 21: + DoScriptText(SAY_EVENT_D_1, me); + SpawnDwarf(3); + JumpToNextStep(20000); + break; + case 22: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_D_2_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(5000); + break; + case 23: + SpawnDwarf(2); + JumpToNextStep(15000); + break; + case 24: + DoScriptText(SAY_EVENT_D_3, me); + SpawnDwarf(3); + JumpToNextStep(5000); + break; + case 25: + SpawnDwarf(1); + JumpToNextStep(5000); + break; + case 26: + SpawnDwarf(2); + JumpToNextStep(10000); + break; + case 27: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_D_4_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 28: + me->SetReactState(REACT_DEFENSIVE); + DoScriptText(SAY_EVENT_END_01, me); + me->SetStandState(UNIT_STAND_STATE_STAND); + if (pInstance) + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),true); + if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + bIsBattle = true; + SetEscortPaused(false); + JumpToNextStep(6500); + break; + case 29: + DoScriptText(SAY_EVENT_END_02, me); + if (pInstance) + { + pInstance->SetData(DATA_BRANN_EVENT, DONE); + + // Achievement criteria is with spell 59046 which does not exist. + // There is thus no way it can be given by casting the spell on the players. + pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59046); + + if (!bHasBeenDamaged) + pInstance->DoCompleteAchievement(ACHIEV_BRANN_SPANKIN_NEW); + } + + JumpToNextStep(5500); + break; + case 30: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_03_ABED, pTemp); + JumpToNextStep(8500); + break; + case 31: + DoScriptText(SAY_EVENT_END_04, me); + JumpToNextStep(11500); + break; + case 32: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_05_ABED, pTemp); + JumpToNextStep(11500); + break; + case 33: + DoScriptText(SAY_EVENT_END_06, me); + JumpToNextStep(4500); + break; + case 34: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_07_ABED, pTemp); + JumpToNextStep(22500); + break; + case 35: + DoScriptText(SAY_EVENT_END_08, me); + JumpToNextStep(7500); + break; + case 36: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_09_KADD, pTemp); + JumpToNextStep(18500); + break; + case 37: + DoScriptText(SAY_EVENT_END_10, me); + JumpToNextStep(5500); + break; + case 38: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_11_KADD, pTemp); + JumpToNextStep(20500); + break; + case 39: + DoScriptText(SAY_EVENT_END_12, me); + JumpToNextStep(2500); + break; + case 40: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_13_KADD, pTemp); + JumpToNextStep(19500); + break; + case 41: + DoScriptText(SAY_EVENT_END_14, me); + JumpToNextStep(10500); + break; + case 42: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_15_MARN, pTemp); + JumpToNextStep(6500); + break; + case 43: + DoScriptText(SAY_EVENT_END_16, me); + JumpToNextStep(6500); + break; + case 44: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_17_MARN, pTemp); + JumpToNextStep(25500); + break; + case 45: + DoScriptText(SAY_EVENT_END_18, me); + JumpToNextStep(23500); + break; + case 46: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_19_MARN, pTemp); + JumpToNextStep(3500); + break; + case 47: + DoScriptText(SAY_EVENT_END_20, me); + JumpToNextStep(8500); + break; + case 48: + if (pInstance) + if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_21_ABED, pTemp); + JumpToNextStep(5500); + break; + case 49: + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); + pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); + } + Player* pPlayer = GetPlayerForEscort(); + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, me); + me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + JumpToNextStep(180000); + break; + } + case 50: + SetEscortPaused(false); + break; + } + } else uiPhaseTimer -= uiDiff; + + if (!bIsLowHP && HealthBelowPct(30)) + { + DoScriptText(SAY_LOW_HEALTH, me); + bIsLowHP = true; + } + else if (bIsLowHP && !HealthBelowPct(30)) + bIsLowHP = false; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_brann_hos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1 || uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->CLOSE_GOSSIP_MENU(); + CAST_AI(npc_brann_hosAI, pCreature->AI())->StartWP(); + } + + return true; +} + +CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature) +{ + return new mob_tribuna_controllerAI(pCreature); +} + +CreatureAI* GetAI_npc_brann_hos(Creature* pCreature) +{ + return new npc_brann_hosAI(pCreature); +} + +void AddSC_halls_of_stone() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_brann_hos"; + newscript->GetAI = &GetAI_npc_brann_hos; + newscript->pGossipHello = &GossipHello_npc_brann_hos; + newscript->pGossipSelect = &GossipSelect_npc_brann_hos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tribuna_controller"; + newscript->GetAI = &GetAI_mob_tribuna_controller; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h new file mode 100644 index 00000000000..b61e7057ddc --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.h @@ -0,0 +1,48 @@ +#ifndef DEF_HALLS_OF_STONE_H +#define DEF_HALLS_OF_STONE_H +enum Data +{ + DATA_KRYSTALLUS_EVENT, + DATA_MAIDEN_OF_GRIEF_EVENT, + DATA_SJONNIR_EVENT, + DATA_BRANN_EVENT +}; +enum Data64 +{ + DATA_KRYSTALLUS, + DATA_MAIDEN_OF_GRIEF, + DATA_SJONNIR, + DATA_KADDRAK, + DATA_MARNAK, + DATA_ABEDNEUM, + DATA_GO_TRIBUNAL_CONSOLE, + DATA_GO_KADDRAK, + DATA_GO_MARNAK, + DATA_GO_ABEDNEUM, + DATA_GO_SKY_FLOOR, + DATA_SJONNIR_DOOR, + DATA_MAIDEN_DOOR +}; +enum Creatures +{ + CREATURE_MAIDEN = 27975, + CREATURE_KRYSTALLUS = 27977, + CREATURE_SJONNIR = 27978, + CREATURE_MARNAK = 30897, + CREATURE_KADDRAK = 30898, + CREATURE_ABEDNEUM = 30899, + CREATURE_BRANN = 28070 +}; +enum GameObjects +{ + GO_ABEDNEUM = 191669, + GO_MARNAK = 192170, + GO_KADDRAK = 192171, + GO_MAIDEN_DOOR = 191292, + GO_BRANN_DOOR = 191295, + GO_SJONNIR_DOOR = 191296, + GO_TRIBUNAL_CONSOLE = 193907, + GO_TRIBUNAL_CHEST = 190586, + GO_TRIBUNAL_CHEST_HERO = 193996 +}; +#endif diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp new file mode 100644 index 00000000000..69bb3779e70 --- /dev/null +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/instance_halls_of_stone.cpp @@ -0,0 +1,254 @@ +#include "ScriptedPch.h" +#include "halls_of_stone.h" + +#define MAX_ENCOUNTER 4 + +/* Halls of Stone encounters: +0- Krystallus +1- Maiden of Grief +2- Escort Event +3- Sjonnir The Ironshaper +*/ + +struct instance_halls_of_stone : public ScriptedInstance +{ + instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiMaidenOfGrief; + uint64 uiKrystallus; + uint64 uiSjonnir; + + uint64 uiKaddrak; + uint64 uiAbedneum; + uint64 uiMarnak; + uint64 uiBrann; + + uint64 uiMaidenOfGriefDoor; + uint64 uiSjonnirDoor; + uint64 uiBrannDoor; + uint64 uiTribunalConsole; + uint64 uiTribunalChest; + uint64 uiTribunalSkyFloor; + uint64 uiKaddrakGo; + uint64 uiAbedneumGo; + uint64 uiMarnakGo; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + std::string str_data; + + void Initialize() + { + uiMaidenOfGrief = 0; + uiKrystallus = 0; + uiSjonnir = 0; + + uiKaddrak = 0; + uiMarnak = 0; + uiAbedneum = 0; + uiBrann = 0; + + uiMaidenOfGriefDoor = 0; + uiSjonnirDoor = 0; + uiBrannDoor = 0; + uiKaddrakGo = 0; + uiMarnakGo = 0; + uiAbedneumGo = 0; + uiTribunalConsole = 0; + uiTribunalChest = 0; + uiTribunalSkyFloor = 0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + m_auiEncounter[i] = NOT_STARTED; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case CREATURE_MAIDEN: uiMaidenOfGrief = pCreature->GetGUID(); break; + case CREATURE_KRYSTALLUS: uiKrystallus = pCreature->GetGUID(); break; + case CREATURE_SJONNIR: uiSjonnir = pCreature->GetGUID(); break; + case CREATURE_MARNAK: uiMarnak = pCreature->GetGUID(); break; + case CREATURE_KADDRAK: uiKaddrak = pCreature->GetGUID(); break; + case CREATURE_ABEDNEUM: uiAbedneum = pCreature->GetGUID(); break; + case CREATURE_BRANN: uiBrann = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case GO_ABEDNEUM: + uiAbedneumGo = pGo->GetGUID(); + break; + case GO_MARNAK: + uiMarnakGo = pGo->GetGUID(); + break; + case GO_KADDRAK: + uiKaddrakGo = pGo->GetGUID(); + break; + case GO_MAIDEN_DOOR: + uiMaidenOfGriefDoor = pGo->GetGUID(); + if (m_auiEncounter[0] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_BRANN_DOOR: + uiBrannDoor = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_SJONNIR_DOOR: + uiSjonnirDoor = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + else + pGo->SetGoState(GO_STATE_READY); + break; + case GO_TRIBUNAL_CONSOLE: + uiTribunalConsole = pGo->GetGUID(); + break; + case GO_TRIBUNAL_CHEST: + case GO_TRIBUNAL_CHEST_HERO: + uiTribunalChest = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + break; + case 191527: + uiTribunalSkyFloor = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAIDEN_OF_GRIEF_EVENT: + m_auiEncounter[1] = data; + if (m_auiEncounter[1] == DONE) + HandleGameObject(uiBrannDoor,true); + break; + case DATA_KRYSTALLUS_EVENT: + m_auiEncounter[0] = data; + if (m_auiEncounter[0] == DONE) + HandleGameObject(uiMaidenOfGriefDoor,true); + break; + case DATA_SJONNIR_EVENT: + m_auiEncounter[3] = data; + break; + case DATA_BRANN_EVENT: + m_auiEncounter[2] = data; + if (m_auiEncounter[2] == DONE) + { + HandleGameObject(uiSjonnirDoor,true); + GameObject *pGo = instance->GetGameObject(uiTribunalChest); + if (pGo) + pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); + } + break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_KRYSTALLUS_EVENT: return m_auiEncounter[0]; + case DATA_MAIDEN_OF_GRIEF_EVENT: return m_auiEncounter[1]; + case DATA_SJONNIR_EVENT: return m_auiEncounter[2]; + case DATA_BRANN_EVENT: return m_auiEncounter[3]; + } + + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_MAIDEN_OF_GRIEF: return uiMaidenOfGrief; + case DATA_KRYSTALLUS: return uiKrystallus; + case DATA_SJONNIR: return uiSjonnir; + case DATA_KADDRAK: return uiKaddrak; + case DATA_MARNAK: return uiMarnak; + case DATA_ABEDNEUM: return uiAbedneum; + case DATA_GO_TRIBUNAL_CONSOLE: return uiTribunalConsole; + case DATA_GO_KADDRAK: return uiKaddrakGo; + case DATA_GO_ABEDNEUM: return uiAbedneumGo; + case DATA_GO_MARNAK: return uiMarnakGo; + case DATA_GO_SKY_FLOOR: return uiTribunalSkyFloor; + case DATA_SJONNIR_DOOR: return uiSjonnirDoor; + case DATA_MAIDEN_DOOR: return uiMaidenOfGriefDoor; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "H S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'H' && dataHead2 == 'S') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_halls_of_stone(Map* pMap) +{ + return new instance_halls_of_stone(pMap); +} + +void AddSC_instance_halls_of_stone() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_halls_of_stone"; + newscript->GetInstanceData = &GetInstanceData_instance_halls_of_stone; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp deleted file mode 100644 index c2da2a24e71..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_bjarngrim.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss General Bjarngrim -SD%Complete: 70% -SDComment: Waypoint needed, we expect boss to always have 2x Stormforged Lieutenant following -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - //Yell - SAY_AGGRO = -1602000, - SAY_SLAY_1 = -1602001, - SAY_SLAY_2 = -1602002, - SAY_SLAY_3 = -1602003, - SAY_DEATH = -1602004, - SAY_BATTLE_STANCE = -1602005, - EMOTE_BATTLE_STANCE = -1602006, - SAY_BERSEKER_STANCE = -1602007, - EMOTE_BERSEKER_STANCE = -1602008, - SAY_DEFENSIVE_STANCE = -1602009, - EMOTE_DEFENSIVE_STANCE = -1602010, - - SPELL_DEFENSIVE_STANCE = 53790, - //SPELL_DEFENSIVE_AURA = 41105, - SPELL_SPELL_REFLECTION = 36096, - SPELL_PUMMEL = 12555, - SPELL_KNOCK_AWAY = 52029, - SPELL_IRONFORM = 52022, - - SPELL_BERSEKER_STANCE = 53791, - //SPELL_BERSEKER_AURA = 41107, - SPELL_INTERCEPT = 58769, - SPELL_WHIRLWIND = 52027, - SPELL_CLEAVE = 15284, - - SPELL_BATTLE_STANCE = 53792, - //SPELL_BATTLE_AURA = 41106, - SPELL_MORTAL_STRIKE = 16856, - SPELL_SLAM = 52026, - - //OTHER SPELLS - //SPELL_CHARGE_UP = 52098, // only used when starting walk from one platform to the other - //SPELL_TEMPORARY_ELECTRICAL_CHARGE = 52092, // triggered part of above - - NPC_STORMFORGED_LIEUTENANT = 29240, - SPELL_ARC_WELD = 59085, - SPELL_RENEW_STEEL_N = 52774, - SPELL_RENEW_STEEL_H = 59160, - - EQUIP_SWORD = 37871, - EQUIP_SHIELD = 35642, - EQUIP_MACE = 43623, - - STANCE_DEFENSIVE = 0, - STANCE_BERSERKER = 1, - STANCE_BATTLE = 2 -}; - -/*###### -## boss_bjarngrim -######*/ - -struct boss_bjarngrimAI : public ScriptedAI -{ - boss_bjarngrimAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - m_uiStance = STANCE_DEFENSIVE; - memset(&m_auiStormforgedLieutenantGUID, 0, sizeof(m_auiStormforgedLieutenantGUID)); - } - - ScriptedInstance* m_pInstance; - - bool m_bIsChangingStance; - - uint8 m_uiChargingStatus; - uint8 m_uiStance; - - uint32 m_uiCharge_Timer; - uint32 m_uiChangeStance_Timer; - - uint32 m_uiReflection_Timer; - uint32 m_uiKnockAway_Timer; - uint32 m_uiPummel_Timer; - uint32 m_uiIronform_Timer; - - uint32 m_uiIntercept_Timer; - uint32 m_uiWhirlwind_Timer; - uint32 m_uiCleave_Timer; - - uint32 m_uiMortalStrike_Timer; - uint32 m_uiSlam_Timer; - - uint64 m_auiStormforgedLieutenantGUID[2]; - - void Reset() - { - m_bIsChangingStance = false; - - m_uiChargingStatus = 0; - m_uiCharge_Timer = 1000; - - m_uiChangeStance_Timer = 20000 + rand()%5000; - - m_uiReflection_Timer = 8000; - m_uiKnockAway_Timer = 20000; - m_uiPummel_Timer = 10000; - m_uiIronform_Timer = 25000; - - m_uiIntercept_Timer = 5000; - m_uiWhirlwind_Timer = 10000; - m_uiCleave_Timer = 8000; - - m_uiMortalStrike_Timer = 8000; - m_uiSlam_Timer = 10000; - - for (uint8 i = 0; i < 2; ++i) - { - if (Creature* pStormforgedLieutenant = (Unit::GetCreature((*me), m_auiStormforgedLieutenantGUID[i]))) - { - if (!pStormforgedLieutenant->isAlive()) - pStormforgedLieutenant->Respawn(); - } - } - - if (m_uiStance != STANCE_DEFENSIVE) - { - DoRemoveStanceAura(m_uiStance); - DoCast(me, SPELL_DEFENSIVE_STANCE); - m_uiStance = STANCE_DEFENSIVE; - } - - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - //must get both lieutenants here and make sure they are with him - me->CallForHelp(30.0f); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, IN_PROGRESS); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_BJARNGRIM, DONE); - } - - //TODO: remove when removal is done by the core - void DoRemoveStanceAura(uint8 uiStance) - { - switch(uiStance) - { - case STANCE_DEFENSIVE: - me->RemoveAurasDueToSpell(SPELL_DEFENSIVE_STANCE); - break; - case STANCE_BERSERKER: - me->RemoveAurasDueToSpell(SPELL_BERSEKER_STANCE); - break; - case STANCE_BATTLE: - me->RemoveAurasDueToSpell(SPELL_BATTLE_STANCE); - break; - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // Change stance - if (m_uiChangeStance_Timer <= uiDiff) - { - //wait for current spell to finish before change stance - if (me->IsNonMeleeSpellCasted(false)) - return; - - DoRemoveStanceAura(m_uiStance); - - int uiTempStance = rand()%(3-1); - - if (uiTempStance >= m_uiStance) - ++uiTempStance; - - m_uiStance = uiTempStance; - - switch(m_uiStance) - { - case STANCE_DEFENSIVE: - DoScriptText(SAY_DEFENSIVE_STANCE, me); - DoScriptText(EMOTE_DEFENSIVE_STANCE, me); - DoCast(me, SPELL_DEFENSIVE_STANCE); - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SHIELD, EQUIP_NO_CHANGE); - break; - case STANCE_BERSERKER: - DoScriptText(SAY_BERSEKER_STANCE, me); - DoScriptText(EMOTE_BERSEKER_STANCE, me); - DoCast(me, SPELL_BERSEKER_STANCE); - SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_SWORD, EQUIP_NO_CHANGE); - break; - case STANCE_BATTLE: - DoScriptText(SAY_BATTLE_STANCE, me); - DoScriptText(EMOTE_BATTLE_STANCE, me); - DoCast(me, SPELL_BATTLE_STANCE); - SetEquipmentSlots(false, EQUIP_MACE, EQUIP_UNEQUIP, EQUIP_NO_CHANGE); - break; - } - - m_uiChangeStance_Timer = 20000 + rand()%5000; - return; - } - else - m_uiChangeStance_Timer -= uiDiff; - - switch(m_uiStance) - { - case STANCE_DEFENSIVE: - { - if (m_uiReflection_Timer <= uiDiff) - { - DoCast(me, SPELL_SPELL_REFLECTION); - m_uiReflection_Timer = 8000 + rand()%1000; - } - else - m_uiReflection_Timer -= uiDiff; - - if (m_uiKnockAway_Timer <= uiDiff) - { - DoCast(me, SPELL_KNOCK_AWAY); - m_uiKnockAway_Timer = 20000 + rand()%1000; - } - else - m_uiKnockAway_Timer -= uiDiff; - - if (m_uiPummel_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_PUMMEL); - m_uiPummel_Timer = 10000 + rand()%1000; - } - else - m_uiPummel_Timer -= uiDiff; - - if (m_uiIronform_Timer <= uiDiff) - { - DoCast(me, SPELL_IRONFORM); - m_uiIronform_Timer = 25000 + rand()%1000; - } - else - m_uiIronform_Timer -= uiDiff; - - break; - } - case STANCE_BERSERKER: - { - if (m_uiIntercept_Timer <= uiDiff) - { - //not much point is this, better random target and more often? - DoCast(me->getVictim(), SPELL_INTERCEPT); - m_uiIntercept_Timer = 45000 + rand()%1000; - } - else - m_uiIntercept_Timer -= uiDiff; - - if (m_uiWhirlwind_Timer <= uiDiff) - { - DoCast(me, SPELL_WHIRLWIND); - m_uiWhirlwind_Timer = 10000 + rand()%1000; - } - else - m_uiWhirlwind_Timer -= uiDiff; - - if (m_uiCleave_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - m_uiCleave_Timer = 8000 + rand()%1000; - } - else - m_uiCleave_Timer -= uiDiff; - - break; - } - case STANCE_BATTLE: - { - if (m_uiMortalStrike_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - m_uiMortalStrike_Timer = 20000 + rand()%1000; - } - else - m_uiMortalStrike_Timer -= uiDiff; - - if (m_uiSlam_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_SLAM); - m_uiSlam_Timer = 15000 + rand()%1000; - } - else - m_uiSlam_Timer -= uiDiff; - - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -/*###### -## mob_stormforged_lieutenant -######*/ - -struct mob_stormforged_lieutenantAI : public ScriptedAI -{ - mob_stormforged_lieutenantAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 m_uiArcWeld_Timer; - uint32 m_uiRenewSteel_Timer; - - void Reset() - { - m_uiArcWeld_Timer = 20000 + rand()%1000; - m_uiRenewSteel_Timer = 10000 + rand()%1000; - } - - void EnterCombat(Unit* pWho) - { - if (m_pInstance) - { - if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) - { - if (pBjarngrim->isAlive() && !pBjarngrim->getVictim()) - pBjarngrim->AI()->AttackStart(pWho); - } - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_uiArcWeld_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_ARC_WELD); - m_uiArcWeld_Timer = 20000 + rand()%1000; - } - else - m_uiArcWeld_Timer -= uiDiff; - - if (m_uiRenewSteel_Timer <= uiDiff) - { - if (m_pInstance) - { - if (Creature* pBjarngrim = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_BJARNGRIM))) - { - if (pBjarngrim->isAlive()) - DoCast(pBjarngrim, SPELL_RENEW_STEEL_N); - } - } - m_uiRenewSteel_Timer = 10000 + rand()%4000; - } - else - m_uiRenewSteel_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_bjarngrim(Creature* pCreature) -{ - return new boss_bjarngrimAI(pCreature); -} - -CreatureAI* GetAI_mob_stormforged_lieutenant(Creature* pCreature) -{ - return new mob_stormforged_lieutenantAI(pCreature); -} - -void AddSC_boss_bjarngrim() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_bjarngrim"; - newscript->GetAI = &GetAI_boss_bjarngrim; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stormforged_lieutenant"; - newscript->GetAI = &GetAI_mob_stormforged_lieutenant; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp deleted file mode 100644 index ecf61188b3e..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_ionar.cpp +++ /dev/null @@ -1,388 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* - * Comment: Timer check pending - */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum Spells -{ - SPELL_BALL_LIGHTNING = 52780, - H_SPELL_BALL_LIGHTNING = 59800, - SPELL_STATIC_OVERLOAD = 52658, - H_SPELL_STATIC_OVERLOAD = 59795, - - SPELL_DISPERSE = 52770, - SPELL_SUMMON_SPARK = 52746, - SPELL_SPARK_DESPAWN = 52776, - - //Spark of Ionar - SPELL_SPARK_VISUAL_TRIGGER = 52667, - H_SPELL_SPARK_VISUAL_TRIGGER = 59833 -}; - -enum Yells -{ - SAY_AGGRO = -1602011, - SAY_SLAY_1 = -1602012, - SAY_SLAY_2 = -1602013, - SAY_SLAY_3 = -1602014, - SAY_DEATH = -1602015, - SAY_SPLIT_1 = -1602016, - SAY_SPLIT_2 = -1602017 -}; - -enum Creatures -{ - NPC_SPARK_OF_IONAR = 28926 -}; - -enum Misc -{ - DATA_MAX_SPARKS = 5, - DATA_MAX_SPARK_DISTANCE = 90, // Distance to boss - prevent runs through the whole instance - DATA_POINT_CALLBACK = 0 -}; - -/*###### -## Boss Ionar -######*/ - -struct boss_ionarAI : public ScriptedAI -{ - boss_ionarAI(Creature *pCreature) : ScriptedAI(pCreature), lSparkList(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - SummonList lSparkList; - - bool bIsSplitPhase; - bool bHasDispersed; - - uint32 uiSplitTimer; - - uint32 uiStaticOverloadTimer; - uint32 uiBallLightningTimer; - - uint32 uiDisperseHealth; - - void Reset() - { - lSparkList.DespawnAll(); - - bIsSplitPhase = true; - bHasDispersed = false; - - uiSplitTimer = 25*IN_MILISECONDS; - - uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); - uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); - - uiDisperseHealth = 45 + urand(0,10); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - if (me->GetVisibility() == VISIBILITY_OFF) - me->SetVisibility(VISIBILITY_ON); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - lSparkList.DespawnAll(); - - if (pInstance) - pInstance->SetData(TYPE_IONAR, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - //make sparks come back - void CallBackSparks() - { - //should never be empty here, but check - if (lSparkList.empty()) - return; - - Position pos; - me->GetPosition(&pos); - - for (std::list::const_iterator itr = lSparkList.begin(); itr != lSparkList.end(); ++itr) - { - if (Creature* pSpark = Unit::GetCreature(*me, *itr)) - { - if (pSpark->isAlive()) - { - pSpark->SetSpeed(MOVE_RUN, 2.0f); - pSpark->GetMotionMaster()->Clear(); - pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); - } - else - pSpark->ForcedDespawn(); - } - } - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - if (me->GetVisibility() == VISIBILITY_OFF) - uiDamage = 0; - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) - { - lSparkList.Summon(pSummoned); - - pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_SPARK_VISUAL_TRIGGER,H_SPELL_SPARK_VISUAL_TRIGGER), true); - - Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - pSummoned->SetInCombatWith(pTarget); - pSummoned->GetMotionMaster()->Clear(); - pSummoned->GetMotionMaster()->MoveFollow(pTarget, 0.0f, 0.0f); - } - } - } - - void SummonedCreatureDespawn(Creature *pSummoned) - { - if (pSummoned->GetEntry() == NPC_SPARK_OF_IONAR) - lSparkList.Despawn(pSummoned); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - // Splitted - if (me->GetVisibility() == VISIBILITY_OFF) - { - if (uiSplitTimer <= uiDiff) - { - uiSplitTimer = 2.5*IN_MILISECONDS; - - // Return sparks to where Ionar splitted - if (bIsSplitPhase) - { - CallBackSparks(); - bIsSplitPhase = false; - } - // Lightning effect and restore Ionar - else if (lSparkList.empty()) - { - me->SetVisibility(VISIBILITY_ON); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - DoCast(me, SPELL_SPARK_DESPAWN, false); - - uiSplitTimer = 25*IN_MILISECONDS; - bIsSplitPhase = true; - - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - } - else - uiSplitTimer -= uiDiff; - - return; - } - - if (uiStaticOverloadTimer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_STATIC_OVERLOAD); - - uiStaticOverloadTimer = urand(5*IN_MILISECONDS, 6*IN_MILISECONDS); - } - else - uiStaticOverloadTimer -= uiDiff; - - if (uiBallLightningTimer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_BALL_LIGHTNING); - uiBallLightningTimer = urand(10*IN_MILISECONDS, 11*IN_MILISECONDS); - } - else - uiBallLightningTimer -= uiDiff; - - // Health check - if (!bHasDispersed && HealthBelowPct(uiDisperseHealth)) - { - bHasDispersed = true; - - DoScriptText(RAND(SAY_SPLIT_1,SAY_SPLIT_2), me); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me, SPELL_DISPERSE, true); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ionar(Creature* pCreature) -{ - return new boss_ionarAI(pCreature); -} - -bool EffectDummyCreature_boss_ionar(Unit* /*pCaster*/, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_DISPERSE && uiEffIndex == 0) - { - if (pCreatureTarget->GetEntry() != NPC_IONAR) - return true; - - for (uint8 i = 0; i < DATA_MAX_SPARKS; ++i) - pCreatureTarget->CastSpell(pCreatureTarget, SPELL_SUMMON_SPARK, true); - - pCreatureTarget->AttackStop(); - pCreatureTarget->SetVisibility(VISIBILITY_OFF); - pCreatureTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_DISABLE_MOVE); - - pCreatureTarget->GetMotionMaster()->Clear(); - pCreatureTarget->GetMotionMaster()->MoveIdle(); - - //always return true when we are handling this spell and effect - return true; - } - return false; -} - -/*###### -## mob_spark_of_ionar -######*/ - -struct mob_spark_of_ionarAI : public ScriptedAI -{ - mob_spark_of_ionarAI(Creature *pCreature) : ScriptedAI(pCreature) - { - pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 uiCheckTimer; - - void Reset() - { - uiCheckTimer = 2*IN_MILISECONDS; - me->SetReactState(REACT_PASSIVE); - } - - void MovementInform(uint32 uiType, uint32 uiPointId) - { - if (uiType != POINT_MOTION_TYPE || !pInstance) - return; - - if (uiPointId == DATA_POINT_CALLBACK) - me->ForcedDespawn(); - } - - void DamageTaken(Unit * /*pDoneBy*/, uint32 &uiDamage) - { - uiDamage = 0; - } - - void UpdateAI(const uint32 uiDiff) - { - // Despawn if the encounter is not running - if (pInstance && pInstance->GetData(TYPE_IONAR) != IN_PROGRESS) - { - me->ForcedDespawn(); - return; - } - - // Prevent them to follow players through the whole instance - if (uiCheckTimer <= uiDiff) - { - if (pInstance) - { - Creature* pIonar = pInstance->instance->GetCreature(pInstance->GetData64(DATA_IONAR)); - if (pIonar && pIonar->isAlive()) - { - if (me->GetDistance(pIonar) > DATA_MAX_SPARK_DISTANCE) - { - Position pos; - pIonar->GetPosition(&pos); - - me->SetSpeed(MOVE_RUN, 2.0f); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos); - } - } - else - me->ForcedDespawn(); - } - uiCheckTimer = 2*IN_MILISECONDS; - } - else - uiCheckTimer -= uiDiff; - - // No melee attack at all! - } -}; - -CreatureAI* GetAI_mob_spark_of_ionar(Creature* pCreature) -{ - return new mob_spark_of_ionarAI(pCreature); -} - -void AddSC_boss_ionar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ionar"; - newscript->GetAI = &GetAI_boss_ionar; - newscript->pEffectDummyCreature = &EffectDummyCreature_boss_ionar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_spark_of_ionar"; - newscript->GetAI = &GetAI_mob_spark_of_ionar; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp deleted file mode 100644 index f08c19efca2..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_loken.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Loken -SD%Complete: 60% -SDComment: Missing intro. Remove hack of Pulsing Shockwave when core supports. Aura is not working (59414) -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - ACHIEV_TIMELY_DEATH_START_EVENT = 20384, - - SAY_AGGRO = -1602018, - SAY_INTRO_1 = -1602019, - SAY_INTRO_2 = -1602020, - SAY_SLAY_1 = -1602021, - SAY_SLAY_2 = -1602022, - SAY_SLAY_3 = -1602023, - SAY_DEATH = -1602024, - SAY_NOVA_1 = -1602025, - SAY_NOVA_2 = -1602026, - SAY_NOVA_3 = -1602027, - SAY_75HEALTH = -1602028, - SAY_50HEALTH = -1602029, - SAY_25HEALTH = -1602030, - EMOTE_NOVA = -1602031, - - SPELL_ARC_LIGHTNING = 52921, - SPELL_LIGHTNING_NOVA_N = 52960, - SPELL_LIGHTNING_NOVA_H = 59835, - - SPELL_PULSING_SHOCKWAVE_N = 52961, - SPELL_PULSING_SHOCKWAVE_H = 59836, - SPELL_PULSING_SHOCKWAVE_AURA = 59414 -}; - -/*###### -## Boss Loken -######*/ - -struct boss_lokenAI : public ScriptedAI -{ - boss_lokenAI(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - bool m_bIsAura; - - uint32 m_uiArcLightning_Timer; - uint32 m_uiLightningNova_Timer; - uint32 m_uiPulsingShockwave_Timer; - uint32 m_uiResumePulsingShockwave_Timer; - - uint32 m_uiHealthAmountModifier; - - void Reset() - { - m_bIsAura = false; - - m_uiArcLightning_Timer = 15000; - m_uiLightningNova_Timer = 20000; - m_uiPulsingShockwave_Timer = 2000; - m_uiResumePulsingShockwave_Timer = 15000; - - m_uiHealthAmountModifier = 1; - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_LOKEN, NOT_STARTED); - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); - } - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - if (m_pInstance) - { - m_pInstance->SetData(TYPE_LOKEN, IN_PROGRESS); - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMELY_DEATH_START_EVENT); - } - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_LOKEN, DONE); - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_bIsAura) - { - // workaround for PULSING_SHOCKWAVE - if (m_uiPulsingShockwave_Timer <= uiDiff) - { - Map* pMap = me->GetMap(); - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - - if (PlayerList.isEmpty()) - return; - - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (i->getSource() && i->getSource()->isAlive() && i->getSource()->isTargetableForAttack()) - { - int32 dmg; - float m_fDist = me->GetExactDist(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()); - - dmg = DUNGEON_MODE(100, 150); // need to correct damage - if (m_fDist > 1.0f) // Further from 1 yard - dmg *= m_fDist; - - me->CastCustomSpell(i->getSource(), DUNGEON_MODE(52942, 59837), &dmg, 0, 0, false); - } - } - m_uiPulsingShockwave_Timer = 2000; - } else m_uiPulsingShockwave_Timer -= uiDiff; - } - else - { - if (m_uiResumePulsingShockwave_Timer <= uiDiff) - { - //breaks at movement, can we assume when it's time, this spell is casted and also must stop movement? - DoCast(me, SPELL_PULSING_SHOCKWAVE_AURA, true); - - DoCast(me, SPELL_PULSING_SHOCKWAVE_N); // need core support - m_bIsAura = true; - m_uiResumePulsingShockwave_Timer = 0; - } - else - m_uiResumePulsingShockwave_Timer -= uiDiff; - } - - if (m_uiArcLightning_Timer <= uiDiff) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_ARC_LIGHTNING); - - m_uiArcLightning_Timer = 15000 + rand()%1000; - } - else - m_uiArcLightning_Timer -= uiDiff; - - if (m_uiLightningNova_Timer <= uiDiff) - { - DoScriptText(RAND(SAY_NOVA_1,SAY_NOVA_2,SAY_NOVA_3), me); - DoScriptText(EMOTE_NOVA, me); - DoCast(me, SPELL_LIGHTNING_NOVA_N); - - m_bIsAura = false; - m_uiResumePulsingShockwave_Timer = DUNGEON_MODE(5000, 4000); // Pause Pulsing Shockwave aura - m_uiLightningNova_Timer = 20000 + rand()%1000; - } - else - m_uiLightningNova_Timer -= uiDiff; - - // Health check - if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(25*m_uiHealthAmountModifier))) - { - switch(m_uiHealthAmountModifier) - { - case 1: DoScriptText(SAY_75HEALTH, me); break; - case 2: DoScriptText(SAY_50HEALTH, me); break; - case 3: DoScriptText(SAY_25HEALTH, me); break; - } - - ++m_uiHealthAmountModifier; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_loken(Creature* pCreature) -{ - return new boss_lokenAI(pCreature); -} - -void AddSC_boss_loken() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_loken"; - newscript->GetAI = &GetAI_boss_loken; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp deleted file mode 100644 index 184050e3103..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/boss_volkhan.cpp +++ /dev/null @@ -1,478 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss Volkhan -SD%Complete: 60% -SDComment: Not considered complete. Some events may fail and need further development -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -enum eEnums -{ - SAY_AGGRO = -1602032, - SAY_SLAY_1 = -1602033, - SAY_SLAY_2 = -1602034, - SAY_SLAY_3 = -1602035, - SAY_DEATH = -1602036, - SAY_STOMP_1 = -1602037, - SAY_STOMP_2 = -1602038, - SAY_FORGE_1 = -1602039, - SAY_FORGE_2 = -1602040, - EMOTE_TO_ANVIL = -1602041, - EMOTE_SHATTER = -1602042, - - SPELL_HEAT_N = 52387, - SPELL_HEAT_H = 59528, - SPELL_SHATTERING_STOMP_N = 52237, - SPELL_SHATTERING_STOMP_H = 59529, - - //unclear how "directions" of spells must be. Last, summoning GO, what is it for? Script depend on: - SPELL_TEMPER = 52238, //TARGET_SCRIPT boss->anvil - SPELL_TEMPER_DUMMY = 52654, //TARGET_SCRIPT anvil->boss - - //SPELL_TEMPER_VISUAL = 52661, //summons GO - - SPELL_SUMMON_MOLTEN_GOLEM = 52405, - - //Molten Golem - SPELL_BLAST_WAVE = 23113, - SPELL_IMMOLATION_STRIKE_N = 52433, - SPELL_IMMOLATION_STRIKE_H = 59530, - SPELL_SHATTER_N = 52429, - SPELL_SHATTER_H = 59527, - - NPC_VOLKHAN_ANVIL = 28823, - NPC_MOLTEN_GOLEM = 28695, - NPC_BRITTLE_GOLEM = 28681, - - POINT_ID_ANVIL = 0, - MAX_GOLEM = 2, - - ACHIEVEMENT_SHATTER_RESISTANT = 2042 -}; - -/*###### -## Boss Volkhan -######*/ - -struct boss_volkhanAI : public ScriptedAI -{ - boss_volkhanAI(Creature *pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - std::list m_lGolemGUIDList; - - bool m_bHasTemper; - bool m_bIsStriking; - bool m_bCanShatterGolem; - - uint8 GolemsShattered; - uint32 m_uiPause_Timer; - uint32 m_uiShatteringStomp_Timer; - uint32 m_uiShatter_Timer; - - uint32 m_uiHealthAmountModifier; - - void Reset() - { - m_bIsStriking = false; - m_bHasTemper = false; - m_bCanShatterGolem = false; - - m_uiPause_Timer = 3500; - m_uiShatteringStomp_Timer = 0; - m_uiShatter_Timer = 5000; - GolemsShattered = 0; - - m_uiHealthAmountModifier = 1; - - DespawnGolem(); - m_lGolemGUIDList.clear(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, NOT_STARTED); - } - - void EnterCombat(Unit* /*pWho*/) - { - DoScriptText(SAY_AGGRO, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, IN_PROGRESS); - } - - void AttackStart(Unit* pWho) - { - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - if (!m_bHasTemper) - me->GetMotionMaster()->MoveChase(pWho); - } - } - - void JustDied(Unit* /*pKiller*/) - { - DoScriptText(SAY_DEATH, me); - DespawnGolem(); - - if (m_pInstance) - m_pInstance->SetData(TYPE_VOLKHAN, DONE); - - if (IsHeroic() && GolemsShattered < 5) - { - AchievementEntry const *AchievShatterResistant = GetAchievementStore()->LookupEntry(ACHIEVEMENT_SHATTER_RESISTANT); - if (AchievShatterResistant) - { - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievShatterResistant); - } - } - } - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void DespawnGolem() - { - if (m_lGolemGUIDList.empty()) - return; - - for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - if (pTemp->isAlive()) - pTemp->ForcedDespawn(); - } - } - - m_lGolemGUIDList.clear(); - } - - void ShatterGolem() - { - if (m_lGolemGUIDList.empty()) - return; - - for (std::list::const_iterator itr = m_lGolemGUIDList.begin(); itr != m_lGolemGUIDList.end(); ++itr) - { - if (Creature* pTemp = Unit::GetCreature(*me, *itr)) - { - // only shatter brittle golems - if (pTemp->isAlive() && pTemp->GetEntry() == NPC_BRITTLE_GOLEM) - { - pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SHATTER_N, SPELL_SHATTER_H), false); - GolemsShattered += 1; - } - } - } - } - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - if (pSpell->Id == SPELL_TEMPER_DUMMY) - m_bIsStriking = true; - } - - void JustSummoned(Creature* pSummoned) - { - if (pSummoned->GetEntry() == NPC_MOLTEN_GOLEM) - { - m_lGolemGUIDList.push_back(pSummoned->GetGUID()); - - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - - //why healing when just summoned? - pSummoned->CastSpell(pSummoned, DUNGEON_MODE(SPELL_HEAT_N, SPELL_HEAT_H), false, NULL, NULL, me->GetGUID()); - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_bIsStriking) - { - if (m_uiPause_Timer <= uiDiff) - { - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() != TARGETED_MOTION_TYPE) - { - if (me->getVictim()) - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - - m_bHasTemper = false; - m_bIsStriking = false; - m_uiPause_Timer = 3500; - } - else - m_uiPause_Timer -= uiDiff; - - return; - } - - // When to start shatter? After 60, 40 or 20% hp? - if (!m_bHasTemper && m_uiHealthAmountModifier >= 3) - { - if (m_uiShatteringStomp_Timer <= uiDiff) - { - //should he stomp even if he has no brittle golem to shatter? - - DoScriptText(RAND(SAY_STOMP_1,SAY_STOMP_2), me); - - DoCast(me, SPELL_SHATTERING_STOMP_N); - - DoScriptText(EMOTE_SHATTER, me); - - m_uiShatteringStomp_Timer = 30000; - m_bCanShatterGolem = true; - } - else - m_uiShatteringStomp_Timer -= uiDiff; - } - - // Shatter Golems 3 seconds after Shattering Stomp - if (m_bCanShatterGolem) - { - if (m_uiShatter_Timer <= uiDiff) - { - ShatterGolem(); - m_uiShatter_Timer = 3000; - m_bCanShatterGolem = false; - } - else - m_uiShatter_Timer -= uiDiff; - } - - // Health check - if (!m_bCanShatterGolem && (me->GetHealth()*100 / me->GetMaxHealth()) < (100-(20*m_uiHealthAmountModifier))) - { - ++m_uiHealthAmountModifier; - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoScriptText(RAND(SAY_FORGE_1,SAY_FORGE_2), me); - - m_bHasTemper = true; - - DoCast(me, SPELL_TEMPER, false); - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_volkhan(Creature* pCreature) -{ - return new boss_volkhanAI(pCreature); -} - -bool EffectDummyCreature_boss_volkhan(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_TEMPER_DUMMY && uiEffIndex == 0) - { - if (pCaster->GetEntry() != NPC_VOLKHAN_ANVIL || pCreatureTarget->GetEntry() != NPC_VOLKHAN) - return true; - - for (uint8 i = 0; i < MAX_GOLEM; ++i) - { - pCreatureTarget->CastSpell(pCaster, SPELL_SUMMON_MOLTEN_GOLEM, true); - } - - //always return true when we are handling this spell and effect - return true; - } - - return false; -} - -/*###### -## npc_volkhan_anvil -######*/ - -bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, uint32 uiEffIndex, Creature* pCreatureTarget) -{ - //always check spellid and effectindex - if (uiSpellId == SPELL_TEMPER && uiEffIndex == 0) - { - if (pCaster->GetEntry() != NPC_VOLKHAN || pCreatureTarget->GetEntry() != NPC_VOLKHAN_ANVIL) - return true; - - Creature *cre = CAST_CRE(pCaster); - - DoScriptText(EMOTE_TO_ANVIL, pCaster); - - float fX, fY, fZ; - pCreatureTarget->GetContactPoint(pCaster, fX, fY, fZ, INTERACTION_DISTANCE); - - pCaster->AttackStop(); - - if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - pCaster->GetMotionMaster()->MovementExpired(); - - cre->GetMap()->CreatureRelocation(cre, fX, fY, fZ, pCreatureTarget->GetOrientation()); - cre->SendMonsterMove(fX, fY, fZ, 0, cre->GetUnitMovementFlags(), 1); - - pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); - - //always return true when we are handling this spell and effect - return true; - } - - return false; -} - -/*###### -## mob_molten_golem -######*/ - -struct mob_molten_golemAI : public ScriptedAI -{ - mob_molten_golemAI(Creature *pCreature) : ScriptedAI(pCreature) - { - } - - bool m_bIsFrozen; - - uint32 m_uiBlast_Timer; - uint32 m_uiDeathDelay_Timer; - uint32 m_uiImmolation_Timer; - - void Reset() - { - m_bIsFrozen = false; - - m_uiBlast_Timer = 20000; - m_uiDeathDelay_Timer = 0; - m_uiImmolation_Timer = 5000; - } - - void AttackStart(Unit* pWho) - { - if (me->Attack(pWho, true)) - { - me->AddThreat(pWho, 0.0f); - me->SetInCombatWith(pWho); - pWho->SetInCombatWith(me); - - if (!m_bIsFrozen) - me->GetMotionMaster()->MoveChase(pWho); - } - } - - void DamageTaken(Unit* /*pDoneBy*/, uint32 &uiDamage) - { - if (uiDamage > me->GetHealth()) - { - me->UpdateEntry(NPC_BRITTLE_GOLEM); - me->SetHealth(1); - uiDamage = 0; - me->RemoveAllAuras(); - me->AttackStop(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - m_bIsFrozen = true; - } - } - - void SpellHit(Unit* /*pCaster*/, const SpellEntry* pSpell) - { - //this is the dummy effect of the spells - if (pSpell->Id == SPELL_SHATTER_N || pSpell->Id == SPELL_SHATTER_H) - { - if (me->GetEntry() == NPC_BRITTLE_GOLEM) - me->ForcedDespawn(); - } - } - - void UpdateAI(const uint32 uiDiff) - { - //Return since we have no target or if we are frozen - if (!UpdateVictim() || m_bIsFrozen) - return; - - if (m_uiBlast_Timer <= uiDiff) - { - DoCast(me, SPELL_BLAST_WAVE); - m_uiBlast_Timer = 20000; - } - else - m_uiBlast_Timer -= uiDiff; - - if (m_uiImmolation_Timer <= uiDiff) - { - DoCast(me->getVictim(), SPELL_IMMOLATION_STRIKE_N); - m_uiImmolation_Timer = 5000; - } - else - m_uiImmolation_Timer -= uiDiff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_molten_golem(Creature* pCreature) -{ - return new mob_molten_golemAI(pCreature); -} - -void AddSC_boss_volkhan() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_volkhan"; - newscript->GetAI = &GetAI_boss_volkhan; - newscript->pEffectDummyCreature = &EffectDummyCreature_boss_volkhan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "npc_volkhan_anvil"; - newscript->pEffectDummyCreature = &EffectDummyCreature_npc_volkhan_anvil; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_molten_golem"; - newscript->GetAI = &GetAI_mob_molten_golem; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h deleted file mode 100644 index d9739fdf888..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/halls_of_lightning.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_HALLS_OF_LIGHTNING_H -#define DEF_HALLS_OF_LIGHTNING_H - -enum eTypes -{ - MAX_ENCOUNTER = 4, - - DATA_BJARNGRIM = 1, - DATA_IONAR = 2, - DATA_LOKEN = 3, - DATA_VOLKHAN = 4, - - TYPE_BJARNGRIM = 10, - TYPE_IONAR = 11, - TYPE_LOKEN = 12, - TYPE_VOLKHAN = 13, - - NPC_BJARNGRIM = 28586, - NPC_VOLKHAN = 28587, - NPC_IONAR = 28546, - NPC_LOKEN = 28923, - - GO_BJARNGRIM_DOOR = 191416, //_doors10 - GO_VOLKHAN_DOOR = 191325, //_doors07 - GO_IONAR_DOOR = 191326, //_doors05 - GO_LOKEN_DOOR = 191324, //_doors02 - GO_LOKEN_THRONE = 192654 -}; - -#endif diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp deleted file mode 100644 index 46cd5c9cccc..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_lightning/instance_halls_of_lightning.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Halls_of_Lightning -SD%Complete: 90% -SDComment: All ready. -SDCategory: Halls of Lightning -EndScriptData */ - -#include "ScriptedPch.h" -#include "halls_of_lightning.h" - -/* Halls of Lightning encounters: -0 - General Bjarngrim -1 - Volkhan -2 - Ionar -3 - Loken -*/ - -struct instance_halls_of_lightning : public ScriptedInstance -{ - instance_halls_of_lightning(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 m_uiGeneralBjarngrimGUID; - uint64 m_uiIonarGUID; - uint64 m_uiLokenGUID; - uint64 m_uiVolkhanGUID; - - uint64 m_uiBjarngrimDoorGUID; - uint64 m_uiVolkhanDoorGUID; - uint64 m_uiIonarDoorGUID; - uint64 m_uiLokenDoorGUID; - uint64 m_uiLokenGlobeGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiGeneralBjarngrimGUID = 0; - m_uiVolkhanGUID = 0; - m_uiIonarGUID = 0; - m_uiLokenGUID = 0; - - m_uiBjarngrimDoorGUID = 0; - m_uiVolkhanDoorGUID = 0; - m_uiIonarDoorGUID = 0; - m_uiLokenDoorGUID = 0; - m_uiLokenGlobeGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case NPC_BJARNGRIM: - m_uiGeneralBjarngrimGUID = pCreature->GetGUID(); - break; - case NPC_VOLKHAN: - m_uiVolkhanGUID = pCreature->GetGUID(); - break; - case NPC_IONAR: - m_uiIonarGUID = pCreature->GetGUID(); - break; - case NPC_LOKEN: - m_uiLokenGUID = pCreature->GetGUID(); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_BJARNGRIM_DOOR: - m_uiBjarngrimDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_VOLKHAN_DOOR: - m_uiVolkhanDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_IONAR_DOOR: - m_uiIonarDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_LOKEN_DOOR: - m_uiLokenDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_LOKEN_THRONE: - m_uiLokenGlobeGUID = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - switch(uiType) - { - case TYPE_BJARNGRIM: - if (uiData == DONE) - DoUseDoorOrButton(m_uiBjarngrimDoorGUID); - m_auiEncounter[0] = uiData; - break; - case TYPE_VOLKHAN: - if (uiData == DONE) - DoUseDoorOrButton(m_uiVolkhanDoorGUID); - m_auiEncounter[1] = uiData; - break; - case TYPE_IONAR: - if (uiData == DONE) - DoUseDoorOrButton(m_uiIonarDoorGUID); - m_auiEncounter[2] = uiData; - break; - case TYPE_LOKEN: - if (uiData == DONE) - { - DoUseDoorOrButton(m_uiLokenDoorGUID); - - //Appears to be type 5 GO with animation. Need to figure out how this work, code below only placeholder - if (GameObject* pGlobe = instance->GetGameObject(m_uiLokenGlobeGUID)) - pGlobe->SetGoState(GO_STATE_ACTIVE); - } - m_auiEncounter[3] = uiData; - break; - } - - if (uiData == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 uiType) - { - switch(uiType) - { - case TYPE_BJARNGRIM: - return m_auiEncounter[0]; - case TYPE_VOLKHAN: - return m_auiEncounter[1]; - case TYPE_IONAR: - return m_auiEncounter[2]; - case TYPE_LOKEN: - return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 uiData) - { - switch(uiData) - { - case DATA_BJARNGRIM: - return m_uiGeneralBjarngrimGUID; - case DATA_VOLKHAN: - return m_uiVolkhanGUID; - case DATA_IONAR: - return m_uiIonarGUID; - case DATA_LOKEN: - return m_uiLokenGUID; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H L " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - OUT_SAVE_INST_DATA_COMPLETE; - return saveStream.str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'H' && dataHead2 == 'L') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_halls_of_lightning(Map* pMap) -{ - return new instance_halls_of_lightning(pMap); -} - -void AddSC_instance_halls_of_lightning() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_lightning"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_lightning; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp deleted file mode 100644 index 0674b7c79eb..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_krystallus.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* Script Data Start -SDName: Boss krystallus -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_krystallus' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_BOULDER_TOSS = 50843, - H_SPELL_BOULDER_TOSS = 59742, - SPELL_GROUND_SPIKE = 59750, - SPELL_GROUND_SLAM = 50827, - SPELL_SHATTER = 50810, - H_SPELL_SHATTER = 61546, - SPELL_STOMP = 48131, - H_SPELL_STOMP = 59744 -}; - -enum Yells -{ - SAY_AGGRO = -1599007, - SAY_KILL = -1599008, - SAY_DEATH = -1599009, - SAY_SHATTER = -1599010 -}; - -struct boss_krystallusAI : public ScriptedAI -{ - boss_krystallusAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiBoulderTossTimer; - uint32 uiGroundSpikeTimer; - uint32 uiGroundSlamTimer; - uint32 uiShatterTimer; - uint32 uiStompTimer; - - bool bIsSlam; - - ScriptedInstance* pInstance; - - void Reset() - { - bIsSlam = false; - - uiBoulderTossTimer = 3000 + rand()%6000; - uiGroundSpikeTimer = 9000 + rand()%5000; - uiGroundSlamTimer = 15000 + rand()%3000; - uiStompTimer = 20000 + rand()%9000; - uiShatterTimer = 0; - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, NOT_STARTED); - } - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiBoulderTossTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_BOULDER_TOSS); - uiBoulderTossTimer = 9000 + rand()%6000; - } else uiBoulderTossTimer -= diff; - - if (uiGroundSpikeTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_GROUND_SPIKE); - uiGroundSpikeTimer = 12000 + rand()%5000; - } else uiGroundSpikeTimer -= diff; - - if (uiStompTimer <= diff) - { - DoCast(me, SPELL_STOMP); - uiStompTimer = 20000 + rand()%9000; - } else uiStompTimer -= diff; - - if (uiGroundSlamTimer <= diff) - { - DoCast(me, SPELL_GROUND_SLAM); - bIsSlam = true; - uiShatterTimer = 10000; - uiGroundSlamTimer = 15000 + rand()%3000; - } else uiGroundSlamTimer -= diff; - - if (bIsSlam) - { - if (uiShatterTimer <= diff) - { - DoCast(me, SPELL_SHATTER); - bIsSlam = false; - } else uiShatterTimer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_KRYSTALLUS_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(SAY_KILL, me); - } -}; - -CreatureAI* GetAI_boss_krystallus(Creature* pCreature) -{ - return new boss_krystallusAI (pCreature); -} - -void AddSC_boss_krystallus() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_krystallus"; - newscript->GetAI = &GetAI_boss_krystallus; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp deleted file mode 100644 index b3c3c675347..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_maiden_of_grief.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* Script Data Start -SDName: Boss maiden_of_grief -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_maiden_of_grief' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_PARTING_SORROW = 59723, - SPELL_STORM_OF_GRIEF_N = 50752, - SPELL_STORM_OF_GRIEF_H = 59772, - SPELL_SHOCK_OF_SORROW_N = 50760, - SPELL_SHOCK_OF_SORROW_H = 59726, - SPELL_PILLAR_OF_WOE_N = 50761, - SPELL_PILLAR_OF_WOE_H = 59727 -}; - -enum Yells -{ - SAY_AGGRO = -1599000, - SAY_SLAY_1 = -1599001, - SAY_SLAY_2 = -1599002, - SAY_SLAY_3 = -1599003, - SAY_SLAY_4 = -1599004, - SAY_DEATH = -1599005, - SAY_STUN = -1599006 -}; - -enum Achievements -{ - ACHIEV_GOOD_GRIEF_START_EVENT = 20383, -}; - -struct boss_maiden_of_griefAI : public ScriptedAI -{ - boss_maiden_of_griefAI(Creature *c) : ScriptedAI(c) - { - pInstance = me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 PartingSorrowTimer; - uint32 StormOfGriefTimer; - uint32 ShockOfSorrowTimer; - uint32 PillarOfWoeTimer; - - void Reset() - { - PartingSorrowTimer = 25000 + rand()%5000; - StormOfGriefTimer = 10000; - ShockOfSorrowTimer = 20000+rand()%5000; - PillarOfWoeTimer = 5000 + rand()%10000; - - if (pInstance) - { - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, NOT_STARTED); - pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_MAIDEN_DOOR))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, IN_PROGRESS); - pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_GOOD_GRIEF_START_EVENT); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (IsHeroic()) - { - if (PartingSorrowTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget) - DoCast(pTarget, SPELL_PARTING_SORROW); - - PartingSorrowTimer = 30000 + rand()%10000; - } else PartingSorrowTimer -= diff; - } - - if (StormOfGriefTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STORM_OF_GRIEF_N, true); - StormOfGriefTimer = 15000 + rand()%5000; - } else StormOfGriefTimer -= diff; - - if (ShockOfSorrowTimer <= diff) - { - DoResetThreat(); - DoScriptText(SAY_STUN, me); - DoCast(me, SPELL_SHOCK_OF_SORROW_N); - ShockOfSorrowTimer = 20000 + rand()%10000; - } else ShockOfSorrowTimer -= diff; - - if (PillarOfWoeTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - - if (pTarget) - DoCast(pTarget, SPELL_PILLAR_OF_WOE_N); - else - DoCast(me->getVictim(), SPELL_PILLAR_OF_WOE_N); - - PillarOfWoeTimer = 5000 + rand()%20000; - } else PillarOfWoeTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MAIDEN_OF_GRIEF_EVENT, DONE); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } -}; - -CreatureAI* GetAI_boss_maiden_of_grief(Creature* pCreature) -{ - return new boss_maiden_of_griefAI (pCreature); -} - -void AddSC_boss_maiden_of_grief() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_maiden_of_grief"; - newscript->GetAI = &GetAI_boss_maiden_of_grief; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp deleted file mode 100644 index 68c3e34e6bf..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_stone/boss_sjonnir.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/* Script Data Start -SDName: Boss sjonnir -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_sjonnir' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -enum Spells -{ - SPELL_LIGHTING_RING = 51849, //Periodic Trigger (interval 2s) spell = 50841 - H_SPELL_LIGHTING_RING = 59861, //Periodic Trigger (interval 2s) spell = 59849 - SPELL_LIGHTING_RING_1 = 50840, //Periodic Trigger (interval 2s) spell = 50841 - H_SPELL_LIGHTING_RING_1 = 59848, //Periodic Trigger (interval 2s) spell = 59849 - SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835 - H_SPELL_STATIC_CHARGE = 59846, //Periodic Trigger 2s interval, spell =50847 - SPELL_CHAIN_LIGHTING = 50830, - H_SPELL_CHAIN_LIGHTING = 59844, - SPELL_LIGHTING_SHIELD = 50831, - H_SPELL_LIGHTING_SHIELD = 59845, - SPELL_FRENZY = 28747 -}; - -enum Yells -{ - SAY_AGGRO = -1599011, - SAY_SLAY_1 = -1599012, - SAY_SLAY_2 = -1599013, - SAY_SLAY_3 = -1599014, - SAY_DEATH = -1599015 -}; - -#define EMOTE_GENERIC_FRENZY -1000002 - -enum SjonnirCreatures -{ - CREATURE_FORGED_IRON_TROGG = 27979, - CREATURE_MALFORMED_OOZE = 27981, - CREATURE_FORGED_IRON_DWARF = 27982, - CREATURE_IRON_SLUDGE = 28165 -}; - -enum Misc -{ - DATA_TIME_BEFORE_OOZE = 150000, //2min 30 secs - ACHIEV_ABUSE_THE_OOZE = 2155 -}; - -struct Locations -{ - float x, y, z; -}; - -static Locations PipeLocations[] = -{ - {1295.44, 734.07, 200.3}, //left - {1297.7, 595.6, 199.9} //right -}; - -static Locations CenterPoint = {1295.21, 667.157, 189.691}; - -struct boss_sjonnirAI : public ScriptedAI -{ - boss_sjonnirAI(Creature *c) : ScriptedAI(c), lSummons(me) - { - pInstance = c->GetInstanceData(); - } - - bool bIsFrenzy; - - uint32 uiChainLightningTimer; - uint32 uiLightningShieldTimer; - uint32 uiStaticChargeTimer; - uint32 uiLightningRingTimer; - uint32 uiSummonTimer; - uint32 uiFrenzyTimer; - uint32 uiEncounterTimer; - uint32 uiKilledIronSludges; - - SummonList lSummons; - - ScriptedInstance* pInstance; - - void Reset() - { - bIsFrenzy = false; - - uiEncounterTimer = 0; - uiChainLightningTimer = 3000 + rand()%5000; - uiLightningShieldTimer = 20000 + rand()%5000; - uiStaticChargeTimer = 20000 + rand()%5000; - uiLightningRingTimer = 30000 + rand()%5000; - uiSummonTimer = 5000; - uiFrenzyTimer = 300000; //5 minutes - uiKilledIronSludges = 0; - - lSummons.DespawnAll(); - - if (pInstance) - pInstance->SetData(DATA_SJONNIR_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - uiEncounterTimer = 0; - - if (pInstance) - { - if (GameObject *pDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_SJONNIR_DOOR))) - if (pDoor->GetGoState() == GO_STATE_READY) - { - EnterEvadeMode(); - return; - } - - pInstance->SetData(DATA_SJONNIR_EVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiChainLightningTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_CHAIN_LIGHTING); - uiChainLightningTimer = 10000 + rand()%5000; - } else uiChainLightningTimer -= diff; - - if (uiLightningShieldTimer <= diff) - { - DoCast(me, SPELL_LIGHTING_SHIELD); - uiLightningShieldTimer -= diff; - } - - if (uiStaticChargeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STATIC_CHARGE); - uiStaticChargeTimer = 20000 + rand()%5000; - } uiStaticChargeTimer -= diff; - - if (uiLightningRingTimer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_LIGHTING_RING); - uiLightningRingTimer = 30000 + rand()%5000; - } else uiLightningRingTimer -= diff; - - if (uiSummonTimer <= diff) - { - uint32 uiSummonPipe = rand()%2; - me->SummonCreature(uiEncounterTimer > DATA_TIME_BEFORE_OOZE ? CREATURE_MALFORMED_OOZE : - RAND(CREATURE_FORGED_IRON_DWARF,CREATURE_FORGED_IRON_TROGG), - PipeLocations[uiSummonPipe].x, PipeLocations[uiSummonPipe].y, PipeLocations[uiSummonPipe].z, 0.0f, - TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - uiSummonTimer = 20000; - } else uiSummonTimer -= diff; - - if (!bIsFrenzy) - { - if (uiFrenzyTimer <= diff) - { - DoCast(me, SPELL_FRENZY); - bIsFrenzy = true; - } - else uiFrenzyTimer -= diff; - } - - uiEncounterTimer +=diff; - - DoMeleeAttackIfReady(); - } - - void JustSummoned(Creature* summon) - { - summon->GetMotionMaster()->MovePoint(0, CenterPoint.x, CenterPoint.y, CenterPoint.z); - /*if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - summon->AI()->AttackStart(pTarget);*/ - lSummons.Summon(summon); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - lSummons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_SJONNIR_EVENT, DONE); - if (IsHeroic() && uiKilledIronSludges > 4) - pInstance->DoCompleteAchievement(ACHIEV_ABUSE_THE_OOZE); - } - } - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void KilledIronSludge() - { - ++uiKilledIronSludges; - } -}; - -CreatureAI* GetAI_boss_sjonnir(Creature* pCreature) -{ - return new boss_sjonnirAI (pCreature); -} - -struct mob_malformed_oozeAI : public ScriptedAI -{ - mob_malformed_oozeAI(Creature *c) : ScriptedAI(c) {} - - uint32 uiMergeTimer; - - void Reset() - { - uiMergeTimer = 10000; - } - - void UpdateAI(const uint32 diff) - { - if (uiMergeTimer <= diff) - { - if (Creature* pTemp = me->FindNearestCreature(CREATURE_MALFORMED_OOZE, 3.0f, true)) - { - DoSpawnCreature(CREATURE_IRON_SLUDGE, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 20000); - pTemp->DisappearAndDie(); - me->DisappearAndDie(); - } - uiMergeTimer = 3000; - } else uiMergeTimer -= diff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_malformed_ooze(Creature* pCreature) -{ - return new mob_malformed_oozeAI(pCreature); -} - -struct mob_iron_sludgeAI : public ScriptedAI -{ - mob_iron_sludgeAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void JustDied(Unit* /*pKiller*/) - { - if (pInstance) - if (Creature* pSjonnir = Unit::GetCreature(*me, pInstance->GetData64(DATA_SJONNIR))) - CAST_AI(boss_sjonnirAI, pSjonnir->AI())->KilledIronSludge(); - } -}; - -CreatureAI* GetAI_mob_iron_sludge(Creature* pCreature) -{ - return new mob_iron_sludgeAI(pCreature); -} - -void AddSC_boss_sjonnir() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_sjonnir"; - newscript->GetAI = &GetAI_boss_sjonnir; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_malformed_ooze"; - newscript->GetAI = &GetAI_mob_malformed_ooze; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_iron_sludge"; - newscript->GetAI = &GetAI_mob_iron_sludge; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp deleted file mode 100644 index 8febdaab879..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.cpp +++ /dev/null @@ -1,724 +0,0 @@ -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "halls_of_stone.h" - -enum Texts -{ - SAY_KILL_1 = -1599016, - SAY_KILL_2 = -1599017, - SAY_KILL_3 = -1599018, - SAY_LOW_HEALTH = -1599019, - SAY_DEATH = -1599020, - SAY_PLAYER_DEATH_1 = -1599021, - SAY_PLAYER_DEATH_2 = -1599022, - SAY_PLAYER_DEATH_3 = -1599023, - SAY_ESCORT_START = -1599024, - - SAY_SPAWN_DWARF = -1599025, - SAY_SPAWN_TROGG = -1599026, - SAY_SPAWN_OOZE = -1599027, - SAY_SPAWN_EARTHEN = -1599028, - - SAY_EVENT_INTRO_1 = -1599029, - SAY_EVENT_INTRO_2 = -1599030, - SAY_EVENT_INTRO_3_ABED = -1599031, - - SAY_EVENT_A_1 = -1599032, - SAY_EVENT_A_2_KADD = -1599033, - SAY_EVENT_A_3 = -1599034, - - SAY_EVENT_B_1 = -1599035, - SAY_EVENT_B_2_MARN = -1599036, - SAY_EVENT_B_3 = -1599037, - - SAY_EVENT_C_1 = -1599038, - SAY_EVENT_C_2_ABED = -1599039, - SAY_EVENT_C_3 = -1599040, - - SAY_EVENT_D_1 = -1599041, - SAY_EVENT_D_2_ABED = -1599042, - SAY_EVENT_D_3 = -1599043, - SAY_EVENT_D_4_ABED = -1599044, - - SAY_EVENT_END_01 = -1599045, - SAY_EVENT_END_02 = -1599046, - SAY_EVENT_END_03_ABED = -1599047, - SAY_EVENT_END_04 = -1599048, - SAY_EVENT_END_05_ABED = -1599049, - SAY_EVENT_END_06 = -1599050, - SAY_EVENT_END_07_ABED = -1599051, - SAY_EVENT_END_08 = -1599052, - SAY_EVENT_END_09_KADD = -1599053, - SAY_EVENT_END_10 = -1599054, - SAY_EVENT_END_11_KADD = -1599055, - SAY_EVENT_END_12 = -1599056, - SAY_EVENT_END_13_KADD = -1599057, - SAY_EVENT_END_14 = -1599058, - SAY_EVENT_END_15_MARN = -1599059, - SAY_EVENT_END_16 = -1599060, - SAY_EVENT_END_17_MARN = -1599061, - SAY_EVENT_END_18 = -1599062, - SAY_EVENT_END_19_MARN = -1599063, - SAY_EVENT_END_20 = -1599064, - SAY_EVENT_END_21_ABED = -1599065, - - SAY_VICTORY_SJONNIR_1 = -1599066, - SAY_VICTORY_SJONNIR_2 = -1599067, - - SAY_ENTRANCE_MEET = -1599068, - - TEXT_ID_START = 13100, - TEXT_ID_PROGRESS = 13101 -}; - -enum BrannCreatures -{ - CREATURE_TRIBUNAL_OF_THE_AGES = 28234, - CREATURE_BRANN_BRONZEBEARD = 28070, - CREATURE_DARK_MATTER_TARGET = 28237, - CREATURE_SEARING_GAZE_TARGET = 28265, - CREATURE_DARK_RUNE_PROTECTOR = 27983, - CREATURE_DARK_RUNE_STORMCALLER = 27984, - CREATURE_IRON_GOLEM_CUSTODIAN = 27985, -}; - -enum Spells -{ - SPELL_STEALTH = 58506, - //Kadrak - SPELL_GLARE_OF_THE_TRIBUNAL = 50988, - H_SPELL_GLARE_OF_THE_TRIBUNAL = 59868, - //Marnak - SPELL_DARK_MATTER = 51012, - H_SPELL_DARK_MATTER = 59868, - //Abedneum - SPELL_SEARING_GAZE = 51136, - H_SPELL_SEARING_GAZE = 59867 -}; - -enum Quests -{ - QUEST_HALLS_OF_STONE = 13207 -}; - -enum Achievements -{ - ACHIEV_BRANN_SPANKIN_NEW = 2154 -}; - -#define GOSSIP_ITEM_START "Brann, it would be our honor!" -#define GOSSIP_ITEM_PROGRESS "Let's move Brann, enough of the history lessons!" - -static Position SpawnLocations[]= -{ - {946.992, 397.016, 208.374}, - {960.748, 382.944, 208.374}, -}; - -struct mob_tribuna_controllerAI : public ScriptedAI -{ - mob_tribuna_controllerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - SetCombatMovement(false); - } - - ScriptedInstance* pInstance; - - uint32 uiKaddrakEncounterTimer; - uint32 uiMarnakEncounterTimer; - uint32 uiAbedneumEncounterTimer; - - bool bKaddrakActivated; - bool bMarnakActivated; - bool bAbedneumActivated; - - std::list KaddrakGUIDList; - - void Reset() - { - uiKaddrakEncounterTimer = 1500; - uiMarnakEncounterTimer = 10000; - uiAbedneumEncounterTimer = 10000; - - bKaddrakActivated = false; - bMarnakActivated = false; - bAbedneumActivated = false; - - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); - } - - KaddrakGUIDList.clear(); - } - - void UpdateFacesList() - { - /*GetCreatureListWithEntryInGrid(lKaddrakGUIDList, me, CREATURE_KADDRAK, 50.0f); - if (!lKaddrakGUIDList.empty()) - { - uint32 uiPositionCounter = 0; - for (std::list::const_iterator itr = lKaddrakGUIDList.begin(); itr != lKaddrakGUIDList.end(); ++itr) - { - if ((*itr)->isAlive()) - { - if (uiPositionCounter == 0) - { - (*itr)->GetMap()->CreatureRelocation((*itr), 927.265, 333.200, 218.780, (*itr)->GetOrientation()); - (*itr)->SendMonsterMove(927.265, 333.200, 218.780, 0, (*itr)->GetMovementFlags(), 1); - } - else - { - (*itr)->GetMap()->CreatureRelocation((*itr), 921.745, 328.076, 218.780, (*itr)->GetOrientation()); - (*itr)->SendMonsterMove(921.745, 328.076, 218.780, 0, (*itr)->GetMovementFlags(), 1); - } - } - ++uiPositionCounter; - } - }*/ - } - - void UpdateAI(const uint32 diff) - { - if (bKaddrakActivated) - { - if (uiKaddrakEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (!KaddrakGUIDList.empty()) - for (std::list::const_iterator itr = KaddrakGUIDList.begin(); itr != KaddrakGUIDList.end(); ++itr) - { - if (Creature *pKaddrak = Unit::GetCreature(*me, *itr)) - { - if (pKaddrak->isAlive()) - pKaddrak->CastSpell(pTarget, DUNGEON_MODE(SPELL_GLARE_OF_THE_TRIBUNAL, H_SPELL_GLARE_OF_THE_TRIBUNAL), true); - } - } - uiKaddrakEncounterTimer = 1500; - } else uiKaddrakEncounterTimer -= diff; - } - if (bMarnakActivated) - { - if (uiMarnakEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature* pSummon = me->SummonCreature(CREATURE_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) - { - pSummon->SetDisplayId(11686); - pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_DARK_MATTER, H_SPELL_DARK_MATTER), true); - } - } - uiMarnakEncounterTimer = 30000 + rand()%1000; - } else uiMarnakEncounterTimer -= diff; - } - if (bAbedneumActivated) - { - if (uiAbedneumEncounterTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - if (Creature* pSummon = me->SummonCreature(CREATURE_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) - { - pSummon->SetDisplayId(11686); - pSummon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pSummon->CastSpell(pTarget, DUNGEON_MODE(SPELL_SEARING_GAZE, H_SPELL_SEARING_GAZE), true); - } - } - uiAbedneumEncounterTimer = 30000 + rand()%1000; - } else uiAbedneumEncounterTimer -= diff; - } - } -}; - -struct npc_brann_hosAI : public npc_escortAI -{ - npc_brann_hosAI(Creature *c) : npc_escortAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiStep; - uint32 uiPhaseTimer; - - uint64 uiControllerGUID; - std::list lDwarfGUIDList; - - ScriptedInstance* pInstance; - - bool bIsBattle; - bool bIsLowHP; - bool bHasBeenDamaged; - - void Reset() - { - if (!HasEscortState(STATE_ESCORT_ESCORTING)) - { - bIsLowHP = false; - bIsBattle = false; - bHasBeenDamaged = false; - uiStep = 0; - uiPhaseTimer = 0; - uiControllerGUID = 0; - - DespawnDwarf(); - - if (pInstance) - pInstance->SetData(DATA_BRANN_EVENT, NOT_STARTED); - } - } - - void DespawnDwarf() - { - if (lDwarfGUIDList.empty()) - return; - for (std::list::const_iterator itr = lDwarfGUIDList.begin(); itr != lDwarfGUIDList.end(); ++itr) - { - Creature* pTemp = Unit::GetCreature(*me, pInstance ? (*itr) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->ForcedDespawn(); - } - lDwarfGUIDList.clear(); - } - - void WaypointReached(uint32 uiPointId) - { - switch(uiPointId) - { - case 7: - if (Creature* pCreature = GetClosestCreatureWithEntry(me, CREATURE_TRIBUNAL_OF_THE_AGES, 100.0f)) - { - if (!pCreature->isAlive()) - pCreature->Respawn(); - CAST_AI(mob_tribuna_controllerAI, pCreature->AI())->UpdateFacesList(); - uiControllerGUID = pCreature->GetGUID(); - } - break; - case 13: - DoScriptText(SAY_EVENT_INTRO_1, me); - SetEscortPaused(true); - JumpToNextStep(20000); - break; - case 17: - DoScriptText(SAY_EVENT_INTRO_2, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_TRIBUNAL_CONSOLE),true); - me->SetStandState(UNIT_STAND_STATE_KNEEL); - SetEscortPaused(true); - JumpToNextStep(8500); - break; - case 18: - SetEscortPaused(true); - break; - } - } - - void SpawnDwarf(uint32 uiType) - { - switch(uiType) - { - case 1: - { - uint32 uiSpawnNumber = DUNGEON_MODE(2,3); - for (uint8 i = 0; i < uiSpawnNumber; ++i) - me->SummonCreature(CREATURE_DARK_RUNE_PROTECTOR, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - } - case 2: - for (uint8 i = 0; i < 2; ++i) - me->SummonCreature(CREATURE_DARK_RUNE_STORMCALLER, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - case 3: - me->SummonCreature(CREATURE_IRON_GOLEM_CUSTODIAN, SpawnLocations[0], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); - break; - } - } - - void JustSummoned(Creature* pSummoned) - { - lDwarfGUIDList.push_back(pSummoned->GetGUID()); - pSummoned->AddThreat(me, 0.0f); - pSummoned->AI()->AttackStart(me); - } - - void JumpToNextStep(uint32 uiTimer) - { - uiPhaseTimer = uiTimer; - ++uiStep; - } - - void StartWP() - { - me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - SetEscortPaused(false); - uiStep = 1; - Start(); - } - - void DamageTaken(Unit* /*done_by*/, uint32 & /*damage*/) - { - if (!bHasBeenDamaged) - bHasBeenDamaged = true; - } - - void UpdateEscortAI(const uint32 uiDiff) - { - if (uiPhaseTimer <= uiDiff) - { - switch(uiStep) - { - case 1: - if (pInstance) - { - if (pInstance->GetData(DATA_BRANN_EVENT) != NOT_STARTED) - return; - pInstance->SetData(DATA_BRANN_EVENT, IN_PROGRESS); - } - bIsBattle = false; - DoScriptText(SAY_ESCORT_START, me); - SetRun(true); - JumpToNextStep(0); - break; - case 3: - SetEscortPaused(false); - JumpToNextStep(0); - break; - case 5: - if (pInstance) - if (Creature* pTemp = (Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM)))) - DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp); - JumpToNextStep(8500); - break; - case 6: - DoScriptText(SAY_EVENT_A_1, me); - JumpToNextStep(6500); - break; - case 7: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_A_2_KADD, pTemp); - JumpToNextStep(12500); - break; - case 8: - DoScriptText(SAY_EVENT_A_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bKaddrakActivated = true; - JumpToNextStep(5000); - break; - case 9: - me->SetReactState(REACT_PASSIVE); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 10: - DoScriptText(SAY_EVENT_B_1, me); - JumpToNextStep(6000); - break; - case 11: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_B_2_MARN, pTemp); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 12: - DoScriptText(SAY_EVENT_B_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bMarnakActivated = true; - JumpToNextStep(10000); - break; - case 13: - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 14: - SpawnDwarf(2); - JumpToNextStep(20000); - break; - case 15: - DoScriptText(SAY_EVENT_C_1, me); - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 16: - SpawnDwarf(2); - JumpToNextStep(20000); - break; - case 17: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_C_2_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(20000); - break; - case 18: - DoScriptText(SAY_EVENT_C_3, me); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - CAST_AI(mob_tribuna_controllerAI, pTemp->AI())->bAbedneumActivated = true; - JumpToNextStep(5000); - break; - case 19: - SpawnDwarf(2); - JumpToNextStep(10000); - break; - case 20: - SpawnDwarf(1); - JumpToNextStep(15000); - break; - case 21: - DoScriptText(SAY_EVENT_D_1, me); - SpawnDwarf(3); - JumpToNextStep(20000); - break; - case 22: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_D_2_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(5000); - break; - case 23: - SpawnDwarf(2); - JumpToNextStep(15000); - break; - case 24: - DoScriptText(SAY_EVENT_D_3, me); - SpawnDwarf(3); - JumpToNextStep(5000); - break; - case 25: - SpawnDwarf(1); - JumpToNextStep(5000); - break; - case 26: - SpawnDwarf(2); - JumpToNextStep(10000); - break; - case 27: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_D_4_ABED, pTemp); - SpawnDwarf(1); - JumpToNextStep(10000); - break; - case 28: - me->SetReactState(REACT_DEFENSIVE); - DoScriptText(SAY_EVENT_END_01, me); - me->SetStandState(UNIT_STAND_STATE_STAND); - if (pInstance) - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),true); - if (Creature* pTemp = Unit::GetCreature(*me, uiControllerGUID)) - pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - bIsBattle = true; - SetEscortPaused(false); - JumpToNextStep(6500); - break; - case 29: - DoScriptText(SAY_EVENT_END_02, me); - if (pInstance) - { - pInstance->SetData(DATA_BRANN_EVENT, DONE); - - // Achievement criteria is with spell 59046 which does not exist. - // There is thus no way it can be given by casting the spell on the players. - pInstance->DoUpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, 59046); - - if (!bHasBeenDamaged) - pInstance->DoCompleteAchievement(ACHIEV_BRANN_SPANKIN_NEW); - } - - JumpToNextStep(5500); - break; - case 30: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_03_ABED, pTemp); - JumpToNextStep(8500); - break; - case 31: - DoScriptText(SAY_EVENT_END_04, me); - JumpToNextStep(11500); - break; - case 32: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_05_ABED, pTemp); - JumpToNextStep(11500); - break; - case 33: - DoScriptText(SAY_EVENT_END_06, me); - JumpToNextStep(4500); - break; - case 34: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_07_ABED, pTemp); - JumpToNextStep(22500); - break; - case 35: - DoScriptText(SAY_EVENT_END_08, me); - JumpToNextStep(7500); - break; - case 36: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_09_KADD, pTemp); - JumpToNextStep(18500); - break; - case 37: - DoScriptText(SAY_EVENT_END_10, me); - JumpToNextStep(5500); - break; - case 38: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_11_KADD, pTemp); - JumpToNextStep(20500); - break; - case 39: - DoScriptText(SAY_EVENT_END_12, me); - JumpToNextStep(2500); - break; - case 40: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_KADDRAK))) - DoScriptText(SAY_EVENT_END_13_KADD, pTemp); - JumpToNextStep(19500); - break; - case 41: - DoScriptText(SAY_EVENT_END_14, me); - JumpToNextStep(10500); - break; - case 42: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_15_MARN, pTemp); - JumpToNextStep(6500); - break; - case 43: - DoScriptText(SAY_EVENT_END_16, me); - JumpToNextStep(6500); - break; - case 44: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_17_MARN, pTemp); - JumpToNextStep(25500); - break; - case 45: - DoScriptText(SAY_EVENT_END_18, me); - JumpToNextStep(23500); - break; - case 46: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_MARNAK))) - DoScriptText(SAY_EVENT_END_19_MARN, pTemp); - JumpToNextStep(3500); - break; - case 47: - DoScriptText(SAY_EVENT_END_20, me); - JumpToNextStep(8500); - break; - case 48: - if (pInstance) - if (Creature* pTemp = Unit::GetCreature(*me, pInstance->GetData64(DATA_ABEDNEUM))) - DoScriptText(SAY_EVENT_END_21_ABED, pTemp); - JumpToNextStep(5500); - break; - case 49: - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_KADDRAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_MARNAK),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_ABEDNEUM),false); - pInstance->HandleGameObject(pInstance->GetData64(DATA_GO_SKY_FLOOR),false); - } - Player* pPlayer = GetPlayerForEscort(); - if (pPlayer) - pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, me); - me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); - JumpToNextStep(180000); - break; - } - case 50: - SetEscortPaused(false); - break; - } - } else uiPhaseTimer -= uiDiff; - - if (!bIsLowHP && HealthBelowPct(30)) - { - DoScriptText(SAY_LOW_HEALTH, me); - bIsLowHP = true; - } - else if (bIsLowHP && !HealthBelowPct(30)) - bIsLowHP = false; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - - pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_brann_hos(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) -{ - if (uiAction == GOSSIP_ACTION_INFO_DEF+1 || uiAction == GOSSIP_ACTION_INFO_DEF+2) - { - pPlayer->CLOSE_GOSSIP_MENU(); - CAST_AI(npc_brann_hosAI, pCreature->AI())->StartWP(); - } - - return true; -} - -CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature) -{ - return new mob_tribuna_controllerAI(pCreature); -} - -CreatureAI* GetAI_npc_brann_hos(Creature* pCreature) -{ - return new npc_brann_hosAI(pCreature); -} - -void AddSC_halls_of_stone() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_brann_hos"; - newscript->GetAI = &GetAI_npc_brann_hos; - newscript->pGossipHello = &GossipHello_npc_brann_hos; - newscript->pGossipSelect = &GossipSelect_npc_brann_hos; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tribuna_controller"; - newscript->GetAI = &GetAI_mob_tribuna_controller; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h b/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h deleted file mode 100644 index b61e7057ddc..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_stone/halls_of_stone.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef DEF_HALLS_OF_STONE_H -#define DEF_HALLS_OF_STONE_H -enum Data -{ - DATA_KRYSTALLUS_EVENT, - DATA_MAIDEN_OF_GRIEF_EVENT, - DATA_SJONNIR_EVENT, - DATA_BRANN_EVENT -}; -enum Data64 -{ - DATA_KRYSTALLUS, - DATA_MAIDEN_OF_GRIEF, - DATA_SJONNIR, - DATA_KADDRAK, - DATA_MARNAK, - DATA_ABEDNEUM, - DATA_GO_TRIBUNAL_CONSOLE, - DATA_GO_KADDRAK, - DATA_GO_MARNAK, - DATA_GO_ABEDNEUM, - DATA_GO_SKY_FLOOR, - DATA_SJONNIR_DOOR, - DATA_MAIDEN_DOOR -}; -enum Creatures -{ - CREATURE_MAIDEN = 27975, - CREATURE_KRYSTALLUS = 27977, - CREATURE_SJONNIR = 27978, - CREATURE_MARNAK = 30897, - CREATURE_KADDRAK = 30898, - CREATURE_ABEDNEUM = 30899, - CREATURE_BRANN = 28070 -}; -enum GameObjects -{ - GO_ABEDNEUM = 191669, - GO_MARNAK = 192170, - GO_KADDRAK = 192171, - GO_MAIDEN_DOOR = 191292, - GO_BRANN_DOOR = 191295, - GO_SJONNIR_DOOR = 191296, - GO_TRIBUNAL_CONSOLE = 193907, - GO_TRIBUNAL_CHEST = 190586, - GO_TRIBUNAL_CHEST_HERO = 193996 -}; -#endif diff --git a/src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp deleted file mode 100644 index 69bb3779e70..00000000000 --- a/src/server/scripts/Northrend/Ulduar/halls_of_stone/instance_halls_of_stone.cpp +++ /dev/null @@ -1,254 +0,0 @@ -#include "ScriptedPch.h" -#include "halls_of_stone.h" - -#define MAX_ENCOUNTER 4 - -/* Halls of Stone encounters: -0- Krystallus -1- Maiden of Grief -2- Escort Event -3- Sjonnir The Ironshaper -*/ - -struct instance_halls_of_stone : public ScriptedInstance -{ - instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiMaidenOfGrief; - uint64 uiKrystallus; - uint64 uiSjonnir; - - uint64 uiKaddrak; - uint64 uiAbedneum; - uint64 uiMarnak; - uint64 uiBrann; - - uint64 uiMaidenOfGriefDoor; - uint64 uiSjonnirDoor; - uint64 uiBrannDoor; - uint64 uiTribunalConsole; - uint64 uiTribunalChest; - uint64 uiTribunalSkyFloor; - uint64 uiKaddrakGo; - uint64 uiAbedneumGo; - uint64 uiMarnakGo; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() - { - uiMaidenOfGrief = 0; - uiKrystallus = 0; - uiSjonnir = 0; - - uiKaddrak = 0; - uiMarnak = 0; - uiAbedneum = 0; - uiBrann = 0; - - uiMaidenOfGriefDoor = 0; - uiSjonnirDoor = 0; - uiBrannDoor = 0; - uiKaddrakGo = 0; - uiMarnakGo = 0; - uiAbedneumGo = 0; - uiTribunalConsole = 0; - uiTribunalChest = 0; - uiTribunalSkyFloor = 0; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i] = NOT_STARTED; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case CREATURE_MAIDEN: uiMaidenOfGrief = pCreature->GetGUID(); break; - case CREATURE_KRYSTALLUS: uiKrystallus = pCreature->GetGUID(); break; - case CREATURE_SJONNIR: uiSjonnir = pCreature->GetGUID(); break; - case CREATURE_MARNAK: uiMarnak = pCreature->GetGUID(); break; - case CREATURE_KADDRAK: uiKaddrak = pCreature->GetGUID(); break; - case CREATURE_ABEDNEUM: uiAbedneum = pCreature->GetGUID(); break; - case CREATURE_BRANN: uiBrann = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case GO_ABEDNEUM: - uiAbedneumGo = pGo->GetGUID(); - break; - case GO_MARNAK: - uiMarnakGo = pGo->GetGUID(); - break; - case GO_KADDRAK: - uiKaddrakGo = pGo->GetGUID(); - break; - case GO_MAIDEN_DOOR: - uiMaidenOfGriefDoor = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_BRANN_DOOR: - uiBrannDoor = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_SJONNIR_DOOR: - uiSjonnirDoor = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - else - pGo->SetGoState(GO_STATE_READY); - break; - case GO_TRIBUNAL_CONSOLE: - uiTribunalConsole = pGo->GetGUID(); - break; - case GO_TRIBUNAL_CHEST: - case GO_TRIBUNAL_CHEST_HERO: - uiTribunalChest = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - break; - case 191527: - uiTribunalSkyFloor = pGo->GetGUID(); - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MAIDEN_OF_GRIEF_EVENT: - m_auiEncounter[1] = data; - if (m_auiEncounter[1] == DONE) - HandleGameObject(uiBrannDoor,true); - break; - case DATA_KRYSTALLUS_EVENT: - m_auiEncounter[0] = data; - if (m_auiEncounter[0] == DONE) - HandleGameObject(uiMaidenOfGriefDoor,true); - break; - case DATA_SJONNIR_EVENT: - m_auiEncounter[3] = data; - break; - case DATA_BRANN_EVENT: - m_auiEncounter[2] = data; - if (m_auiEncounter[2] == DONE) - { - HandleGameObject(uiSjonnirDoor,true); - GameObject *pGo = instance->GetGameObject(uiTribunalChest); - if (pGo) - pGo->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND); - } - break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_KRYSTALLUS_EVENT: return m_auiEncounter[0]; - case DATA_MAIDEN_OF_GRIEF_EVENT: return m_auiEncounter[1]; - case DATA_SJONNIR_EVENT: return m_auiEncounter[2]; - case DATA_BRANN_EVENT: return m_auiEncounter[3]; - } - - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_MAIDEN_OF_GRIEF: return uiMaidenOfGrief; - case DATA_KRYSTALLUS: return uiKrystallus; - case DATA_SJONNIR: return uiSjonnir; - case DATA_KADDRAK: return uiKaddrak; - case DATA_MARNAK: return uiMarnak; - case DATA_ABEDNEUM: return uiAbedneum; - case DATA_GO_TRIBUNAL_CONSOLE: return uiTribunalConsole; - case DATA_GO_KADDRAK: return uiKaddrakGo; - case DATA_GO_ABEDNEUM: return uiAbedneumGo; - case DATA_GO_MARNAK: return uiMarnakGo; - case DATA_GO_SKY_FLOOR: return uiTribunalSkyFloor; - case DATA_SJONNIR_DOOR: return uiSjonnirDoor; - case DATA_MAIDEN_DOOR: return uiMaidenOfGriefDoor; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "H S " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'H' && dataHead2 == 'S') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_halls_of_stone(Map* pMap) -{ - return new instance_halls_of_stone(pMap); -} - -void AddSC_instance_halls_of_stone() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_halls_of_stone"; - newscript->GetInstanceData = &GetInstanceData_instance_halls_of_stone; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp new file mode 100644 index 00000000000..77f824c48d5 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -0,0 +1,442 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ingvar_The_Plunderer +SD%Complete: 95 +SDComment: Some Problems with Annhylde Movement, Blizzlike Timers +SDCategory: Udgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum Yells +{ + //Yells Ingvar + YELL_AGGRO_1 = -1574005, + YELL_AGGRO_2 = -1574006, + + YELL_DEAD_1 = -1574007, + YELL_DEAD_2 = -1574008, + + YELL_KILL_1 = -1574009, + YELL_KILL_2 = -1574010, +}; + +enum Creatures +{ + MOB_INGVAR_HUMAN = 23954, + MOB_ANNHYLDE_THE_CALLER = 24068, + MOB_INGVAR_UNDEAD = 23980, +}; + +enum Spells +{ + //Ingvar Spells human form + SPELL_CLEAVE = 42724, + SPELL_SMASH = 42669, + H_SPELL_SMASH = 59706, + SPELL_STAGGERING_ROAR = 42708, + H_SPELL_STAGGERING_ROAR = 59708, + SPELL_ENRAGE = 42705, + H_SPELL_ENRAGE = 59707, + + SPELL_INGVAR_FEIGN_DEATH = 42795, + SPELL_SUMMON_BANSHEE = 42912, + SPELL_SCOURG_RESURRECTION = 42863, // Spawn resurrect effect around Ingvar + + //Ingvar Spells undead form + SPELL_DARK_SMASH = 42723, + SPELL_DREADFUL_ROAR = 42729, + H_SPELL_DREADFUL_ROAR = 59734, + SPELL_WOE_STRIKE = 42730, + H_SPELL_WOE_STRIKE = 59735, + + ENTRY_THROW_TARGET = 23996, + SPELL_SHADOW_AXE_SUMMON = 42749 +}; + +struct boss_ingvar_the_plundererAI : public ScriptedAI +{ + boss_ingvar_the_plundererAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool bIsUndead; + bool bEventInProgress; + + uint32 uiCleaveTimer; + uint32 uiSmashTimer; + uint32 uiEnrageTimer; + uint32 uiRoarTimer; + uint32 uiSpawnResTimer; + + void Reset() + { + if (bIsUndead) + me->UpdateEntry(MOB_INGVAR_HUMAN); + + bIsUndead = false; + bEventInProgress = false; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + + uiCleaveTimer = 2000; + uiSmashTimer = 5000; + uiEnrageTimer = 10000; + uiRoarTimer = 15000; + + uiSpawnResTimer = 3000; + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, NOT_STARTED); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (damage >= me->GetHealth() && !bIsUndead) + { + //DoCast(me, SPELL_INGVAR_FEIGN_DEATH, true); // Dont work ??? + // visuel hack + me->SetHealth(0); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + // visuel hack end + + bEventInProgress = true; + bIsUndead = true; + + DoScriptText(YELL_DEAD_1,me); + } + + if (bEventInProgress) + { + damage = 0; + } + } + + void StartZombiePhase() + { + bIsUndead = true; + bEventInProgress = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->UpdateEntry(MOB_INGVAR_UNDEAD); + me->SetInCombatWith(me->getVictim()); + me->GetMotionMaster()->MoveChase(me->getVictim()); + + DoScriptText(YELL_AGGRO_2,me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(YELL_AGGRO_1,me); + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(YELL_DEAD_2,me); + + if (pInstance) + pInstance->SetData(DATA_INGVAR_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + if (bIsUndead) + DoScriptText(YELL_KILL_1,me); + else + DoScriptText(YELL_KILL_2,me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (bEventInProgress) + { + if (uiSpawnResTimer) + if (uiSpawnResTimer <= diff) + { + DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position + // DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ? + uiSpawnResTimer = 0; + } else uiSpawnResTimer -= diff; + + return; + } + + if (uiCleaveTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me->getVictim(), SPELL_WOE_STRIKE); + else + DoCast(me->getVictim(), SPELL_CLEAVE); + uiCleaveTimer = rand()%5000 + 2000; + } + } else uiCleaveTimer -= diff; + + if (uiSmashTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me->getVictim(), SPELL_DARK_SMASH); + else + DoCast(me->getVictim(), SPELL_SMASH); + uiSmashTimer = 10000; + } + } else uiSmashTimer -= diff; + + if (!bIsUndead) + { + if (uiEnrageTimer <= diff) + { + DoCast(me, SPELL_ENRAGE); + uiEnrageTimer = 10000; + } else uiEnrageTimer -= diff; + } else // In Undead form used to summon weapon + { + if (uiEnrageTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + // Spawn target for Axe + Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + if (pTarget) + { + me->SummonCreature(ENTRY_THROW_TARGET,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,2000); + + DoCast(me, SPELL_SHADOW_AXE_SUMMON); + } + uiEnrageTimer = 30000; + } + } else uiEnrageTimer -= diff; + } + + if (uiRoarTimer <= diff) + { + if (!me->hasUnitState(UNIT_STAT_CASTING)) + { + if (bIsUndead) + DoCast(me, SPELL_DREADFUL_ROAR); + else + DoCast(me, SPELL_STAGGERING_ROAR); + uiRoarTimer = 10000; + } + } else uiRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ingvar_the_plunderer(Creature* pCreature) +{ + return new boss_ingvar_the_plundererAI(pCreature); +} + +enum eSpells +{ +//we don't have that text in db so comment it until we get this text +// YELL_RESSURECT = -1574025, + +//Spells for Annhylde + SPELL_SCOURG_RESURRECTION_HEAL = 42704, //Heal Max + DummyAura + SPELL_SCOURG_RESURRECTION_BEAM = 42857, //Channeling Beam of Annhylde + SPELL_SCOURG_RESURRECTION_DUMMY = 42862, //Some Emote Dummy? + SPELL_INGVAR_TRANSFORM = 42796 +}; + +struct mob_annhylde_the_callerAI : public ScriptedAI +{ + mob_annhylde_the_callerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + float x,y,z; + ScriptedInstance* pInstance; + uint32 uiResurectTimer; + uint32 uiResurectPhase; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_HOVER); + me->SetSpeed(MOVE_SWIM , 1.0f); + me->SetSpeed(MOVE_RUN , 1.0f); + me->SetSpeed(MOVE_WALK , 1.0f); + //me->SetSpeed(MOVE_FLIGHT , 1.0f); + + me->GetPosition(x,y,z); + DoTeleportTo(x+1,y,z+30); + + Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + me->GetMotionMaster()->MovePoint(1,x,y,z+15); + +// DoScriptText(YELL_RESSURECT,me); + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + Unit* ingvar = Unit::GetUnit((*me), pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + switch (id) + { + case 1: + ingvar->RemoveAura(SPELL_SUMMON_BANSHEE); + ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_DUMMY,true); + DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); + uiResurectTimer = 8000; + uiResurectPhase = 1; + break; + case 2: + me->SetVisibility(VISIBILITY_OFF); + me->DealDamage(me,me->GetHealth()); + me->RemoveCorpse(); + break; + } + } + } + + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit * /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (uiResurectTimer) + if (uiResurectTimer <= diff) + { + if (uiResurectPhase == 1) + { + Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); + if (ingvar) + { + ingvar->SetStandState(UNIT_STAND_STATE_STAND); + ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_HEAL,false); + } + uiResurectTimer = 3000; + uiResurectPhase = 2; + } + else if (uiResurectPhase == 2) + { + if (Creature* ingvar = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0)) + { + ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); + + if (boss_ingvar_the_plundererAI* pAI = CAST_AI(boss_ingvar_the_plundererAI, ingvar->AI())) + pAI->StartZombiePhase(); + + me->GetMotionMaster()->MovePoint(2,x+1,y,z+30); + ++uiResurectPhase; + uiResurectTimer = 0; + } + } + + } else uiResurectTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_annhylde_the_caller(Creature* pCreature) +{ + return new mob_annhylde_the_callerAI (pCreature); +} + +enum eShadowAxe +{ + SPELL_SHADOW_AXE_DAMAGE = 42750, + H_SPELL_SHADOW_AXE_DAMAGE = 59719 +}; + +struct mob_ingvar_throw_dummyAI : public ScriptedAI +{ + mob_ingvar_throw_dummyAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 uiDespawnTimer; + + void Reset() + { + Unit *pTarget = me->FindNearestCreature(ENTRY_THROW_TARGET,50); + if (pTarget) + { + DoCast(me, SPELL_SHADOW_AXE_DAMAGE); + float x,y,z; + pTarget->GetPosition(x,y,z); + me->GetMotionMaster()->MovePoint(0,x,y,z); + } + uiDespawnTimer = 7000; + } + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void EnterCombat(Unit * /*who*/) {} + void UpdateAI(const uint32 diff) + { + if (uiDespawnTimer <= diff) + { + me->DealDamage(me,me->GetHealth()); + me->RemoveCorpse(); + uiDespawnTimer = 0; + } else uiDespawnTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_ingvar_throw_dummy(Creature* pCreature) +{ + return new mob_ingvar_throw_dummyAI (pCreature); +} + +void AddSC_boss_ingvar_the_plunderer() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ingvar_the_plunderer"; + newscript->GetAI = &GetAI_boss_ingvar_the_plunderer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_annhylde_the_caller"; + newscript->GetAI = &GetAI_mob_annhylde_the_caller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ingvar_throw_dummy"; + newscript->GetAI = &GetAI_mob_ingvar_throw_dummy; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp new file mode 100644 index 00000000000..d69f0eee846 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp @@ -0,0 +1,361 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Prince_Keleseth +SD%Complete: 90 +SDComment: Needs Prince Movements, Needs adjustments to blizzlike timers, Needs Shadowbolt castbar, Needs right Ressurect Visual, Needs Some Heroic Spells +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum eEnums +{ + ACHIEVEMENT_ON_THE_ROCKS = 1919, + + SPELL_SHADOWBOLT = 43667, + SPELL_SHADOWBOLT_HEROIC = 59389, + SPELL_FROST_TOMB = 48400, + SPELL_FROST_TOMB_SUMMON = 42714, + SPELL_DECREPIFY = 42702, + SPELL_SCOURGE_RESSURRECTION = 42704, + CREATURE_FROSTTOMB = 23965, + CREATURE_SKELETON = 23970, + + SAY_AGGRO = -1574000, + SAY_FROST_TOMB = -1574001, + SAY_SKELETONS = -1574002, + SAY_KILL = -1574003, + SAY_DEATH = -1574004 +}; + +#define SKELETONSPAWN_Z 42.8668 + +float SkeletonSpawnPoint[5][5]= +{ + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, + {156.2559, 259.2093}, +}; + +float AttackLoc[3]={197.636, 194.046, 40.8164}; + +bool ShatterFrostTomb; // needed for achievement: On The Rocks(1919) + +struct mob_frost_tombAI : public ScriptedAI +{ + mob_frost_tombAI(Creature *c) : ScriptedAI(c) + { + FrostTombGUID = 0; + } + + uint64 FrostTombGUID; + + void SetPrisoner(Unit* uPrisoner) + { + FrostTombGUID = uPrisoner->GetGUID(); + } + + void Reset(){ FrostTombGUID = 0; } + void EnterCombat(Unit* /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + + void JustDied(Unit *killer) + { + if (killer->GetGUID() != me->GetGUID()) + ShatterFrostTomb = true; + + if (FrostTombGUID) + { + Unit* FrostTomb = Unit::GetUnit((*me),FrostTombGUID); + if (FrostTomb) + FrostTomb->RemoveAurasDueToSpell(SPELL_FROST_TOMB); + } + } + + void UpdateAI(const uint32 /*diff*/) + { + Unit* temp = Unit::GetUnit((*me),FrostTombGUID); + if ((temp && temp->isAlive() && !temp->HasAura(SPELL_FROST_TOMB)) || !temp) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } +}; + +struct boss_kelesethAI : public ScriptedAI +{ + boss_kelesethAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 FrostTombTimer; + uint32 SummonSkeletonsTimer; + uint32 RespawnSkeletonsTimer; + uint32 ShadowboltTimer; + uint64 SkeletonGUID[5]; + bool Skeletons; + bool RespawnSkeletons; + + void Reset() + { + ShadowboltTimer = 0; + Skeletons = false; + + ShatterFrostTomb = false; + + ResetTimer(); + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); + } + + void KilledUnit(Unit * victim) + { + if (victim == me) + return; + + DoScriptText(SAY_KILL, me); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (IsHeroic() && !ShatterFrostTomb) + { + AchievementEntry const *AchievOnTheRocks = GetAchievementStore()->LookupEntry(ACHIEVEMENT_ON_THE_ROCKS); + if (AchievOnTheRocks) + { + Map* pMap = me->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + itr->getSource()->CompletedAchievement(AchievOnTheRocks); + } + } + } + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); + } + + void ResetTimer(uint32 inc = 0) + { + SummonSkeletonsTimer = 5000 + inc; + FrostTombTimer = 28000 + inc; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowboltTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + me->CastSpell(pTarget, DUNGEON_MODE(SPELL_SHADOWBOLT, SPELL_SHADOWBOLT_HEROIC), true); + ShadowboltTimer = 10000; + } else ShadowboltTimer -= diff; + + if (!Skeletons) + if ((SummonSkeletonsTimer <= diff)) + { + Creature* Skeleton; + DoScriptText(SAY_SKELETONS, me); + for (uint8 i = 0; i < 5; ++i) + { + Skeleton = me->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1] , SKELETONSPAWN_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); + if (Skeleton) + { + Skeleton->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + Skeleton->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY() , me->GetPositionZ()); + Skeleton->AddThreat(me->getVictim(), 0.0f); + DoZoneInCombat(Skeleton); + } + } + Skeletons = true; + } else SummonSkeletonsTimer -= diff; + + if (FrostTombTimer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + if (pTarget->isAlive()) + { + //DoCast(pTarget, SPELL_FROST_TOMB_SUMMON, true); + if (Creature *pChains = me->SummonCreature(CREATURE_FROSTTOMB, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) + { + CAST_AI(mob_frost_tombAI, pChains->AI())->SetPrisoner(pTarget); + pChains->CastSpell(pTarget, SPELL_FROST_TOMB, true); + + DoScriptText(SAY_FROST_TOMB, me); + } + } + FrostTombTimer = 15000; + } else FrostTombTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct mob_vrykul_skeletonAI : public ScriptedAI +{ + mob_vrykul_skeletonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 Respawn_Time; + uint64 Target_Guid; + uint32 Decrepify_Timer; + + bool isDead; + + void Reset() + { + Respawn_Time = 12000; + Decrepify_Timer = urand(10000,20000); + isDead = false; + } + + void EnterCombat(Unit * /*who*/){} + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() == me->GetGUID()) + return; + + if (damage >= me->GetHealth()) + { + PretendToDie(); + damage = 0; + } + } + + void PretendToDie() + { + isDead = true; + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->GetMotionMaster()->MovementExpired(false); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + }; + + void Resurrect() + { + isDead = false; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_SCOURGE_RESSURRECTION, true); + + if (me->getVictim()) + { + me->GetMotionMaster()->MoveChase(me->getVictim()); + me->AI()->AttackStart(me->getVictim()); + } + else + me->GetMotionMaster()->Initialize(); + }; + + void UpdateAI(const uint32 diff) + { + if (pInstance && pInstance->GetData(DATA_PRINCEKELESETH_EVENT) == IN_PROGRESS) + { + if (isDead) + { + if (Respawn_Time <= diff) + { + Resurrect(); + Respawn_Time = 12000; + } else Respawn_Time -= diff; + } + else + { + if (!UpdateVictim()) + return; + + if (Decrepify_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DECREPIFY); + Decrepify_Timer = 30000; + } else Decrepify_Timer -= diff; + + DoMeleeAttackIfReady(); + } + }else + { + if (me->isAlive()) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + } +}; + +CreatureAI* GetAI_mob_frost_tomb(Creature* pCreature) +{ + return new mob_frost_tombAI(pCreature); +} + +CreatureAI* GetAI_boss_keleseth(Creature* pCreature) +{ + return new boss_kelesethAI (pCreature); +} + +CreatureAI* GetAI_mob_vrykul_skeleton(Creature* pCreature) +{ + return new mob_vrykul_skeletonAI (pCreature); +} + +void AddSC_boss_keleseth() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_keleseth"; + newscript->GetAI = &GetAI_boss_keleseth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_tomb"; + newscript->GetAI = &GetAI_mob_frost_tomb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vrykul_skeleton"; + newscript->GetAI = &GetAI_mob_vrykul_skeleton; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp new file mode 100644 index 00000000000..2146d37635b --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_skarvald_dalronn.cpp @@ -0,0 +1,389 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Skarvald_Dalronn +SD%Complete: 95 +SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +enum eEnums +{ + //signed for 24200, but used by 24200,27390 + YELL_SKARVALD_AGGRO = -1574011, + YELL_SKARVALD_DAL_DIED = -1574012, + YELL_SKARVALD_SKA_DIEDFIRST = -1574013, + YELL_SKARVALD_KILL = -1574014, + YELL_SKARVALD_DAL_DIEDFIRST = -1574015, + + //signed for 24201, but used by 24201,27389 + YELL_DALRONN_AGGRO = -1574016, + YELL_DALRONN_SKA_DIED = -1574017, + YELL_DALRONN_DAL_DIEDFIRST = -1574018, + YELL_DALRONN_KILL = -1574019, + YELL_DALRONN_SKA_DIEDFIRST = -1574020, + +//Spells of Skarvald and his Ghost + MOB_SKARVALD_THE_CONSTRUCTOR = 24200, + SPELL_CHARGE = 43651, + SPELL_STONE_STRIKE = 48583, + SPELL_SUMMON_SKARVALD_GHOST = 48613, + MOB_SKARVALD_GHOST = 27390, +//Spells of Dalronn and his Ghost + MOB_DALRONN_THE_CONTROLLER = 24201, + SPELL_SHADOW_BOLT = 43649, + H_SPELL_SHADOW_BOLT = 59575, + H_SPELL_SUMMON_SKELETONS = 52611, + SPELL_DEBILITATE = 43650, + SPELL_SUMMON_DALRONN_GHOST = 48612, + MOB_DALRONN_GHOST = 27389 +}; + +struct boss_skarvald_the_constructorAI : public ScriptedAI +{ + boss_skarvald_the_constructorAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool ghost; + uint32 Charge_Timer; + uint32 StoneStrike_Timer; + uint32 Response_Timer; + uint32 Check_Timer; + bool Dalronn_isDead; + + void Reset() + { + Charge_Timer = 5000; + StoneStrike_Timer = 10000; + Dalronn_isDead = false; + Check_Timer = 5000; + + ghost = (me->GetEntry() == MOB_SKARVALD_GHOST); + if (!ghost && pInstance) + { + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn && dalronn->isDead()) + CAST_CRE(dalronn)->Respawn(); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit * who) + { + if (!ghost && pInstance) + { + DoScriptText(YELL_SKARVALD_AGGRO,me); + + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn && dalronn->isAlive() && !dalronn->getVictim()) + dalronn->getThreatManager().addThreat(who,0.0f); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* Killer) + { + if (!ghost && pInstance) + { + Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); + if (dalronn) + { + if (dalronn->isDead()) + { + DoScriptText(YELL_SKARVALD_DAL_DIED,me); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); + } + else + { + DoScriptText(YELL_SKARVALD_SKA_DIEDFIRST,me); + + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true); + Creature* temp = me->SummonCreature(MOB_SKARVALD_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); + if (temp) + { + temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(Killer); + } + } + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + if (!ghost) + { + DoScriptText(YELL_SKARVALD_KILL,me); + } + } + + void UpdateAI(const uint32 diff) + { + if (ghost) + { + if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (!UpdateVictim()) + return; + + if (!ghost) + { + if (Check_Timer) + if (Check_Timer <= diff) + { + Check_Timer = 5000; + Unit* dalronn = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_DALRONN) : 0); + if (dalronn && dalronn->isDead()) + { + Dalronn_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } + } else Check_Timer -= diff; + + if (Response_Timer) + if (Dalronn_isDead) + if (Response_Timer <= diff) + { + DoScriptText(YELL_SKARVALD_DAL_DIEDFIRST,me); + + Response_Timer = 0; + } else Response_Timer -= diff; + } + + if (Charge_Timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE); + Charge_Timer = 5000+rand()%5000; + } else Charge_Timer -= diff; + + if (StoneStrike_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STONE_STRIKE); + StoneStrike_Timer = 5000+rand()%5000; + } else StoneStrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_skarvald_the_constructor(Creature* pCreature) +{ + return new boss_skarvald_the_constructorAI (pCreature); +} + +struct boss_dalronn_the_controllerAI : public ScriptedAI +{ + boss_dalronn_the_controllerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool ghost; + uint32 ShadowBolt_Timer; + uint32 Debilitate_Timer; + uint32 Summon_Timer; + + uint32 Response_Timer; + uint32 Check_Timer; + uint32 AggroYell_Timer; + bool Skarvald_isDead; + + void Reset() + { + ShadowBolt_Timer = 1000; + Debilitate_Timer = 5000; + Summon_Timer = 10000; + Check_Timer = 5000; + Skarvald_isDead = false; + AggroYell_Timer = 0; + + ghost = me->GetEntry() == MOB_DALRONN_GHOST; + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald && skarvald->isDead()) + CAST_CRE(skarvald)->Respawn(); + + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); + } + } + + void EnterCombat(Unit * who) + { + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald && skarvald->isAlive() && !skarvald->getVictim()) + skarvald->getThreatManager().addThreat(who,0.0f); + + AggroYell_Timer = 5000; + + if (pInstance) + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); + } + } + + void JustDied(Unit* Killer) + { + if (!ghost && pInstance) + { + Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); + if (skarvald) + if (skarvald->isDead()) + { + DoScriptText(YELL_DALRONN_SKA_DIED,me); + + if (pInstance) + pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); + } + else + { + DoScriptText(YELL_DALRONN_DAL_DIEDFIRST,me); + + me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true); + Creature* temp = me->SummonCreature(MOB_DALRONN_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); + if (temp) + { + temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); + temp->AI()->AttackStart(Killer); + } + } + } + } + + void KilledUnit(Unit * /*victim*/) + { + if (!ghost) + { + DoScriptText(YELL_DALRONN_KILL,me); + } + } + + void UpdateAI(const uint32 diff) + { + if (ghost) + { + if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (!UpdateVictim()) + return; + + if (AggroYell_Timer) + if (AggroYell_Timer <= diff) + { + DoScriptText(YELL_DALRONN_AGGRO,me); + + AggroYell_Timer = 0; + } else AggroYell_Timer -= diff; + + if (!ghost) + { + if (Check_Timer) + if (Check_Timer <= diff) + { + Check_Timer = 5000; + Unit* skarvald = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SKARVALD) : 0); + if (skarvald && skarvald->isDead()) + { + Skarvald_isDead = true; + Response_Timer = 2000; + Check_Timer = 0; + } + } else Check_Timer -= diff; + + if (Response_Timer) + if (Skarvald_isDead) + if (Response_Timer <= diff) + { + DoScriptText(YELL_DALRONN_SKA_DIEDFIRST,me); + + Response_Timer = 0; + } else Response_Timer -= diff; + } + + if (ShadowBolt_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells + } + } else ShadowBolt_Timer -= diff; + + if (Debilitate_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DEBILITATE); + Debilitate_Timer = 5000+rand()%5000; + } + } else Debilitate_Timer -= diff; + + if (IsHeroic()) + if (Summon_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, H_SPELL_SUMMON_SKELETONS); + Summon_Timer = (rand()%10000) + 20000; + } + } else Summon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_dalronn_the_controller(Creature* pCreature) +{ + return new boss_dalronn_the_controllerAI (pCreature); +} + +void AddSC_boss_skarvald_dalronn() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_skarvald_the_constructor"; + newscript->GetAI = &GetAI_boss_skarvald_the_constructor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_dalronn_the_controller"; + newscript->GetAI = &GetAI_boss_dalronn_the_controller; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp new file mode 100644 index 00000000000..03f97b1d27e --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/instance_utgarde_keep.cpp @@ -0,0 +1,312 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Utgarde_Keep +SD%Complete: 90 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Utgarde Keep Scripts +SDCategory: Utgarde Keep +EndScriptData */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +#define MAX_ENCOUNTER 3 + +#define ENTRY_BELLOW_1 186688 +#define ENTRY_BELLOW_2 186689 +#define ENTRY_BELLOW_3 186690 + +#define ENTRY_FORGEFIRE_1 186692 +#define ENTRY_FORGEFIRE_2 186693 +#define ENTRY_FORGEFIRE_3 186691 + +#define ENTRY_GLOWING_ANVIL_1 186609 +#define ENTRY_GLOWING_ANVIL_2 186610 +#define ENTRY_GLOWING_ANVIL_3 186611 + +#define ENTRY_GIANT_PORTCULLIS_1 186756 +#define ENTRY_GIANT_PORTCULLIS_2 186694 + +/* Utgarde Keep encounters: +0 - Prince Keleseth +1 - Skarvald Dalronn +2 - Ingvar the Plunderer +*/ + +struct instance_utgarde_keep : public ScriptedInstance +{ + instance_utgarde_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 Keleseth; + uint64 Skarvald; + uint64 Dalronn; + uint64 Ingvar; + + uint64 forge_bellow[3]; + uint64 forge_fire[3]; + uint64 forge_anvil[3]; + uint64 portcullis[2]; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 forge_event[3]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + Keleseth = 0; + Skarvald = 0; + Dalronn = 0; + Ingvar = 0; + + for (uint8 i = 0; i < 3; ++i) + { + forge_bellow[i] = 0; + forge_fire[i] = 0; + forge_anvil[i] = 0; + forge_event[i] = NOT_STARTED; + } + + portcullis[0] = 0; + portcullis[1] = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + Player* GetPlayerInMap() + { + Map::PlayerList const& players = instance->GetPlayers(); + + if (!players.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if (Player* plr = itr->getSource()) + return plr; + } + } + + debug_log("TSCR: Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); + return NULL; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 23953: Keleseth = pCreature->GetGUID(); break; + case 24201: Dalronn = pCreature->GetGUID(); break; + case 24200: Skarvald = pCreature->GetGUID(); break; + case 23954: Ingvar = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + //door and object id + case ENTRY_BELLOW_1: forge_bellow[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_BELLOW_2: forge_bellow[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_BELLOW_3: forge_bellow[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_1: forge_fire[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_2: forge_fire[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_FORGEFIRE_3: forge_fire[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_1: forge_anvil[0] = pGo->GetGUID(); + if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_2: forge_anvil[1] = pGo->GetGUID(); + if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GLOWING_ANVIL_3: forge_anvil[2] = pGo->GetGUID(); + if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GIANT_PORTCULLIS_1: portcullis[0] = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; + case ENTRY_GIANT_PORTCULLIS_2: portcullis[1] = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_PRINCEKELESETH: return Keleseth; + case DATA_DALRONN: return Dalronn; + case DATA_SKARVALD: return Skarvald; + case DATA_INGVAR: return Ingvar; + } + + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_PRINCEKELESETH_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_SKARVALD_DALRONN_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_INGVAR_EVENT: + if (data == DONE) + { + HandleGameObject(portcullis[0], true); + HandleGameObject(portcullis[1], true); + } + m_auiEncounter[2] = data; + break; + case EVENT_FORGE_1: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[0],false); + HandleGameObject(forge_fire[0],false); + HandleGameObject(forge_anvil[0],false); + }else + { + HandleGameObject(forge_bellow[0],true); + HandleGameObject(forge_fire[0],true); + HandleGameObject(forge_anvil[0],true); + } + forge_event[0] = data; + break; + case EVENT_FORGE_2: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[1],false); + HandleGameObject(forge_fire[1],false); + HandleGameObject(forge_anvil[1],false); + }else + { + HandleGameObject(forge_bellow[1],true); + HandleGameObject(forge_fire[1],true); + HandleGameObject(forge_anvil[1],true); + } + forge_event[1] = data; + break; + case EVENT_FORGE_3: + if (data == NOT_STARTED) + { + HandleGameObject(forge_bellow[2],false); + HandleGameObject(forge_fire[2],false); + HandleGameObject(forge_anvil[2],false); + }else + { + HandleGameObject(forge_bellow[2],true); + HandleGameObject(forge_fire[2],true); + HandleGameObject(forge_anvil[2],true); + } + forge_event[2] = data; + break; + } + + if (data == DONE) + { + SaveToDB(); + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_PRINCEKELESETH_EVENT: return m_auiEncounter[0]; + case DATA_SKARVALD_DALRONN_EVENT: return m_auiEncounter[1]; + case DATA_INGVAR_EVENT: return m_auiEncounter[2]; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "U K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << forge_event[0] << " " << forge_event[1] << " " << forge_event[2]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3, data4, data5; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; + + if (dataHead1 == 'U' && dataHead2 == 'K') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + forge_event[0] = data3; + forge_event[1] = data4; + forge_event[2] = data5; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_utgarde_keep(Map* pMap) +{ + return new instance_utgarde_keep(pMap); +} + +void AddSC_instance_utgarde_keep() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_utgarde_keep"; + newscript->GetInstanceData = &GetInstanceData_instance_utgarde_keep; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp new file mode 100644 index 00000000000..95825aa49b6 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "utgarde_keep.h" + +uint32 entry_search[3] = +{ + 186609, + 186610, + 186611 +}; + +struct npc_dragonflayer_forge_masterAI : public ScriptedAI +{ + npc_dragonflayer_forge_masterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + fm_Type = 0; + } + + ScriptedInstance* pInstance; + uint8 fm_Type; + + void Reset() + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + CheckForge(); + } + + void CheckForge() + { + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,me->isAlive() ? NOT_STARTED : DONE); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,me->isAlive() ? NOT_STARTED : DONE); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,me->isAlive() ? NOT_STARTED : DONE); + break; + } + } + } + + void JustDied(Unit * /*killer*/) + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,DONE); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,DONE); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,DONE); + break; + } + } + } + + void EnterCombat(Unit * /*who*/) + { + if (fm_Type == 0) fm_Type = GetForgeMasterType(); + if (pInstance) + { + switch(fm_Type) + { + case 1: + pInstance->SetData(EVENT_FORGE_1,IN_PROGRESS); + break; + case 2: + pInstance->SetData(EVENT_FORGE_2,IN_PROGRESS); + break; + case 3: + pInstance->SetData(EVENT_FORGE_3,IN_PROGRESS); + break; + } + } + me->SetUInt32Value(UNIT_NPC_EMOTESTATE ,EMOTE_ONESHOT_NONE); + } + + uint8 GetForgeMasterType() + { + float diff = 30.0f; + int near_f = 0; + + for (uint8 i = 0; i < 3 ; ++i) + { + GameObject* temp; + temp = me->FindNearestGameObject(entry_search[i],30); + if (temp) + { + if (me->IsWithinDist(temp,diff,false)) + { + near_f = i + 1; + diff = me->GetDistance2d(temp); + + } + } + } + + switch (near_f) + { + case 1: return 1; + case 2: return 2; + case 3: return 3; + default: return 0; + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (fm_Type == 0) + fm_Type = GetForgeMasterType(); + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_dragonflayer_forge_master(Creature* pCreature) +{ + return new npc_dragonflayer_forge_masterAI(pCreature); +} + +void AddSC_utgarde_keep() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_dragonflayer_forge_master"; + newscript->GetAI = &GetAI_npc_dragonflayer_forge_master; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h new file mode 100644 index 00000000000..b630e156564 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/utgarde_keep.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 Trinity + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef DEF_UTGARDE_KEEP_H +#define DEF_UTGARDE_KEEP_H + +#define DATA_PRINCEKELESETH 1 +#define DATA_SKARVALD 3 +#define DATA_DALRONN 4 +#define DATA_INGVAR 6 + +#define DATA_PRINCEKELESETH_EVENT 2 +#define DATA_SKARVALD_DALRONN_EVENT 5 +#define DATA_INGVAR_EVENT 7 + +#define EVENT_FORGE_1 8 +#define EVENT_FORGE_2 9 +#define EVENT_FORGE_3 10 + +#endif diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp new file mode 100644 index 00000000000..297fe37b7d8 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp @@ -0,0 +1,830 @@ +/* Script Data Start +SDName: Boss palehoof +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_palehoof' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_ARCING_SMASH = 48260, + SPELL_IMPALE = 48261, + H_SPELL_IMPALE = 59268, + SPELL_WITHERING_ROAR = 48256, + H_SPELL_WITHERING_ROAR = 59267, + SPELL_FREEZE = 16245 +}; + +//Orb spells +enum OrbSpells +{ + SPELL_ORB_VISUAL = 48044, + SPELL_ORB_CHANNEL = 48048 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1575000, + SAY_SLAY_1 = -1575001, + SAY_SLAY_2 = -1575002, + SAY_DEATH = -1575003 +}; + +enum Creatures +{ + MOB_STASIS_CONTROLLER = 26688 +}; + +struct Locations +{ + float x, y, z; +}; + +struct Locations moveLocs[]= +{ + {261.6,-449.3,109.5}, + {263.3,-454.0,109.5}, + {291.5,-450.4,109.5}, + {291.5,-454.0,109.5}, + {310.0,-453.4,109.5}, + {238.6,-460.7,109.5} +}; + +enum Phase +{ + PHASE_FRENZIED_WORGEN, + PHASE_RAVENOUS_FURLBORG, + PHASE_MASSIVE_JORMUNGAR, + PHASE_FEROCIOUS_RHINO, + PHASE_GORTOK_PALEHOOF, + PHASE_NONE +}; + +struct boss_palehoofAI : public ScriptedAI +{ + boss_palehoofAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiArcingSmashTimer; + uint32 uiImpaleTimer; + uint32 uiWhiteringRoarTimer; + uint32 uiWaitingTimer; + Phase currentPhase; + uint8 AddCount; + bool DoneAdds[4]; + + ScriptedInstance *pInstance; + + void Reset() + { + uiArcingSmashTimer = 15000; + uiImpaleTimer = 12000; + uiWhiteringRoarTimer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + for (uint32 i=0;i<4;i++) + DoneAdds[i]=false; + AddCount=0; + + currentPhase=PHASE_NONE; + + if (pInstance) + { + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, NOT_STARTED); + + Creature* pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG)); + if (pTemp && !pTemp->isAlive()) + pTemp->Respawn(); + + GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GORTOK_PALEHOOF_SPHERE)); + if (pGo) + { + pGo->SetGoState(GO_STATE_READY); + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void UpdateAI(const uint32 diff) + { + if (currentPhase != PHASE_GORTOK_PALEHOOF) + return; + //Return since we have no target + if (!UpdateVictim()) + return; + + Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->DisappearAndDie(); + + if (uiArcingSmashTimer <= diff) + { + DoCast(me, SPELL_ARCING_SMASH); + uiArcingSmashTimer = urand(13000,17000); + } else uiArcingSmashTimer -= diff; + + if (uiImpaleTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_IMPALE); + uiImpaleTimer = urand(8000,12000); + } else uiImpaleTimer -= diff; + + if (uiWhiteringRoarTimer <= diff) + { + DoCast(me, SPELL_WITHERING_ROAR); + uiWhiteringRoarTimer = urand(8000,12000); + } else uiWhiteringRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + if (pInstance) + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, DONE); + Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pTemp && pTemp->isAlive()) + pTemp->DisappearAndDie(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void NextPhase() + { + if (currentPhase == PHASE_NONE) + { + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); + me->SummonCreature(MOB_STASIS_CONTROLLER,moveLocs[5].x,moveLocs[5].y,moveLocs[5].z,0,TEMPSUMMON_CORPSE_DESPAWN); + } + Phase move = PHASE_NONE; + if (AddCount >= DUNGEON_MODE(2,4)) + move = PHASE_GORTOK_PALEHOOF; + else + { + //select random not yet defeated add + uint8 next = urand(0,3); + for (uint8 i=0; i < 16; i++) + { + if (!DoneAdds[i%4] && next == 0) + { + move = (Phase)(i%4); + break; + } else if (!DoneAdds[i%4] && next > 0) + --next; + } + ++AddCount; + DoneAdds[move] = true; + move = (Phase)(move%4); + } + //send orb to summon spot + Creature *pOrb = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); + if (pOrb && pOrb->isAlive()) + { + if (currentPhase == PHASE_NONE) + pOrb->CastSpell(me,SPELL_ORB_VISUAL,true); + pOrb->GetMotionMaster()->MovePoint(move,moveLocs[move].x,moveLocs[move].y,moveLocs[move].z); + } + currentPhase = move; + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_boss_palehoof(Creature* pCreature) +{ + return new boss_palehoofAI (pCreature); +} + +//ravenous furbolg's spells +enum RavenousSpells +{ + SPELL_CHAIN_LIGHTING = 48140, + H_SPELL_CHAIN_LIGHTING = 59273, + SPELL_CRAZED = 48139, + SPELL_TERRIFYING_ROAR = 48144 +}; + +struct mob_ravenous_furbolgAI : public ScriptedAI +{ + mob_ravenous_furbolgAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiChainLightingTimer; + uint32 uiCrazedTimer; + uint32 uiTerrifyingRoarTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiChainLightingTimer = 5000; + uiCrazedTimer = 10000; + uiTerrifyingRoarTimer = 15000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiChainLightingTimer <= diff) + { + DoCast(me->getVictim(), SPELL_CHAIN_LIGHTING); + uiChainLightingTimer = 5000 + rand()%5000; + } else uiChainLightingTimer -= diff; + + if (uiCrazedTimer <= diff) + { + DoCast(me, SPELL_CRAZED); + uiCrazedTimer = 8000 + rand()%4000; + } else uiCrazedTimer -= diff; + + if (uiTerrifyingRoarTimer <= diff) + { + DoCast(me, SPELL_TERRIFYING_ROAR); + uiTerrifyingRoarTimer = 10000 + rand()%10000; + } else uiTerrifyingRoarTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_ravenous_furbolg(Creature* pCreature) +{ + return new mob_ravenous_furbolgAI (pCreature); +} + +//frenzied worgen's spells +enum FrenziedSpells +{ + SPELL_MORTAL_WOUND = 48137, + H_SPELL_MORTAL_WOUND = 59265, + SPELL_ENRAGE_1 = 48138, + SPELL_ENRAGE_2 = 48142 +}; + +struct mob_frenzied_worgenAI : public ScriptedAI +{ + mob_frenzied_worgenAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiMortalWoundTimer; + uint32 uiEnrage1Timer; + uint32 uiEnrage2Timer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiMortalWoundTimer = 5000; + uiEnrage1Timer = 15000; + uiEnrage2Timer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiMortalWoundTimer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + uiMortalWoundTimer = 3000 + rand()%4000; + } else uiMortalWoundTimer -= diff; + + if (uiEnrage1Timer <= diff) + { + DoCast(me, SPELL_ENRAGE_1); + uiEnrage1Timer = 15000; + } else uiEnrage1Timer -= diff; + + if (uiEnrage2Timer <= diff) + { + DoCast(me, SPELL_ENRAGE_2); + uiEnrage2Timer = 10000; + } else uiEnrage2Timer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + if (pInstance) + pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance->GetData64(DATA_GORTOK_PALEHOOF)); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_frenzied_worgen(Creature* pCreature) +{ + return new mob_frenzied_worgenAI (pCreature); +} + +//ferocious rhino's spells +enum FerociousSpells +{ + SPELL_GORE = 48130, + H_SPELL_GORE = 59264, + SPELL_GRIEVOUS_WOUND = 48105, + H_SPELL_GRIEVOUS_WOUND = 59263, + SPELL_STOMP = 48131 +}; + +struct mob_ferocious_rhinoAI : public ScriptedAI +{ + mob_ferocious_rhinoAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiStompTimer; + uint32 uiGoreTimer; + uint32 uiGrievousWoundTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiStompTimer = 10000; + uiGoreTimer = 15000; + uiGrievousWoundTimer = 20000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiStompTimer <= diff) + { + DoCast(me->getVictim(), SPELL_STOMP); + uiStompTimer = 8000 + rand()%4000; + } else uiStompTimer -= diff; + + if (uiGoreTimer <= diff) + { + DoCast(me->getVictim(), SPELL_GORE); + uiGoreTimer = 13000 + rand()%4000; + } else uiGoreTimer -= diff; + + if (uiGrievousWoundTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_GRIEVOUS_WOUND); + uiGrievousWoundTimer = 18000 + rand()%4000; + } else uiGrievousWoundTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_ferocious_rhino(Creature* pCreature) +{ + return new mob_ferocious_rhinoAI (pCreature); +} + +//massive jormungar's spells +enum MassiveSpells +{ + SPELL_ACID_SPIT = 48132, + SPELL_ACID_SPLATTER = 48136, + H_SPELL_ACID_SPLATTER = 59272, + SPELL_POISON_BREATH = 48133, + H_SPELL_POISON_BREATH = 59271 +}; + +enum MassiveAdds +{ + CREATURE_JORMUNGAR_WORM = 27228 +}; + +struct mob_massive_jormungarAI : public ScriptedAI +{ + mob_massive_jormungarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiAcidSpitTimer; + uint32 uiAcidSplatterTimer; + uint32 uiPoisonBreathTimer; + + ScriptedInstance *pInstance; + + void Reset() + { + uiAcidSpitTimer = 3000; + uiAcidSplatterTimer = 12000; + uiPoisonBreathTimer = 10000; + + me->GetMotionMaster()->MoveTargetedHome(); + + if (pInstance) + if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiAcidSpitTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_ACID_SPIT); + uiAcidSpitTimer = 2000 + rand()%2000; + } else uiAcidSpitTimer -= diff; + + if (uiAcidSplatterTimer <= diff) + { + DoCast(me, SPELL_POISON_BREATH); + uiAcidSplatterTimer = 10000 + rand()%4000; + } else uiAcidSplatterTimer -= diff; + + if (uiPoisonBreathTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + DoCast(pTarget, SPELL_POISON_BREATH); + uiPoisonBreathTimer = 8000 + rand()%4000; + } else uiPoisonBreathTimer -= diff; + + DoMeleeAttackIfReady(); + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + DoStartMovement(who); + } + } + + void JustDied(Unit* /*killer*/) + { + if (pInstance) + { + Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof) + CAST_AI(boss_palehoofAI,pPalehoof->AI())->NextPhase(); + } + } + + void JustReachedHome() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->SetStandState(UNIT_STAND_STATE_STAND); + DoCast(me, SPELL_FREEZE); + } +}; + +CreatureAI* GetAI_mob_massive_jormungar(Creature* pCreature) +{ + return new mob_massive_jormungarAI (pCreature); +} + + +struct mob_palehoof_orbAI : public ScriptedAI +{ + mob_palehoof_orbAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 SummonTimer; + Phase currentPhase; + + void Reset() + { + currentPhase=PHASE_NONE; + SummonTimer=5000; + me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); + me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL); + me->SetSpeed(MOVE_FLIGHT , 0.5f); + } + + void UpdateAI(const uint32 diff) + { + if (currentPhase == PHASE_NONE) + return; + + if (SummonTimer <= diff) + { + if (currentPhase<5&¤tPhase >= 0) + { + Creature *pNext = NULL; + switch(currentPhase) + { + case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; + case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; + case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; + case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; + case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; + } + + if (pNext) + { + pNext->RemoveAurasDueToSpell(SPELL_FREEZE); + pNext->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); + pNext->SetStandState(UNIT_STAND_STATE_STAND); + pNext->SetInCombatWithZone(); + pNext->Attack(pNext->SelectNearestTarget(100),true); + + } + currentPhase=PHASE_NONE; + } + } else SummonTimer-=diff; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + if (id<0 || id>4) + return; + Creature *pNext = NULL; + switch(id) + { + case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; + case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; + case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; + case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; + case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; + } + if (pNext) + DoCast(pNext, SPELL_ORB_CHANNEL, false); + currentPhase=(Phase)id; + SummonTimer=5000; + } +}; + +CreatureAI* GetAI_mob_palehoof_orb(Creature* pCreature) +{ + return new mob_palehoof_orbAI (pCreature); +} + + + +bool GOHello_palehoof_sphere(Player * /*pPlayer*/, GameObject *pGO) +{ + ScriptedInstance *pInstance = pGO->GetInstanceData(); + + Creature *pPalehoof = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); + if (pPalehoof && pPalehoof->isAlive()) + { + // maybe these are hacks :( + pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pGO->SetGoState(GO_STATE_ACTIVE); + + CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); + } + return true; +} + + + +void AddSC_boss_palehoof() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_palehoof"; + newscript->GetAI = &GetAI_boss_palehoof; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ravenous_furbolg"; + newscript->GetAI = &GetAI_mob_ravenous_furbolg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frenzied_worgen"; + newscript->GetAI = &GetAI_mob_frenzied_worgen; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ferocious_rhino"; + newscript->GetAI = &GetAI_mob_ferocious_rhino; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_massive_jormungar"; + newscript->GetAI = &GetAI_mob_massive_jormungar; + newscript->RegisterSelf(); + + + newscript = new Script; + newscript->Name = "mob_palehoof_orb"; + newscript->GetAI = &GetAI_mob_palehoof_orb; + newscript->RegisterSelf(); + + + newscript = new Script; + newscript->Name = "go_palehoof_sphere"; + newscript->pGOHello=&GOHello_palehoof_sphere; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp new file mode 100644 index 00000000000..a75eb3465be --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -0,0 +1,477 @@ +/* Copyright (C) 2008 - 2010 Trinity + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Script Data Start +SDName: Boss_Skadi +SDAuthor: LordVanMartin, JohnHoliver +SD%Complete: 90% +SDComment: + After Unmount() he appears to still be flying even with SetFlying(false) + +SDCategory: Utgarde Pinnacle +Script Data End */ + +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +//Yell +enum eYells +{ + SAY_AGGRO = -1575004, + SAY_KILL_1 = -1575005, + SAY_KILL_2 = -1575006, + EMOTE_RANGE = -1575007, //Skadi + SAY_DEATH = -1575008, + SAY_DRAKE_DEATH = -1575009, + EMOTE_BREATH = -1575010, //Grauf + SAY_DRAKE_BREATH_1 = -1575011, + SAY_DRAKE_BREATH_2 = -1575012, + SAY_DRAKE_BREATH_3 = -1575013, +}; + +static Position SpawnLoc = {468.931, -513.555, 104.723}; +static Position Location[]= +{ + // Boss + {341.740997, -516.955017, 104.66900}, // 0 + {293.299, -505.95, 142.03}, // 1 + {301.664, -535.164, 146.097}, // 2 + {521.031006, -544.667847, 128.80064}, // 3 + {477.311981, -509.296814, 104.72308}, // 4 + {341.740997, -516.955017, 104.66900}, // 5 + {341.740997, -516.955017, 104.66900}, // 6 + {341.740997, -516.955017, 104.66900}, // 7 + // Triggers Left + {469.661, -484.546, 104.712}, // 8 + {483.315, -485.028, 104.718}, // 9 + {476.87, -487.994, 104.735}, //10 + {477.512, -497.772, 104.728}, //11 + {486.287, -500.759, 104.722}, //12 + {480.1, -503.895, 104.722}, //13 + {472.391, -505.103, 104.723}, //14 + {478.885, -510.803, 104.723}, //15 + {489.529, -508.615, 104.723}, //16 + {484.272, -508.589, 104.723}, //17 + {465.328, -506.495, 104.427}, //18 + {456.885, -508.104, 104.447}, //19 + {450.177, -507.989, 105.247}, //20 + {442.273, -508.029, 104.813}, //21 + {434.225, -508.19, 104.787}, //22 + {423.902, -508.525, 104.274}, //23 + {414.551, -508.645, 105.136}, //24 + {405.787, -508.755, 104.988}, //25 + {398.812, -507.224, 104.82}, //26 + {389.702, -506.846, 104.729}, //27 + {381.856, -506.76, 104.756}, //28 + {372.881, -507.254, 104.779}, //29 + {364.978, -508.182, 104.673}, //30 + {357.633, -508.075, 104.647}, //31 + {350.008, -506.826, 104.588}, //32 + {341.69, -506.77, 104.499}, //33 + {335.31, -505.745, 105.18}, //34 + {471.178, -510.74, 104.723}, //35 + {461.759, -510.365, 104.199}, //36 + {424.07287, -510.082916, 104.711082}, //37 + // Triggers Right + {489.46, -513.297, 105.413}, //38 + {485.706, -517.175, 104.724}, //39 + {480.98, -519.313, 104.724}, //40 + {475.05, -520.52, 104.724}, //41 + {482.97, -512.099, 104.724}, //42 + {477.082, -514.172, 104.724}, //43 + {468.991, -516.691, 104.724}, //44 + {461.722, -517.063, 104.627}, //45 + {455.88, -517.681, 104.707}, //46 + {450.499, -519.099, 104.701}, //47 + {444.889, -518.963, 104.82}, //48 + {440.181, -518.893, 104.861}, //49 + {434.393, -518.758, 104.891}, //50 + {429.328, -518.583, 104.904}, //51 + {423.844, -518.394, 105.004}, //52 + {418.707, -518.266, 105.135}, //53 + {413.377, -518.085, 105.153}, //54 + {407.277, -517.844, 104.893}, //55 + {401.082, -517.443, 104.723}, //56 + {394.933, -514.64, 104.724}, //57 + {388.917, -514.688, 104.734}, //58 + {383.814, -515.834, 104.73}, //59 + {377.887, -518.653, 104.777}, //60 + {371.376, -518.289, 104.781}, //61 + {365.669, -517.822, 104.758}, //62 + {359.572, -517.314, 104.706}, //63 + {353.632, -517.146, 104.647}, //64 + {347.998, -517.038, 104.538}, //65 + {341.803, -516.98, 104.584}, //66 + {335.879, -516.674, 104.628}, //67 + {329.871, -515.92, 104.711}, //68 + // Breach Zone + {485.4577, -511.2515, 115.3011}, //69 + {435.1892, -514.5232, 118.6719}, //70 + {413.9327, -540.9407, 138.2614}, //71 +}; + +enum eCombatPhase +{ + FLYING, + SKADI +}; + +enum eSpells +{ + //Skadi Spells + SPELL_CRUSH = 50234, + SPELL_POISONED_SPEAR = 50225, //isn't being casted =/ + SPELL_WHIRLWIND = 50228, //random target, but not the tank approx. every 20s + SPELL_RAPID_FIRE = 56570, + SPELL_HARPOON_DAMAGE = 56578, + SPELL_FREEZING_CLOUD = 47579, +}; + +enum eCreature +{ + CREATURE_YMIRJAR_WARRIOR = 26690, + CREATURE_YMIRJAR_WITCH_DOCTOR = 26691, + CREATURE_YMIRJAR_HARPOONER = 26692, + CREATURE_GRAUF = 26893, + CREATURE_TRIGGER = 28351, + DATA_MOUNT = 27043, +}; + +enum eAchievments +{ + ACHIEV_TIMED_START_EVENT = 17726, +}; + +struct boss_skadiAI : public ScriptedAI +{ + boss_skadiAI(Creature *c) : ScriptedAI(c), Summons(me) + { + m_pInstance = c->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + SummonList Summons; + uint64 m_uiGraufGUID; + std::vector triggersGUID; + + uint32 m_uiCrushTimer; + uint32 m_uiPoisonedSpearTimer; + uint32 m_uiWhirlwindTimer; + uint32 m_uiWaypointId; + uint32 m_uiMovementTimer; + uint32 m_uiMountTimer; + uint32 m_uiSummonTimer; + uint8 m_uiSpellHitCount; + bool m_bSaidEmote; + + eCombatPhase Phase; + + void Reset() + { + triggersGUID.clear(); + + m_uiCrushTimer = 8000; + m_uiPoisonedSpearTimer = 10000; + m_uiWhirlwindTimer = 20000; + m_uiMountTimer = 3000; + m_uiWaypointId = 0; + m_bSaidEmote = false; + m_uiSpellHitCount = 0; + + Phase = SKADI; + + Summons.DespawnAll(); + me->SetSpeed(MOVE_FLIGHT, 3.0f); + if ((Unit::GetCreature((*me), m_uiGraufGUID) == NULL) && !me->IsMounted()) + me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); + if (m_pInstance) + { + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, NOT_STARTED); + m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + } + } + + void JustReachedHome() + { + me->SetFlying(false); + me->Unmount(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + if (Unit::GetCreature((*me), m_uiGraufGUID) == NULL) + me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + + Phase = FLYING; + + m_uiMovementTimer = 1000; + m_uiSummonTimer = 10000; + me->SetInCombatWithZone(); + if (m_pInstance) + { + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, IN_PROGRESS); + m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); + me->GetMotionMaster()->MoveJump(Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 5.0f, 10.0f); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + m_uiMountTimer = 1000; + Summons.DespawnEntry(CREATURE_GRAUF); + } + } + + void JustSummoned(Creature* pSummoned) + { + switch (pSummoned->GetEntry()) + { + case CREATURE_GRAUF: + m_uiGraufGUID = pSummoned->GetGUID(); + break; + case CREATURE_YMIRJAR_WARRIOR: + case CREATURE_YMIRJAR_WITCH_DOCTOR: + case CREATURE_YMIRJAR_HARPOONER: + pSummoned->setActive(true); + pSummoned->SetInCombatWithZone(); + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + break; + case CREATURE_TRIGGER: + pSummoned->CastSpell((Unit*)NULL, SPELL_FREEZING_CLOUD, true); + pSummoned->ForcedDespawn(10*IN_MILISECONDS); + break; + } + Summons.Summon(pSummoned); + } + + void SummonedCreatureDespawn(Creature* pSummoned) + { + if (pSummoned->GetEntry() == CREATURE_GRAUF) + m_uiGraufGUID = 0; + Summons.Despawn(pSummoned); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if (spell->Id == SPELL_HARPOON_DAMAGE) + { + m_uiSpellHitCount++; + if (m_uiSpellHitCount >= 5) + { + Phase = SKADI; + me->SetFlying(false); + me->Unmount(); + if(Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILISECONDS)) + { + pGrauf->GetMotionMaster()->MoveFall(0); + pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); + } + sLog.outBasic("[Skadi] Fly off"); + me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + DoScriptText(SAY_DRAKE_DEATH, me); + m_uiCrushTimer = 8000; + m_uiPoisonedSpearTimer = 10000; + m_uiWhirlwindTimer = 20000; + me->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); + } + } + } + + + void UpdateAI(const uint32 diff) + { + switch(Phase) + { + case FLYING: + if (!UpdateVictim()) + return; + + if (me->GetPositionX() >= 519) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + if (!m_bSaidEmote) + { + DoScriptText(EMOTE_RANGE, me); + m_bSaidEmote = true; + } + } + else + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); + m_bSaidEmote = false; + } + + if (m_uiMountTimer && m_uiMountTimer <= diff) + { + me->Mount(DATA_MOUNT); + me->SetFlying(true); + m_uiMountTimer = 0; + } else m_uiMountTimer -= diff; + + if (m_uiSummonTimer <= diff) + { + SpawnMobs(); + m_uiSummonTimer = 25000; + } else m_uiSummonTimer -= diff; + + if (m_uiMovementTimer <= diff) + { + switch(m_uiWaypointId) + { + case 0: + me->GetMotionMaster()->MovePoint(0, Location[1].GetPositionX(), Location[1].GetPositionY(), Location[1].GetPositionZ()); + m_uiMovementTimer = 5000; + break; + case 1: + me->GetMotionMaster()->MovePoint(0, Location[2].GetPositionX(), Location[2].GetPositionY(), Location[2].GetPositionZ()); + m_uiMovementTimer = 2000; + break; + case 2: + me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); + m_uiMovementTimer = 15000; + break; + case 3: + me->GetMotionMaster()->MovePoint(0, Location[69].GetPositionX(), Location[69].GetPositionY(), Location[69].GetPositionZ()); + DoScriptText(RAND(SAY_DRAKE_BREATH_1,SAY_DRAKE_BREATH_2), me); + DoScriptText(EMOTE_BREATH, me); + m_uiMovementTimer = 2500; + break; + case 4: + me->GetMotionMaster()->MovePoint(0, Location[70].GetPositionX(), Location[70].GetPositionY(), Location[70].GetPositionZ()); + m_uiMovementTimer = 2000; + SpawnTrigger(); + break; + case 5: + me->GetMotionMaster()->MovePoint(0, Location[71].GetPositionX(), Location[71].GetPositionY(), Location[71].GetPositionZ()); + m_uiMovementTimer = 3000; + break; + case 6: + me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); + m_uiWaypointId = 2; + m_uiMovementTimer = 15000; + break; + } + m_uiWaypointId++; + } else m_uiMovementTimer -= diff; + break; + case SKADI: + //Return since we have no target + if (!UpdateVictim()) + return; + + if (m_uiCrushTimer <= diff) + { + DoCastVictim(SPELL_CRUSH); + m_uiCrushTimer = 8000; + } else m_uiCrushTimer -= diff; + + if (m_uiPoisonedSpearTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) + DoCast(pTarget, SPELL_POISONED_SPEAR); + m_uiPoisonedSpearTimer = 10000; + } else m_uiPoisonedSpearTimer -= diff; + + if (m_uiWhirlwindTimer <= diff) + { + DoCastAOE(SPELL_WHIRLWIND); + m_uiWhirlwindTimer = 20000; + } else m_uiWhirlwindTimer -= diff; + + DoMeleeAttackIfReady(); + break; + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + Summons.DespawnAll(); + if (m_pInstance) + m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void SpawnMobs() + { + for (uint8 i = 0; i < DUNGEON_MODE(5,6); ++i) + { + switch (urand(0,2)) + { + case 0: me->SummonCreature(CREATURE_YMIRJAR_WARRIOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + case 1: me->SummonCreature(CREATURE_YMIRJAR_WITCH_DOCTOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + case 2: me->SummonCreature(CREATURE_YMIRJAR_HARPOONER, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; + } + } + } + + void SpawnTrigger() + { + uint8 iStart,iEnd; + switch (urand(0,1)) + { + case 0: + iStart = 8; + iEnd = 37; + break; + case 1: + iStart = 38; + iEnd = 68; + break; + } + for(uint32 i = iStart; i < iEnd; ++i) + me->SummonCreature(CREATURE_TRIGGER,Location[i]); + } +}; + +bool GOHello_go_harpoon_launcher(Player *pPlayer, GameObject *pGO) +{ + ScriptedInstance* m_pInstance; + m_pInstance = (ScriptedInstance*)pGO->GetInstanceData(); + if (!m_pInstance) return false; + + if (Creature* pSkadi = Unit::GetCreature((*pGO),m_pInstance->GetData64(DATA_SKADI_THE_RUTHLESS))) + { + pPlayer->CastSpell(pSkadi,SPELL_RAPID_FIRE, true); + } + return false; +} + +CreatureAI* GetAI_boss_skadi(Creature* pCreature) +{ + return new boss_skadiAI (pCreature); +} + +void AddSC_boss_skadi() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_skadi"; + newscript->GetAI = &GetAI_boss_skadi; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_harpoon_launcher"; + newscript->pGOHello = &GOHello_go_harpoon_launcher; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp new file mode 100644 index 00000000000..aae1015ddab --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp @@ -0,0 +1,408 @@ +/* Copyright (C) 2008 - 2010 TrinityCore + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_CALL_FLAMES = 48258, + SPELL_RITUAL_OF_THE_SWORD = 48276, //Effect #1 Teleport, Effect #2 Dummy + SPELL_SINSTER_STRIKE = 15667, + H_SPELL_SINSTER_STRIKE = 59409, + SPELL_SVALA_TRANSFORMING1 = 54140, + SPELL_SVALA_TRANSFORMING2 = 54205 +}; +//not in db +enum Yells +{ + SAY_DIALOG_WITH_ARTHAS_1 = -1575015, + SAY_DIALOG_WITH_ARTHAS_2 = -1575016, + SAY_DIALOG_WITH_ARTHAS_3 = -1575017, + SAY_AGGRO = -1575018, + SAY_SLAY_1 = -1575019, + SAY_SLAY_2 = -1575020, + SAY_SLAY_3 = -1575021, + SAY_DEATH = -1575022, + SAY_SACRIFICE_PLAYER_1 = -1575023, + SAY_SACRIFICE_PLAYER_2 = -1575024, + SAY_SACRIFICE_PLAYER_3 = -1575025, + SAY_SACRIFICE_PLAYER_4 = -1575026, + SAY_SACRIFICE_PLAYER_5 = -1575027, + SAY_DIALOG_OF_ARTHAS_1 = -1575028, + SAY_DIALOG_OF_ARTHAS_2 = -1575029 +}; +enum Creatures +{ + CREATURE_ARTHAS = 24266, // Image of Arthas + CREATURE_SVALA_SORROWGRAVE = 26668, // Svala after transformation + CREATURE_SVALA = 29281, // Svala before transformation + CREATURE_RITUAL_CHANNELER = 27281 +}; +enum ChannelerSpells +{ + //ritual channeler's spells + SPELL_PARALYZE = 48278, + SPELL_SHADOWS_IN_THE_DARK = 59407 +}; +enum Misc +{ + DATA_SVALA_DISPLAY_ID = 25944 +}; +enum IntroPhase +{ + IDLE, + INTRO, + FINISHED +}; +enum CombatPhase +{ + NORMAL, + SACRIFICING +}; + +static Position RitualChannelerPos[]= +{ + {296.42, -355.01, 90.94}, + {302.36, -352.01, 90.54}, + {291.39, -350.89, 90.54} +}; +static Position ArthasPos = { 295.81, -366.16, 92.57, 1.58 }; +static Position SvalaPos = { 296.632, -346.075, 90.6307, 1.58 }; + +struct boss_svalaAI : public ScriptedAI +{ + boss_svalaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiIntroTimer; + + uint8 uiIntroPhase; + + IntroPhase Phase; + + TempSummon* pArthas; + uint64 uiArthasGUID; + + ScriptedInstance* pInstance; + + void Reset() + { + Phase = IDLE; + uiIntroTimer = 1*IN_MILISECONDS; + uiIntroPhase = 0; + uiArthasGUID = 0; + + if (pInstance) + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (Phase == IDLE && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && me->IsWithinDistInMap(pWho, 40)) + { + Phase = INTRO; + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Creature *pArthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) + { + pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + pArthas->SetFloatValue(OBJECT_FIELD_SCALE_X, 5); + uiArthasGUID = pArthas->GetGUID(); + } + } + } + + void AttackStart(Unit* /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (Phase != INTRO) + return; + + if (uiIntroTimer <= diff) + { + Creature *pArthas = Unit::GetCreature(*me, uiArthasGUID); + if (!pArthas) + return; + + switch (uiIntroPhase) + { + case 0: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_1, me); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 1: + DoScriptText(SAY_DIALOG_OF_ARTHAS_1, pArthas); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 2: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_2, me); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 3: + DoScriptText(SAY_DIALOG_OF_ARTHAS_2, pArthas); + ++uiIntroPhase; + uiIntroTimer = 3.5*IN_MILISECONDS; + break; + case 4: + DoScriptText(SAY_DIALOG_WITH_ARTHAS_3, me); + DoCast(me, SPELL_SVALA_TRANSFORMING1); + ++uiIntroPhase; + uiIntroTimer = 2.8*IN_MILISECONDS; + break; + case 5: + DoCast(me, SPELL_SVALA_TRANSFORMING2); + ++uiIntroPhase; + uiIntroTimer = 200; + break; + case 6: + if (Creature* pSvalaSorrowgrave = me->SummonCreature(CREATURE_SVALA_SORROWGRAVE, SvalaPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60*IN_MILISECONDS)) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(DATA_SVALA_DISPLAY_ID); + pArthas->ToTempSummon()->UnSummon(); + uiArthasGUID = 0; + Phase = FINISHED; + } + else + Reset(); + break; + } + } else uiIntroTimer -= diff; + } +}; + +struct mob_ritual_channelerAI : public Scripted_NoMovementAI +{ + mob_ritual_channelerAI(Creature *c) :Scripted_NoMovementAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + void Reset() + { + DoCast(me, SPELL_SHADOWS_IN_THE_DARK); + } + + // called by svala sorrowgrave to set guid of victim + void DoAction(uint32 /*action*/) + { + if (pInstance) + if (Unit *pVictim = me->GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER))) + DoCast(pVictim, SPELL_PARALYZE); + } + + void EnterCombat(Unit* /*who*/) + { + } +}; + +struct boss_svala_sorrowgraveAI : public ScriptedAI +{ + boss_svala_sorrowgraveAI(Creature *c) : ScriptedAI(c), summons(c) + { + pInstance = c->GetInstanceData(); + } + + uint32 uiSinsterStrikeTimer; + uint32 uiCallFlamesTimer; + uint32 uiRitualOfSwordTimer; + uint32 uiSacrificeTimer; + + CombatPhase Phase; + + SummonList summons; + + bool bSacrificed; + + ScriptedInstance* pInstance; + + void Reset() + { + uiSinsterStrikeTimer = 7*IN_MILISECONDS; + uiCallFlamesTimer = 10*IN_MILISECONDS; + uiRitualOfSwordTimer = 20*IN_MILISECONDS; + uiSacrificeTimer = 8*IN_MILISECONDS; + + bSacrificed = false; + + Phase = NORMAL; + + DoTeleportTo(296.632, -346.075, 90.6307); + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + + summons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); + pInstance->SetData64(DATA_SACRIFICED_PLAYER,0); + } + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); + } + + void JustSummoned(Creature *summon) + { + summons.Summon(summon); + } + + void SummonedCreatureDespawn(Creature *summon) + { + summons.Despawn(summon); + } + + void UpdateAI(const uint32 diff) + { + if (Phase == NORMAL) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (uiSinsterStrikeTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); + uiSinsterStrikeTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); + } else uiSinsterStrikeTimer -= diff; + + if (uiCallFlamesTimer <= diff) + { + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoCast(pTarget, SPELL_CALL_FLAMES); + uiCallFlamesTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); + } + } else uiCallFlamesTimer -= diff; + + if (!bSacrificed) + if (uiRitualOfSwordTimer <= diff) + { + if (Unit* pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + { + DoScriptText(RAND(SAY_SACRIFICE_PLAYER_1,SAY_SACRIFICE_PLAYER_2,SAY_SACRIFICE_PLAYER_3,SAY_SACRIFICE_PLAYER_4,SAY_SACRIFICE_PLAYER_5),me); + DoCast(pSacrificeTarget, SPELL_RITUAL_OF_THE_SWORD); + //Spell doesn't teleport + DoTeleportPlayer(pSacrificeTarget, 296.632, -346.075, 90.63, 4.6); + me->SetUnitMovementFlags(MOVEMENTFLAG_FLY_MODE); + DoTeleportTo(296.632, -346.075, 120.85); + Phase = SACRIFICING; + if (pInstance) + { + pInstance->SetData64(DATA_SACRIFICED_PLAYER,pSacrificeTarget->GetGUID()); + + for (uint8 i = 0; i < 3; ++i) + if (Creature* pSummon = me->SummonCreature(CREATURE_RITUAL_CHANNELER, RitualChannelerPos[i], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) + pSummon->AI()->DoAction(0); + } + + bSacrificed = true; + } + } else uiRitualOfSwordTimer -= diff; + + DoMeleeAttackIfReady(); + } + else //SACRIFICING + { + if (uiSacrificeTimer <= diff) + { + Unit* pSacrificeTarget = pInstance ? Unit::GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER)) : NULL; + if (pInstance && !summons.empty() && pSacrificeTarget && pSacrificeTarget->isAlive()) + me->Kill(pSacrificeTarget, false); // durability damage? + + //go down + Phase = NORMAL; + pSacrificeTarget = NULL; + me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) + me->GetMotionMaster()->MoveChase(pTarget); + + uiSacrificeTimer = 8*IN_MILISECONDS; + } + else uiSacrificeTimer -= diff; + } + } + + void KilledUnit(Unit* /*pVictim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void JustDied(Unit* pKiller) + { + if (pInstance) + { + Creature* pSvala = Unit::GetCreature((*me), pInstance->GetData64(DATA_SVALA)); + if (pSvala && pSvala->isAlive()) + pKiller->Kill(pSvala); + + pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); + } + DoScriptText(SAY_DEATH, me); + } +}; + +CreatureAI* GetAI_boss_svala(Creature* pCreature) +{ + return new boss_svalaAI (pCreature); +} + +CreatureAI* GetAI_mob_ritual_channeler(Creature* pCreature) +{ + return new mob_ritual_channelerAI(pCreature); +} + +CreatureAI* GetAI_boss_svala_sorrowgrave(Creature* pCreature) +{ + return new boss_svala_sorrowgraveAI(pCreature); +} + +void AddSC_boss_svala() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_svala"; + newscript->GetAI = &GetAI_boss_svala; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ritual_channeler"; + newscript->GetAI = &GetAI_mob_ritual_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_svala_sorrowgrave"; + newscript->GetAI = &GetAI_boss_svala_sorrowgrave; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp new file mode 100644 index 00000000000..1a650f94101 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp @@ -0,0 +1,367 @@ +/* Script Data Start +SDName: Boss ymiron +SDAuthor: LordVanMartin +SD%Complete: +SDComment: +SDCategory: +Script Data End */ + +/*** SQL START *** +update creature_template set scriptname = 'boss_ymiron' where entry = ''; +*** SQL END ***/ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +enum Spells +{ + SPELL_BANE = 48294, + H_SPELL_BANE = 59301, + SPELL_DARK_SLASH = 48292, + SPELL_FETID_ROT = 48291, + H_SPELL_FETID_ROT = 59300, + SPELL_SCREAMS_OF_THE_DEAD = 51750, + SPELL_SPIRIT_BURST = 48529, + H_SPELL_SPIRIT_BURST = 59305, + SPELL_SPIRIT_STRIKE = 48423, + H_SPELL_SPIRIT_STRIKE = 59304, + SPELL_ANCESTORS_VENGEANCE = 16939, + + SPELL_SUMMON_AVENGING_SPIRIT = 48592, + SPELL_SUMMON_SPIRIT_FOUNT = 48386, + + SPELL_CHANNEL_SPIRIT_TO_YMIRON = 48316, + SPELL_CHANNEL_YMIRON_TO_SPIRIT = 48307, + + SPELL_SPIRIT_FOUNT = 48380, + H_SPELL_SPIRIT_FOUNT = 59320 +}; + +//not in db +enum Yells +{ + SAY_AGGRO = -1575028, + SAY_SLAY_1 = -1575029, + SAY_SLAY_2 = -1575030, + SAY_SLAY_3 = -1575031, + SAY_SLAY_4 = -1575032, + SAY_DEATH = -1575033, + SAY_SUMMON_BJORN = -1575034, + SAY_SUMMON_HALDOR = -1575035, + SAY_SUMMON_RANULF = -1575036, + SAY_SUMMON_TORGYN = -1575037 +}; + +enum Creatures +{ + CREATURE_BJORN = 27303, + CREATURE_BJORN_VISUAL = 27304, + CREATURE_HALDOR = 27307, + CREATURE_HALDOR_VISUAL = 27310, + CREATURE_RANULF = 27308, + CREATURE_RANULF_VISUAL = 27311, + CREATURE_TORGYN = 27309, + CREATURE_TORGYN_VISUAL = 27312, + CREATURE_SPIRIT_FOUNT = 27339, + CREATURE_AVENGING_SPIRIT = 27386 +}; + +struct ActiveBoatStruct +{ + uint32 npc; + int32 say; + float MoveX,MoveY,MoveZ,SpawnX,SpawnY,SpawnZ,SpawnO; +}; + +static ActiveBoatStruct ActiveBot[4] = +{ + {CREATURE_BJORN_VISUAL, SAY_SUMMON_BJORN, 404.379, -335.335, 104.756, 413.594, -335.408, 107.995, 3.157}, + {CREATURE_HALDOR_VISUAL, SAY_SUMMON_HALDOR, 380.813, -335.069, 104.756, 369.994, -334.771, 107.995, 6.232}, + {CREATURE_RANULF_VISUAL, SAY_SUMMON_RANULF, 381.546, -314.362, 104.756, 370.841, -314.426, 107.995, 6.232}, + {CREATURE_TORGYN_VISUAL, SAY_SUMMON_TORGYN, 404.310, -314.761, 104.756, 413.992, -314.703, 107.995, 3.157} +}; + +struct boss_ymironAI : public ScriptedAI +{ + boss_ymironAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + srand(time(NULL)); + for (int i = 0; i < 4; ++i) + m_uiActiveOrder[i] = i; + for (int i = 0; i < 3; ++i) + { + int r = i + (rand()%(4-i)); + int temp = m_uiActiveOrder[i]; + m_uiActiveOrder[i] = m_uiActiveOrder[r]; + m_uiActiveOrder[r] = temp; + } + } + + bool m_bIsWalking; + bool m_bIsPause; + bool m_bIsActiveWithBJORN; + bool m_bIsActiveWithHALDOR; + bool m_bIsActiveWithRANULF; + bool m_bIsActiveWithTORGYN; + + uint8 m_uiActiveOrder[4]; + uint8 m_uiActivedNumber; + + uint32 m_uiFetidRot_Timer; + uint32 m_uiBane_Timer; + uint32 m_uiDarkSlash_Timer; + uint32 m_uiAncestors_Vengeance_Timer; + + uint32 m_uiAbility_BJORN_Timer; + uint32 m_uiAbility_HALDOR_Timer; + uint32 m_uiAbility_RANULF_Timer; + uint32 m_uiAbility_TORGYN_Timer; + + uint32 m_uiPause_Timer; + uint32 m_uiHealthAmountModifier; + uint32 m_uiHealthAmountMultipler; + + uint64 m_uiActivedCreatureGUID; + uint64 m_uiOrbGUID; + + ScriptedInstance *pInstance; + + void Reset() + { + m_bIsPause = false; + m_bIsActiveWithBJORN = false; + m_bIsActiveWithHALDOR = false; + m_bIsActiveWithRANULF = false; + m_bIsActiveWithTORGYN = false; + + m_uiFetidRot_Timer = urand(8000,13000); + m_uiBane_Timer = urand(18000,23000); + m_uiDarkSlash_Timer = urand(28000,33000); + m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(60000,45000); + m_uiPause_Timer = 0; + + m_uiAbility_BJORN_Timer = 0; + m_uiAbility_HALDOR_Timer = 0; + m_uiAbility_RANULF_Timer = 0; + m_uiAbility_TORGYN_Timer = 0; + + m_uiActivedNumber = 0; + m_uiHealthAmountModifier = 1; + m_uiHealthAmountMultipler = DUNGEON_MODE(20,25); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (m_bIsWalking) + { + if (m_uiPause_Timer <= diff) + { + DoScriptText(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].say, me); + DoCast(me, SPELL_CHANNEL_YMIRON_TO_SPIRIT); // should be on spirit + if (Creature* pTemp = me->SummonCreature(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].npc, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnX, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnY, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnZ, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnO, TEMPSUMMON_CORPSE_DESPAWN, 0)) + { + m_uiActivedCreatureGUID = pTemp->GetGUID(); + pTemp->CastSpell(me, SPELL_CHANNEL_SPIRIT_TO_YMIRON, true); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + switch(m_uiActiveOrder[m_uiActivedNumber]) + { + case 0: m_bIsActiveWithBJORN = true; break; + case 1: m_bIsActiveWithHALDOR = true; break; + case 2: m_bIsActiveWithRANULF = true; break; + case 3: m_bIsActiveWithTORGYN = true; break; + } + } + + m_bIsPause = true; + m_bIsWalking = false; + m_uiPause_Timer = 3000; + } else m_uiPause_Timer -= diff; + return; + } + else if (m_bIsPause) + { + if (m_uiPause_Timer <= diff) + { + m_uiAbility_BJORN_Timer = 5000; + m_uiAbility_HALDOR_Timer = 5000; + m_uiAbility_RANULF_Timer = 5000; + m_uiAbility_TORGYN_Timer = 5000; + + m_bIsPause = false; + m_uiPause_Timer = 0; + } else m_uiPause_Timer -= diff; + return; + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + if (!m_bIsPause) + { + // Normal spells ------------------------------------------------------------------------ + if (m_uiBane_Timer <= diff) + { + DoCast(me, SPELL_BANE); + m_uiBane_Timer = urand(20000,25000); + } else m_uiBane_Timer -= diff; + + if (m_uiFetidRot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FETID_ROT); + m_uiFetidRot_Timer = urand(10000,15000); + } else m_uiFetidRot_Timer -= diff; + + if (m_uiDarkSlash_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DARK_SLASH); + m_uiDarkSlash_Timer = urand(30000,35000); + } else m_uiDarkSlash_Timer -= diff; + + if (m_uiAncestors_Vengeance_Timer <= diff) + { + DoCast(me, SPELL_ANCESTORS_VENGEANCE); + m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(urand(60000,65000),urand(45000,50000)); + } else m_uiAncestors_Vengeance_Timer -= diff; + + // Abilities ------------------------------------------------------------------------------ + if (m_bIsActiveWithBJORN && m_uiAbility_BJORN_Timer <= diff) + { + //DoCast(me, SPELL_SUMMON_SPIRIT_FOUNT); // works fine, but using summon has better control + if (Creature* pTemp = me->SummonCreature(CREATURE_SPIRIT_FOUNT, 385+rand()%10, -330+rand()%10, 104.756, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) + { + pTemp->SetSpeed(MOVE_RUN, 0.4f); + pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SPIRIT_FOUNT, H_SPELL_SPIRIT_FOUNT), true); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->SetDisplayId(11686); + //pTemp->GetMotionMaster()->MoveChase(me->getVictim()); + m_uiOrbGUID = pTemp->GetGUID(); + } + m_bIsActiveWithBJORN = false; // only one orb + } else m_uiAbility_BJORN_Timer -= diff; + + if (m_bIsActiveWithHALDOR && m_uiAbility_HALDOR_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SPIRIT_STRIKE); + m_uiAbility_HALDOR_Timer = 5000; // overtime + } else m_uiAbility_HALDOR_Timer -= diff; + + if (m_bIsActiveWithRANULF && m_uiAbility_RANULF_Timer <= diff) + { + DoCast(me, SPELL_SPIRIT_BURST); + m_uiAbility_RANULF_Timer = 10000; // overtime + } else m_uiAbility_RANULF_Timer -= diff; + + if (m_bIsActiveWithTORGYN && m_uiAbility_TORGYN_Timer <= diff) + { + float x,y,z; + x = me->GetPositionX()-5; + y = me->GetPositionY()-5; + z = me->GetPositionZ(); + for (uint8 i = 0; i < 4; ++i) + { + //DoCast(me, SPELL_SUMMON_AVENGING_SPIRIT); // works fine, but using summon has better control + if (Creature* pTemp = me->SummonCreature(CREATURE_AVENGING_SPIRIT, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + pTemp->AddThreat(pTarget, 0.0f); + pTemp->AI()->AttackStart(pTarget); + } + } + } + m_uiAbility_TORGYN_Timer = 15000; // overtime + } else m_uiAbility_TORGYN_Timer -= diff; + + // Health check ----------------------------------------------------------------------------- + if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(m_uiHealthAmountMultipler * m_uiHealthAmountModifier))) + { + uint8 m_uiOrder = m_uiHealthAmountModifier - 1; + ++m_uiHealthAmountModifier; + + me->InterruptNonMeleeSpells(true); + DoCast(me, SPELL_SCREAMS_OF_THE_DEAD); + me->GetMotionMaster()->Clear(); + me->StopMoving(); + me->AttackStop(); + me->GetMotionMaster()->MovePoint(0, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveX, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveY, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveZ); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + m_bIsActiveWithBJORN = false; + m_bIsActiveWithHALDOR = false; + m_bIsActiveWithRANULF = false; + m_bIsActiveWithTORGYN = false; + + m_uiBane_Timer += 8000; + m_uiFetidRot_Timer += 8000; + m_uiDarkSlash_Timer += 8000; + m_uiAncestors_Vengeance_Timer += 8000; + + m_uiActivedNumber = m_uiOrder; + m_bIsWalking = true; + m_uiPause_Timer = 2000; + return; + } + DoMeleeAttackIfReady(); + } + } + + void JustDied(Unit* /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + DespawnBoatGhosts(m_uiActivedCreatureGUID); + DespawnBoatGhosts(m_uiOrbGUID); + + if (pInstance) + pInstance->SetData(DATA_KING_YMIRON_EVENT, DONE); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); + } + + void DespawnBoatGhosts(uint64& m_uiCreatureGUID) + { + if (m_uiCreatureGUID) + if (Creature* pTemp = Unit::GetCreature(*me, m_uiCreatureGUID)) + pTemp->DisappearAndDie(); + + m_uiCreatureGUID = 0; + } +}; + +CreatureAI* GetAI_boss_ymiron(Creature* pCreature) +{ + return new boss_ymironAI(pCreature); +} + +void AddSC_boss_ymiron() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_ymiron"; + newscript->GetAI = &GetAI_boss_ymiron; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp new file mode 100644 index 00000000000..cf042867707 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/instance_pinnacle.cpp @@ -0,0 +1,241 @@ +#include "ScriptedPch.h" +#include "utgarde_pinnacle.h" + +#define MAX_ENCOUNTER 4 + +/* Utgarde Pinnacle encounters: +0 - Svala Sorrowgrave +1 - Gortok Palehoof +2 - Skadi the Ruthless +3 - King Ymiron +*/ + +enum GameObjects +{ + ENTRY_SKADI_THE_RUTHLESS_DOOR = 192173, + ENTRY_KING_YMIRON_DOOR = 192174, + ENTRY_GORK_PALEHOOF_SPHERE = 188593 +}; + +struct instance_pinnacle : public ScriptedInstance +{ + instance_pinnacle(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 uiSvalaSorrowgrave; + uint64 uiGortokPalehoof; + uint64 uiSkadiTheRuthless; + uint64 uiKingYmiron; + + uint64 uiSkadiTheRuthlessDoor; + uint64 uiKingYmironDoor; + uint64 uiGortokPalehoofSphere; + + uint64 uiFrenziedWorgen; + uint64 uiRavenousFurbolg; + uint64 uiFerociousRhino; + uint64 uiMassiveJormungar; + uint64 uiPalehoofOrb; + + uint64 uiSvala; + uint64 uiSacrificedPlayer; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + std::string str_data; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + m_auiEncounter[i] = NOT_STARTED; + + uiSvalaSorrowgrave = 0; + uiGortokPalehoof = 0; + uiSkadiTheRuthless = 0; + uiKingYmiron = 0; + + uiSkadiTheRuthlessDoor = 0; + uiKingYmironDoor = 0; + uiGortokPalehoofSphere = 0; + + uiFrenziedWorgen = 0; + uiRavenousFurbolg = 0; + uiFerociousRhino = 0; + uiMassiveJormungar = 0; + uiPalehoofOrb = 0; + + uiSvala = 0; + uiSacrificedPlayer = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case BOSS_SVALA_SORROWGRAVE: uiSvalaSorrowgrave = pCreature->GetGUID(); break; + case BOSS_GORTOK_PALEHOOF: uiGortokPalehoof = pCreature->GetGUID(); break; + case BOSS_SKADI_RUTHLESS: uiSkadiTheRuthless = pCreature->GetGUID(); break; + case BOSS_KING_YMIRON: uiKingYmiron = pCreature->GetGUID(); break; + case MOB_FRENZIED_WORGEN: uiFrenziedWorgen = pCreature->GetGUID(); break; + case MOB_RAVENOUS_FURBOLG: uiRavenousFurbolg = pCreature->GetGUID(); break; + case MOB_MASSIVE_JORMUNGAR: uiMassiveJormungar = pCreature->GetGUID(); break; + case MOB_FEROCIOUS_RHINO: uiFerociousRhino = pCreature->GetGUID(); break; + case MOB_SVALA: uiSvala = pCreature->GetGUID(); break; + case MOB_PALEHOOF_ORB: uiPalehoofOrb = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case ENTRY_SKADI_THE_RUTHLESS_DOOR: + uiSkadiTheRuthlessDoor = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) HandleGameObject(NULL,true,pGo); + break; + case ENTRY_KING_YMIRON_DOOR: + uiKingYmironDoor = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) HandleGameObject(NULL,true,pGo); + break; + case ENTRY_GORK_PALEHOOF_SPHERE: + uiGortokPalehoofSphere = pGo->GetGUID(); + if (m_auiEncounter[1] == DONE) + { + HandleGameObject(NULL,true,pGo); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + } + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_SVALA_SORROWGRAVE_EVENT: + m_auiEncounter[0] = data; + break; + case DATA_GORTOK_PALEHOOF_EVENT: + m_auiEncounter[1] = data; + break; + case DATA_SKADI_THE_RUTHLESS_EVENT: + if (data == DONE) + HandleGameObject(uiSkadiTheRuthlessDoor,true); + m_auiEncounter[2] = data; + break; + case DATA_KING_YMIRON_EVENT: + if (data == DONE) + HandleGameObject(uiKingYmironDoor,true); + m_auiEncounter[3] = data; + break; + } + + if (data == DONE) + SaveToDB(); + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_SACRIFICED_PLAYER) + uiSacrificedPlayer = data; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_SVALA_SORROWGRAVE_EVENT: return m_auiEncounter[0]; + case DATA_GORTOK_PALEHOOF_EVENT: return m_auiEncounter[1]; + case DATA_SKADI_THE_RUTHLESS_EVENT: return m_auiEncounter[2]; + case DATA_KING_YMIRON_EVENT: return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_SVALA_SORROWGRAVE: return uiSvalaSorrowgrave; + case DATA_GORTOK_PALEHOOF: return uiGortokPalehoof; + case DATA_SKADI_THE_RUTHLESS: return uiSkadiTheRuthless; + case DATA_KING_YMIRON: return uiKingYmiron; + case DATA_MOB_FRENZIED_WORGEN: return uiFrenziedWorgen; + case DATA_MOB_RAVENOUS_FURBOLG: return uiRavenousFurbolg; + case DATA_MOB_MASSIVE_JORMUNGAR: return uiMassiveJormungar; + case DATA_MOB_FEROCIOUS_RHINO: return uiFerociousRhino; + case DATA_MOB_ORB: return uiPalehoofOrb; + case DATA_SVALA: return uiSvala; + case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; + } + + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << "U P " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3]; + + str_data = saveStream.str(); + + OUT_SAVE_INST_DATA_COMPLETE; + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + char dataHead1, dataHead2; + uint16 data0, data1, data2, data3; + + std::istringstream loadStream(in); + loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; + + if (dataHead1 == 'U' && dataHead2 == 'P') + { + m_auiEncounter[0] = data0; + m_auiEncounter[1] = data1; + m_auiEncounter[2] = data2; + m_auiEncounter[3] = data3; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + } else OUT_LOAD_INST_DATA_FAIL; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_utgarde_pinnacle(Map* pMap) +{ + return new instance_pinnacle(pMap); +} + +void AddSC_instance_utgarde_pinnacle() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_utgarde_pinnacle"; + newscript->GetInstanceData = &GetInstanceData_instance_utgarde_pinnacle; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h new file mode 100644 index 00000000000..a51d7aceda0 --- /dev/null +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/utgarde_pinnacle.h @@ -0,0 +1,42 @@ +#ifndef DEF_PINNACLE_H +#define DEF_PINNACLE_H + +enum Data +{ + DATA_SVALA_SORROWGRAVE_EVENT, + DATA_GORTOK_PALEHOOF_EVENT, + DATA_SKADI_THE_RUTHLESS_EVENT, + DATA_KING_YMIRON_EVENT +}; +enum Data64 +{ + DATA_SVALA, + DATA_SVALA_SORROWGRAVE, + DATA_GORTOK_PALEHOOF, + DATA_SKADI_THE_RUTHLESS, + DATA_MOB_GRAUF, + DATA_KING_YMIRON, + DATA_MOB_FRENZIED_WORGEN, + DATA_MOB_RAVENOUS_FURBOLG, + DATA_MOB_MASSIVE_JORMUNGAR, + DATA_MOB_FEROCIOUS_RHINO, + DATA_MOB_ORB, + DATA_GORTOK_PALEHOOF_SPHERE, + DATA_SACRIFICED_PLAYER +}; + +enum eCreatures +{ + BOSS_SVALA_SORROWGRAVE = 26668, + BOSS_GORTOK_PALEHOOF = 26687, + BOSS_SKADI_RUTHLESS = 26693, + BOSS_KING_YMIRON = 26861, + MOB_FRENZIED_WORGEN = 26683, + MOB_RAVENOUS_FURBOLG = 26684, + MOB_MASSIVE_JORMUNGAR = 26685, + MOB_FEROCIOUS_RHINO = 26686, + MOB_SVALA = 29281, + MOB_PALEHOOF_ORB = 26688, +}; + +#endif diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp deleted file mode 100644 index 77f824c48d5..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_ingvar_the_plunderer.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ingvar_The_Plunderer -SD%Complete: 95 -SDComment: Some Problems with Annhylde Movement, Blizzlike Timers -SDCategory: Udgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum Yells -{ - //Yells Ingvar - YELL_AGGRO_1 = -1574005, - YELL_AGGRO_2 = -1574006, - - YELL_DEAD_1 = -1574007, - YELL_DEAD_2 = -1574008, - - YELL_KILL_1 = -1574009, - YELL_KILL_2 = -1574010, -}; - -enum Creatures -{ - MOB_INGVAR_HUMAN = 23954, - MOB_ANNHYLDE_THE_CALLER = 24068, - MOB_INGVAR_UNDEAD = 23980, -}; - -enum Spells -{ - //Ingvar Spells human form - SPELL_CLEAVE = 42724, - SPELL_SMASH = 42669, - H_SPELL_SMASH = 59706, - SPELL_STAGGERING_ROAR = 42708, - H_SPELL_STAGGERING_ROAR = 59708, - SPELL_ENRAGE = 42705, - H_SPELL_ENRAGE = 59707, - - SPELL_INGVAR_FEIGN_DEATH = 42795, - SPELL_SUMMON_BANSHEE = 42912, - SPELL_SCOURG_RESURRECTION = 42863, // Spawn resurrect effect around Ingvar - - //Ingvar Spells undead form - SPELL_DARK_SMASH = 42723, - SPELL_DREADFUL_ROAR = 42729, - H_SPELL_DREADFUL_ROAR = 59734, - SPELL_WOE_STRIKE = 42730, - H_SPELL_WOE_STRIKE = 59735, - - ENTRY_THROW_TARGET = 23996, - SPELL_SHADOW_AXE_SUMMON = 42749 -}; - -struct boss_ingvar_the_plundererAI : public ScriptedAI -{ - boss_ingvar_the_plundererAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool bIsUndead; - bool bEventInProgress; - - uint32 uiCleaveTimer; - uint32 uiSmashTimer; - uint32 uiEnrageTimer; - uint32 uiRoarTimer; - uint32 uiSpawnResTimer; - - void Reset() - { - if (bIsUndead) - me->UpdateEntry(MOB_INGVAR_HUMAN); - - bIsUndead = false; - bEventInProgress = false; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - - uiCleaveTimer = 2000; - uiSmashTimer = 5000; - uiEnrageTimer = 10000; - uiRoarTimer = 15000; - - uiSpawnResTimer = 3000; - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, NOT_STARTED); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (damage >= me->GetHealth() && !bIsUndead) - { - //DoCast(me, SPELL_INGVAR_FEIGN_DEATH, true); // Dont work ??? - // visuel hack - me->SetHealth(0); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - // visuel hack end - - bEventInProgress = true; - bIsUndead = true; - - DoScriptText(YELL_DEAD_1,me); - } - - if (bEventInProgress) - { - damage = 0; - } - } - - void StartZombiePhase() - { - bIsUndead = true; - bEventInProgress = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->UpdateEntry(MOB_INGVAR_UNDEAD); - me->SetInCombatWith(me->getVictim()); - me->GetMotionMaster()->MoveChase(me->getVictim()); - - DoScriptText(YELL_AGGRO_2,me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(YELL_AGGRO_1,me); - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(YELL_DEAD_2,me); - - if (pInstance) - pInstance->SetData(DATA_INGVAR_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - if (bIsUndead) - DoScriptText(YELL_KILL_1,me); - else - DoScriptText(YELL_KILL_2,me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (bEventInProgress) - { - if (uiSpawnResTimer) - if (uiSpawnResTimer <= diff) - { - DoCast(me, SPELL_SUMMON_BANSHEE); // Summons directly on caster position - // DoCast(me, SPELL_SCOURG_RESURRECTION, true); // Not needed ? - uiSpawnResTimer = 0; - } else uiSpawnResTimer -= diff; - - return; - } - - if (uiCleaveTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me->getVictim(), SPELL_WOE_STRIKE); - else - DoCast(me->getVictim(), SPELL_CLEAVE); - uiCleaveTimer = rand()%5000 + 2000; - } - } else uiCleaveTimer -= diff; - - if (uiSmashTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me->getVictim(), SPELL_DARK_SMASH); - else - DoCast(me->getVictim(), SPELL_SMASH); - uiSmashTimer = 10000; - } - } else uiSmashTimer -= diff; - - if (!bIsUndead) - { - if (uiEnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - uiEnrageTimer = 10000; - } else uiEnrageTimer -= diff; - } else // In Undead form used to summon weapon - { - if (uiEnrageTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - // Spawn target for Axe - Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); - if (pTarget) - { - me->SummonCreature(ENTRY_THROW_TARGET,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,2000); - - DoCast(me, SPELL_SHADOW_AXE_SUMMON); - } - uiEnrageTimer = 30000; - } - } else uiEnrageTimer -= diff; - } - - if (uiRoarTimer <= diff) - { - if (!me->hasUnitState(UNIT_STAT_CASTING)) - { - if (bIsUndead) - DoCast(me, SPELL_DREADFUL_ROAR); - else - DoCast(me, SPELL_STAGGERING_ROAR); - uiRoarTimer = 10000; - } - } else uiRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_ingvar_the_plunderer(Creature* pCreature) -{ - return new boss_ingvar_the_plundererAI(pCreature); -} - -enum eSpells -{ -//we don't have that text in db so comment it until we get this text -// YELL_RESSURECT = -1574025, - -//Spells for Annhylde - SPELL_SCOURG_RESURRECTION_HEAL = 42704, //Heal Max + DummyAura - SPELL_SCOURG_RESURRECTION_BEAM = 42857, //Channeling Beam of Annhylde - SPELL_SCOURG_RESURRECTION_DUMMY = 42862, //Some Emote Dummy? - SPELL_INGVAR_TRANSFORM = 42796 -}; - -struct mob_annhylde_the_callerAI : public ScriptedAI -{ - mob_annhylde_the_callerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - float x,y,z; - ScriptedInstance* pInstance; - uint32 uiResurectTimer; - uint32 uiResurectPhase; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING | MOVEMENTFLAG_HOVER); - me->SetSpeed(MOVE_SWIM , 1.0f); - me->SetSpeed(MOVE_RUN , 1.0f); - me->SetSpeed(MOVE_WALK , 1.0f); - //me->SetSpeed(MOVE_FLIGHT , 1.0f); - - me->GetPosition(x,y,z); - DoTeleportTo(x+1,y,z+30); - - Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - me->GetMotionMaster()->MovePoint(1,x,y,z+15); - -// DoScriptText(YELL_RESSURECT,me); - } - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - Unit* ingvar = Unit::GetUnit((*me), pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - switch (id) - { - case 1: - ingvar->RemoveAura(SPELL_SUMMON_BANSHEE); - ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_DUMMY,true); - DoCast(ingvar, SPELL_SCOURG_RESURRECTION_BEAM); - uiResurectTimer = 8000; - uiResurectPhase = 1; - break; - case 2: - me->SetVisibility(VISIBILITY_OFF); - me->DealDamage(me,me->GetHealth()); - me->RemoveCorpse(); - break; - } - } - } - - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit * /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (uiResurectTimer) - if (uiResurectTimer <= diff) - { - if (uiResurectPhase == 1) - { - Unit* ingvar = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0); - if (ingvar) - { - ingvar->SetStandState(UNIT_STAND_STATE_STAND); - ingvar->CastSpell(ingvar,SPELL_SCOURG_RESURRECTION_HEAL,false); - } - uiResurectTimer = 3000; - uiResurectPhase = 2; - } - else if (uiResurectPhase == 2) - { - if (Creature* ingvar = Unit::GetCreature(*me, pInstance ? pInstance->GetData64(DATA_INGVAR) : 0)) - { - ingvar->RemoveAurasDueToSpell(SPELL_SCOURG_RESURRECTION_DUMMY); - - if (boss_ingvar_the_plundererAI* pAI = CAST_AI(boss_ingvar_the_plundererAI, ingvar->AI())) - pAI->StartZombiePhase(); - - me->GetMotionMaster()->MovePoint(2,x+1,y,z+30); - ++uiResurectPhase; - uiResurectTimer = 0; - } - } - - } else uiResurectTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_annhylde_the_caller(Creature* pCreature) -{ - return new mob_annhylde_the_callerAI (pCreature); -} - -enum eShadowAxe -{ - SPELL_SHADOW_AXE_DAMAGE = 42750, - H_SPELL_SHADOW_AXE_DAMAGE = 59719 -}; - -struct mob_ingvar_throw_dummyAI : public ScriptedAI -{ - mob_ingvar_throw_dummyAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 uiDespawnTimer; - - void Reset() - { - Unit *pTarget = me->FindNearestCreature(ENTRY_THROW_TARGET,50); - if (pTarget) - { - DoCast(me, SPELL_SHADOW_AXE_DAMAGE); - float x,y,z; - pTarget->GetPosition(x,y,z); - me->GetMotionMaster()->MovePoint(0,x,y,z); - } - uiDespawnTimer = 7000; - } - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void EnterCombat(Unit * /*who*/) {} - void UpdateAI(const uint32 diff) - { - if (uiDespawnTimer <= diff) - { - me->DealDamage(me,me->GetHealth()); - me->RemoveCorpse(); - uiDespawnTimer = 0; - } else uiDespawnTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_ingvar_throw_dummy(Creature* pCreature) -{ - return new mob_ingvar_throw_dummyAI (pCreature); -} - -void AddSC_boss_ingvar_the_plunderer() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ingvar_the_plunderer"; - newscript->GetAI = &GetAI_boss_ingvar_the_plunderer; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_annhylde_the_caller"; - newscript->GetAI = &GetAI_mob_annhylde_the_caller; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ingvar_throw_dummy"; - newscript->GetAI = &GetAI_mob_ingvar_throw_dummy; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp deleted file mode 100644 index d69f0eee846..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_keleseth.cpp +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Prince_Keleseth -SD%Complete: 90 -SDComment: Needs Prince Movements, Needs adjustments to blizzlike timers, Needs Shadowbolt castbar, Needs right Ressurect Visual, Needs Some Heroic Spells -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum eEnums -{ - ACHIEVEMENT_ON_THE_ROCKS = 1919, - - SPELL_SHADOWBOLT = 43667, - SPELL_SHADOWBOLT_HEROIC = 59389, - SPELL_FROST_TOMB = 48400, - SPELL_FROST_TOMB_SUMMON = 42714, - SPELL_DECREPIFY = 42702, - SPELL_SCOURGE_RESSURRECTION = 42704, - CREATURE_FROSTTOMB = 23965, - CREATURE_SKELETON = 23970, - - SAY_AGGRO = -1574000, - SAY_FROST_TOMB = -1574001, - SAY_SKELETONS = -1574002, - SAY_KILL = -1574003, - SAY_DEATH = -1574004 -}; - -#define SKELETONSPAWN_Z 42.8668 - -float SkeletonSpawnPoint[5][5]= -{ - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, - {156.2559, 259.2093}, -}; - -float AttackLoc[3]={197.636, 194.046, 40.8164}; - -bool ShatterFrostTomb; // needed for achievement: On The Rocks(1919) - -struct mob_frost_tombAI : public ScriptedAI -{ - mob_frost_tombAI(Creature *c) : ScriptedAI(c) - { - FrostTombGUID = 0; - } - - uint64 FrostTombGUID; - - void SetPrisoner(Unit* uPrisoner) - { - FrostTombGUID = uPrisoner->GetGUID(); - } - - void Reset(){ FrostTombGUID = 0; } - void EnterCombat(Unit* /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - - void JustDied(Unit *killer) - { - if (killer->GetGUID() != me->GetGUID()) - ShatterFrostTomb = true; - - if (FrostTombGUID) - { - Unit* FrostTomb = Unit::GetUnit((*me),FrostTombGUID); - if (FrostTomb) - FrostTomb->RemoveAurasDueToSpell(SPELL_FROST_TOMB); - } - } - - void UpdateAI(const uint32 /*diff*/) - { - Unit* temp = Unit::GetUnit((*me),FrostTombGUID); - if ((temp && temp->isAlive() && !temp->HasAura(SPELL_FROST_TOMB)) || !temp) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } -}; - -struct boss_kelesethAI : public ScriptedAI -{ - boss_kelesethAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 FrostTombTimer; - uint32 SummonSkeletonsTimer; - uint32 RespawnSkeletonsTimer; - uint32 ShadowboltTimer; - uint64 SkeletonGUID[5]; - bool Skeletons; - bool RespawnSkeletons; - - void Reset() - { - ShadowboltTimer = 0; - Skeletons = false; - - ShatterFrostTomb = false; - - ResetTimer(); - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, NOT_STARTED); - } - - void KilledUnit(Unit * victim) - { - if (victim == me) - return; - - DoScriptText(SAY_KILL, me); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (IsHeroic() && !ShatterFrostTomb) - { - AchievementEntry const *AchievOnTheRocks = GetAchievementStore()->LookupEntry(ACHIEVEMENT_ON_THE_ROCKS); - if (AchievOnTheRocks) - { - Map* pMap = me->GetMap(); - if (pMap && pMap->IsDungeon()) - { - Map::PlayerList const &players = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - itr->getSource()->CompletedAchievement(AchievOnTheRocks); - } - } - } - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, DONE); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_PRINCEKELESETH_EVENT, IN_PROGRESS); - } - - void ResetTimer(uint32 inc = 0) - { - SummonSkeletonsTimer = 5000 + inc; - FrostTombTimer = 28000 + inc; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowboltTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) - me->CastSpell(pTarget, DUNGEON_MODE(SPELL_SHADOWBOLT, SPELL_SHADOWBOLT_HEROIC), true); - ShadowboltTimer = 10000; - } else ShadowboltTimer -= diff; - - if (!Skeletons) - if ((SummonSkeletonsTimer <= diff)) - { - Creature* Skeleton; - DoScriptText(SAY_SKELETONS, me); - for (uint8 i = 0; i < 5; ++i) - { - Skeleton = me->SummonCreature(CREATURE_SKELETON, SkeletonSpawnPoint[i][0], SkeletonSpawnPoint[i][1] , SKELETONSPAWN_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000); - if (Skeleton) - { - Skeleton->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - Skeleton->GetMotionMaster()->MovePoint(0, me->GetPositionX(), me->GetPositionY() , me->GetPositionZ()); - Skeleton->AddThreat(me->getVictim(), 0.0f); - DoZoneInCombat(Skeleton); - } - } - Skeletons = true; - } else SummonSkeletonsTimer -= diff; - - if (FrostTombTimer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - if (pTarget->isAlive()) - { - //DoCast(pTarget, SPELL_FROST_TOMB_SUMMON, true); - if (Creature *pChains = me->SummonCreature(CREATURE_FROSTTOMB, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) - { - CAST_AI(mob_frost_tombAI, pChains->AI())->SetPrisoner(pTarget); - pChains->CastSpell(pTarget, SPELL_FROST_TOMB, true); - - DoScriptText(SAY_FROST_TOMB, me); - } - } - FrostTombTimer = 15000; - } else FrostTombTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct mob_vrykul_skeletonAI : public ScriptedAI -{ - mob_vrykul_skeletonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 Respawn_Time; - uint64 Target_Guid; - uint32 Decrepify_Timer; - - bool isDead; - - void Reset() - { - Respawn_Time = 12000; - Decrepify_Timer = urand(10000,20000); - isDead = false; - } - - void EnterCombat(Unit * /*who*/){} - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() == me->GetGUID()) - return; - - if (damage >= me->GetHealth()) - { - PretendToDie(); - damage = 0; - } - } - - void PretendToDie() - { - isDead = true; - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->GetMotionMaster()->MovementExpired(false); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - }; - - void Resurrect() - { - isDead = false; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_SCOURGE_RESSURRECTION, true); - - if (me->getVictim()) - { - me->GetMotionMaster()->MoveChase(me->getVictim()); - me->AI()->AttackStart(me->getVictim()); - } - else - me->GetMotionMaster()->Initialize(); - }; - - void UpdateAI(const uint32 diff) - { - if (pInstance && pInstance->GetData(DATA_PRINCEKELESETH_EVENT) == IN_PROGRESS) - { - if (isDead) - { - if (Respawn_Time <= diff) - { - Resurrect(); - Respawn_Time = 12000; - } else Respawn_Time -= diff; - } - else - { - if (!UpdateVictim()) - return; - - if (Decrepify_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DECREPIFY); - Decrepify_Timer = 30000; - } else Decrepify_Timer -= diff; - - DoMeleeAttackIfReady(); - } - }else - { - if (me->isAlive()) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - } -}; - -CreatureAI* GetAI_mob_frost_tomb(Creature* pCreature) -{ - return new mob_frost_tombAI(pCreature); -} - -CreatureAI* GetAI_boss_keleseth(Creature* pCreature) -{ - return new boss_kelesethAI (pCreature); -} - -CreatureAI* GetAI_mob_vrykul_skeleton(Creature* pCreature) -{ - return new mob_vrykul_skeletonAI (pCreature); -} - -void AddSC_boss_keleseth() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_keleseth"; - newscript->GetAI = &GetAI_boss_keleseth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frost_tomb"; - newscript->GetAI = &GetAI_mob_frost_tomb; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_vrykul_skeleton"; - newscript->GetAI = &GetAI_mob_vrykul_skeleton; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp deleted file mode 100644 index 2146d37635b..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/boss_skarvald_dalronn.cpp +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Skarvald_Dalronn -SD%Complete: 95 -SDComment: Needs adjustments to blizzlike timers, Yell Text + Sound to DB -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -enum eEnums -{ - //signed for 24200, but used by 24200,27390 - YELL_SKARVALD_AGGRO = -1574011, - YELL_SKARVALD_DAL_DIED = -1574012, - YELL_SKARVALD_SKA_DIEDFIRST = -1574013, - YELL_SKARVALD_KILL = -1574014, - YELL_SKARVALD_DAL_DIEDFIRST = -1574015, - - //signed for 24201, but used by 24201,27389 - YELL_DALRONN_AGGRO = -1574016, - YELL_DALRONN_SKA_DIED = -1574017, - YELL_DALRONN_DAL_DIEDFIRST = -1574018, - YELL_DALRONN_KILL = -1574019, - YELL_DALRONN_SKA_DIEDFIRST = -1574020, - -//Spells of Skarvald and his Ghost - MOB_SKARVALD_THE_CONSTRUCTOR = 24200, - SPELL_CHARGE = 43651, - SPELL_STONE_STRIKE = 48583, - SPELL_SUMMON_SKARVALD_GHOST = 48613, - MOB_SKARVALD_GHOST = 27390, -//Spells of Dalronn and his Ghost - MOB_DALRONN_THE_CONTROLLER = 24201, - SPELL_SHADOW_BOLT = 43649, - H_SPELL_SHADOW_BOLT = 59575, - H_SPELL_SUMMON_SKELETONS = 52611, - SPELL_DEBILITATE = 43650, - SPELL_SUMMON_DALRONN_GHOST = 48612, - MOB_DALRONN_GHOST = 27389 -}; - -struct boss_skarvald_the_constructorAI : public ScriptedAI -{ - boss_skarvald_the_constructorAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool ghost; - uint32 Charge_Timer; - uint32 StoneStrike_Timer; - uint32 Response_Timer; - uint32 Check_Timer; - bool Dalronn_isDead; - - void Reset() - { - Charge_Timer = 5000; - StoneStrike_Timer = 10000; - Dalronn_isDead = false; - Check_Timer = 5000; - - ghost = (me->GetEntry() == MOB_SKARVALD_GHOST); - if (!ghost && pInstance) - { - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn && dalronn->isDead()) - CAST_CRE(dalronn)->Respawn(); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit * who) - { - if (!ghost && pInstance) - { - DoScriptText(YELL_SKARVALD_AGGRO,me); - - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn && dalronn->isAlive() && !dalronn->getVictim()) - dalronn->getThreatManager().addThreat(who,0.0f); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* Killer) - { - if (!ghost && pInstance) - { - Unit* dalronn = Unit::GetUnit((*me),pInstance->GetData64(DATA_DALRONN)); - if (dalronn) - { - if (dalronn->isDead()) - { - DoScriptText(YELL_SKARVALD_DAL_DIED,me); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); - } - else - { - DoScriptText(YELL_SKARVALD_SKA_DIEDFIRST,me); - - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - //DoCast(me, SPELL_SUMMON_SKARVALD_GHOST, true); - Creature* temp = me->SummonCreature(MOB_SKARVALD_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); - if (temp) - { - temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - temp->AI()->AttackStart(Killer); - } - } - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - if (!ghost) - { - DoScriptText(YELL_SKARVALD_KILL,me); - } - } - - void UpdateAI(const uint32 diff) - { - if (ghost) - { - if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (!UpdateVictim()) - return; - - if (!ghost) - { - if (Check_Timer) - if (Check_Timer <= diff) - { - Check_Timer = 5000; - Unit* dalronn = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_DALRONN) : 0); - if (dalronn && dalronn->isDead()) - { - Dalronn_isDead = true; - Response_Timer = 2000; - Check_Timer = 0; - } - } else Check_Timer -= diff; - - if (Response_Timer) - if (Dalronn_isDead) - if (Response_Timer <= diff) - { - DoScriptText(YELL_SKARVALD_DAL_DIEDFIRST,me); - - Response_Timer = 0; - } else Response_Timer -= diff; - } - - if (Charge_Timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 1), SPELL_CHARGE); - Charge_Timer = 5000+rand()%5000; - } else Charge_Timer -= diff; - - if (StoneStrike_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STONE_STRIKE); - StoneStrike_Timer = 5000+rand()%5000; - } else StoneStrike_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_skarvald_the_constructor(Creature* pCreature) -{ - return new boss_skarvald_the_constructorAI (pCreature); -} - -struct boss_dalronn_the_controllerAI : public ScriptedAI -{ - boss_dalronn_the_controllerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool ghost; - uint32 ShadowBolt_Timer; - uint32 Debilitate_Timer; - uint32 Summon_Timer; - - uint32 Response_Timer; - uint32 Check_Timer; - uint32 AggroYell_Timer; - bool Skarvald_isDead; - - void Reset() - { - ShadowBolt_Timer = 1000; - Debilitate_Timer = 5000; - Summon_Timer = 10000; - Check_Timer = 5000; - Skarvald_isDead = false; - AggroYell_Timer = 0; - - ghost = me->GetEntry() == MOB_DALRONN_GHOST; - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald && skarvald->isDead()) - CAST_CRE(skarvald)->Respawn(); - - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, NOT_STARTED); - } - } - - void EnterCombat(Unit * who) - { - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald && skarvald->isAlive() && !skarvald->getVictim()) - skarvald->getThreatManager().addThreat(who,0.0f); - - AggroYell_Timer = 5000; - - if (pInstance) - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, IN_PROGRESS); - } - } - - void JustDied(Unit* Killer) - { - if (!ghost && pInstance) - { - Unit* skarvald = Unit::GetUnit((*me),pInstance->GetData64(DATA_SKARVALD)); - if (skarvald) - if (skarvald->isDead()) - { - DoScriptText(YELL_DALRONN_SKA_DIED,me); - - if (pInstance) - pInstance->SetData(DATA_SKARVALD_DALRONN_EVENT, DONE); - } - else - { - DoScriptText(YELL_DALRONN_DAL_DIEDFIRST,me); - - me->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); - //DoCast(me, SPELL_SUMMON_DALRONN_GHOST, true); - Creature* temp = me->SummonCreature(MOB_DALRONN_GHOST,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),0,TEMPSUMMON_CORPSE_DESPAWN,5000); - if (temp) - { - temp->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_NON_ATTACKABLE); - temp->AI()->AttackStart(Killer); - } - } - } - } - - void KilledUnit(Unit * /*victim*/) - { - if (!ghost) - { - DoScriptText(YELL_DALRONN_KILL,me); - } - } - - void UpdateAI(const uint32 diff) - { - if (ghost) - { - if (pInstance && pInstance->GetData(DATA_SKARVALD_DALRONN_EVENT) != IN_PROGRESS) - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - if (!UpdateVictim()) - return; - - if (AggroYell_Timer) - if (AggroYell_Timer <= diff) - { - DoScriptText(YELL_DALRONN_AGGRO,me); - - AggroYell_Timer = 0; - } else AggroYell_Timer -= diff; - - if (!ghost) - { - if (Check_Timer) - if (Check_Timer <= diff) - { - Check_Timer = 5000; - Unit* skarvald = Unit::GetUnit(*me, pInstance ? pInstance->GetData64(DATA_SKARVALD) : 0); - if (skarvald && skarvald->isDead()) - { - Skarvald_isDead = true; - Response_Timer = 2000; - Check_Timer = 0; - } - } else Check_Timer -= diff; - - if (Response_Timer) - if (Skarvald_isDead) - if (Response_Timer <= diff) - { - DoScriptText(YELL_DALRONN_SKA_DIEDFIRST,me); - - Response_Timer = 0; - } else Response_Timer -= diff; - } - - if (ShadowBolt_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_SHADOW_BOLT); - ShadowBolt_Timer = 2100;//give a 100ms pause to try cast other spells - } - } else ShadowBolt_Timer -= diff; - - if (Debilitate_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), SPELL_DEBILITATE); - Debilitate_Timer = 5000+rand()%5000; - } - } else Debilitate_Timer -= diff; - - if (IsHeroic()) - if (Summon_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, H_SPELL_SUMMON_SKELETONS); - Summon_Timer = (rand()%10000) + 20000; - } - } else Summon_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_dalronn_the_controller(Creature* pCreature) -{ - return new boss_dalronn_the_controllerAI (pCreature); -} - -void AddSC_boss_skarvald_dalronn() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_skarvald_the_constructor"; - newscript->GetAI = &GetAI_boss_skarvald_the_constructor; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_dalronn_the_controller"; - newscript->GetAI = &GetAI_boss_dalronn_the_controller; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp deleted file mode 100644 index 03f97b1d27e..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/instance_utgarde_keep.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Utgarde_Keep -SD%Complete: 90 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Utgarde Keep Scripts -SDCategory: Utgarde Keep -EndScriptData */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -#define MAX_ENCOUNTER 3 - -#define ENTRY_BELLOW_1 186688 -#define ENTRY_BELLOW_2 186689 -#define ENTRY_BELLOW_3 186690 - -#define ENTRY_FORGEFIRE_1 186692 -#define ENTRY_FORGEFIRE_2 186693 -#define ENTRY_FORGEFIRE_3 186691 - -#define ENTRY_GLOWING_ANVIL_1 186609 -#define ENTRY_GLOWING_ANVIL_2 186610 -#define ENTRY_GLOWING_ANVIL_3 186611 - -#define ENTRY_GIANT_PORTCULLIS_1 186756 -#define ENTRY_GIANT_PORTCULLIS_2 186694 - -/* Utgarde Keep encounters: -0 - Prince Keleseth -1 - Skarvald Dalronn -2 - Ingvar the Plunderer -*/ - -struct instance_utgarde_keep : public ScriptedInstance -{ - instance_utgarde_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 Keleseth; - uint64 Skarvald; - uint64 Dalronn; - uint64 Ingvar; - - uint64 forge_bellow[3]; - uint64 forge_fire[3]; - uint64 forge_anvil[3]; - uint64 portcullis[2]; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint32 forge_event[3]; - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - Keleseth = 0; - Skarvald = 0; - Dalronn = 0; - Ingvar = 0; - - for (uint8 i = 0; i < 3; ++i) - { - forge_bellow[i] = 0; - forge_fire[i] = 0; - forge_anvil[i] = 0; - forge_event[i] = NOT_STARTED; - } - - portcullis[0] = 0; - portcullis[1] = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - Player* GetPlayerInMap() - { - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) - { - for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } - } - - debug_log("TSCR: Instance Utgarde Keep: GetPlayerInMap, but PlayerList is empty!"); - return NULL; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 23953: Keleseth = pCreature->GetGUID(); break; - case 24201: Dalronn = pCreature->GetGUID(); break; - case 24200: Skarvald = pCreature->GetGUID(); break; - case 23954: Ingvar = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - //door and object id - case ENTRY_BELLOW_1: forge_bellow[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_BELLOW_2: forge_bellow[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_BELLOW_3: forge_bellow[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_1: forge_fire[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_2: forge_fire[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_FORGEFIRE_3: forge_fire[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_1: forge_anvil[0] = pGo->GetGUID(); - if (forge_event[0] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_2: forge_anvil[1] = pGo->GetGUID(); - if (forge_event[1] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GLOWING_ANVIL_3: forge_anvil[2] = pGo->GetGUID(); - if (forge_event[2] != NOT_STARTED)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GIANT_PORTCULLIS_1: portcullis[0] = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; - case ENTRY_GIANT_PORTCULLIS_2: portcullis[1] = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE)HandleGameObject(NULL,true,pGo);break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_PRINCEKELESETH: return Keleseth; - case DATA_DALRONN: return Dalronn; - case DATA_SKARVALD: return Skarvald; - case DATA_INGVAR: return Ingvar; - } - - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_PRINCEKELESETH_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_SKARVALD_DALRONN_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_INGVAR_EVENT: - if (data == DONE) - { - HandleGameObject(portcullis[0], true); - HandleGameObject(portcullis[1], true); - } - m_auiEncounter[2] = data; - break; - case EVENT_FORGE_1: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[0],false); - HandleGameObject(forge_fire[0],false); - HandleGameObject(forge_anvil[0],false); - }else - { - HandleGameObject(forge_bellow[0],true); - HandleGameObject(forge_fire[0],true); - HandleGameObject(forge_anvil[0],true); - } - forge_event[0] = data; - break; - case EVENT_FORGE_2: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[1],false); - HandleGameObject(forge_fire[1],false); - HandleGameObject(forge_anvil[1],false); - }else - { - HandleGameObject(forge_bellow[1],true); - HandleGameObject(forge_fire[1],true); - HandleGameObject(forge_anvil[1],true); - } - forge_event[1] = data; - break; - case EVENT_FORGE_3: - if (data == NOT_STARTED) - { - HandleGameObject(forge_bellow[2],false); - HandleGameObject(forge_fire[2],false); - HandleGameObject(forge_anvil[2],false); - }else - { - HandleGameObject(forge_bellow[2],true); - HandleGameObject(forge_fire[2],true); - HandleGameObject(forge_anvil[2],true); - } - forge_event[2] = data; - break; - } - - if (data == DONE) - { - SaveToDB(); - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_PRINCEKELESETH_EVENT: return m_auiEncounter[0]; - case DATA_SKARVALD_DALRONN_EVENT: return m_auiEncounter[1]; - case DATA_INGVAR_EVENT: return m_auiEncounter[2]; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "U K " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << forge_event[0] << " " << forge_event[1] << " " << forge_event[2]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3, data4, data5; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3 >> data4 >> data5; - - if (dataHead1 == 'U' && dataHead2 == 'K') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - forge_event[0] = data3; - forge_event[1] = data4; - forge_event[2] = data5; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_utgarde_keep(Map* pMap) -{ - return new instance_utgarde_keep(pMap); -} - -void AddSC_instance_utgarde_keep() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_utgarde_keep"; - newscript->GetInstanceData = &GetInstanceData_instance_utgarde_keep; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp deleted file mode 100644 index 95825aa49b6..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "utgarde_keep.h" - -uint32 entry_search[3] = -{ - 186609, - 186610, - 186611 -}; - -struct npc_dragonflayer_forge_masterAI : public ScriptedAI -{ - npc_dragonflayer_forge_masterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - fm_Type = 0; - } - - ScriptedInstance* pInstance; - uint8 fm_Type; - - void Reset() - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - CheckForge(); - } - - void CheckForge() - { - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,me->isAlive() ? NOT_STARTED : DONE); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,me->isAlive() ? NOT_STARTED : DONE); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,me->isAlive() ? NOT_STARTED : DONE); - break; - } - } - } - - void JustDied(Unit * /*killer*/) - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,DONE); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,DONE); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,DONE); - break; - } - } - } - - void EnterCombat(Unit * /*who*/) - { - if (fm_Type == 0) fm_Type = GetForgeMasterType(); - if (pInstance) - { - switch(fm_Type) - { - case 1: - pInstance->SetData(EVENT_FORGE_1,IN_PROGRESS); - break; - case 2: - pInstance->SetData(EVENT_FORGE_2,IN_PROGRESS); - break; - case 3: - pInstance->SetData(EVENT_FORGE_3,IN_PROGRESS); - break; - } - } - me->SetUInt32Value(UNIT_NPC_EMOTESTATE ,EMOTE_ONESHOT_NONE); - } - - uint8 GetForgeMasterType() - { - float diff = 30.0f; - int near_f = 0; - - for (uint8 i = 0; i < 3 ; ++i) - { - GameObject* temp; - temp = me->FindNearestGameObject(entry_search[i],30); - if (temp) - { - if (me->IsWithinDist(temp,diff,false)) - { - near_f = i + 1; - diff = me->GetDistance2d(temp); - - } - } - } - - switch (near_f) - { - case 1: return 1; - case 2: return 2; - case 3: return 3; - default: return 0; - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (fm_Type == 0) - fm_Type = GetForgeMasterType(); - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_npc_dragonflayer_forge_master(Creature* pCreature) -{ - return new npc_dragonflayer_forge_masterAI(pCreature); -} - -void AddSC_utgarde_keep() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "npc_dragonflayer_forge_master"; - newscript->GetAI = &GetAI_npc_dragonflayer_forge_master; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h b/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h deleted file mode 100644 index b630e156564..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_keep/utgarde_keep.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2009 Trinity - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef DEF_UTGARDE_KEEP_H -#define DEF_UTGARDE_KEEP_H - -#define DATA_PRINCEKELESETH 1 -#define DATA_SKARVALD 3 -#define DATA_DALRONN 4 -#define DATA_INGVAR 6 - -#define DATA_PRINCEKELESETH_EVENT 2 -#define DATA_SKARVALD_DALRONN_EVENT 5 -#define DATA_INGVAR_EVENT 7 - -#define EVENT_FORGE_1 8 -#define EVENT_FORGE_2 9 -#define EVENT_FORGE_3 10 - -#endif diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp deleted file mode 100644 index 297fe37b7d8..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_palehoof.cpp +++ /dev/null @@ -1,830 +0,0 @@ -/* Script Data Start -SDName: Boss palehoof -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_palehoof' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_ARCING_SMASH = 48260, - SPELL_IMPALE = 48261, - H_SPELL_IMPALE = 59268, - SPELL_WITHERING_ROAR = 48256, - H_SPELL_WITHERING_ROAR = 59267, - SPELL_FREEZE = 16245 -}; - -//Orb spells -enum OrbSpells -{ - SPELL_ORB_VISUAL = 48044, - SPELL_ORB_CHANNEL = 48048 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1575000, - SAY_SLAY_1 = -1575001, - SAY_SLAY_2 = -1575002, - SAY_DEATH = -1575003 -}; - -enum Creatures -{ - MOB_STASIS_CONTROLLER = 26688 -}; - -struct Locations -{ - float x, y, z; -}; - -struct Locations moveLocs[]= -{ - {261.6,-449.3,109.5}, - {263.3,-454.0,109.5}, - {291.5,-450.4,109.5}, - {291.5,-454.0,109.5}, - {310.0,-453.4,109.5}, - {238.6,-460.7,109.5} -}; - -enum Phase -{ - PHASE_FRENZIED_WORGEN, - PHASE_RAVENOUS_FURLBORG, - PHASE_MASSIVE_JORMUNGAR, - PHASE_FEROCIOUS_RHINO, - PHASE_GORTOK_PALEHOOF, - PHASE_NONE -}; - -struct boss_palehoofAI : public ScriptedAI -{ - boss_palehoofAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiArcingSmashTimer; - uint32 uiImpaleTimer; - uint32 uiWhiteringRoarTimer; - uint32 uiWaitingTimer; - Phase currentPhase; - uint8 AddCount; - bool DoneAdds[4]; - - ScriptedInstance *pInstance; - - void Reset() - { - uiArcingSmashTimer = 15000; - uiImpaleTimer = 12000; - uiWhiteringRoarTimer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - for (uint32 i=0;i<4;i++) - DoneAdds[i]=false; - AddCount=0; - - currentPhase=PHASE_NONE; - - if (pInstance) - { - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, NOT_STARTED); - - Creature* pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - pTemp = Unit::GetCreature((*me), pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG)); - if (pTemp && !pTemp->isAlive()) - pTemp->Respawn(); - - GameObject* pGo = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_GORTOK_PALEHOOF_SPHERE)); - if (pGo) - { - pGo->SetGoState(GO_STATE_READY); - pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void UpdateAI(const uint32 diff) - { - if (currentPhase != PHASE_GORTOK_PALEHOOF) - return; - //Return since we have no target - if (!UpdateVictim()) - return; - - Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->DisappearAndDie(); - - if (uiArcingSmashTimer <= diff) - { - DoCast(me, SPELL_ARCING_SMASH); - uiArcingSmashTimer = urand(13000,17000); - } else uiArcingSmashTimer -= diff; - - if (uiImpaleTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_IMPALE); - uiImpaleTimer = urand(8000,12000); - } else uiImpaleTimer -= diff; - - if (uiWhiteringRoarTimer <= diff) - { - DoCast(me, SPELL_WITHERING_ROAR); - uiWhiteringRoarTimer = urand(8000,12000); - } else uiWhiteringRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - if (pInstance) - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, DONE); - Creature* pTemp = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pTemp && pTemp->isAlive()) - pTemp->DisappearAndDie(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void NextPhase() - { - if (currentPhase == PHASE_NONE) - { - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); - me->SummonCreature(MOB_STASIS_CONTROLLER,moveLocs[5].x,moveLocs[5].y,moveLocs[5].z,0,TEMPSUMMON_CORPSE_DESPAWN); - } - Phase move = PHASE_NONE; - if (AddCount >= DUNGEON_MODE(2,4)) - move = PHASE_GORTOK_PALEHOOF; - else - { - //select random not yet defeated add - uint8 next = urand(0,3); - for (uint8 i=0; i < 16; i++) - { - if (!DoneAdds[i%4] && next == 0) - { - move = (Phase)(i%4); - break; - } else if (!DoneAdds[i%4] && next > 0) - --next; - } - ++AddCount; - DoneAdds[move] = true; - move = (Phase)(move%4); - } - //send orb to summon spot - Creature *pOrb = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_ORB) : 0); - if (pOrb && pOrb->isAlive()) - { - if (currentPhase == PHASE_NONE) - pOrb->CastSpell(me,SPELL_ORB_VISUAL,true); - pOrb->GetMotionMaster()->MovePoint(move,moveLocs[move].x,moveLocs[move].y,moveLocs[move].z); - } - currentPhase = move; - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_boss_palehoof(Creature* pCreature) -{ - return new boss_palehoofAI (pCreature); -} - -//ravenous furbolg's spells -enum RavenousSpells -{ - SPELL_CHAIN_LIGHTING = 48140, - H_SPELL_CHAIN_LIGHTING = 59273, - SPELL_CRAZED = 48139, - SPELL_TERRIFYING_ROAR = 48144 -}; - -struct mob_ravenous_furbolgAI : public ScriptedAI -{ - mob_ravenous_furbolgAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiChainLightingTimer; - uint32 uiCrazedTimer; - uint32 uiTerrifyingRoarTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiChainLightingTimer = 5000; - uiCrazedTimer = 10000; - uiTerrifyingRoarTimer = 15000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiChainLightingTimer <= diff) - { - DoCast(me->getVictim(), SPELL_CHAIN_LIGHTING); - uiChainLightingTimer = 5000 + rand()%5000; - } else uiChainLightingTimer -= diff; - - if (uiCrazedTimer <= diff) - { - DoCast(me, SPELL_CRAZED); - uiCrazedTimer = 8000 + rand()%4000; - } else uiCrazedTimer -= diff; - - if (uiTerrifyingRoarTimer <= diff) - { - DoCast(me, SPELL_TERRIFYING_ROAR); - uiTerrifyingRoarTimer = 10000 + rand()%10000; - } else uiTerrifyingRoarTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_ravenous_furbolg(Creature* pCreature) -{ - return new mob_ravenous_furbolgAI (pCreature); -} - -//frenzied worgen's spells -enum FrenziedSpells -{ - SPELL_MORTAL_WOUND = 48137, - H_SPELL_MORTAL_WOUND = 59265, - SPELL_ENRAGE_1 = 48138, - SPELL_ENRAGE_2 = 48142 -}; - -struct mob_frenzied_worgenAI : public ScriptedAI -{ - mob_frenzied_worgenAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiMortalWoundTimer; - uint32 uiEnrage1Timer; - uint32 uiEnrage2Timer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiMortalWoundTimer = 5000; - uiEnrage1Timer = 15000; - uiEnrage2Timer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiMortalWoundTimer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - uiMortalWoundTimer = 3000 + rand()%4000; - } else uiMortalWoundTimer -= diff; - - if (uiEnrage1Timer <= diff) - { - DoCast(me, SPELL_ENRAGE_1); - uiEnrage1Timer = 15000; - } else uiEnrage1Timer -= diff; - - if (uiEnrage2Timer <= diff) - { - DoCast(me, SPELL_ENRAGE_2); - uiEnrage2Timer = 10000; - } else uiEnrage2Timer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - if (pInstance) - pInstance->SetData(DATA_GORTOK_PALEHOOF_EVENT, IN_PROGRESS); - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance->GetData64(DATA_GORTOK_PALEHOOF)); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_frenzied_worgen(Creature* pCreature) -{ - return new mob_frenzied_worgenAI (pCreature); -} - -//ferocious rhino's spells -enum FerociousSpells -{ - SPELL_GORE = 48130, - H_SPELL_GORE = 59264, - SPELL_GRIEVOUS_WOUND = 48105, - H_SPELL_GRIEVOUS_WOUND = 59263, - SPELL_STOMP = 48131 -}; - -struct mob_ferocious_rhinoAI : public ScriptedAI -{ - mob_ferocious_rhinoAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiStompTimer; - uint32 uiGoreTimer; - uint32 uiGrievousWoundTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiStompTimer = 10000; - uiGoreTimer = 15000; - uiGrievousWoundTimer = 20000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiStompTimer <= diff) - { - DoCast(me->getVictim(), SPELL_STOMP); - uiStompTimer = 8000 + rand()%4000; - } else uiStompTimer -= diff; - - if (uiGoreTimer <= diff) - { - DoCast(me->getVictim(), SPELL_GORE); - uiGoreTimer = 13000 + rand()%4000; - } else uiGoreTimer -= diff; - - if (uiGrievousWoundTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_GRIEVOUS_WOUND); - uiGrievousWoundTimer = 18000 + rand()%4000; - } else uiGrievousWoundTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_ferocious_rhino(Creature* pCreature) -{ - return new mob_ferocious_rhinoAI (pCreature); -} - -//massive jormungar's spells -enum MassiveSpells -{ - SPELL_ACID_SPIT = 48132, - SPELL_ACID_SPLATTER = 48136, - H_SPELL_ACID_SPLATTER = 59272, - SPELL_POISON_BREATH = 48133, - H_SPELL_POISON_BREATH = 59271 -}; - -enum MassiveAdds -{ - CREATURE_JORMUNGAR_WORM = 27228 -}; - -struct mob_massive_jormungarAI : public ScriptedAI -{ - mob_massive_jormungarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiAcidSpitTimer; - uint32 uiAcidSplatterTimer; - uint32 uiPoisonBreathTimer; - - ScriptedInstance *pInstance; - - void Reset() - { - uiAcidSpitTimer = 3000; - uiAcidSplatterTimer = 12000; - uiPoisonBreathTimer = 10000; - - me->GetMotionMaster()->MoveTargetedHome(); - - if (pInstance) - if (pInstance->GetData(DATA_GORTOK_PALEHOOF_EVENT) == IN_PROGRESS) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - CAST_AI(boss_palehoofAI, pPalehoof->AI())->Reset(); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiAcidSpitTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_ACID_SPIT); - uiAcidSpitTimer = 2000 + rand()%2000; - } else uiAcidSpitTimer -= diff; - - if (uiAcidSplatterTimer <= diff) - { - DoCast(me, SPELL_POISON_BREATH); - uiAcidSplatterTimer = 10000 + rand()%4000; - } else uiAcidSplatterTimer -= diff; - - if (uiPoisonBreathTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - DoCast(pTarget, SPELL_POISON_BREATH); - uiPoisonBreathTimer = 8000 + rand()%4000; - } else uiPoisonBreathTimer -= diff; - - DoMeleeAttackIfReady(); - } - - void AttackStart(Unit* who) - { - if (!who) - return; - - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - DoStartMovement(who); - } - } - - void JustDied(Unit* /*killer*/) - { - if (pInstance) - { - Creature *pPalehoof = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof) - CAST_AI(boss_palehoofAI,pPalehoof->AI())->NextPhase(); - } - } - - void JustReachedHome() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(me, SPELL_FREEZE); - } -}; - -CreatureAI* GetAI_mob_massive_jormungar(Creature* pCreature) -{ - return new mob_massive_jormungarAI (pCreature); -} - - -struct mob_palehoof_orbAI : public ScriptedAI -{ - mob_palehoof_orbAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 SummonTimer; - Phase currentPhase; - - void Reset() - { - currentPhase=PHASE_NONE; - SummonTimer=5000; - me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING); - me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL); - me->SetSpeed(MOVE_FLIGHT , 0.5f); - } - - void UpdateAI(const uint32 diff) - { - if (currentPhase == PHASE_NONE) - return; - - if (SummonTimer <= diff) - { - if (currentPhase<5&¤tPhase >= 0) - { - Creature *pNext = NULL; - switch(currentPhase) - { - case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; - case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; - case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; - case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; - case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; - } - - if (pNext) - { - pNext->RemoveAurasDueToSpell(SPELL_FREEZE); - pNext->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE|UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_ATTACKABLE_1|UNIT_FLAG_OOC_NOT_ATTACKABLE); - pNext->SetStandState(UNIT_STAND_STATE_STAND); - pNext->SetInCombatWithZone(); - pNext->Attack(pNext->SelectNearestTarget(100),true); - - } - currentPhase=PHASE_NONE; - } - } else SummonTimer-=diff; - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - if (id<0 || id>4) - return; - Creature *pNext = NULL; - switch(id) - { - case PHASE_FRENZIED_WORGEN: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FRENZIED_WORGEN) : 0); break; - case PHASE_RAVENOUS_FURLBORG: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_RAVENOUS_FURBOLG) : 0); break; - case PHASE_MASSIVE_JORMUNGAR: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_MASSIVE_JORMUNGAR) : 0); break; - case PHASE_FEROCIOUS_RHINO: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_MOB_FEROCIOUS_RHINO) : 0); break; - case PHASE_GORTOK_PALEHOOF: pNext = Unit::GetCreature((*me), pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); break; - } - if (pNext) - DoCast(pNext, SPELL_ORB_CHANNEL, false); - currentPhase=(Phase)id; - SummonTimer=5000; - } -}; - -CreatureAI* GetAI_mob_palehoof_orb(Creature* pCreature) -{ - return new mob_palehoof_orbAI (pCreature); -} - - - -bool GOHello_palehoof_sphere(Player * /*pPlayer*/, GameObject *pGO) -{ - ScriptedInstance *pInstance = pGO->GetInstanceData(); - - Creature *pPalehoof = Unit::GetCreature(*pGO, pInstance ? pInstance->GetData64(DATA_GORTOK_PALEHOOF) : 0); - if (pPalehoof && pPalehoof->isAlive()) - { - // maybe these are hacks :( - pGO->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - pGO->SetGoState(GO_STATE_ACTIVE); - - CAST_AI(boss_palehoofAI, pPalehoof->AI())->NextPhase(); - } - return true; -} - - - -void AddSC_boss_palehoof() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_palehoof"; - newscript->GetAI = &GetAI_boss_palehoof; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ravenous_furbolg"; - newscript->GetAI = &GetAI_mob_ravenous_furbolg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_frenzied_worgen"; - newscript->GetAI = &GetAI_mob_frenzied_worgen; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ferocious_rhino"; - newscript->GetAI = &GetAI_mob_ferocious_rhino; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_massive_jormungar"; - newscript->GetAI = &GetAI_mob_massive_jormungar; - newscript->RegisterSelf(); - - - newscript = new Script; - newscript->Name = "mob_palehoof_orb"; - newscript->GetAI = &GetAI_mob_palehoof_orb; - newscript->RegisterSelf(); - - - newscript = new Script; - newscript->Name = "go_palehoof_sphere"; - newscript->pGOHello=&GOHello_palehoof_sphere; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp deleted file mode 100644 index a75eb3465be..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_skadi.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* Copyright (C) 2008 - 2010 Trinity - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* Script Data Start -SDName: Boss_Skadi -SDAuthor: LordVanMartin, JohnHoliver -SD%Complete: 90% -SDComment: - After Unmount() he appears to still be flying even with SetFlying(false) - -SDCategory: Utgarde Pinnacle -Script Data End */ - -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -//Yell -enum eYells -{ - SAY_AGGRO = -1575004, - SAY_KILL_1 = -1575005, - SAY_KILL_2 = -1575006, - EMOTE_RANGE = -1575007, //Skadi - SAY_DEATH = -1575008, - SAY_DRAKE_DEATH = -1575009, - EMOTE_BREATH = -1575010, //Grauf - SAY_DRAKE_BREATH_1 = -1575011, - SAY_DRAKE_BREATH_2 = -1575012, - SAY_DRAKE_BREATH_3 = -1575013, -}; - -static Position SpawnLoc = {468.931, -513.555, 104.723}; -static Position Location[]= -{ - // Boss - {341.740997, -516.955017, 104.66900}, // 0 - {293.299, -505.95, 142.03}, // 1 - {301.664, -535.164, 146.097}, // 2 - {521.031006, -544.667847, 128.80064}, // 3 - {477.311981, -509.296814, 104.72308}, // 4 - {341.740997, -516.955017, 104.66900}, // 5 - {341.740997, -516.955017, 104.66900}, // 6 - {341.740997, -516.955017, 104.66900}, // 7 - // Triggers Left - {469.661, -484.546, 104.712}, // 8 - {483.315, -485.028, 104.718}, // 9 - {476.87, -487.994, 104.735}, //10 - {477.512, -497.772, 104.728}, //11 - {486.287, -500.759, 104.722}, //12 - {480.1, -503.895, 104.722}, //13 - {472.391, -505.103, 104.723}, //14 - {478.885, -510.803, 104.723}, //15 - {489.529, -508.615, 104.723}, //16 - {484.272, -508.589, 104.723}, //17 - {465.328, -506.495, 104.427}, //18 - {456.885, -508.104, 104.447}, //19 - {450.177, -507.989, 105.247}, //20 - {442.273, -508.029, 104.813}, //21 - {434.225, -508.19, 104.787}, //22 - {423.902, -508.525, 104.274}, //23 - {414.551, -508.645, 105.136}, //24 - {405.787, -508.755, 104.988}, //25 - {398.812, -507.224, 104.82}, //26 - {389.702, -506.846, 104.729}, //27 - {381.856, -506.76, 104.756}, //28 - {372.881, -507.254, 104.779}, //29 - {364.978, -508.182, 104.673}, //30 - {357.633, -508.075, 104.647}, //31 - {350.008, -506.826, 104.588}, //32 - {341.69, -506.77, 104.499}, //33 - {335.31, -505.745, 105.18}, //34 - {471.178, -510.74, 104.723}, //35 - {461.759, -510.365, 104.199}, //36 - {424.07287, -510.082916, 104.711082}, //37 - // Triggers Right - {489.46, -513.297, 105.413}, //38 - {485.706, -517.175, 104.724}, //39 - {480.98, -519.313, 104.724}, //40 - {475.05, -520.52, 104.724}, //41 - {482.97, -512.099, 104.724}, //42 - {477.082, -514.172, 104.724}, //43 - {468.991, -516.691, 104.724}, //44 - {461.722, -517.063, 104.627}, //45 - {455.88, -517.681, 104.707}, //46 - {450.499, -519.099, 104.701}, //47 - {444.889, -518.963, 104.82}, //48 - {440.181, -518.893, 104.861}, //49 - {434.393, -518.758, 104.891}, //50 - {429.328, -518.583, 104.904}, //51 - {423.844, -518.394, 105.004}, //52 - {418.707, -518.266, 105.135}, //53 - {413.377, -518.085, 105.153}, //54 - {407.277, -517.844, 104.893}, //55 - {401.082, -517.443, 104.723}, //56 - {394.933, -514.64, 104.724}, //57 - {388.917, -514.688, 104.734}, //58 - {383.814, -515.834, 104.73}, //59 - {377.887, -518.653, 104.777}, //60 - {371.376, -518.289, 104.781}, //61 - {365.669, -517.822, 104.758}, //62 - {359.572, -517.314, 104.706}, //63 - {353.632, -517.146, 104.647}, //64 - {347.998, -517.038, 104.538}, //65 - {341.803, -516.98, 104.584}, //66 - {335.879, -516.674, 104.628}, //67 - {329.871, -515.92, 104.711}, //68 - // Breach Zone - {485.4577, -511.2515, 115.3011}, //69 - {435.1892, -514.5232, 118.6719}, //70 - {413.9327, -540.9407, 138.2614}, //71 -}; - -enum eCombatPhase -{ - FLYING, - SKADI -}; - -enum eSpells -{ - //Skadi Spells - SPELL_CRUSH = 50234, - SPELL_POISONED_SPEAR = 50225, //isn't being casted =/ - SPELL_WHIRLWIND = 50228, //random target, but not the tank approx. every 20s - SPELL_RAPID_FIRE = 56570, - SPELL_HARPOON_DAMAGE = 56578, - SPELL_FREEZING_CLOUD = 47579, -}; - -enum eCreature -{ - CREATURE_YMIRJAR_WARRIOR = 26690, - CREATURE_YMIRJAR_WITCH_DOCTOR = 26691, - CREATURE_YMIRJAR_HARPOONER = 26692, - CREATURE_GRAUF = 26893, - CREATURE_TRIGGER = 28351, - DATA_MOUNT = 27043, -}; - -enum eAchievments -{ - ACHIEV_TIMED_START_EVENT = 17726, -}; - -struct boss_skadiAI : public ScriptedAI -{ - boss_skadiAI(Creature *c) : ScriptedAI(c), Summons(me) - { - m_pInstance = c->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - SummonList Summons; - uint64 m_uiGraufGUID; - std::vector triggersGUID; - - uint32 m_uiCrushTimer; - uint32 m_uiPoisonedSpearTimer; - uint32 m_uiWhirlwindTimer; - uint32 m_uiWaypointId; - uint32 m_uiMovementTimer; - uint32 m_uiMountTimer; - uint32 m_uiSummonTimer; - uint8 m_uiSpellHitCount; - bool m_bSaidEmote; - - eCombatPhase Phase; - - void Reset() - { - triggersGUID.clear(); - - m_uiCrushTimer = 8000; - m_uiPoisonedSpearTimer = 10000; - m_uiWhirlwindTimer = 20000; - m_uiMountTimer = 3000; - m_uiWaypointId = 0; - m_bSaidEmote = false; - m_uiSpellHitCount = 0; - - Phase = SKADI; - - Summons.DespawnAll(); - me->SetSpeed(MOVE_FLIGHT, 3.0f); - if ((Unit::GetCreature((*me), m_uiGraufGUID) == NULL) && !me->IsMounted()) - me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); - if (m_pInstance) - { - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, NOT_STARTED); - m_pInstance->DoStopTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - } - } - - void JustReachedHome() - { - me->SetFlying(false); - me->Unmount(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - if (Unit::GetCreature((*me), m_uiGraufGUID) == NULL) - me->SummonCreature(CREATURE_GRAUF,Location[0].GetPositionX(),Location[0].GetPositionY(),Location[0].GetPositionZ(),3.0f); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - - Phase = FLYING; - - m_uiMovementTimer = 1000; - m_uiSummonTimer = 10000; - me->SetInCombatWithZone(); - if (m_pInstance) - { - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, IN_PROGRESS); - m_pInstance->DoStartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_EVENT, ACHIEV_TIMED_START_EVENT); - me->GetMotionMaster()->MoveJump(Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 5.0f, 10.0f); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - m_uiMountTimer = 1000; - Summons.DespawnEntry(CREATURE_GRAUF); - } - } - - void JustSummoned(Creature* pSummoned) - { - switch (pSummoned->GetEntry()) - { - case CREATURE_GRAUF: - m_uiGraufGUID = pSummoned->GetGUID(); - break; - case CREATURE_YMIRJAR_WARRIOR: - case CREATURE_YMIRJAR_WITCH_DOCTOR: - case CREATURE_YMIRJAR_HARPOONER: - pSummoned->setActive(true); - pSummoned->SetInCombatWithZone(); - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - break; - case CREATURE_TRIGGER: - pSummoned->CastSpell((Unit*)NULL, SPELL_FREEZING_CLOUD, true); - pSummoned->ForcedDespawn(10*IN_MILISECONDS); - break; - } - Summons.Summon(pSummoned); - } - - void SummonedCreatureDespawn(Creature* pSummoned) - { - if (pSummoned->GetEntry() == CREATURE_GRAUF) - m_uiGraufGUID = 0; - Summons.Despawn(pSummoned); - } - - void SpellHit(Unit *caster, const SpellEntry *spell) - { - if (spell->Id == SPELL_HARPOON_DAMAGE) - { - m_uiSpellHitCount++; - if (m_uiSpellHitCount >= 5) - { - Phase = SKADI; - me->SetFlying(false); - me->Unmount(); - if(Creature* pGrauf = me->SummonCreature(CREATURE_GRAUF, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3*IN_MILISECONDS)) - { - pGrauf->GetMotionMaster()->MoveFall(0); - pGrauf->HandleEmoteCommand(EMOTE_ONESHOT_FLYDEATH); - } - sLog.outBasic("[Skadi] Fly off"); - me->GetMotionMaster()->MoveJump(Location[4].GetPositionX(), Location[4].GetPositionY(), Location[4].GetPositionZ(), 5.0f, 10.0f); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - DoScriptText(SAY_DRAKE_DEATH, me); - m_uiCrushTimer = 8000; - m_uiPoisonedSpearTimer = 10000; - m_uiWhirlwindTimer = 20000; - me->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM)); - } - } - } - - - void UpdateAI(const uint32 diff) - { - switch(Phase) - { - case FLYING: - if (!UpdateVictim()) - return; - - if (me->GetPositionX() >= 519) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - if (!m_bSaidEmote) - { - DoScriptText(EMOTE_RANGE, me); - m_bSaidEmote = true; - } - } - else - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE); - m_bSaidEmote = false; - } - - if (m_uiMountTimer && m_uiMountTimer <= diff) - { - me->Mount(DATA_MOUNT); - me->SetFlying(true); - m_uiMountTimer = 0; - } else m_uiMountTimer -= diff; - - if (m_uiSummonTimer <= diff) - { - SpawnMobs(); - m_uiSummonTimer = 25000; - } else m_uiSummonTimer -= diff; - - if (m_uiMovementTimer <= diff) - { - switch(m_uiWaypointId) - { - case 0: - me->GetMotionMaster()->MovePoint(0, Location[1].GetPositionX(), Location[1].GetPositionY(), Location[1].GetPositionZ()); - m_uiMovementTimer = 5000; - break; - case 1: - me->GetMotionMaster()->MovePoint(0, Location[2].GetPositionX(), Location[2].GetPositionY(), Location[2].GetPositionZ()); - m_uiMovementTimer = 2000; - break; - case 2: - me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); - m_uiMovementTimer = 15000; - break; - case 3: - me->GetMotionMaster()->MovePoint(0, Location[69].GetPositionX(), Location[69].GetPositionY(), Location[69].GetPositionZ()); - DoScriptText(RAND(SAY_DRAKE_BREATH_1,SAY_DRAKE_BREATH_2), me); - DoScriptText(EMOTE_BREATH, me); - m_uiMovementTimer = 2500; - break; - case 4: - me->GetMotionMaster()->MovePoint(0, Location[70].GetPositionX(), Location[70].GetPositionY(), Location[70].GetPositionZ()); - m_uiMovementTimer = 2000; - SpawnTrigger(); - break; - case 5: - me->GetMotionMaster()->MovePoint(0, Location[71].GetPositionX(), Location[71].GetPositionY(), Location[71].GetPositionZ()); - m_uiMovementTimer = 3000; - break; - case 6: - me->GetMotionMaster()->MovePoint(0, Location[3].GetPositionX(), Location[3].GetPositionY(), Location[3].GetPositionZ()); - m_uiWaypointId = 2; - m_uiMovementTimer = 15000; - break; - } - m_uiWaypointId++; - } else m_uiMovementTimer -= diff; - break; - case SKADI: - //Return since we have no target - if (!UpdateVictim()) - return; - - if (m_uiCrushTimer <= diff) - { - DoCastVictim(SPELL_CRUSH); - m_uiCrushTimer = 8000; - } else m_uiCrushTimer -= diff; - - if (m_uiPoisonedSpearTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM)) - DoCast(pTarget, SPELL_POISONED_SPEAR); - m_uiPoisonedSpearTimer = 10000; - } else m_uiPoisonedSpearTimer -= diff; - - if (m_uiWhirlwindTimer <= diff) - { - DoCastAOE(SPELL_WHIRLWIND); - m_uiWhirlwindTimer = 20000; - } else m_uiWhirlwindTimer -= diff; - - DoMeleeAttackIfReady(); - break; - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - Summons.DespawnAll(); - if (m_pInstance) - m_pInstance->SetData(DATA_SKADI_THE_RUTHLESS_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void SpawnMobs() - { - for (uint8 i = 0; i < DUNGEON_MODE(5,6); ++i) - { - switch (urand(0,2)) - { - case 0: me->SummonCreature(CREATURE_YMIRJAR_WARRIOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - case 1: me->SummonCreature(CREATURE_YMIRJAR_WITCH_DOCTOR, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - case 2: me->SummonCreature(CREATURE_YMIRJAR_HARPOONER, SpawnLoc.GetPositionX()+rand()%5, SpawnLoc.GetPositionY()+rand()%5, SpawnLoc.GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000); break; - } - } - } - - void SpawnTrigger() - { - uint8 iStart,iEnd; - switch (urand(0,1)) - { - case 0: - iStart = 8; - iEnd = 37; - break; - case 1: - iStart = 38; - iEnd = 68; - break; - } - for(uint32 i = iStart; i < iEnd; ++i) - me->SummonCreature(CREATURE_TRIGGER,Location[i]); - } -}; - -bool GOHello_go_harpoon_launcher(Player *pPlayer, GameObject *pGO) -{ - ScriptedInstance* m_pInstance; - m_pInstance = (ScriptedInstance*)pGO->GetInstanceData(); - if (!m_pInstance) return false; - - if (Creature* pSkadi = Unit::GetCreature((*pGO),m_pInstance->GetData64(DATA_SKADI_THE_RUTHLESS))) - { - pPlayer->CastSpell(pSkadi,SPELL_RAPID_FIRE, true); - } - return false; -} - -CreatureAI* GetAI_boss_skadi(Creature* pCreature) -{ - return new boss_skadiAI (pCreature); -} - -void AddSC_boss_skadi() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_skadi"; - newscript->GetAI = &GetAI_boss_skadi; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_harpoon_launcher"; - newscript->pGOHello = &GOHello_go_harpoon_launcher; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp deleted file mode 100644 index aae1015ddab..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_svala.cpp +++ /dev/null @@ -1,408 +0,0 @@ -/* Copyright (C) 2008 - 2010 TrinityCore - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_CALL_FLAMES = 48258, - SPELL_RITUAL_OF_THE_SWORD = 48276, //Effect #1 Teleport, Effect #2 Dummy - SPELL_SINSTER_STRIKE = 15667, - H_SPELL_SINSTER_STRIKE = 59409, - SPELL_SVALA_TRANSFORMING1 = 54140, - SPELL_SVALA_TRANSFORMING2 = 54205 -}; -//not in db -enum Yells -{ - SAY_DIALOG_WITH_ARTHAS_1 = -1575015, - SAY_DIALOG_WITH_ARTHAS_2 = -1575016, - SAY_DIALOG_WITH_ARTHAS_3 = -1575017, - SAY_AGGRO = -1575018, - SAY_SLAY_1 = -1575019, - SAY_SLAY_2 = -1575020, - SAY_SLAY_3 = -1575021, - SAY_DEATH = -1575022, - SAY_SACRIFICE_PLAYER_1 = -1575023, - SAY_SACRIFICE_PLAYER_2 = -1575024, - SAY_SACRIFICE_PLAYER_3 = -1575025, - SAY_SACRIFICE_PLAYER_4 = -1575026, - SAY_SACRIFICE_PLAYER_5 = -1575027, - SAY_DIALOG_OF_ARTHAS_1 = -1575028, - SAY_DIALOG_OF_ARTHAS_2 = -1575029 -}; -enum Creatures -{ - CREATURE_ARTHAS = 24266, // Image of Arthas - CREATURE_SVALA_SORROWGRAVE = 26668, // Svala after transformation - CREATURE_SVALA = 29281, // Svala before transformation - CREATURE_RITUAL_CHANNELER = 27281 -}; -enum ChannelerSpells -{ - //ritual channeler's spells - SPELL_PARALYZE = 48278, - SPELL_SHADOWS_IN_THE_DARK = 59407 -}; -enum Misc -{ - DATA_SVALA_DISPLAY_ID = 25944 -}; -enum IntroPhase -{ - IDLE, - INTRO, - FINISHED -}; -enum CombatPhase -{ - NORMAL, - SACRIFICING -}; - -static Position RitualChannelerPos[]= -{ - {296.42, -355.01, 90.94}, - {302.36, -352.01, 90.54}, - {291.39, -350.89, 90.54} -}; -static Position ArthasPos = { 295.81, -366.16, 92.57, 1.58 }; -static Position SvalaPos = { 296.632, -346.075, 90.6307, 1.58 }; - -struct boss_svalaAI : public ScriptedAI -{ - boss_svalaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiIntroTimer; - - uint8 uiIntroPhase; - - IntroPhase Phase; - - TempSummon* pArthas; - uint64 uiArthasGUID; - - ScriptedInstance* pInstance; - - void Reset() - { - Phase = IDLE; - uiIntroTimer = 1*IN_MILISECONDS; - uiIntroPhase = 0; - uiArthasGUID = 0; - - if (pInstance) - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); - } - - void MoveInLineOfSight(Unit* pWho) - { - if (!pWho) - return; - - if (Phase == IDLE && pWho->isTargetableForAttack() && me->IsHostileTo(pWho) && me->IsWithinDistInMap(pWho, 40)) - { - Phase = INTRO; - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Creature *pArthas = me->SummonCreature(CREATURE_ARTHAS, ArthasPos, TEMPSUMMON_MANUAL_DESPAWN)) - { - pArthas->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - pArthas->SetFloatValue(OBJECT_FIELD_SCALE_X, 5); - uiArthasGUID = pArthas->GetGUID(); - } - } - } - - void AttackStart(Unit* /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (Phase != INTRO) - return; - - if (uiIntroTimer <= diff) - { - Creature *pArthas = Unit::GetCreature(*me, uiArthasGUID); - if (!pArthas) - return; - - switch (uiIntroPhase) - { - case 0: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_1, me); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 1: - DoScriptText(SAY_DIALOG_OF_ARTHAS_1, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 2: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_2, me); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 3: - DoScriptText(SAY_DIALOG_OF_ARTHAS_2, pArthas); - ++uiIntroPhase; - uiIntroTimer = 3.5*IN_MILISECONDS; - break; - case 4: - DoScriptText(SAY_DIALOG_WITH_ARTHAS_3, me); - DoCast(me, SPELL_SVALA_TRANSFORMING1); - ++uiIntroPhase; - uiIntroTimer = 2.8*IN_MILISECONDS; - break; - case 5: - DoCast(me, SPELL_SVALA_TRANSFORMING2); - ++uiIntroPhase; - uiIntroTimer = 200; - break; - case 6: - if (Creature* pSvalaSorrowgrave = me->SummonCreature(CREATURE_SVALA_SORROWGRAVE, SvalaPos, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 60*IN_MILISECONDS)) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(DATA_SVALA_DISPLAY_ID); - pArthas->ToTempSummon()->UnSummon(); - uiArthasGUID = 0; - Phase = FINISHED; - } - else - Reset(); - break; - } - } else uiIntroTimer -= diff; - } -}; - -struct mob_ritual_channelerAI : public Scripted_NoMovementAI -{ - mob_ritual_channelerAI(Creature *c) :Scripted_NoMovementAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - void Reset() - { - DoCast(me, SPELL_SHADOWS_IN_THE_DARK); - } - - // called by svala sorrowgrave to set guid of victim - void DoAction(uint32 /*action*/) - { - if (pInstance) - if (Unit *pVictim = me->GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER))) - DoCast(pVictim, SPELL_PARALYZE); - } - - void EnterCombat(Unit* /*who*/) - { - } -}; - -struct boss_svala_sorrowgraveAI : public ScriptedAI -{ - boss_svala_sorrowgraveAI(Creature *c) : ScriptedAI(c), summons(c) - { - pInstance = c->GetInstanceData(); - } - - uint32 uiSinsterStrikeTimer; - uint32 uiCallFlamesTimer; - uint32 uiRitualOfSwordTimer; - uint32 uiSacrificeTimer; - - CombatPhase Phase; - - SummonList summons; - - bool bSacrificed; - - ScriptedInstance* pInstance; - - void Reset() - { - uiSinsterStrikeTimer = 7*IN_MILISECONDS; - uiCallFlamesTimer = 10*IN_MILISECONDS; - uiRitualOfSwordTimer = 20*IN_MILISECONDS; - uiSacrificeTimer = 8*IN_MILISECONDS; - - bSacrificed = false; - - Phase = NORMAL; - - DoTeleportTo(296.632, -346.075, 90.6307); - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - - summons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, NOT_STARTED); - pInstance->SetData64(DATA_SACRIFICED_PLAYER,0); - } - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, IN_PROGRESS); - } - - void JustSummoned(Creature *summon) - { - summons.Summon(summon); - } - - void SummonedCreatureDespawn(Creature *summon) - { - summons.Despawn(summon); - } - - void UpdateAI(const uint32 diff) - { - if (Phase == NORMAL) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (uiSinsterStrikeTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SINSTER_STRIKE); - uiSinsterStrikeTimer = urand(5*IN_MILISECONDS,9*IN_MILISECONDS); - } else uiSinsterStrikeTimer -= diff; - - if (uiCallFlamesTimer <= diff) - { - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoCast(pTarget, SPELL_CALL_FLAMES); - uiCallFlamesTimer = urand(8*IN_MILISECONDS,12*IN_MILISECONDS); - } - } else uiCallFlamesTimer -= diff; - - if (!bSacrificed) - if (uiRitualOfSwordTimer <= diff) - { - if (Unit* pSacrificeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - { - DoScriptText(RAND(SAY_SACRIFICE_PLAYER_1,SAY_SACRIFICE_PLAYER_2,SAY_SACRIFICE_PLAYER_3,SAY_SACRIFICE_PLAYER_4,SAY_SACRIFICE_PLAYER_5),me); - DoCast(pSacrificeTarget, SPELL_RITUAL_OF_THE_SWORD); - //Spell doesn't teleport - DoTeleportPlayer(pSacrificeTarget, 296.632, -346.075, 90.63, 4.6); - me->SetUnitMovementFlags(MOVEMENTFLAG_FLY_MODE); - DoTeleportTo(296.632, -346.075, 120.85); - Phase = SACRIFICING; - if (pInstance) - { - pInstance->SetData64(DATA_SACRIFICED_PLAYER,pSacrificeTarget->GetGUID()); - - for (uint8 i = 0; i < 3; ++i) - if (Creature* pSummon = me->SummonCreature(CREATURE_RITUAL_CHANNELER, RitualChannelerPos[i], TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 360000)) - pSummon->AI()->DoAction(0); - } - - bSacrificed = true; - } - } else uiRitualOfSwordTimer -= diff; - - DoMeleeAttackIfReady(); - } - else //SACRIFICING - { - if (uiSacrificeTimer <= diff) - { - Unit* pSacrificeTarget = pInstance ? Unit::GetUnit(*me, pInstance->GetData64(DATA_SACRIFICED_PLAYER)) : NULL; - if (pInstance && !summons.empty() && pSacrificeTarget && pSacrificeTarget->isAlive()) - me->Kill(pSacrificeTarget, false); // durability damage? - - //go down - Phase = NORMAL; - pSacrificeTarget = NULL; - me->SetUnitMovementFlags(MOVEMENTFLAG_WALK_MODE); - if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) - me->GetMotionMaster()->MoveChase(pTarget); - - uiSacrificeTimer = 8*IN_MILISECONDS; - } - else uiSacrificeTimer -= diff; - } - } - - void KilledUnit(Unit* /*pVictim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void JustDied(Unit* pKiller) - { - if (pInstance) - { - Creature* pSvala = Unit::GetCreature((*me), pInstance->GetData64(DATA_SVALA)); - if (pSvala && pSvala->isAlive()) - pKiller->Kill(pSvala); - - pInstance->SetData(DATA_SVALA_SORROWGRAVE_EVENT, DONE); - } - DoScriptText(SAY_DEATH, me); - } -}; - -CreatureAI* GetAI_boss_svala(Creature* pCreature) -{ - return new boss_svalaAI (pCreature); -} - -CreatureAI* GetAI_mob_ritual_channeler(Creature* pCreature) -{ - return new mob_ritual_channelerAI(pCreature); -} - -CreatureAI* GetAI_boss_svala_sorrowgrave(Creature* pCreature) -{ - return new boss_svala_sorrowgraveAI(pCreature); -} - -void AddSC_boss_svala() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_svala"; - newscript->GetAI = &GetAI_boss_svala; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ritual_channeler"; - newscript->GetAI = &GetAI_mob_ritual_channeler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_svala_sorrowgrave"; - newscript->GetAI = &GetAI_boss_svala_sorrowgrave; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp deleted file mode 100644 index 1a650f94101..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/boss_ymiron.cpp +++ /dev/null @@ -1,367 +0,0 @@ -/* Script Data Start -SDName: Boss ymiron -SDAuthor: LordVanMartin -SD%Complete: -SDComment: -SDCategory: -Script Data End */ - -/*** SQL START *** -update creature_template set scriptname = 'boss_ymiron' where entry = ''; -*** SQL END ***/ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -enum Spells -{ - SPELL_BANE = 48294, - H_SPELL_BANE = 59301, - SPELL_DARK_SLASH = 48292, - SPELL_FETID_ROT = 48291, - H_SPELL_FETID_ROT = 59300, - SPELL_SCREAMS_OF_THE_DEAD = 51750, - SPELL_SPIRIT_BURST = 48529, - H_SPELL_SPIRIT_BURST = 59305, - SPELL_SPIRIT_STRIKE = 48423, - H_SPELL_SPIRIT_STRIKE = 59304, - SPELL_ANCESTORS_VENGEANCE = 16939, - - SPELL_SUMMON_AVENGING_SPIRIT = 48592, - SPELL_SUMMON_SPIRIT_FOUNT = 48386, - - SPELL_CHANNEL_SPIRIT_TO_YMIRON = 48316, - SPELL_CHANNEL_YMIRON_TO_SPIRIT = 48307, - - SPELL_SPIRIT_FOUNT = 48380, - H_SPELL_SPIRIT_FOUNT = 59320 -}; - -//not in db -enum Yells -{ - SAY_AGGRO = -1575028, - SAY_SLAY_1 = -1575029, - SAY_SLAY_2 = -1575030, - SAY_SLAY_3 = -1575031, - SAY_SLAY_4 = -1575032, - SAY_DEATH = -1575033, - SAY_SUMMON_BJORN = -1575034, - SAY_SUMMON_HALDOR = -1575035, - SAY_SUMMON_RANULF = -1575036, - SAY_SUMMON_TORGYN = -1575037 -}; - -enum Creatures -{ - CREATURE_BJORN = 27303, - CREATURE_BJORN_VISUAL = 27304, - CREATURE_HALDOR = 27307, - CREATURE_HALDOR_VISUAL = 27310, - CREATURE_RANULF = 27308, - CREATURE_RANULF_VISUAL = 27311, - CREATURE_TORGYN = 27309, - CREATURE_TORGYN_VISUAL = 27312, - CREATURE_SPIRIT_FOUNT = 27339, - CREATURE_AVENGING_SPIRIT = 27386 -}; - -struct ActiveBoatStruct -{ - uint32 npc; - int32 say; - float MoveX,MoveY,MoveZ,SpawnX,SpawnY,SpawnZ,SpawnO; -}; - -static ActiveBoatStruct ActiveBot[4] = -{ - {CREATURE_BJORN_VISUAL, SAY_SUMMON_BJORN, 404.379, -335.335, 104.756, 413.594, -335.408, 107.995, 3.157}, - {CREATURE_HALDOR_VISUAL, SAY_SUMMON_HALDOR, 380.813, -335.069, 104.756, 369.994, -334.771, 107.995, 6.232}, - {CREATURE_RANULF_VISUAL, SAY_SUMMON_RANULF, 381.546, -314.362, 104.756, 370.841, -314.426, 107.995, 6.232}, - {CREATURE_TORGYN_VISUAL, SAY_SUMMON_TORGYN, 404.310, -314.761, 104.756, 413.992, -314.703, 107.995, 3.157} -}; - -struct boss_ymironAI : public ScriptedAI -{ - boss_ymironAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - srand(time(NULL)); - for (int i = 0; i < 4; ++i) - m_uiActiveOrder[i] = i; - for (int i = 0; i < 3; ++i) - { - int r = i + (rand()%(4-i)); - int temp = m_uiActiveOrder[i]; - m_uiActiveOrder[i] = m_uiActiveOrder[r]; - m_uiActiveOrder[r] = temp; - } - } - - bool m_bIsWalking; - bool m_bIsPause; - bool m_bIsActiveWithBJORN; - bool m_bIsActiveWithHALDOR; - bool m_bIsActiveWithRANULF; - bool m_bIsActiveWithTORGYN; - - uint8 m_uiActiveOrder[4]; - uint8 m_uiActivedNumber; - - uint32 m_uiFetidRot_Timer; - uint32 m_uiBane_Timer; - uint32 m_uiDarkSlash_Timer; - uint32 m_uiAncestors_Vengeance_Timer; - - uint32 m_uiAbility_BJORN_Timer; - uint32 m_uiAbility_HALDOR_Timer; - uint32 m_uiAbility_RANULF_Timer; - uint32 m_uiAbility_TORGYN_Timer; - - uint32 m_uiPause_Timer; - uint32 m_uiHealthAmountModifier; - uint32 m_uiHealthAmountMultipler; - - uint64 m_uiActivedCreatureGUID; - uint64 m_uiOrbGUID; - - ScriptedInstance *pInstance; - - void Reset() - { - m_bIsPause = false; - m_bIsActiveWithBJORN = false; - m_bIsActiveWithHALDOR = false; - m_bIsActiveWithRANULF = false; - m_bIsActiveWithTORGYN = false; - - m_uiFetidRot_Timer = urand(8000,13000); - m_uiBane_Timer = urand(18000,23000); - m_uiDarkSlash_Timer = urand(28000,33000); - m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(60000,45000); - m_uiPause_Timer = 0; - - m_uiAbility_BJORN_Timer = 0; - m_uiAbility_HALDOR_Timer = 0; - m_uiAbility_RANULF_Timer = 0; - m_uiAbility_TORGYN_Timer = 0; - - m_uiActivedNumber = 0; - m_uiHealthAmountModifier = 1; - m_uiHealthAmountMultipler = DUNGEON_MODE(20,25); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (m_bIsWalking) - { - if (m_uiPause_Timer <= diff) - { - DoScriptText(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].say, me); - DoCast(me, SPELL_CHANNEL_YMIRON_TO_SPIRIT); // should be on spirit - if (Creature* pTemp = me->SummonCreature(ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].npc, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnX, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnY, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnZ, ActiveBot[m_uiActiveOrder[m_uiActivedNumber]].SpawnO, TEMPSUMMON_CORPSE_DESPAWN, 0)) - { - m_uiActivedCreatureGUID = pTemp->GetGUID(); - pTemp->CastSpell(me, SPELL_CHANNEL_SPIRIT_TO_YMIRON, true); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - switch(m_uiActiveOrder[m_uiActivedNumber]) - { - case 0: m_bIsActiveWithBJORN = true; break; - case 1: m_bIsActiveWithHALDOR = true; break; - case 2: m_bIsActiveWithRANULF = true; break; - case 3: m_bIsActiveWithTORGYN = true; break; - } - } - - m_bIsPause = true; - m_bIsWalking = false; - m_uiPause_Timer = 3000; - } else m_uiPause_Timer -= diff; - return; - } - else if (m_bIsPause) - { - if (m_uiPause_Timer <= diff) - { - m_uiAbility_BJORN_Timer = 5000; - m_uiAbility_HALDOR_Timer = 5000; - m_uiAbility_RANULF_Timer = 5000; - m_uiAbility_TORGYN_Timer = 5000; - - m_bIsPause = false; - m_uiPause_Timer = 0; - } else m_uiPause_Timer -= diff; - return; - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - if (!m_bIsPause) - { - // Normal spells ------------------------------------------------------------------------ - if (m_uiBane_Timer <= diff) - { - DoCast(me, SPELL_BANE); - m_uiBane_Timer = urand(20000,25000); - } else m_uiBane_Timer -= diff; - - if (m_uiFetidRot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FETID_ROT); - m_uiFetidRot_Timer = urand(10000,15000); - } else m_uiFetidRot_Timer -= diff; - - if (m_uiDarkSlash_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DARK_SLASH); - m_uiDarkSlash_Timer = urand(30000,35000); - } else m_uiDarkSlash_Timer -= diff; - - if (m_uiAncestors_Vengeance_Timer <= diff) - { - DoCast(me, SPELL_ANCESTORS_VENGEANCE); - m_uiAncestors_Vengeance_Timer = DUNGEON_MODE(urand(60000,65000),urand(45000,50000)); - } else m_uiAncestors_Vengeance_Timer -= diff; - - // Abilities ------------------------------------------------------------------------------ - if (m_bIsActiveWithBJORN && m_uiAbility_BJORN_Timer <= diff) - { - //DoCast(me, SPELL_SUMMON_SPIRIT_FOUNT); // works fine, but using summon has better control - if (Creature* pTemp = me->SummonCreature(CREATURE_SPIRIT_FOUNT, 385+rand()%10, -330+rand()%10, 104.756, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 180000)) - { - pTemp->SetSpeed(MOVE_RUN, 0.4f); - pTemp->CastSpell(pTemp, DUNGEON_MODE(SPELL_SPIRIT_FOUNT, H_SPELL_SPIRIT_FOUNT), true); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->SetDisplayId(11686); - //pTemp->GetMotionMaster()->MoveChase(me->getVictim()); - m_uiOrbGUID = pTemp->GetGUID(); - } - m_bIsActiveWithBJORN = false; // only one orb - } else m_uiAbility_BJORN_Timer -= diff; - - if (m_bIsActiveWithHALDOR && m_uiAbility_HALDOR_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SPIRIT_STRIKE); - m_uiAbility_HALDOR_Timer = 5000; // overtime - } else m_uiAbility_HALDOR_Timer -= diff; - - if (m_bIsActiveWithRANULF && m_uiAbility_RANULF_Timer <= diff) - { - DoCast(me, SPELL_SPIRIT_BURST); - m_uiAbility_RANULF_Timer = 10000; // overtime - } else m_uiAbility_RANULF_Timer -= diff; - - if (m_bIsActiveWithTORGYN && m_uiAbility_TORGYN_Timer <= diff) - { - float x,y,z; - x = me->GetPositionX()-5; - y = me->GetPositionY()-5; - z = me->GetPositionZ(); - for (uint8 i = 0; i < 4; ++i) - { - //DoCast(me, SPELL_SUMMON_AVENGING_SPIRIT); // works fine, but using summon has better control - if (Creature* pTemp = me->SummonCreature(CREATURE_AVENGING_SPIRIT, x+rand()%10, y+rand()%10, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - pTemp->AddThreat(pTarget, 0.0f); - pTemp->AI()->AttackStart(pTarget); - } - } - } - m_uiAbility_TORGYN_Timer = 15000; // overtime - } else m_uiAbility_TORGYN_Timer -= diff; - - // Health check ----------------------------------------------------------------------------- - if ((me->GetHealth()*100 / me->GetMaxHealth()) < (100-(m_uiHealthAmountMultipler * m_uiHealthAmountModifier))) - { - uint8 m_uiOrder = m_uiHealthAmountModifier - 1; - ++m_uiHealthAmountModifier; - - me->InterruptNonMeleeSpells(true); - DoCast(me, SPELL_SCREAMS_OF_THE_DEAD); - me->GetMotionMaster()->Clear(); - me->StopMoving(); - me->AttackStop(); - me->GetMotionMaster()->MovePoint(0, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveX, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveY, ActiveBot[m_uiActiveOrder[m_uiOrder]].MoveZ); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - m_bIsActiveWithBJORN = false; - m_bIsActiveWithHALDOR = false; - m_bIsActiveWithRANULF = false; - m_bIsActiveWithTORGYN = false; - - m_uiBane_Timer += 8000; - m_uiFetidRot_Timer += 8000; - m_uiDarkSlash_Timer += 8000; - m_uiAncestors_Vengeance_Timer += 8000; - - m_uiActivedNumber = m_uiOrder; - m_bIsWalking = true; - m_uiPause_Timer = 2000; - return; - } - DoMeleeAttackIfReady(); - } - } - - void JustDied(Unit* /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - DespawnBoatGhosts(m_uiActivedCreatureGUID); - DespawnBoatGhosts(m_uiOrbGUID); - - if (pInstance) - pInstance->SetData(DATA_KING_YMIRON_EVENT, DONE); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3,SAY_SLAY_4), me); - } - - void DespawnBoatGhosts(uint64& m_uiCreatureGUID) - { - if (m_uiCreatureGUID) - if (Creature* pTemp = Unit::GetCreature(*me, m_uiCreatureGUID)) - pTemp->DisappearAndDie(); - - m_uiCreatureGUID = 0; - } -}; - -CreatureAI* GetAI_boss_ymiron(Creature* pCreature) -{ - return new boss_ymironAI(pCreature); -} - -void AddSC_boss_ymiron() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_ymiron"; - newscript->GetAI = &GetAI_boss_ymiron; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp deleted file mode 100644 index cf042867707..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/instance_pinnacle.cpp +++ /dev/null @@ -1,241 +0,0 @@ -#include "ScriptedPch.h" -#include "utgarde_pinnacle.h" - -#define MAX_ENCOUNTER 4 - -/* Utgarde Pinnacle encounters: -0 - Svala Sorrowgrave -1 - Gortok Palehoof -2 - Skadi the Ruthless -3 - King Ymiron -*/ - -enum GameObjects -{ - ENTRY_SKADI_THE_RUTHLESS_DOOR = 192173, - ENTRY_KING_YMIRON_DOOR = 192174, - ENTRY_GORK_PALEHOOF_SPHERE = 188593 -}; - -struct instance_pinnacle : public ScriptedInstance -{ - instance_pinnacle(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 uiSvalaSorrowgrave; - uint64 uiGortokPalehoof; - uint64 uiSkadiTheRuthless; - uint64 uiKingYmiron; - - uint64 uiSkadiTheRuthlessDoor; - uint64 uiKingYmironDoor; - uint64 uiGortokPalehoofSphere; - - uint64 uiFrenziedWorgen; - uint64 uiRavenousFurbolg; - uint64 uiFerociousRhino; - uint64 uiMassiveJormungar; - uint64 uiPalehoofOrb; - - uint64 uiSvala; - uint64 uiSacrificedPlayer; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - std::string str_data; - - void Initialize() - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - m_auiEncounter[i] = NOT_STARTED; - - uiSvalaSorrowgrave = 0; - uiGortokPalehoof = 0; - uiSkadiTheRuthless = 0; - uiKingYmiron = 0; - - uiSkadiTheRuthlessDoor = 0; - uiKingYmironDoor = 0; - uiGortokPalehoofSphere = 0; - - uiFrenziedWorgen = 0; - uiRavenousFurbolg = 0; - uiFerociousRhino = 0; - uiMassiveJormungar = 0; - uiPalehoofOrb = 0; - - uiSvala = 0; - uiSacrificedPlayer = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case BOSS_SVALA_SORROWGRAVE: uiSvalaSorrowgrave = pCreature->GetGUID(); break; - case BOSS_GORTOK_PALEHOOF: uiGortokPalehoof = pCreature->GetGUID(); break; - case BOSS_SKADI_RUTHLESS: uiSkadiTheRuthless = pCreature->GetGUID(); break; - case BOSS_KING_YMIRON: uiKingYmiron = pCreature->GetGUID(); break; - case MOB_FRENZIED_WORGEN: uiFrenziedWorgen = pCreature->GetGUID(); break; - case MOB_RAVENOUS_FURBOLG: uiRavenousFurbolg = pCreature->GetGUID(); break; - case MOB_MASSIVE_JORMUNGAR: uiMassiveJormungar = pCreature->GetGUID(); break; - case MOB_FEROCIOUS_RHINO: uiFerociousRhino = pCreature->GetGUID(); break; - case MOB_SVALA: uiSvala = pCreature->GetGUID(); break; - case MOB_PALEHOOF_ORB: uiPalehoofOrb = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case ENTRY_SKADI_THE_RUTHLESS_DOOR: - uiSkadiTheRuthlessDoor = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) HandleGameObject(NULL,true,pGo); - break; - case ENTRY_KING_YMIRON_DOOR: - uiKingYmironDoor = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) HandleGameObject(NULL,true,pGo); - break; - case ENTRY_GORK_PALEHOOF_SPHERE: - uiGortokPalehoofSphere = pGo->GetGUID(); - if (m_auiEncounter[1] == DONE) - { - HandleGameObject(NULL,true,pGo); - pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); - } - break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_SVALA_SORROWGRAVE_EVENT: - m_auiEncounter[0] = data; - break; - case DATA_GORTOK_PALEHOOF_EVENT: - m_auiEncounter[1] = data; - break; - case DATA_SKADI_THE_RUTHLESS_EVENT: - if (data == DONE) - HandleGameObject(uiSkadiTheRuthlessDoor,true); - m_auiEncounter[2] = data; - break; - case DATA_KING_YMIRON_EVENT: - if (data == DONE) - HandleGameObject(uiKingYmironDoor,true); - m_auiEncounter[3] = data; - break; - } - - if (data == DONE) - SaveToDB(); - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_SACRIFICED_PLAYER) - uiSacrificedPlayer = data; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_SVALA_SORROWGRAVE_EVENT: return m_auiEncounter[0]; - case DATA_GORTOK_PALEHOOF_EVENT: return m_auiEncounter[1]; - case DATA_SKADI_THE_RUTHLESS_EVENT: return m_auiEncounter[2]; - case DATA_KING_YMIRON_EVENT: return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_SVALA_SORROWGRAVE: return uiSvalaSorrowgrave; - case DATA_GORTOK_PALEHOOF: return uiGortokPalehoof; - case DATA_SKADI_THE_RUTHLESS: return uiSkadiTheRuthless; - case DATA_KING_YMIRON: return uiKingYmiron; - case DATA_MOB_FRENZIED_WORGEN: return uiFrenziedWorgen; - case DATA_MOB_RAVENOUS_FURBOLG: return uiRavenousFurbolg; - case DATA_MOB_MASSIVE_JORMUNGAR: return uiMassiveJormungar; - case DATA_MOB_FEROCIOUS_RHINO: return uiFerociousRhino; - case DATA_MOB_ORB: return uiPalehoofOrb; - case DATA_SVALA: return uiSvala; - case DATA_GORTOK_PALEHOOF_SPHERE: return uiGortokPalehoofSphere; - } - - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << "U P " << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3]; - - str_data = saveStream.str(); - - OUT_SAVE_INST_DATA_COMPLETE; - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - char dataHead1, dataHead2; - uint16 data0, data1, data2, data3; - - std::istringstream loadStream(in); - loadStream >> dataHead1 >> dataHead2 >> data0 >> data1 >> data2 >> data3; - - if (dataHead1 == 'U' && dataHead2 == 'P') - { - m_auiEncounter[0] = data0; - m_auiEncounter[1] = data1; - m_auiEncounter[2] = data2; - m_auiEncounter[3] = data3; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - } else OUT_LOAD_INST_DATA_FAIL; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_utgarde_pinnacle(Map* pMap) -{ - return new instance_pinnacle(pMap); -} - -void AddSC_instance_utgarde_pinnacle() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_utgarde_pinnacle"; - newscript->GetInstanceData = &GetInstanceData_instance_utgarde_pinnacle; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h b/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h deleted file mode 100644 index a51d7aceda0..00000000000 --- a/src/server/scripts/Northrend/UtgardeKeep/utgarde_pinnacle/utgarde_pinnacle.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef DEF_PINNACLE_H -#define DEF_PINNACLE_H - -enum Data -{ - DATA_SVALA_SORROWGRAVE_EVENT, - DATA_GORTOK_PALEHOOF_EVENT, - DATA_SKADI_THE_RUTHLESS_EVENT, - DATA_KING_YMIRON_EVENT -}; -enum Data64 -{ - DATA_SVALA, - DATA_SVALA_SORROWGRAVE, - DATA_GORTOK_PALEHOOF, - DATA_SKADI_THE_RUTHLESS, - DATA_MOB_GRAUF, - DATA_KING_YMIRON, - DATA_MOB_FRENZIED_WORGEN, - DATA_MOB_RAVENOUS_FURBOLG, - DATA_MOB_MASSIVE_JORMUNGAR, - DATA_MOB_FEROCIOUS_RHINO, - DATA_MOB_ORB, - DATA_GORTOK_PALEHOOF_SPHERE, - DATA_SACRIFICED_PLAYER -}; - -enum eCreatures -{ - BOSS_SVALA_SORROWGRAVE = 26668, - BOSS_GORTOK_PALEHOOF = 26687, - BOSS_SKADI_RUTHLESS = 26693, - BOSS_KING_YMIRON = 26861, - MOB_FRENZIED_WORGEN = 26683, - MOB_RAVENOUS_FURBOLG = 26684, - MOB_MASSIVE_JORMUNGAR = 26685, - MOB_FEROCIOUS_RHINO = 26686, - MOB_SVALA = 29281, - MOB_PALEHOOF_ORB = 26688, -}; - -#endif diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp new file mode 100644 index 00000000000..bfde95ffcb0 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_exarch_maladaar.cpp @@ -0,0 +1,348 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Exarch_Maladaar +SD%Complete: 95 +SDComment: Most of event implemented, some adjustments to timers remain and possibly make some better code for switching his dark side in to better "images" of player. +SDCategory: Auchindoun, Auchenai Crypts +EndScriptData */ + +/* ContentData +mob_stolen_soul +boss_exarch_maladaar +mob_avatar_of_martyred +EndContentData */ + +#include "ScriptedPch.h" + +#define SPELL_MOONFIRE 37328 +#define SPELL_FIREBALL 37329 +#define SPELL_MIND_FLAY 37330 +#define SPELL_HEMORRHAGE 37331 +#define SPELL_FROSTSHOCK 37332 +#define SPELL_CURSE_OF_AGONY 37334 +#define SPELL_MORTAL_STRIKE 37335 +#define SPELL_FREEZING_TRAP 37368 +#define SPELL_HAMMER_OF_JUSTICE 37369 + +struct mob_stolen_soulAI : public ScriptedAI +{ + mob_stolen_soulAI(Creature *c) : ScriptedAI(c) {} + + uint8 myClass; + uint32 Class_Timer; + + void Reset() + { + Class_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { } + + void SetMyClass(uint8 myclass) + { + myClass = myclass; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Class_Timer <= diff) + { + switch (myClass) + { + case CLASS_WARRIOR: + DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); + Class_Timer = 6000; + break; + case CLASS_PALADIN: + DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); + Class_Timer = 6000; + break; + case CLASS_HUNTER: + DoCast(me->getVictim(), SPELL_FREEZING_TRAP); + Class_Timer = 20000; + break; + case CLASS_ROGUE: + DoCast(me->getVictim(), SPELL_HEMORRHAGE); + Class_Timer = 10000; + break; + case CLASS_PRIEST: + DoCast(me->getVictim(), SPELL_MIND_FLAY); + Class_Timer = 5000; + break; + case CLASS_SHAMAN: + DoCast(me->getVictim(), SPELL_FROSTSHOCK); + Class_Timer = 8000; + break; + case CLASS_MAGE: + DoCast(me->getVictim(), SPELL_FIREBALL); + Class_Timer = 5000; + break; + case CLASS_WARLOCK: + DoCast(me->getVictim(), SPELL_CURSE_OF_AGONY); + Class_Timer = 20000; + break; + case CLASS_DRUID: + DoCast(me->getVictim(), SPELL_MOONFIRE); + Class_Timer = 10000; + break; + } + } else Class_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_stolen_soul(Creature* pCreature) +{ + return new mob_stolen_soulAI (pCreature); +} + +#define SAY_INTRO -1558000 +#define SAY_SUMMON -1558001 + +#define SAY_AGGRO_1 -1558002 +#define SAY_AGGRO_2 -1558003 +#define SAY_AGGRO_3 -1558004 + +#define SAY_ROAR -1558005 +#define SAY_SOUL_CLEAVE -1558006 + +#define SAY_SLAY_1 -1558007 +#define SAY_SLAY_2 -1558008 + +#define SAY_DEATH -1558009 + +#define SPELL_RIBBON_OF_SOULS 32422 +#define SPELL_SOUL_SCREAM 32421 + +#define SPELL_STOLEN_SOUL 32346 +#define SPELL_STOLEN_SOUL_VISUAL 32395 + +#define SPELL_SUMMON_AVATAR 32424 + +#define ENTRY_STOLEN_SOUL 18441 + +struct boss_exarch_maladaarAI : public ScriptedAI +{ + boss_exarch_maladaarAI(Creature *c) : ScriptedAI(c) + { + HasTaunted = false; + } + + uint32 soulmodel; + uint64 soulholder; + uint8 soulclass; + + uint32 Fear_timer; + uint32 Ribbon_of_Souls_timer; + uint32 StolenSoul_Timer; + + bool HasTaunted; + bool Avatar_summoned; + + void Reset() + { + soulmodel = 0; + soulholder = 0; + soulclass = 0; + + Fear_timer = 15000 + rand()% 5000; + Ribbon_of_Souls_timer = 5000; + StolenSoul_Timer = 25000 + rand()% 10000; + + Avatar_summoned = false; + } + + void MoveInLineOfSight(Unit *who) + { + if (!HasTaunted && me->IsWithinDistInMap(who, 150.0)) + { + DoScriptText(SAY_INTRO, me); + HasTaunted = true; + } + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == ENTRY_STOLEN_SOUL) + { + //SPELL_STOLEN_SOUL_VISUAL has shapeshift effect, but not implemented feature in Trinity for this spell. + summoned->CastSpell(summoned,SPELL_STOLEN_SOUL_VISUAL,false); + summoned->SetDisplayId(soulmodel); + summoned->setFaction(me->getFaction()); + + if (Unit *pTarget = Unit::GetUnit(*me,soulholder)) + { + + CAST_AI(mob_stolen_soulAI, summoned->AI())->SetMyClass(soulclass); + summoned->AI()->AttackStart(pTarget); + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + //When Exarch Maladar is defeated D'ore appear. + me->SummonCreature(19412, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 600000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (!Avatar_summoned && ((me->GetHealth()*100) / me->GetMaxHealth() < 25)) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(SAY_SUMMON, me); + + DoCast(me, SPELL_SUMMON_AVATAR); + Avatar_summoned = true; + StolenSoul_Timer = 15000 + rand()% 15000; + } + + if (StolenSoul_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + uint32 i = urand(1,2); + if (i == 1) + DoScriptText(SAY_ROAR, me); + else + DoScriptText(SAY_SOUL_CLEAVE, me); + + soulmodel = pTarget->GetDisplayId(); + soulholder = pTarget->GetGUID(); + soulclass = pTarget->getClass(); + + DoCast(pTarget, SPELL_STOLEN_SOUL); + me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); + + StolenSoul_Timer = 20000 + rand()% 10000; + } else StolenSoul_Timer = 1000; + } + } else StolenSoul_Timer -= diff; + + if (Ribbon_of_Souls_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_RIBBON_OF_SOULS); + + Ribbon_of_Souls_timer = 5000 + (rand()%20 * 1000); + } else Ribbon_of_Souls_timer -= diff; + + if (Fear_timer <= diff) + { + DoCast(me, SPELL_SOUL_SCREAM); + Fear_timer = 15000 + rand()% 15000; + } else Fear_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_exarch_maladaar(Creature* pCreature) +{ + return new boss_exarch_maladaarAI (pCreature); +} + +#define SPELL_AV_MORTAL_STRIKE 16856 +#define SPELL_AV_SUNDER_ARMOR 16145 + +struct mob_avatar_of_martyredAI : public ScriptedAI +{ + mob_avatar_of_martyredAI(Creature *c) : ScriptedAI(c) {} + + uint32 Mortal_Strike_timer; + + void Reset() + { + Mortal_Strike_timer = 10000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Mortal_Strike_timer <= diff) + { + DoCast(me->getVictim(), SPELL_AV_MORTAL_STRIKE); + Mortal_Strike_timer = 10000 + rand()%20 * 1000; + } else Mortal_Strike_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_avatar_of_martyred(Creature* pCreature) +{ + return new mob_avatar_of_martyredAI (pCreature); +} + +void AddSC_boss_exarch_maladaar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_exarch_maladaar"; + newscript->GetAI = &GetAI_boss_exarch_maladaar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_avatar_of_martyred"; + newscript->GetAI = &GetAI_mob_avatar_of_martyred; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_stolen_soul"; + newscript->GetAI = &GetAI_mob_stolen_soul; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp new file mode 100644 index 00000000000..c13e2905171 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/AuchenaiCrypts/boss_shirrak_the_dead_watcher.cpp @@ -0,0 +1,211 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +Name: Boss_Shirrak_the_dead_watcher +%Complete: 80 +Comment: InhibitMagic should stack slower far from the boss, proper Visual for Focus Fire, heroic implemented +Category: Auchindoun, Auchenai Crypts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_INHIBITMAGIC 32264 +#define SPELL_ATTRACTMAGIC 32265 +#define N_SPELL_CARNIVOROUSBITE 36383 +#define H_SPELL_CARNIVOROUSBITE 39382 +#define SPELL_CARNIVOROUSBITE DUNGEON_MODE(N_SPELL_CARNIVOROUSBITE, H_SPELL_CARNIVOROUSBITE) + +#define ENTRY_FOCUS_FIRE 18374 + +#define N_SPELL_FIERY_BLAST 32302 +#define H_SPELL_FIERY_BLAST 38382 +#define SPELL_FIERY_BLAST DUNGEON_MODE(N_SPELL_FIERY_BLAST, H_SPELL_FIERY_BLAST) +#define SPELL_FOCUS_FIRE_VISUAL 42075 //need to find better visual + +#define EMOTE_FOCUSES_ON "focuses on " + +struct boss_shirrak_the_dead_watcherAI : public ScriptedAI +{ + boss_shirrak_the_dead_watcherAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Inhibitmagic_Timer; + uint32 Attractmagic_Timer; + uint32 Carnivorousbite_Timer; + uint32 FocusFire_Timer; + + uint64 FocusedTargetGUID; + + void Reset() + { + Inhibitmagic_Timer = 0; + Attractmagic_Timer = 28000; + Carnivorousbite_Timer = 10000; + FocusFire_Timer = 17000; + FocusedTargetGUID = 0; + } + + void EnterCombat(Unit * /*who*/) + { } + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == ENTRY_FOCUS_FIRE) + { + summoned->CastSpell(summoned,SPELL_FOCUS_FIRE_VISUAL,false); + summoned->setFaction(me->getFaction()); + summoned->SetLevel(me->getLevel()); + summoned->addUnitState(UNIT_STAT_ROOT); + + if (Unit *pFocusedTarget = Unit::GetUnit(*me, FocusedTargetGUID)) + summoned->AI()->AttackStart(pFocusedTarget); + } + } + + void UpdateAI(const uint32 diff) + { + //Inhibitmagic_Timer + if (Inhibitmagic_Timer <= diff) + { + float dist; + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* i_pl = i->getSource()) + if (i_pl->isAlive() && (dist = i_pl->IsWithinDist(me, 45))) + { + i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC); + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 35) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 25) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + if (dist < 15) + me->AddAura(SPELL_INHIBITMAGIC, i_pl); + } + Inhibitmagic_Timer = 3000+(rand()%1000); + } else Inhibitmagic_Timer -= diff; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Attractmagic_Timer + if (Attractmagic_Timer <= diff) + { + DoCast(me, SPELL_ATTRACTMAGIC); + Attractmagic_Timer = 30000; + Carnivorousbite_Timer = 1500; + } else Attractmagic_Timer -= diff; + + //Carnivorousbite_Timer + if (Carnivorousbite_Timer <= diff) + { + DoCast(me, SPELL_CARNIVOROUSBITE); + Carnivorousbite_Timer = 10000; + } else Carnivorousbite_Timer -= diff; + + //FocusFire_Timer + if (FocusFire_Timer <= diff) + { + // Summon Focus Fire & Emote + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + { + FocusedTargetGUID = pTarget->GetGUID(); + me->SummonCreature(ENTRY_FOCUS_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,5500); + + // TODO: Find better way to handle emote + // Emote + std::string *emote = new std::string(EMOTE_FOCUSES_ON); + emote->append(pTarget->GetName()); + emote->append("!"); + const char* text = emote->c_str(); + me->MonsterTextEmote(text, 0, true); + delete emote; + } + FocusFire_Timer = 15000+(rand()%5000); + } else FocusFire_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_shirrak_the_dead_watcher(Creature* pCreature) +{ + return new boss_shirrak_the_dead_watcherAI (pCreature); +} + +struct mob_focus_fireAI : public ScriptedAI +{ + mob_focus_fireAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 FieryBlast_Timer; + bool fiery1, fiery2; + + void Reset() + { + FieryBlast_Timer = 3000+(rand()%1000); + fiery1 = fiery2 = true; + } + + void EnterCombat(Unit * /*who*/) + { } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //FieryBlast_Timer + if (fiery2 && FieryBlast_Timer <= diff) + { + DoCast(me, SPELL_FIERY_BLAST); + + if (fiery1) fiery1 = false; + else if (fiery2) fiery2 = false; + + FieryBlast_Timer = 1000; + } else FieryBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_focus_fire(Creature* pCreature) +{ + return new mob_focus_fireAI (pCreature); +} + +void AddSC_boss_shirrak_the_dead_watcher() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_shirrak_the_dead_watcher"; + newscript->GetAI = &GetAI_boss_shirrak_the_dead_watcher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_focus_fire"; + newscript->GetAI = &GetAI_mob_focus_fire; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp b/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp new file mode 100644 index 00000000000..5b15178c33e --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_nexusprince_shaffar.cpp @@ -0,0 +1,358 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_NexusPrince_Shaffar +SD%Complete: 80 +SDComment: Need more tuning of spell timers, it should not be as linear fight as current. Also should possibly find a better way to deal with his three initial beacons to make sure all aggro. +SDCategory: Auchindoun, Mana Tombs +EndScriptData */ + +/* ContentData +boss_nexusprince_shaffar +mob_ethereal_beacon +EndContentData */ + +#include "ScriptedPch.h" + +enum ePrince +{ + SAY_INTRO = -1557000, + SAY_AGGRO_1 = -1557001, + SAY_AGGRO_2 = -1557002, + SAY_AGGRO_3 = -1557003, + SAY_SLAY_1 = -1557004, + SAY_SLAY_2 = -1557005, + SAY_SUMMON = -1557006, + SAY_DEAD = -1557007, + + SPELL_BLINK = 34605, + SPELL_FROSTBOLT = 32364, + SPELL_FIREBALL = 32363, + SPELL_FROSTNOVA = 32365, + + SPELL_ETHEREAL_BEACON = 32371, // Summons NPC_BEACON + SPELL_ETHEREAL_BEACON_VISUAL = 32368, + + NPC_BEACON = 18431, + NPC_SHAFFAR = 18344, + + NR_INITIAL_BEACONS = 3 +}; + +struct boss_nexusprince_shaffarAI : public ScriptedAI +{ + boss_nexusprince_shaffarAI(Creature *c) : ScriptedAI(c), summons(me) { HasTaunted = false; } + + uint32 Blink_Timer; + uint32 Beacon_Timer; + uint32 FireBall_Timer; + uint32 Frostbolt_Timer; + uint32 FrostNova_Timer; + + SummonList summons; + + bool HasTaunted; + bool CanBlink; + + void Reset() + { + Blink_Timer = 1500; + Beacon_Timer = 10000; + FireBall_Timer = 8000; + Frostbolt_Timer = 4000; + FrostNova_Timer = 15000; + + CanBlink = false; + + float dist = 8.0f; + float posX, posY, posZ, angle; + me->GetHomePosition(posX, posY, posZ, angle); + + me->SummonCreature(NPC_BEACON, posX - dist, posY - dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + me->SummonCreature(NPC_BEACON, posX - dist, posY + dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + me->SummonCreature(NPC_BEACON, posX + dist, posY, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); + } + + void EnterEvadeMode() + { + summons.DespawnAll(); + ScriptedAI::EnterEvadeMode(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!HasTaunted && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 100.0f)) + { + DoScriptText(SAY_INTRO, me); + HasTaunted = true; + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + DoZoneInCombat(); + summons.DoZoneInCombat(); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == NPC_BEACON) + { + summoned->CastSpell(summoned,SPELL_ETHEREAL_BEACON_VISUAL,false); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(pTarget); + } + + summons.Summon(summoned); + } + + void SummonedCreatureDespawn(Creature *summon) + { + summons.Despawn(summon); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEAD, me); + summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (FrostNova_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoCast(me, SPELL_FROSTNOVA); + FrostNova_Timer = 17500 + rand()%7500; + CanBlink = true; + } else FrostNova_Timer -= diff; + + if (Frostbolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROSTBOLT); + Frostbolt_Timer = 4500 + rand()%1500; + } else Frostbolt_Timer -= diff; + + if (FireBall_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIREBALL); + FireBall_Timer = 4500 + rand()%1500; + } else FireBall_Timer -= diff; + + if (CanBlink) + { + if (Blink_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + //expire movement, will prevent from running right back to victim after cast + //(but should MoveChase be used again at a certain time or should he not move?) + if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) + me->GetMotionMaster()->MovementExpired(); + + DoCast(me, SPELL_BLINK); + Blink_Timer = 1000 + rand()%1500; + CanBlink = false; + } else Blink_Timer -= diff; + } + + if (Beacon_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + if (!urand(0,3)) + DoScriptText(SAY_SUMMON, me); + + DoCast(me, SPELL_ETHEREAL_BEACON, true); + + Beacon_Timer = 10000; + } else Beacon_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nexusprince_shaffar(Creature* pCreature) +{ + return new boss_nexusprince_shaffarAI (pCreature); +} + +enum eEnums +{ + SPELL_ARCANE_BOLT = 15254, + SPELL_ETHEREAL_APPRENTICE = 32372 // Summon 18430 +}; + +struct mob_ethereal_beaconAI : public ScriptedAI +{ + mob_ethereal_beaconAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Apprentice_Timer; + uint32 ArcaneBolt_Timer; + uint32 Check_Timer; + + void KillSelf() + { + me->Kill(me); + } + + void Reset() + { + Apprentice_Timer = DUNGEON_MODE(20000, 10000); + ArcaneBolt_Timer = 1000; + Check_Timer = 1000; + } + + void EnterCombat(Unit * who) + { + // Send Shaffar to fight + Creature* Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); + if (!Shaffar || Shaffar->isDead()) + { + KillSelf(); + return; + } + if (!Shaffar->isInCombat()) + Shaffar->AI()->AttackStart(who); + } + + void JustSummoned(Creature *summoned) + { + summoned->AI()->AttackStart(me->getVictim()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Check_Timer <= diff) + { + Creature *Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); + if (!Shaffar || Shaffar->isDead() || !Shaffar->isInCombat()) + { + KillSelf(); + return; + } + Check_Timer = 1000; + } else Check_Timer -= diff; + + if (ArcaneBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BOLT); + ArcaneBolt_Timer = 2000 + rand()%2500; + } else ArcaneBolt_Timer -= diff; + + if (Apprentice_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoCast(me, SPELL_ETHEREAL_APPRENTICE, true); + me->ForcedDespawn(); + return; + } else Apprentice_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_ethereal_beacon(Creature* pCreature) +{ + return new mob_ethereal_beaconAI (pCreature); +} + +enum eEthereal +{ + SPELL_ETHEREAL_APPRENTICE_FIREBOLT = 32369, + SPELL_ETHEREAL_APPRENTICE_FROSTBOLT = 32370 +}; + +struct mob_ethereal_apprenticeAI : public ScriptedAI +{ + mob_ethereal_apprenticeAI(Creature *c) : ScriptedAI(c) {} + + uint32 Cast_Timer; + + bool isFireboltTurn; + + void Reset() + { + Cast_Timer = 3000; + isFireboltTurn = true; + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Cast_Timer <= diff) + { + if (isFireboltTurn) + { + DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FIREBOLT, true); + isFireboltTurn = false; + }else{ + DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FROSTBOLT, true); + isFireboltTurn = true; + } + Cast_Timer = 3000; + } else Cast_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_ethereal_apprentice(Creature* pCreature) +{ + return new mob_ethereal_apprenticeAI (pCreature); +} + +void AddSC_boss_nexusprince_shaffar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_nexusprince_shaffar"; + newscript->GetAI = &GetAI_boss_nexusprince_shaffar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ethereal_beacon"; + newscript->GetAI = &GetAI_mob_ethereal_beacon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ethereal_apprentice"; + newscript->GetAI = &GetAI_mob_ethereal_apprentice; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_pandemonius.cpp b/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_pandemonius.cpp new file mode 100644 index 00000000000..51ec2e83b46 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ManaTombs/boss_pandemonius.cpp @@ -0,0 +1,126 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Pandemonius +SD%Complete: 75 +SDComment: Not known how void blast is done (amount of rapid cast seems to be related to players in party). All mobs remaining in surrounding area should aggro when engaged. +SDCategory: Auchindoun, Mana Tombs +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1557008 +#define SAY_AGGRO_2 -1557009 +#define SAY_AGGRO_3 -1557010 + +#define SAY_KILL_1 -1557011 +#define SAY_KILL_2 -1557012 + +#define SAY_DEATH -1557013 + +#define EMOTE_DARK_SHELL -1557014 + +#define SPELL_VOID_BLAST 32325 +#define H_SPELL_VOID_BLAST 38760 +#define SPELL_DARK_SHELL 32358 +#define H_SPELL_DARK_SHELL 38759 + +struct boss_pandemoniusAI : public ScriptedAI +{ + boss_pandemoniusAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 VoidBlast_Timer; + uint32 DarkShell_Timer; + uint32 VoidBlast_Counter; + + void Reset() + { + VoidBlast_Timer = 8000+rand()%15000; + DarkShell_Timer = 20000; + VoidBlast_Counter = 0; + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (VoidBlast_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_VOID_BLAST); + VoidBlast_Timer = 500; + ++VoidBlast_Counter; + } + + if (VoidBlast_Counter == 5) + { + VoidBlast_Timer = 15000+rand()%10000; + VoidBlast_Counter = 0; + } + } else VoidBlast_Timer -= diff; + + if (!VoidBlast_Counter) + { + if (DarkShell_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(EMOTE_DARK_SHELL, me); + + DoCast(me, SPELL_DARK_SHELL); + DarkShell_Timer = 20000; + } else DarkShell_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_pandemonius(Creature* pCreature) +{ + return new boss_pandemoniusAI (pCreature); +} + +void AddSC_boss_pandemonius() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_pandemonius"; + newscript->GetAI = &GetAI_boss_pandemonius; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp new file mode 100644 index 00000000000..9628fa1a98f --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_darkweaver_syth.cpp @@ -0,0 +1,414 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Darkweaver_Syth +SD%Complete: 85 +SDComment: Shock spells/times need more work. Heroic partly implemented. +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_SUMMON -1556000 + +#define SAY_AGGRO_1 -1556001 +#define SAY_AGGRO_2 -1556002 +#define SAY_AGGRO_3 -1556003 + +#define SAY_SLAY_1 -1556004 +#define SAY_SLAY_2 -1556005 + +#define SAY_DEATH -1556006 + +#define SPELL_FROST_SHOCK 21401 //37865 +#define SPELL_FLAME_SHOCK 34354 +#define SPELL_SHADOW_SHOCK 30138 +#define SPELL_ARCANE_SHOCK 37132 + +#define SPELL_CHAIN_LIGHTNING 15659 //15305 + +#define SPELL_SUMMON_SYTH_FIRE 33537 // Spawns 19203 +#define SPELL_SUMMON_SYTH_ARCANE 33538 // Spawns 19205 +#define SPELL_SUMMON_SYTH_FROST 33539 // Spawns 19204 +#define SPELL_SUMMON_SYTH_SHADOW 33540 // Spawns 19206 + +#define SPELL_FLAME_BUFFET DUNGEON_MODE(33526, 38141) +#define SPELL_ARCANE_BUFFET DUNGEON_MODE(33527, 38138) +#define SPELL_FROST_BUFFET DUNGEON_MODE(33528, 38142) +#define SPELL_SHADOW_BUFFET DUNGEON_MODE(33529, 38143) + +struct boss_darkweaver_sythAI : public ScriptedAI +{ + boss_darkweaver_sythAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 flameshock_timer; + uint32 arcaneshock_timer; + uint32 frostshock_timer; + uint32 shadowshock_timer; + uint32 chainlightning_timer; + + bool summon90; + bool summon50; + bool summon10; + + void Reset() + { + flameshock_timer = 2000; + arcaneshock_timer = 4000; + frostshock_timer = 6000; + shadowshock_timer = 8000; + chainlightning_timer = 15000; + + summon90 = false; + summon50 = false; + summon10 = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustSummoned(Creature *summoned) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(pTarget); + } + + void SythSummoning() + { + DoScriptText(SAY_SUMMON, me); + + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + DoCast(me, SPELL_SUMMON_SYTH_ARCANE, true); //front + DoCast(me, SPELL_SUMMON_SYTH_FIRE, true); //back + DoCast(me, SPELL_SUMMON_SYTH_FROST, true); //left + DoCast(me, SPELL_SUMMON_SYTH_SHADOW, true); //right + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 90) && !summon90) + { + SythSummoning(); + summon90 = true; + } + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 50) && !summon50) + { + SythSummoning(); + summon50 = true; + } + + if (((me->GetHealth()*100) / me->GetMaxHealth() < 10) && !summon10) + { + SythSummoning(); + summon10 = true; + } + + if (flameshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_SHOCK); + + flameshock_timer = 10000 + rand()%5000; + } else flameshock_timer -= diff; + + if (arcaneshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_SHOCK); + + arcaneshock_timer = 10000 + rand()%5000; + } else arcaneshock_timer -= diff; + + if (frostshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_SHOCK); + + frostshock_timer = 10000 + rand()%5000; + } else frostshock_timer -= diff; + + if (shadowshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_SHOCK); + + shadowshock_timer = 10000 + rand()%5000; + } else shadowshock_timer -= diff; + + if (chainlightning_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_CHAIN_LIGHTNING); + + chainlightning_timer = 25000; + } else chainlightning_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_darkweaver_syth(Creature* pCreature) +{ + return new boss_darkweaver_sythAI (pCreature); +} + +/* ELEMENTALS */ + +struct mob_syth_fireAI : public ScriptedAI +{ + mob_syth_fireAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 flameshock_timer; + uint32 flamebuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + flameshock_timer = 2500; + flamebuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (flameshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_SHOCK); + + flameshock_timer = 5000; + } else flameshock_timer -= diff; + + if (flamebuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FLAME_BUFFET); + + flamebuffet_timer = 5000; + } else flamebuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_fire(Creature* pCreature) +{ + return new mob_syth_fireAI (pCreature); +} + +struct mob_syth_arcaneAI : public ScriptedAI +{ + mob_syth_arcaneAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 arcaneshock_timer; + uint32 arcanebuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); + arcaneshock_timer = 2500; + arcanebuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (arcaneshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_SHOCK); + + arcaneshock_timer = 5000; + } else arcaneshock_timer -= diff; + + if (arcanebuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ARCANE_BUFFET); + + arcanebuffet_timer = 5000; + } else arcanebuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_arcane(Creature* pCreature) +{ + return new mob_syth_arcaneAI (pCreature); +} + +struct mob_syth_frostAI : public ScriptedAI +{ + mob_syth_frostAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 frostshock_timer; + uint32 frostbuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + frostshock_timer = 2500; + frostbuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (frostshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_SHOCK); + + frostshock_timer = 5000; + } else frostshock_timer -= diff; + + if (frostbuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_FROST_BUFFET); + + frostbuffet_timer = 5000; + } else frostbuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_frost(Creature* pCreature) +{ + return new mob_syth_frostAI (pCreature); +} + +struct mob_syth_shadowAI : public ScriptedAI +{ + mob_syth_shadowAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 shadowshock_timer; + uint32 shadowbuffet_timer; + + void Reset() + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); + shadowshock_timer = 2500; + shadowbuffet_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (shadowshock_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_SHOCK); + + shadowshock_timer = 5000; + } else shadowshock_timer -= diff; + + if (shadowbuffet_timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_BUFFET); + + shadowbuffet_timer = 5000; + } else shadowbuffet_timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_syth_shadow(Creature* pCreature) +{ + return new mob_syth_shadowAI (pCreature); +} + +void AddSC_boss_darkweaver_syth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_darkweaver_syth"; + newscript->GetAI = &GetAI_boss_darkweaver_syth; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_fire"; + newscript->GetAI = &GetAI_mob_syth_arcane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_arcane"; + newscript->GetAI = &GetAI_mob_syth_arcane; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_frost"; + newscript->GetAI = &GetAI_mob_syth_frost; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_syth_shadow"; + newscript->GetAI = &GetAI_mob_syth_shadow; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp new file mode 100644 index 00000000000..32b97293ca3 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_tailonking_ikiss.cpp @@ -0,0 +1,213 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Talon_King_Ikiss +SD%Complete: 80 +SDComment: Heroic supported. Some details missing, but most are spell related. +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "sethekk_halls.h" + +#define SAY_INTRO -1556007 + +#define SAY_AGGRO_1 -1556008 +#define SAY_AGGRO_2 -1556009 +#define SAY_AGGRO_3 -1556010 + +#define SAY_SLAY_1 -1556011 +#define SAY_SLAY_2 -1556012 +#define SAY_DEATH -1556013 +#define EMOTE_ARCANE_EXP -1556015 + +#define SPELL_BLINK 38194 +#define SPELL_BLINK_TELEPORT 38203 +#define SPELL_MANA_SHIELD 38151 +#define SPELL_ARCANE_BUBBLE 9438 +#define H_SPELL_SLOW 35032 + +#define SPELL_POLYMORPH 38245 +#define H_SPELL_POLYMORPH 43309 + +#define SPELL_ARCANE_VOLLEY 35059 +#define H_SPELL_ARCANE_VOLLEY 40424 + +#define SPELL_ARCANE_EXPLOSION 38197 +#define H_SPELL_ARCANE_EXPLOSION 40425 + +struct boss_talon_king_ikissAI : public ScriptedAI +{ + boss_talon_king_ikissAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ArcaneVolley_Timer; + uint32 Sheep_Timer; + uint32 Blink_Timer; + uint32 Slow_Timer; + + bool ManaShield; + bool Blink; + bool Intro; + + void Reset() + { + ArcaneVolley_Timer = 5000; + Sheep_Timer = 8000; + Blink_Timer = 35000; + Slow_Timer = 15000+rand()%15000; + Blink = false; + Intro = false; + ManaShield = false; + } + + void MoveInLineOfSight(Unit *who) + { + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!Intro && me->IsWithinDistInMap(who, 100)) + { + Intro = true; + DoScriptText(SAY_INTRO, me); + } + + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_IKISSDOOREVENT, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Blink) + { + DoCast(me, SPELL_ARCANE_EXPLOSION); + DoCast(me, SPELL_ARCANE_BUBBLE, true); + Blink = false; + } + + if (ArcaneVolley_Timer <= diff) + { + DoCast(me, SPELL_ARCANE_VOLLEY); + ArcaneVolley_Timer = 7000+rand()%5000; + } else ArcaneVolley_Timer -= diff; + + if (Sheep_Timer <= diff) + { + Unit *pTarget; + + //second top aggro target in normal, random target in heroic correct? + if (IsHeroic()) + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + else + pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); + + if (pTarget) + DoCast(pTarget, SPELL_POLYMORPH); + Sheep_Timer = 15000+rand()%2500; + } else Sheep_Timer -= diff; + + //may not be correct time to cast + if (!ManaShield && ((me->GetHealth()*100) / me->GetMaxHealth() < 20)) + { + DoCast(me, SPELL_MANA_SHIELD); + ManaShield = true; + } + + if (IsHeroic()) + { + if (Slow_Timer <= diff) + { + DoCast(me, H_SPELL_SLOW); + Slow_Timer = 15000+rand()%25000; + } else Slow_Timer -= diff; + } + + if (Blink_Timer <= diff) + { + DoScriptText(EMOTE_ARCANE_EXP, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(false); + + //Spell doesn't work, but we use for visual effect at least + DoCast(pTarget, SPELL_BLINK); + + float X = pTarget->GetPositionX(); + float Y = pTarget->GetPositionY(); + float Z = pTarget->GetPositionZ(); + + DoTeleportTo(X,Y,Z); + + DoCast(pTarget, SPELL_BLINK_TELEPORT); + Blink = true; + } + Blink_Timer = 35000+rand()%5000; + } else Blink_Timer -= diff; + + if (!Blink) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_talon_king_ikiss(Creature* pCreature) +{ + return new boss_talon_king_ikissAI (pCreature); +} + +void AddSC_boss_talon_king_ikiss() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_talon_king_ikiss"; + newscript->GetAI = &GetAI_boss_talon_king_ikiss; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp new file mode 100644 index 00000000000..ee27da3cff5 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/instance_sethekk_halls.cpp @@ -0,0 +1,91 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance - Sethekk Halls +SD%Complete: 50 +SDComment: Instance Data for Sethekk Halls instance +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "sethekk_halls.h" + +enum eEnums +{ + NPC_ANZU = 23035, + IKISS_DOOR = 177203, +}; + +struct instance_sethekk_halls : public ScriptedInstance +{ + instance_sethekk_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 AnzuEncounter; + uint64 m_uiIkissDoorGUID; + + void Initialize() + { + AnzuEncounter = NOT_STARTED; + m_uiIkissDoorGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + if (pCreature->GetEntry() == NPC_ANZU) + { + if (AnzuEncounter >= IN_PROGRESS) + pCreature->DisappearAndDie(); + else + AnzuEncounter = IN_PROGRESS; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + if (pGo->GetEntry() == IKISS_DOOR) + m_uiIkissDoorGUID = pGo->GetGUID(); + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_IKISSDOOREVENT: + if (data == DONE) + DoUseDoorOrButton(m_uiIkissDoorGUID,DAY*IN_MILISECONDS); + break; + case TYPE_ANZU_ENCOUNTER: + AnzuEncounter = data; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_sethekk_halls(Map* pMap) +{ + return new instance_sethekk_halls(pMap); +} + +void AddSC_instance_sethekk_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_sethekk_halls"; + newscript->GetInstanceData = &GetInstanceData_instance_sethekk_halls; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h b/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h new file mode 100644 index 00000000000..79a6cd4952d --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/sethekk_halls.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SETHEKK_HALLS_H +#define DEF_SETHEKK_HALLS_H + +enum eTypes +{ + DATA_IKISSDOOREVENT = 1, + TYPE_ANZU_ENCOUNTER = 2, +}; +#endif + diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp new file mode 100644 index 00000000000..2bb6a717a5a --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_ambassador_hellmaw.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Ambassador_Hellmaw +SD%Complete: 80 +SDComment: Enrage spell missing/not known +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "ScriptedEscortAI.h" +#include "shadow_labyrinth.h" + +enum eEnums +{ + SAY_INTRO = -1555000, + SAY_AGGRO1 = -1555001, + SAY_AGGRO2 = -1555002, + SAY_AGGRO3 = -1555003, + SAY_HELP = -1555004, + SAY_SLAY1 = -1555005, + SAY_SLAY2 = -1555006, + SAY_DEATH = -1555007, + + SPELL_BANISH = 30231, + SPELL_CORROSIVE_ACID = 33551, + SPELL_FEAR = 33547, + SPELL_ENRAGE = 34970 +}; + +struct boss_ambassador_hellmawAI : public npc_escortAI +{ + boss_ambassador_hellmawAI(Creature* pCreature) : npc_escortAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + uint32 EventCheck_Timer; + uint32 CorrosiveAcid_Timer; + uint32 Fear_Timer; + uint32 Enrage_Timer; + bool Intro; + bool IsBanished; + bool Enraged; + + void Reset() + { + EventCheck_Timer = 5000; + CorrosiveAcid_Timer = 5000 + rand()%5000; + Fear_Timer = 25000 + rand()%5000; + Enrage_Timer = 180000; + Intro = false; + IsBanished = true; + Enraged = false; + + if (m_pInstance && me->isAlive()) + { + if (m_pInstance->GetData(TYPE_OVERSEER) != DONE) + DoCast(me, SPELL_BANISH, true); + } + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_HELLMAW, FAIL); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (me->HasAura(SPELL_BANISH)) + return; + + npc_escortAI::MoveInLineOfSight(pWho); + } + + void WaypointReached(uint32 /*i*/) + { + } + + void DoIntro() + { + if (me->HasAura(SPELL_BANISH)) + me->RemoveAurasDueToSpell(SPELL_BANISH); + + IsBanished = false; + Intro = true; + + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_HELLMAW) != FAIL) + { + DoScriptText(SAY_INTRO, me); + Start(true, false, 0, NULL, false, true); + } + + m_pInstance->SetData(TYPE_HELLMAW, IN_PROGRESS); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (m_pInstance) + m_pInstance->SetData(TYPE_HELLMAW, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!Intro && !HasEscortState(STATE_ESCORT_ESCORTING)) + { + if (EventCheck_Timer <= diff) + { + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_OVERSEER) == DONE) + { + DoIntro(); + return; + } + } + EventCheck_Timer = 5000; + return; + } + else + { + EventCheck_Timer -= diff; + return; + } + } + + npc_escortAI::UpdateAI(diff); + + if (!UpdateVictim()) + return; + + if (me->HasAura(SPELL_BANISH, 0)) + { + EnterEvadeMode(); + return; + } + + if (CorrosiveAcid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CORROSIVE_ACID); + CorrosiveAcid_Timer = 15000 + rand()%10000; + } else CorrosiveAcid_Timer -= diff; + + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 20000 + rand()%15000; + } else Fear_Timer -= diff; + + if (IsHeroic()) + { + if (!Enraged && Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enraged = true; + } else Enrage_Timer -= diff; + } + } +}; + +CreatureAI* GetAI_boss_ambassador_hellmaw(Creature* pCreature) +{ + return new boss_ambassador_hellmawAI(pCreature); +} + +void AddSC_boss_ambassador_hellmaw() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ambassador_hellmaw"; + newscript->GetAI = &GetAI_boss_ambassador_hellmaw; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp new file mode 100644 index 00000000000..52c60ae0d0e --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp @@ -0,0 +1,169 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Blackheart_the_Inciter +SD%Complete: 75 +SDComment: Incite Chaos not functional since core lacks Mind Control support +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define SPELL_INCITE_CHAOS 33676 +#define SPELL_INCITE_CHAOS_B 33684 //debuff applied to each member of party +#define SPELL_CHARGE 33709 +#define SPELL_WAR_STOMP 33707 + +#define SAY_INTRO1 -1555008 //not used +#define SAY_INTRO2 -1555009 //not used +#define SAY_INTRO3 -1555010 //not used +#define SAY_AGGRO1 -1555011 +#define SAY_AGGRO2 -1555012 +#define SAY_AGGRO3 -1555013 +#define SAY_SLAY1 -1555014 +#define SAY_SLAY2 -1555015 +#define SAY_HELP -1555016 //not used +#define SAY_DEATH -1555017 + +//below, not used +#define SAY2_INTRO1 -1555018 +#define SAY2_INTRO2 -1555019 +#define SAY2_INTRO3 -1555020 +#define SAY2_AGGRO1 -1555021 +#define SAY2_AGGRO2 -1555022 +#define SAY2_AGGRO3 -1555023 +#define SAY2_SLAY1 -1555024 +#define SAY2_SLAY2 -1555025 +#define SAY2_HELP -1555026 +#define SAY2_DEATH -1555027 + +struct boss_blackheart_the_inciterAI : public ScriptedAI +{ + boss_blackheart_the_inciterAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + bool InciteChaos; + uint32 InciteChaos_Timer; + uint32 InciteChaosWait_Timer; + uint32 Charge_Timer; + uint32 Knockback_Timer; + + void Reset() + { + InciteChaos = false; + InciteChaos_Timer = 20000; + InciteChaosWait_Timer = 15000; + Charge_Timer = 5000; + Knockback_Timer = 15000; + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + + if (pInstance) + pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (InciteChaos) + { + if (InciteChaosWait_Timer <= diff) + { + InciteChaos = false; + InciteChaosWait_Timer = 15000; + } else InciteChaosWait_Timer -= diff; + + return; + } + + if (InciteChaos_Timer <= diff) + { + DoCast(me, SPELL_INCITE_CHAOS); + + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + pTarget->CastSpell(pTarget,SPELL_INCITE_CHAOS_B,true); + } + + DoResetThreat(); + InciteChaos = true; + InciteChaos_Timer = 40000; + return; + } else InciteChaos_Timer -= diff; + + //Charge_Timer + if (Charge_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CHARGE); + Charge_Timer = 15000 + rand()%10000; + } else Charge_Timer -= diff; + + //Knockback_Timer + if (Knockback_Timer <= diff) + { + DoCast(me, SPELL_WAR_STOMP); + Knockback_Timer = 18000 + rand()%6000; + } else Knockback_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_blackheart_the_inciter(Creature* pCreature) +{ + return new boss_blackheart_the_inciterAI (pCreature); +} + +void AddSC_boss_blackheart_the_inciter() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_blackheart_the_inciter"; + newscript->GetAI = &GetAI_boss_blackheart_the_inciter; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp new file mode 100644 index 00000000000..8b63b765b47 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_grandmaster_vorpil.cpp @@ -0,0 +1,313 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grandmaster_Vorpil +SD%Complete: 100 +SDComment: +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define SAY_INTRO -1555028 +#define SAY_AGGRO1 -1555029 +#define SAY_AGGRO2 -1555030 +#define SAY_AGGRO3 -1555031 +#define SAY_HELP -1555032 +#define SAY_SLAY1 -1555033 +#define SAY_SLAY2 -1555034 +#define SAY_DEATH -1555035 + +#define SPELL_RAIN_OF_FIRE 33617 +#define H_SPELL_RAIN_OF_FIRE 39363 + +#define SPELL_DRAW_SHADOWS 33563 +#define SPELL_SHADOWBOLT_VOLLEY 33841 +#define SPELL_BANISH 38791 + +#define MOB_VOID_TRAVELER 19226 +#define SPELL_SACRIFICE 33587 +#define SPELL_SHADOW_NOVA 33846 +#define SPELL_EMPOWERING_SHADOWS 33783 +#define H_SPELL_EMPOWERING_SHADOWS 39364 + +#define MOB_VOID_PORTAL 19224 +#define SPELL_VOID_PORTAL_VISUAL 33569 + +float VorpilPosition[3] = {-252.8820,-264.3030,17.1}; + +float VoidPortalCoords[5][3] = +{ + {-283.5894, -239.5718, 12.7}, + {-306.5853, -258.4539, 12.7}, + {-295.8789, -269.0899, 12.7}, + {-209.3401, -262.7564, 17.1}, + {-261.4533, -297.3298, 17.1} +}; + +struct mob_voidtravelerAI : public ScriptedAI +{ + mob_voidtravelerAI(Creature *c) : ScriptedAI(c) + { + } + + uint64 VorpilGUID; + uint32 move; + bool sacrificed; + + void Reset() + { + VorpilGUID = 0; + move = 0; + sacrificed = false; + } + + void EnterCombat(Unit * /*who*/){} + + void UpdateAI(const uint32 diff) + { + if (!VorpilGUID) + { + me->Kill(me); + return; + } + if (move <= diff) + { + Creature *Vorpil = Unit::GetCreature(*me, VorpilGUID); + if (!Vorpil) + { + VorpilGUID = 0; + return; + } + + if (sacrificed) + { + me->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), Vorpil); + Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth()/25); + DoCast(me, SPELL_SHADOW_NOVA, true); + me->Kill(me); + return; + } + me->GetMotionMaster()->MoveFollow(Vorpil,0,0); + if (me->IsWithinDist(Vorpil, 3)) + { + DoCast(me, SPELL_SACRIFICE, false); + sacrificed = true; + move = 500; + return; + } + if (!Vorpil->isInCombat() || Vorpil->isDead()) + { + me->Kill(me); + return; + } + move = 1000; + } else move -= diff; + } +}; +CreatureAI* GetAI_mob_voidtraveler(Creature* pCreature) +{ + return new mob_voidtravelerAI (pCreature); +} + +struct boss_grandmaster_vorpilAI : public ScriptedAI +{ + boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = false; + } + + ScriptedInstance *pInstance; + bool Intro, HelpYell; + bool sumportals; + + uint32 ShadowBoltVolley_Timer; + uint32 DrawShadows_Timer; + uint32 summonTraveler_Timer; + uint32 banish_Timer; + uint64 PortalsGuid[5]; + + void Reset() + { + ShadowBoltVolley_Timer = 7000 + rand()%7000; + DrawShadows_Timer = 45000; + summonTraveler_Timer = 90000; + banish_Timer = 17000; + HelpYell = false; + destroyPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED); + } + + void summonPortals() + { + if (!sumportals) + { + for (uint8 i = 0; i < 5; ++i) + { + Creature *Portal = NULL; + Portal = me->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000); + if (Portal) + { + PortalsGuid[i] = Portal->GetGUID(); + Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false); + } + } + sumportals = true; + summonTraveler_Timer = 5000; + } + } + + void destroyPortals() + { + if (sumportals) + { + for (uint8 i = 0; i < 5; ++i) + { + Unit *Portal = Unit::GetUnit((*me), PortalsGuid[i]); + if (Portal && Portal->isAlive()) + Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + PortalsGuid[i] = 0; + } + sumportals = false; + } + } + + void spawnVoidTraveler() + { + int pos = urand(0,4); + me->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,5000); + if (!HelpYell) + { + DoScriptText(SAY_HELP, me); + HelpYell = true; + } + } + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == MOB_VOID_TRAVELER) + CAST_AI(mob_voidtravelerAI, summoned->AI())->VorpilGUID = me->GetGUID(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + destroyPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + summonPortals(); + + if (pInstance) + pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS); + } + + void MoveInLineOfSight(Unit *who) + { + ScriptedAI::MoveInLineOfSight(who); + + if (!Intro && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 100) && me->IsHostileTo(who)) + { + DoScriptText(SAY_INTRO, me); + Intro = true; + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOWBOLT_VOLLEY); + ShadowBoltVolley_Timer = 15000 + rand()%15000; + } else ShadowBoltVolley_Timer -= diff; + + if (IsHeroic() && banish_Timer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,false); + if (pTarget) + { + DoCast(pTarget, SPELL_BANISH); + banish_Timer = 16000; + } + } else banish_Timer -= diff; + + if (DrawShadows_Timer <= diff) + { + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (Player* i_pl = i->getSource()) + if (i_pl->isAlive() && !i_pl->HasAura(SPELL_BANISH)) + i_pl->TeleportTo(me->GetMapId(), VorpilPosition[0],VorpilPosition[1],VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT); + + me->GetMap()->CreatureRelocation(me, VorpilPosition[0],VorpilPosition[1],VorpilPosition[2],0.0f); + DoCast(me, SPELL_DRAW_SHADOWS, true); + + DoCast(me, SPELL_RAIN_OF_FIRE); + + ShadowBoltVolley_Timer = 6000; + DrawShadows_Timer = 30000; + } else DrawShadows_Timer -= diff; + + if (summonTraveler_Timer <= diff) + { + spawnVoidTraveler(); + summonTraveler_Timer = 10000; + //enrage at 20% + if ((me->GetHealth()*5) < me->GetMaxHealth()) + summonTraveler_Timer = 5000; + } else summonTraveler_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_grandmaster_vorpil(Creature* pCreature) +{ + return new boss_grandmaster_vorpilAI (pCreature); +} + +void AddSC_boss_grandmaster_vorpil() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_grandmaster_vorpil"; + newscript->GetAI = &GetAI_boss_grandmaster_vorpil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_voidtraveler"; + newscript->GetAI = &GetAI_mob_voidtraveler; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp new file mode 100644 index 00000000000..14bf249c3b5 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp @@ -0,0 +1,205 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Murmur +SD%Complete: 90 +SDComment: Timers may be incorrect +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define EMOTE_SONIC_BOOM -1555036 + +#define SPELL_SONIC_BOOM_CAST DUNGEON_MODE(33923, 38796) +#define SPELL_SONIC_BOOM_EFFECT DUNGEON_MODE(33666, 38795) +#define SPELL_RESONANCE 33657 +#define SPELL_MURMURS_TOUCH DUNGEON_MODE(33711, 38794) +#define SPELL_MAGNETIC_PULL 33689 +#define SPELL_SONIC_SHOCK 38797 +#define SPELL_THUNDERING_STORM 39365 + +struct boss_murmurAI : public ScriptedAI +{ + boss_murmurAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 SonicBoom_Timer; + uint32 MurmursTouch_Timer; + uint32 Resonance_Timer; + uint32 MagneticPull_Timer; + uint32 SonicShock_Timer; + uint32 ThunderingStorm_Timer; + bool SonicBoom; + + void Reset() + { + SonicBoom_Timer = 30000; + MurmursTouch_Timer = 8000 + rand()%12000; + Resonance_Timer = 5000; + MagneticPull_Timer = 15000 + rand()%15000; + ThunderingStorm_Timer = 15000; + SonicShock_Timer = 10000; + SonicBoom = false; + + //database should have `RegenHealth`=0 to prevent regen + uint32 hp = (me->GetMaxHealth()*40)/100; + if (hp) me->SetHealth(hp); + me->ResetPlayerDamageReq(); + } + + void SonicBoomEffect() + { + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) + { + //Not do anything without aura, spell can be resisted! + if (pTarget->HasAura(SPELL_SONIC_BOOM_CAST) && me->IsWithinDistInMap(pTarget, 34.0f)) + { + //This will be wrong calculation. Also, comments suggest it must deal damage + pTarget->SetHealth(uint32(pTarget->GetMaxHealth() - pTarget->GetMaxHealth() * 0.8)); + } + } + } + } + + void EnterCombat(Unit * /*who*/) { } + + // Sonic Boom instant damage (needs core fix instead of this) + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (pTarget && pTarget->isAlive() && spell && spell->Id == uint32(SPELL_SONIC_BOOM_EFFECT)) + me->DealDamage(pTarget,(pTarget->GetHealth()*90)/100,NULL,SPELL_DIRECT_DAMAGE,SPELL_SCHOOL_MASK_NATURE,spell); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target or casting + if (!UpdateVictim() || me->IsNonMeleeSpellCasted(false)) + return; + + // Sonic Boom + if (SonicBoom) + { + DoCast(me, SPELL_SONIC_BOOM_EFFECT, true); + SonicBoomEffect(); + + SonicBoom = false; + Resonance_Timer = 1500; + } + if (SonicBoom_Timer <= diff) + { + DoScriptText(EMOTE_SONIC_BOOM, me); + DoCast(me, SPELL_SONIC_BOOM_CAST); + SonicBoom_Timer = 30000; + SonicBoom = true; + return; + } else SonicBoom_Timer -= diff; + + // Murmur's Touch + if (MurmursTouch_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,80,true)) + DoCast(pTarget, SPELL_MURMURS_TOUCH); + MurmursTouch_Timer = 25000 + rand()%10000; + } else MurmursTouch_Timer -= diff; + + // Resonance + if (!SonicBoom && !(me->IsWithinMeleeRange(me->getVictim()))) + { + if (Resonance_Timer <= diff) + { + DoCast(me, SPELL_RESONANCE); + Resonance_Timer = 5000; + } else Resonance_Timer -= diff; + } + + // Magnetic Pull + if (MagneticPull_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + if (pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) + { + DoCast(pTarget, SPELL_MAGNETIC_PULL); + MagneticPull_Timer = 15000+rand()%15000; + return; + } + MagneticPull_Timer = 500; + } else MagneticPull_Timer -= diff; + + if (IsHeroic()) + { + // Thundering Storm + if (ThunderingStorm_Timer <= diff) + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) + if (pTarget->isAlive() && !me->IsWithinDist(pTarget, 35, false)) + DoCast(pTarget, SPELL_THUNDERING_STORM, true); + ThunderingStorm_Timer = 15000; + } else ThunderingStorm_Timer -= diff; + + // Sonic Shock + if (SonicShock_Timer <= diff) + { + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,20,false)) + if (pTarget->isAlive()) + DoCast(pTarget, SPELL_SONIC_SHOCK); + SonicShock_Timer = 10000+rand()%10000; + } else SonicShock_Timer -= diff; + } + + // Select nearest most aggro target if top aggro too far + if (!me->isAttackReady()) + return; + if (!me->IsWithinMeleeRange(me->getVictim())) + { + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) + if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) + if (pTarget->isAlive() && me->IsWithinMeleeRange(pTarget)) + { + me->TauntApply(pTarget); + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_murmur(Creature* pCreature) +{ + return new boss_murmurAI (pCreature); +} + +void AddSC_boss_murmur() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_murmur"; + newscript->GetAI = &GetAI_boss_murmur; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp new file mode 100644 index 00000000000..78340e5e132 --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/instance_shadow_labyrinth.cpp @@ -0,0 +1,227 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shadow_Labyrinth +SD%Complete: 85 +SDComment: Some cleanup left along with save +SDCategory: Auchindoun, Shadow Labyrinth +EndScriptData */ + +#include "ScriptedPch.h" +#include "shadow_labyrinth.h" + +#define MAX_ENCOUNTER 5 + +#define REFECTORY_DOOR 183296 //door opened when blackheart the inciter dies +#define SCREAMING_HALL_DOOR 183295 //door opened when grandmaster vorpil dies + +/* Shadow Labyrinth encounters: +1 - Ambassador Hellmaw event +2 - Blackheart the Inciter event +3 - Grandmaster Vorpil event +4 - Murmur event +*/ + +struct instance_shadow_labyrinth : public ScriptedInstance +{ + instance_shadow_labyrinth(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + uint64 m_uiRefectoryDoorGUID; + uint64 m_uiScreamingHallDoorGUID; + + uint64 m_uiGrandmasterVorpil; + uint32 m_uiFelOverseerCount; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiRefectoryDoorGUID = 0; + m_uiScreamingHallDoorGUID = 0; + + m_uiGrandmasterVorpil = 0; + m_uiFelOverseerCount = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case REFECTORY_DOOR: + m_uiRefectoryDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[2] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case SCREAMING_HALL_DOOR: + m_uiScreamingHallDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[3] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 18732: + m_uiGrandmasterVorpil = pCreature->GetGUID(); + break; + case 18796: + if (pCreature->isAlive()) + { + ++m_uiFelOverseerCount; + debug_log("TSCR: Shadow Labyrinth: counting %u Fel Overseers.",m_uiFelOverseerCount); + } + break; + } + } + + void SetData(uint32 type, uint32 uiData) + { + switch(type) + { + case TYPE_HELLMAW: + m_auiEncounter[0] = uiData; + break; + + case TYPE_OVERSEER: + if (uiData != DONE) + { + error_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER did not expect other data than DONE"); + return; + } + if (m_uiFelOverseerCount) + { + --m_uiFelOverseerCount; + + if (m_uiFelOverseerCount) + debug_log("TSCR: Shadow Labyrinth: %u Fel Overseers left to kill.",m_uiFelOverseerCount); + else + { + m_auiEncounter[1] = DONE; + debug_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER == DONE"); + } + } + break; + + case DATA_BLACKHEARTTHEINCITEREVENT: + if (uiData == DONE) + DoUseDoorOrButton(m_uiRefectoryDoorGUID); + m_auiEncounter[2] = uiData; + break; + + case DATA_GRANDMASTERVORPILEVENT: + if (uiData == DONE) + DoUseDoorOrButton(m_uiScreamingHallDoorGUID); + m_auiEncounter[3] = uiData; + break; + + case DATA_MURMUREVENT: + m_auiEncounter[4] = uiData; + break; + } + + if (uiData == DONE) + { + if (type == TYPE_OVERSEER && m_uiFelOverseerCount != 0) + return; + + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " + << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HELLMAW: return m_auiEncounter[0]; + case TYPE_OVERSEER: return m_auiEncounter[1]; + case DATA_GRANDMASTERVORPILEVENT: return m_auiEncounter[3]; + case DATA_MURMUREVENT: return m_auiEncounter[4]; + } + return false; + } + + uint64 GetData64(uint32 identifier) + { + if (identifier == DATA_GRANDMASTERVORPIL) + return m_uiGrandmasterVorpil; + + return 0; + } + + std::string GetSaveData() + { + return str_data; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_shadow_labyrinth(Map* pMap) +{ + return new instance_shadow_labyrinth(pMap); +} + +void AddSC_instance_shadow_labyrinth() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shadow_labyrinth"; + newscript->GetInstanceData = &GetInstanceData_instance_shadow_labyrinth; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h new file mode 100644 index 00000000000..a78955368bf --- /dev/null +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/shadow_labyrinth.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHADOW_LABYRINTH_H +#define DEF_SHADOW_LABYRINTH_H + +#define TYPE_HELLMAW 1 +#define TYPE_OVERSEER 2 +#define DATA_BLACKHEARTTHEINCITEREVENT 3 +#define DATA_GRANDMASTERVORPILEVENT 4 +#define DATA_MURMUREVENT 5 +#define DATA_GRANDMASTERVORPIL 6 +#endif + diff --git a/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp b/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp deleted file mode 100644 index bfde95ffcb0..00000000000 --- a/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Exarch_Maladaar -SD%Complete: 95 -SDComment: Most of event implemented, some adjustments to timers remain and possibly make some better code for switching his dark side in to better "images" of player. -SDCategory: Auchindoun, Auchenai Crypts -EndScriptData */ - -/* ContentData -mob_stolen_soul -boss_exarch_maladaar -mob_avatar_of_martyred -EndContentData */ - -#include "ScriptedPch.h" - -#define SPELL_MOONFIRE 37328 -#define SPELL_FIREBALL 37329 -#define SPELL_MIND_FLAY 37330 -#define SPELL_HEMORRHAGE 37331 -#define SPELL_FROSTSHOCK 37332 -#define SPELL_CURSE_OF_AGONY 37334 -#define SPELL_MORTAL_STRIKE 37335 -#define SPELL_FREEZING_TRAP 37368 -#define SPELL_HAMMER_OF_JUSTICE 37369 - -struct mob_stolen_soulAI : public ScriptedAI -{ - mob_stolen_soulAI(Creature *c) : ScriptedAI(c) {} - - uint8 myClass; - uint32 Class_Timer; - - void Reset() - { - Class_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { } - - void SetMyClass(uint8 myclass) - { - myClass = myclass; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Class_Timer <= diff) - { - switch (myClass) - { - case CLASS_WARRIOR: - DoCast(me->getVictim(), SPELL_MORTAL_STRIKE); - Class_Timer = 6000; - break; - case CLASS_PALADIN: - DoCast(me->getVictim(), SPELL_HAMMER_OF_JUSTICE); - Class_Timer = 6000; - break; - case CLASS_HUNTER: - DoCast(me->getVictim(), SPELL_FREEZING_TRAP); - Class_Timer = 20000; - break; - case CLASS_ROGUE: - DoCast(me->getVictim(), SPELL_HEMORRHAGE); - Class_Timer = 10000; - break; - case CLASS_PRIEST: - DoCast(me->getVictim(), SPELL_MIND_FLAY); - Class_Timer = 5000; - break; - case CLASS_SHAMAN: - DoCast(me->getVictim(), SPELL_FROSTSHOCK); - Class_Timer = 8000; - break; - case CLASS_MAGE: - DoCast(me->getVictim(), SPELL_FIREBALL); - Class_Timer = 5000; - break; - case CLASS_WARLOCK: - DoCast(me->getVictim(), SPELL_CURSE_OF_AGONY); - Class_Timer = 20000; - break; - case CLASS_DRUID: - DoCast(me->getVictim(), SPELL_MOONFIRE); - Class_Timer = 10000; - break; - } - } else Class_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_stolen_soul(Creature* pCreature) -{ - return new mob_stolen_soulAI (pCreature); -} - -#define SAY_INTRO -1558000 -#define SAY_SUMMON -1558001 - -#define SAY_AGGRO_1 -1558002 -#define SAY_AGGRO_2 -1558003 -#define SAY_AGGRO_3 -1558004 - -#define SAY_ROAR -1558005 -#define SAY_SOUL_CLEAVE -1558006 - -#define SAY_SLAY_1 -1558007 -#define SAY_SLAY_2 -1558008 - -#define SAY_DEATH -1558009 - -#define SPELL_RIBBON_OF_SOULS 32422 -#define SPELL_SOUL_SCREAM 32421 - -#define SPELL_STOLEN_SOUL 32346 -#define SPELL_STOLEN_SOUL_VISUAL 32395 - -#define SPELL_SUMMON_AVATAR 32424 - -#define ENTRY_STOLEN_SOUL 18441 - -struct boss_exarch_maladaarAI : public ScriptedAI -{ - boss_exarch_maladaarAI(Creature *c) : ScriptedAI(c) - { - HasTaunted = false; - } - - uint32 soulmodel; - uint64 soulholder; - uint8 soulclass; - - uint32 Fear_timer; - uint32 Ribbon_of_Souls_timer; - uint32 StolenSoul_Timer; - - bool HasTaunted; - bool Avatar_summoned; - - void Reset() - { - soulmodel = 0; - soulholder = 0; - soulclass = 0; - - Fear_timer = 15000 + rand()% 5000; - Ribbon_of_Souls_timer = 5000; - StolenSoul_Timer = 25000 + rand()% 10000; - - Avatar_summoned = false; - } - - void MoveInLineOfSight(Unit *who) - { - if (!HasTaunted && me->IsWithinDistInMap(who, 150.0)) - { - DoScriptText(SAY_INTRO, me); - HasTaunted = true; - } - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == ENTRY_STOLEN_SOUL) - { - //SPELL_STOLEN_SOUL_VISUAL has shapeshift effect, but not implemented feature in Trinity for this spell. - summoned->CastSpell(summoned,SPELL_STOLEN_SOUL_VISUAL,false); - summoned->SetDisplayId(soulmodel); - summoned->setFaction(me->getFaction()); - - if (Unit *pTarget = Unit::GetUnit(*me,soulholder)) - { - - CAST_AI(mob_stolen_soulAI, summoned->AI())->SetMyClass(soulclass); - summoned->AI()->AttackStart(pTarget); - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - //When Exarch Maladar is defeated D'ore appear. - me->SummonCreature(19412, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 600000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (!Avatar_summoned && ((me->GetHealth()*100) / me->GetMaxHealth() < 25)) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(SAY_SUMMON, me); - - DoCast(me, SPELL_SUMMON_AVATAR); - Avatar_summoned = true; - StolenSoul_Timer = 15000 + rand()% 15000; - } - - if (StolenSoul_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - uint32 i = urand(1,2); - if (i == 1) - DoScriptText(SAY_ROAR, me); - else - DoScriptText(SAY_SOUL_CLEAVE, me); - - soulmodel = pTarget->GetDisplayId(); - soulholder = pTarget->GetGUID(); - soulclass = pTarget->getClass(); - - DoCast(pTarget, SPELL_STOLEN_SOUL); - me->SummonCreature(ENTRY_STOLEN_SOUL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); - - StolenSoul_Timer = 20000 + rand()% 10000; - } else StolenSoul_Timer = 1000; - } - } else StolenSoul_Timer -= diff; - - if (Ribbon_of_Souls_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_RIBBON_OF_SOULS); - - Ribbon_of_Souls_timer = 5000 + (rand()%20 * 1000); - } else Ribbon_of_Souls_timer -= diff; - - if (Fear_timer <= diff) - { - DoCast(me, SPELL_SOUL_SCREAM); - Fear_timer = 15000 + rand()% 15000; - } else Fear_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_exarch_maladaar(Creature* pCreature) -{ - return new boss_exarch_maladaarAI (pCreature); -} - -#define SPELL_AV_MORTAL_STRIKE 16856 -#define SPELL_AV_SUNDER_ARMOR 16145 - -struct mob_avatar_of_martyredAI : public ScriptedAI -{ - mob_avatar_of_martyredAI(Creature *c) : ScriptedAI(c) {} - - uint32 Mortal_Strike_timer; - - void Reset() - { - Mortal_Strike_timer = 10000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Mortal_Strike_timer <= diff) - { - DoCast(me->getVictim(), SPELL_AV_MORTAL_STRIKE); - Mortal_Strike_timer = 10000 + rand()%20 * 1000; - } else Mortal_Strike_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_avatar_of_martyred(Creature* pCreature) -{ - return new mob_avatar_of_martyredAI (pCreature); -} - -void AddSC_boss_exarch_maladaar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_exarch_maladaar"; - newscript->GetAI = &GetAI_boss_exarch_maladaar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_avatar_of_martyred"; - newscript->GetAI = &GetAI_mob_avatar_of_martyred; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_stolen_soul"; - newscript->GetAI = &GetAI_mob_stolen_soul; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp b/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp deleted file mode 100644 index c13e2905171..00000000000 --- a/src/server/scripts/Outland/Auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -Name: Boss_Shirrak_the_dead_watcher -%Complete: 80 -Comment: InhibitMagic should stack slower far from the boss, proper Visual for Focus Fire, heroic implemented -Category: Auchindoun, Auchenai Crypts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_INHIBITMAGIC 32264 -#define SPELL_ATTRACTMAGIC 32265 -#define N_SPELL_CARNIVOROUSBITE 36383 -#define H_SPELL_CARNIVOROUSBITE 39382 -#define SPELL_CARNIVOROUSBITE DUNGEON_MODE(N_SPELL_CARNIVOROUSBITE, H_SPELL_CARNIVOROUSBITE) - -#define ENTRY_FOCUS_FIRE 18374 - -#define N_SPELL_FIERY_BLAST 32302 -#define H_SPELL_FIERY_BLAST 38382 -#define SPELL_FIERY_BLAST DUNGEON_MODE(N_SPELL_FIERY_BLAST, H_SPELL_FIERY_BLAST) -#define SPELL_FOCUS_FIRE_VISUAL 42075 //need to find better visual - -#define EMOTE_FOCUSES_ON "focuses on " - -struct boss_shirrak_the_dead_watcherAI : public ScriptedAI -{ - boss_shirrak_the_dead_watcherAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Inhibitmagic_Timer; - uint32 Attractmagic_Timer; - uint32 Carnivorousbite_Timer; - uint32 FocusFire_Timer; - - uint64 FocusedTargetGUID; - - void Reset() - { - Inhibitmagic_Timer = 0; - Attractmagic_Timer = 28000; - Carnivorousbite_Timer = 10000; - FocusFire_Timer = 17000; - FocusedTargetGUID = 0; - } - - void EnterCombat(Unit * /*who*/) - { } - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == ENTRY_FOCUS_FIRE) - { - summoned->CastSpell(summoned,SPELL_FOCUS_FIRE_VISUAL,false); - summoned->setFaction(me->getFaction()); - summoned->SetLevel(me->getLevel()); - summoned->addUnitState(UNIT_STAT_ROOT); - - if (Unit *pFocusedTarget = Unit::GetUnit(*me, FocusedTargetGUID)) - summoned->AI()->AttackStart(pFocusedTarget); - } - } - - void UpdateAI(const uint32 diff) - { - //Inhibitmagic_Timer - if (Inhibitmagic_Timer <= diff) - { - float dist; - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* i_pl = i->getSource()) - if (i_pl->isAlive() && (dist = i_pl->IsWithinDist(me, 45))) - { - i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC); - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 35) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 25) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - if (dist < 15) - me->AddAura(SPELL_INHIBITMAGIC, i_pl); - } - Inhibitmagic_Timer = 3000+(rand()%1000); - } else Inhibitmagic_Timer -= diff; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Attractmagic_Timer - if (Attractmagic_Timer <= diff) - { - DoCast(me, SPELL_ATTRACTMAGIC); - Attractmagic_Timer = 30000; - Carnivorousbite_Timer = 1500; - } else Attractmagic_Timer -= diff; - - //Carnivorousbite_Timer - if (Carnivorousbite_Timer <= diff) - { - DoCast(me, SPELL_CARNIVOROUSBITE); - Carnivorousbite_Timer = 10000; - } else Carnivorousbite_Timer -= diff; - - //FocusFire_Timer - if (FocusFire_Timer <= diff) - { - // Summon Focus Fire & Emote - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) - { - FocusedTargetGUID = pTarget->GetGUID(); - me->SummonCreature(ENTRY_FOCUS_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,5500); - - // TODO: Find better way to handle emote - // Emote - std::string *emote = new std::string(EMOTE_FOCUSES_ON); - emote->append(pTarget->GetName()); - emote->append("!"); - const char* text = emote->c_str(); - me->MonsterTextEmote(text, 0, true); - delete emote; - } - FocusFire_Timer = 15000+(rand()%5000); - } else FocusFire_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_shirrak_the_dead_watcher(Creature* pCreature) -{ - return new boss_shirrak_the_dead_watcherAI (pCreature); -} - -struct mob_focus_fireAI : public ScriptedAI -{ - mob_focus_fireAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 FieryBlast_Timer; - bool fiery1, fiery2; - - void Reset() - { - FieryBlast_Timer = 3000+(rand()%1000); - fiery1 = fiery2 = true; - } - - void EnterCombat(Unit * /*who*/) - { } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //FieryBlast_Timer - if (fiery2 && FieryBlast_Timer <= diff) - { - DoCast(me, SPELL_FIERY_BLAST); - - if (fiery1) fiery1 = false; - else if (fiery2) fiery2 = false; - - FieryBlast_Timer = 1000; - } else FieryBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_focus_fire(Creature* pCreature) -{ - return new mob_focus_fireAI (pCreature); -} - -void AddSC_boss_shirrak_the_dead_watcher() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_shirrak_the_dead_watcher"; - newscript->GetAI = &GetAI_boss_shirrak_the_dead_watcher; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_focus_fire"; - newscript->GetAI = &GetAI_mob_focus_fire; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp b/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp deleted file mode 100644 index 5b15178c33e..00000000000 --- a/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_NexusPrince_Shaffar -SD%Complete: 80 -SDComment: Need more tuning of spell timers, it should not be as linear fight as current. Also should possibly find a better way to deal with his three initial beacons to make sure all aggro. -SDCategory: Auchindoun, Mana Tombs -EndScriptData */ - -/* ContentData -boss_nexusprince_shaffar -mob_ethereal_beacon -EndContentData */ - -#include "ScriptedPch.h" - -enum ePrince -{ - SAY_INTRO = -1557000, - SAY_AGGRO_1 = -1557001, - SAY_AGGRO_2 = -1557002, - SAY_AGGRO_3 = -1557003, - SAY_SLAY_1 = -1557004, - SAY_SLAY_2 = -1557005, - SAY_SUMMON = -1557006, - SAY_DEAD = -1557007, - - SPELL_BLINK = 34605, - SPELL_FROSTBOLT = 32364, - SPELL_FIREBALL = 32363, - SPELL_FROSTNOVA = 32365, - - SPELL_ETHEREAL_BEACON = 32371, // Summons NPC_BEACON - SPELL_ETHEREAL_BEACON_VISUAL = 32368, - - NPC_BEACON = 18431, - NPC_SHAFFAR = 18344, - - NR_INITIAL_BEACONS = 3 -}; - -struct boss_nexusprince_shaffarAI : public ScriptedAI -{ - boss_nexusprince_shaffarAI(Creature *c) : ScriptedAI(c), summons(me) { HasTaunted = false; } - - uint32 Blink_Timer; - uint32 Beacon_Timer; - uint32 FireBall_Timer; - uint32 Frostbolt_Timer; - uint32 FrostNova_Timer; - - SummonList summons; - - bool HasTaunted; - bool CanBlink; - - void Reset() - { - Blink_Timer = 1500; - Beacon_Timer = 10000; - FireBall_Timer = 8000; - Frostbolt_Timer = 4000; - FrostNova_Timer = 15000; - - CanBlink = false; - - float dist = 8.0f; - float posX, posY, posZ, angle; - me->GetHomePosition(posX, posY, posZ, angle); - - me->SummonCreature(NPC_BEACON, posX - dist, posY - dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - me->SummonCreature(NPC_BEACON, posX - dist, posY + dist, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - me->SummonCreature(NPC_BEACON, posX + dist, posY, posZ, angle, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 7200000); - } - - void EnterEvadeMode() - { - summons.DespawnAll(); - ScriptedAI::EnterEvadeMode(); - } - - void MoveInLineOfSight(Unit *who) - { - if (!HasTaunted && who->GetTypeId() == TYPEID_PLAYER && me->IsWithinDistInMap(who, 100.0f)) - { - DoScriptText(SAY_INTRO, me); - HasTaunted = true; - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - DoZoneInCombat(); - summons.DoZoneInCombat(); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == NPC_BEACON) - { - summoned->CastSpell(summoned,SPELL_ETHEREAL_BEACON_VISUAL,false); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(pTarget); - } - - summons.Summon(summoned); - } - - void SummonedCreatureDespawn(Creature *summon) - { - summons.Despawn(summon); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEAD, me); - summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (FrostNova_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoCast(me, SPELL_FROSTNOVA); - FrostNova_Timer = 17500 + rand()%7500; - CanBlink = true; - } else FrostNova_Timer -= diff; - - if (Frostbolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROSTBOLT); - Frostbolt_Timer = 4500 + rand()%1500; - } else Frostbolt_Timer -= diff; - - if (FireBall_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIREBALL); - FireBall_Timer = 4500 + rand()%1500; - } else FireBall_Timer -= diff; - - if (CanBlink) - { - if (Blink_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - //expire movement, will prevent from running right back to victim after cast - //(but should MoveChase be used again at a certain time or should he not move?) - if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == TARGETED_MOTION_TYPE) - me->GetMotionMaster()->MovementExpired(); - - DoCast(me, SPELL_BLINK); - Blink_Timer = 1000 + rand()%1500; - CanBlink = false; - } else Blink_Timer -= diff; - } - - if (Beacon_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - if (!urand(0,3)) - DoScriptText(SAY_SUMMON, me); - - DoCast(me, SPELL_ETHEREAL_BEACON, true); - - Beacon_Timer = 10000; - } else Beacon_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_nexusprince_shaffar(Creature* pCreature) -{ - return new boss_nexusprince_shaffarAI (pCreature); -} - -enum eEnums -{ - SPELL_ARCANE_BOLT = 15254, - SPELL_ETHEREAL_APPRENTICE = 32372 // Summon 18430 -}; - -struct mob_ethereal_beaconAI : public ScriptedAI -{ - mob_ethereal_beaconAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Apprentice_Timer; - uint32 ArcaneBolt_Timer; - uint32 Check_Timer; - - void KillSelf() - { - me->Kill(me); - } - - void Reset() - { - Apprentice_Timer = DUNGEON_MODE(20000, 10000); - ArcaneBolt_Timer = 1000; - Check_Timer = 1000; - } - - void EnterCombat(Unit * who) - { - // Send Shaffar to fight - Creature* Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); - if (!Shaffar || Shaffar->isDead()) - { - KillSelf(); - return; - } - if (!Shaffar->isInCombat()) - Shaffar->AI()->AttackStart(who); - } - - void JustSummoned(Creature *summoned) - { - summoned->AI()->AttackStart(me->getVictim()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Check_Timer <= diff) - { - Creature *Shaffar = me->FindNearestCreature(NPC_SHAFFAR, 100); - if (!Shaffar || Shaffar->isDead() || !Shaffar->isInCombat()) - { - KillSelf(); - return; - } - Check_Timer = 1000; - } else Check_Timer -= diff; - - if (ArcaneBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BOLT); - ArcaneBolt_Timer = 2000 + rand()%2500; - } else ArcaneBolt_Timer -= diff; - - if (Apprentice_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoCast(me, SPELL_ETHEREAL_APPRENTICE, true); - me->ForcedDespawn(); - return; - } else Apprentice_Timer -= diff; - } -}; - -CreatureAI* GetAI_mob_ethereal_beacon(Creature* pCreature) -{ - return new mob_ethereal_beaconAI (pCreature); -} - -enum eEthereal -{ - SPELL_ETHEREAL_APPRENTICE_FIREBOLT = 32369, - SPELL_ETHEREAL_APPRENTICE_FROSTBOLT = 32370 -}; - -struct mob_ethereal_apprenticeAI : public ScriptedAI -{ - mob_ethereal_apprenticeAI(Creature *c) : ScriptedAI(c) {} - - uint32 Cast_Timer; - - bool isFireboltTurn; - - void Reset() - { - Cast_Timer = 3000; - isFireboltTurn = true; - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Cast_Timer <= diff) - { - if (isFireboltTurn) - { - DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FIREBOLT, true); - isFireboltTurn = false; - }else{ - DoCast(me->getVictim(), SPELL_ETHEREAL_APPRENTICE_FROSTBOLT, true); - isFireboltTurn = true; - } - Cast_Timer = 3000; - } else Cast_Timer -= diff; - } -}; - -CreatureAI* GetAI_mob_ethereal_apprentice(Creature* pCreature) -{ - return new mob_ethereal_apprenticeAI (pCreature); -} - -void AddSC_boss_nexusprince_shaffar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_nexusprince_shaffar"; - newscript->GetAI = &GetAI_boss_nexusprince_shaffar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ethereal_beacon"; - newscript->GetAI = &GetAI_mob_ethereal_beacon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ethereal_apprentice"; - newscript->GetAI = &GetAI_mob_ethereal_apprentice; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp b/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp deleted file mode 100644 index 51ec2e83b46..00000000000 --- a/src/server/scripts/Outland/Auchindoun/mana_tombs/boss_pandemonius.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Pandemonius -SD%Complete: 75 -SDComment: Not known how void blast is done (amount of rapid cast seems to be related to players in party). All mobs remaining in surrounding area should aggro when engaged. -SDCategory: Auchindoun, Mana Tombs -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1557008 -#define SAY_AGGRO_2 -1557009 -#define SAY_AGGRO_3 -1557010 - -#define SAY_KILL_1 -1557011 -#define SAY_KILL_2 -1557012 - -#define SAY_DEATH -1557013 - -#define EMOTE_DARK_SHELL -1557014 - -#define SPELL_VOID_BLAST 32325 -#define H_SPELL_VOID_BLAST 38760 -#define SPELL_DARK_SHELL 32358 -#define H_SPELL_DARK_SHELL 38759 - -struct boss_pandemoniusAI : public ScriptedAI -{ - boss_pandemoniusAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 VoidBlast_Timer; - uint32 DarkShell_Timer; - uint32 VoidBlast_Counter; - - void Reset() - { - VoidBlast_Timer = 8000+rand()%15000; - DarkShell_Timer = 20000; - VoidBlast_Counter = 0; - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (VoidBlast_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoCast(pTarget, SPELL_VOID_BLAST); - VoidBlast_Timer = 500; - ++VoidBlast_Counter; - } - - if (VoidBlast_Counter == 5) - { - VoidBlast_Timer = 15000+rand()%10000; - VoidBlast_Counter = 0; - } - } else VoidBlast_Timer -= diff; - - if (!VoidBlast_Counter) - { - if (DarkShell_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(EMOTE_DARK_SHELL, me); - - DoCast(me, SPELL_DARK_SHELL); - DarkShell_Timer = 20000; - } else DarkShell_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_pandemonius(Creature* pCreature) -{ - return new boss_pandemoniusAI (pCreature); -} - -void AddSC_boss_pandemonius() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_pandemonius"; - newscript->GetAI = &GetAI_boss_pandemonius; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp b/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp deleted file mode 100644 index 9628fa1a98f..00000000000 --- a/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_darkweaver_syth.cpp +++ /dev/null @@ -1,414 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Darkweaver_Syth -SD%Complete: 85 -SDComment: Shock spells/times need more work. Heroic partly implemented. -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_SUMMON -1556000 - -#define SAY_AGGRO_1 -1556001 -#define SAY_AGGRO_2 -1556002 -#define SAY_AGGRO_3 -1556003 - -#define SAY_SLAY_1 -1556004 -#define SAY_SLAY_2 -1556005 - -#define SAY_DEATH -1556006 - -#define SPELL_FROST_SHOCK 21401 //37865 -#define SPELL_FLAME_SHOCK 34354 -#define SPELL_SHADOW_SHOCK 30138 -#define SPELL_ARCANE_SHOCK 37132 - -#define SPELL_CHAIN_LIGHTNING 15659 //15305 - -#define SPELL_SUMMON_SYTH_FIRE 33537 // Spawns 19203 -#define SPELL_SUMMON_SYTH_ARCANE 33538 // Spawns 19205 -#define SPELL_SUMMON_SYTH_FROST 33539 // Spawns 19204 -#define SPELL_SUMMON_SYTH_SHADOW 33540 // Spawns 19206 - -#define SPELL_FLAME_BUFFET DUNGEON_MODE(33526, 38141) -#define SPELL_ARCANE_BUFFET DUNGEON_MODE(33527, 38138) -#define SPELL_FROST_BUFFET DUNGEON_MODE(33528, 38142) -#define SPELL_SHADOW_BUFFET DUNGEON_MODE(33529, 38143) - -struct boss_darkweaver_sythAI : public ScriptedAI -{ - boss_darkweaver_sythAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 flameshock_timer; - uint32 arcaneshock_timer; - uint32 frostshock_timer; - uint32 shadowshock_timer; - uint32 chainlightning_timer; - - bool summon90; - bool summon50; - bool summon10; - - void Reset() - { - flameshock_timer = 2000; - arcaneshock_timer = 4000; - frostshock_timer = 6000; - shadowshock_timer = 8000; - chainlightning_timer = 15000; - - summon90 = false; - summon50 = false; - summon10 = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustSummoned(Creature *summoned) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(pTarget); - } - - void SythSummoning() - { - DoScriptText(SAY_SUMMON, me); - - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - DoCast(me, SPELL_SUMMON_SYTH_ARCANE, true); //front - DoCast(me, SPELL_SUMMON_SYTH_FIRE, true); //back - DoCast(me, SPELL_SUMMON_SYTH_FROST, true); //left - DoCast(me, SPELL_SUMMON_SYTH_SHADOW, true); //right - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 90) && !summon90) - { - SythSummoning(); - summon90 = true; - } - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 50) && !summon50) - { - SythSummoning(); - summon50 = true; - } - - if (((me->GetHealth()*100) / me->GetMaxHealth() < 10) && !summon10) - { - SythSummoning(); - summon10 = true; - } - - if (flameshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_SHOCK); - - flameshock_timer = 10000 + rand()%5000; - } else flameshock_timer -= diff; - - if (arcaneshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_SHOCK); - - arcaneshock_timer = 10000 + rand()%5000; - } else arcaneshock_timer -= diff; - - if (frostshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_SHOCK); - - frostshock_timer = 10000 + rand()%5000; - } else frostshock_timer -= diff; - - if (shadowshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_SHOCK); - - shadowshock_timer = 10000 + rand()%5000; - } else shadowshock_timer -= diff; - - if (chainlightning_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_CHAIN_LIGHTNING); - - chainlightning_timer = 25000; - } else chainlightning_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_darkweaver_syth(Creature* pCreature) -{ - return new boss_darkweaver_sythAI (pCreature); -} - -/* ELEMENTALS */ - -struct mob_syth_fireAI : public ScriptedAI -{ - mob_syth_fireAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 flameshock_timer; - uint32 flamebuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - flameshock_timer = 2500; - flamebuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (flameshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_SHOCK); - - flameshock_timer = 5000; - } else flameshock_timer -= diff; - - if (flamebuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FLAME_BUFFET); - - flamebuffet_timer = 5000; - } else flamebuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_fire(Creature* pCreature) -{ - return new mob_syth_fireAI (pCreature); -} - -struct mob_syth_arcaneAI : public ScriptedAI -{ - mob_syth_arcaneAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 arcaneshock_timer; - uint32 arcanebuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_ARCANE, true); - arcaneshock_timer = 2500; - arcanebuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (arcaneshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_SHOCK); - - arcaneshock_timer = 5000; - } else arcaneshock_timer -= diff; - - if (arcanebuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ARCANE_BUFFET); - - arcanebuffet_timer = 5000; - } else arcanebuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_arcane(Creature* pCreature) -{ - return new mob_syth_arcaneAI (pCreature); -} - -struct mob_syth_frostAI : public ScriptedAI -{ - mob_syth_frostAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 frostshock_timer; - uint32 frostbuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - frostshock_timer = 2500; - frostbuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (frostshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_SHOCK); - - frostshock_timer = 5000; - } else frostshock_timer -= diff; - - if (frostbuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_FROST_BUFFET); - - frostbuffet_timer = 5000; - } else frostbuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_frost(Creature* pCreature) -{ - return new mob_syth_frostAI (pCreature); -} - -struct mob_syth_shadowAI : public ScriptedAI -{ - mob_syth_shadowAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 shadowshock_timer; - uint32 shadowbuffet_timer; - - void Reset() - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_SHADOW, true); - shadowshock_timer = 2500; - shadowbuffet_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (shadowshock_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_SHOCK); - - shadowshock_timer = 5000; - } else shadowshock_timer -= diff; - - if (shadowbuffet_timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_BUFFET); - - shadowbuffet_timer = 5000; - } else shadowbuffet_timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_syth_shadow(Creature* pCreature) -{ - return new mob_syth_shadowAI (pCreature); -} - -void AddSC_boss_darkweaver_syth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_darkweaver_syth"; - newscript->GetAI = &GetAI_boss_darkweaver_syth; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_fire"; - newscript->GetAI = &GetAI_mob_syth_arcane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_arcane"; - newscript->GetAI = &GetAI_mob_syth_arcane; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_frost"; - newscript->GetAI = &GetAI_mob_syth_frost; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_syth_shadow"; - newscript->GetAI = &GetAI_mob_syth_shadow; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp deleted file mode 100644 index 32b97293ca3..00000000000 --- a/src/server/scripts/Outland/Auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp +++ /dev/null @@ -1,213 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Talon_King_Ikiss -SD%Complete: 80 -SDComment: Heroic supported. Some details missing, but most are spell related. -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "sethekk_halls.h" - -#define SAY_INTRO -1556007 - -#define SAY_AGGRO_1 -1556008 -#define SAY_AGGRO_2 -1556009 -#define SAY_AGGRO_3 -1556010 - -#define SAY_SLAY_1 -1556011 -#define SAY_SLAY_2 -1556012 -#define SAY_DEATH -1556013 -#define EMOTE_ARCANE_EXP -1556015 - -#define SPELL_BLINK 38194 -#define SPELL_BLINK_TELEPORT 38203 -#define SPELL_MANA_SHIELD 38151 -#define SPELL_ARCANE_BUBBLE 9438 -#define H_SPELL_SLOW 35032 - -#define SPELL_POLYMORPH 38245 -#define H_SPELL_POLYMORPH 43309 - -#define SPELL_ARCANE_VOLLEY 35059 -#define H_SPELL_ARCANE_VOLLEY 40424 - -#define SPELL_ARCANE_EXPLOSION 38197 -#define H_SPELL_ARCANE_EXPLOSION 40425 - -struct boss_talon_king_ikissAI : public ScriptedAI -{ - boss_talon_king_ikissAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ArcaneVolley_Timer; - uint32 Sheep_Timer; - uint32 Blink_Timer; - uint32 Slow_Timer; - - bool ManaShield; - bool Blink; - bool Intro; - - void Reset() - { - ArcaneVolley_Timer = 5000; - Sheep_Timer = 8000; - Blink_Timer = 35000; - Slow_Timer = 15000+rand()%15000; - Blink = false; - Intro = false; - ManaShield = false; - } - - void MoveInLineOfSight(Unit *who) - { - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (!Intro && me->IsWithinDistInMap(who, 100)) - { - Intro = true; - DoScriptText(SAY_INTRO, me); - } - - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_IKISSDOOREVENT, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Blink) - { - DoCast(me, SPELL_ARCANE_EXPLOSION); - DoCast(me, SPELL_ARCANE_BUBBLE, true); - Blink = false; - } - - if (ArcaneVolley_Timer <= diff) - { - DoCast(me, SPELL_ARCANE_VOLLEY); - ArcaneVolley_Timer = 7000+rand()%5000; - } else ArcaneVolley_Timer -= diff; - - if (Sheep_Timer <= diff) - { - Unit *pTarget; - - //second top aggro target in normal, random target in heroic correct? - if (IsHeroic()) - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - else - pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO,1); - - if (pTarget) - DoCast(pTarget, SPELL_POLYMORPH); - Sheep_Timer = 15000+rand()%2500; - } else Sheep_Timer -= diff; - - //may not be correct time to cast - if (!ManaShield && ((me->GetHealth()*100) / me->GetMaxHealth() < 20)) - { - DoCast(me, SPELL_MANA_SHIELD); - ManaShield = true; - } - - if (IsHeroic()) - { - if (Slow_Timer <= diff) - { - DoCast(me, H_SPELL_SLOW); - Slow_Timer = 15000+rand()%25000; - } else Slow_Timer -= diff; - } - - if (Blink_Timer <= diff) - { - DoScriptText(EMOTE_ARCANE_EXP, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(false); - - //Spell doesn't work, but we use for visual effect at least - DoCast(pTarget, SPELL_BLINK); - - float X = pTarget->GetPositionX(); - float Y = pTarget->GetPositionY(); - float Z = pTarget->GetPositionZ(); - - DoTeleportTo(X,Y,Z); - - DoCast(pTarget, SPELL_BLINK_TELEPORT); - Blink = true; - } - Blink_Timer = 35000+rand()%5000; - } else Blink_Timer -= diff; - - if (!Blink) - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_talon_king_ikiss(Creature* pCreature) -{ - return new boss_talon_king_ikissAI (pCreature); -} - -void AddSC_boss_talon_king_ikiss() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_talon_king_ikiss"; - newscript->GetAI = &GetAI_boss_talon_king_ikiss; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp b/src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp deleted file mode 100644 index ee27da3cff5..00000000000 --- a/src/server/scripts/Outland/Auchindoun/sethekk_halls/instance_sethekk_halls.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance - Sethekk Halls -SD%Complete: 50 -SDComment: Instance Data for Sethekk Halls instance -SDCategory: Auchindoun, Sethekk Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "sethekk_halls.h" - -enum eEnums -{ - NPC_ANZU = 23035, - IKISS_DOOR = 177203, -}; - -struct instance_sethekk_halls : public ScriptedInstance -{ - instance_sethekk_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 AnzuEncounter; - uint64 m_uiIkissDoorGUID; - - void Initialize() - { - AnzuEncounter = NOT_STARTED; - m_uiIkissDoorGUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - if (pCreature->GetEntry() == NPC_ANZU) - { - if (AnzuEncounter >= IN_PROGRESS) - pCreature->DisappearAndDie(); - else - AnzuEncounter = IN_PROGRESS; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - if (pGo->GetEntry() == IKISS_DOOR) - m_uiIkissDoorGUID = pGo->GetGUID(); - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_IKISSDOOREVENT: - if (data == DONE) - DoUseDoorOrButton(m_uiIkissDoorGUID,DAY*IN_MILISECONDS); - break; - case TYPE_ANZU_ENCOUNTER: - AnzuEncounter = data; - break; - } - } -}; - -InstanceData* GetInstanceData_instance_sethekk_halls(Map* pMap) -{ - return new instance_sethekk_halls(pMap); -} - -void AddSC_instance_sethekk_halls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_sethekk_halls"; - newscript->GetInstanceData = &GetInstanceData_instance_sethekk_halls; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h b/src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h deleted file mode 100644 index 79a6cd4952d..00000000000 --- a/src/server/scripts/Outland/Auchindoun/sethekk_halls/sethekk_halls.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SETHEKK_HALLS_H -#define DEF_SETHEKK_HALLS_H - -enum eTypes -{ - DATA_IKISSDOOREVENT = 1, - TYPE_ANZU_ENCOUNTER = 2, -}; -#endif - diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp deleted file mode 100644 index 2bb6a717a5a..00000000000 --- a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Ambassador_Hellmaw -SD%Complete: 80 -SDComment: Enrage spell missing/not known -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "ScriptedEscortAI.h" -#include "shadow_labyrinth.h" - -enum eEnums -{ - SAY_INTRO = -1555000, - SAY_AGGRO1 = -1555001, - SAY_AGGRO2 = -1555002, - SAY_AGGRO3 = -1555003, - SAY_HELP = -1555004, - SAY_SLAY1 = -1555005, - SAY_SLAY2 = -1555006, - SAY_DEATH = -1555007, - - SPELL_BANISH = 30231, - SPELL_CORROSIVE_ACID = 33551, - SPELL_FEAR = 33547, - SPELL_ENRAGE = 34970 -}; - -struct boss_ambassador_hellmawAI : public npc_escortAI -{ - boss_ambassador_hellmawAI(Creature* pCreature) : npc_escortAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - } - - ScriptedInstance* m_pInstance; - - uint32 EventCheck_Timer; - uint32 CorrosiveAcid_Timer; - uint32 Fear_Timer; - uint32 Enrage_Timer; - bool Intro; - bool IsBanished; - bool Enraged; - - void Reset() - { - EventCheck_Timer = 5000; - CorrosiveAcid_Timer = 5000 + rand()%5000; - Fear_Timer = 25000 + rand()%5000; - Enrage_Timer = 180000; - Intro = false; - IsBanished = true; - Enraged = false; - - if (m_pInstance && me->isAlive()) - { - if (m_pInstance->GetData(TYPE_OVERSEER) != DONE) - DoCast(me, SPELL_BANISH, true); - } - } - - void JustReachedHome() - { - if (m_pInstance) - m_pInstance->SetData(TYPE_HELLMAW, FAIL); - } - - void MoveInLineOfSight(Unit* pWho) - { - if (me->HasAura(SPELL_BANISH)) - return; - - npc_escortAI::MoveInLineOfSight(pWho); - } - - void WaypointReached(uint32 /*i*/) - { - } - - void DoIntro() - { - if (me->HasAura(SPELL_BANISH)) - me->RemoveAurasDueToSpell(SPELL_BANISH); - - IsBanished = false; - Intro = true; - - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_HELLMAW) != FAIL) - { - DoScriptText(SAY_INTRO, me); - Start(true, false, 0, NULL, false, true); - } - - m_pInstance->SetData(TYPE_HELLMAW, IN_PROGRESS); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (m_pInstance) - m_pInstance->SetData(TYPE_HELLMAW, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!Intro && !HasEscortState(STATE_ESCORT_ESCORTING)) - { - if (EventCheck_Timer <= diff) - { - if (m_pInstance) - { - if (m_pInstance->GetData(TYPE_OVERSEER) == DONE) - { - DoIntro(); - return; - } - } - EventCheck_Timer = 5000; - return; - } - else - { - EventCheck_Timer -= diff; - return; - } - } - - npc_escortAI::UpdateAI(diff); - - if (!UpdateVictim()) - return; - - if (me->HasAura(SPELL_BANISH, 0)) - { - EnterEvadeMode(); - return; - } - - if (CorrosiveAcid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CORROSIVE_ACID); - CorrosiveAcid_Timer = 15000 + rand()%10000; - } else CorrosiveAcid_Timer -= diff; - - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 20000 + rand()%15000; - } else Fear_Timer -= diff; - - if (IsHeroic()) - { - if (!Enraged && Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enraged = true; - } else Enrage_Timer -= diff; - } - } -}; - -CreatureAI* GetAI_boss_ambassador_hellmaw(Creature* pCreature) -{ - return new boss_ambassador_hellmawAI(pCreature); -} - -void AddSC_boss_ambassador_hellmaw() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_ambassador_hellmaw"; - newscript->GetAI = &GetAI_boss_ambassador_hellmaw; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp deleted file mode 100644 index 52c60ae0d0e..00000000000 --- a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Blackheart_the_Inciter -SD%Complete: 75 -SDComment: Incite Chaos not functional since core lacks Mind Control support -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define SPELL_INCITE_CHAOS 33676 -#define SPELL_INCITE_CHAOS_B 33684 //debuff applied to each member of party -#define SPELL_CHARGE 33709 -#define SPELL_WAR_STOMP 33707 - -#define SAY_INTRO1 -1555008 //not used -#define SAY_INTRO2 -1555009 //not used -#define SAY_INTRO3 -1555010 //not used -#define SAY_AGGRO1 -1555011 -#define SAY_AGGRO2 -1555012 -#define SAY_AGGRO3 -1555013 -#define SAY_SLAY1 -1555014 -#define SAY_SLAY2 -1555015 -#define SAY_HELP -1555016 //not used -#define SAY_DEATH -1555017 - -//below, not used -#define SAY2_INTRO1 -1555018 -#define SAY2_INTRO2 -1555019 -#define SAY2_INTRO3 -1555020 -#define SAY2_AGGRO1 -1555021 -#define SAY2_AGGRO2 -1555022 -#define SAY2_AGGRO3 -1555023 -#define SAY2_SLAY1 -1555024 -#define SAY2_SLAY2 -1555025 -#define SAY2_HELP -1555026 -#define SAY2_DEATH -1555027 - -struct boss_blackheart_the_inciterAI : public ScriptedAI -{ - boss_blackheart_the_inciterAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - bool InciteChaos; - uint32 InciteChaos_Timer; - uint32 InciteChaosWait_Timer; - uint32 Charge_Timer; - uint32 Knockback_Timer; - - void Reset() - { - InciteChaos = false; - InciteChaos_Timer = 20000; - InciteChaosWait_Timer = 15000; - Charge_Timer = 5000; - Knockback_Timer = 15000; - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - - if (pInstance) - pInstance->SetData(DATA_BLACKHEARTTHEINCITEREVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (InciteChaos) - { - if (InciteChaosWait_Timer <= diff) - { - InciteChaos = false; - InciteChaosWait_Timer = 15000; - } else InciteChaosWait_Timer -= diff; - - return; - } - - if (InciteChaos_Timer <= diff) - { - DoCast(me, SPELL_INCITE_CHAOS); - - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - pTarget->CastSpell(pTarget,SPELL_INCITE_CHAOS_B,true); - } - - DoResetThreat(); - InciteChaos = true; - InciteChaos_Timer = 40000; - return; - } else InciteChaos_Timer -= diff; - - //Charge_Timer - if (Charge_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_CHARGE); - Charge_Timer = 15000 + rand()%10000; - } else Charge_Timer -= diff; - - //Knockback_Timer - if (Knockback_Timer <= diff) - { - DoCast(me, SPELL_WAR_STOMP); - Knockback_Timer = 18000 + rand()%6000; - } else Knockback_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_blackheart_the_inciter(Creature* pCreature) -{ - return new boss_blackheart_the_inciterAI (pCreature); -} - -void AddSC_boss_blackheart_the_inciter() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_blackheart_the_inciter"; - newscript->GetAI = &GetAI_boss_blackheart_the_inciter; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp deleted file mode 100644 index 8b63b765b47..00000000000 --- a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp +++ /dev/null @@ -1,313 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grandmaster_Vorpil -SD%Complete: 100 -SDComment: -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define SAY_INTRO -1555028 -#define SAY_AGGRO1 -1555029 -#define SAY_AGGRO2 -1555030 -#define SAY_AGGRO3 -1555031 -#define SAY_HELP -1555032 -#define SAY_SLAY1 -1555033 -#define SAY_SLAY2 -1555034 -#define SAY_DEATH -1555035 - -#define SPELL_RAIN_OF_FIRE 33617 -#define H_SPELL_RAIN_OF_FIRE 39363 - -#define SPELL_DRAW_SHADOWS 33563 -#define SPELL_SHADOWBOLT_VOLLEY 33841 -#define SPELL_BANISH 38791 - -#define MOB_VOID_TRAVELER 19226 -#define SPELL_SACRIFICE 33587 -#define SPELL_SHADOW_NOVA 33846 -#define SPELL_EMPOWERING_SHADOWS 33783 -#define H_SPELL_EMPOWERING_SHADOWS 39364 - -#define MOB_VOID_PORTAL 19224 -#define SPELL_VOID_PORTAL_VISUAL 33569 - -float VorpilPosition[3] = {-252.8820,-264.3030,17.1}; - -float VoidPortalCoords[5][3] = -{ - {-283.5894, -239.5718, 12.7}, - {-306.5853, -258.4539, 12.7}, - {-295.8789, -269.0899, 12.7}, - {-209.3401, -262.7564, 17.1}, - {-261.4533, -297.3298, 17.1} -}; - -struct mob_voidtravelerAI : public ScriptedAI -{ - mob_voidtravelerAI(Creature *c) : ScriptedAI(c) - { - } - - uint64 VorpilGUID; - uint32 move; - bool sacrificed; - - void Reset() - { - VorpilGUID = 0; - move = 0; - sacrificed = false; - } - - void EnterCombat(Unit * /*who*/){} - - void UpdateAI(const uint32 diff) - { - if (!VorpilGUID) - { - me->Kill(me); - return; - } - if (move <= diff) - { - Creature *Vorpil = Unit::GetCreature(*me, VorpilGUID); - if (!Vorpil) - { - VorpilGUID = 0; - return; - } - - if (sacrificed) - { - me->AddAura(DUNGEON_MODE(SPELL_EMPOWERING_SHADOWS, H_SPELL_EMPOWERING_SHADOWS), Vorpil); - Vorpil->SetHealth(Vorpil->GetHealth() + Vorpil->GetMaxHealth()/25); - DoCast(me, SPELL_SHADOW_NOVA, true); - me->Kill(me); - return; - } - me->GetMotionMaster()->MoveFollow(Vorpil,0,0); - if (me->IsWithinDist(Vorpil, 3)) - { - DoCast(me, SPELL_SACRIFICE, false); - sacrificed = true; - move = 500; - return; - } - if (!Vorpil->isInCombat() || Vorpil->isDead()) - { - me->Kill(me); - return; - } - move = 1000; - } else move -= diff; - } -}; -CreatureAI* GetAI_mob_voidtraveler(Creature* pCreature) -{ - return new mob_voidtravelerAI (pCreature); -} - -struct boss_grandmaster_vorpilAI : public ScriptedAI -{ - boss_grandmaster_vorpilAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = false; - } - - ScriptedInstance *pInstance; - bool Intro, HelpYell; - bool sumportals; - - uint32 ShadowBoltVolley_Timer; - uint32 DrawShadows_Timer; - uint32 summonTraveler_Timer; - uint32 banish_Timer; - uint64 PortalsGuid[5]; - - void Reset() - { - ShadowBoltVolley_Timer = 7000 + rand()%7000; - DrawShadows_Timer = 45000; - summonTraveler_Timer = 90000; - banish_Timer = 17000; - HelpYell = false; - destroyPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, NOT_STARTED); - } - - void summonPortals() - { - if (!sumportals) - { - for (uint8 i = 0; i < 5; ++i) - { - Creature *Portal = NULL; - Portal = me->SummonCreature(MOB_VOID_PORTAL,VoidPortalCoords[i][0],VoidPortalCoords[i][1],VoidPortalCoords[i][2],0,TEMPSUMMON_CORPSE_DESPAWN,3000000); - if (Portal) - { - PortalsGuid[i] = Portal->GetGUID(); - Portal->CastSpell(Portal,SPELL_VOID_PORTAL_VISUAL,false); - } - } - sumportals = true; - summonTraveler_Timer = 5000; - } - } - - void destroyPortals() - { - if (sumportals) - { - for (uint8 i = 0; i < 5; ++i) - { - Unit *Portal = Unit::GetUnit((*me), PortalsGuid[i]); - if (Portal && Portal->isAlive()) - Portal->DealDamage(Portal, Portal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - PortalsGuid[i] = 0; - } - sumportals = false; - } - } - - void spawnVoidTraveler() - { - int pos = urand(0,4); - me->SummonCreature(MOB_VOID_TRAVELER,VoidPortalCoords[pos][0],VoidPortalCoords[pos][1],VoidPortalCoords[pos][2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,5000); - if (!HelpYell) - { - DoScriptText(SAY_HELP, me); - HelpYell = true; - } - } - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == MOB_VOID_TRAVELER) - CAST_AI(mob_voidtravelerAI, summoned->AI())->VorpilGUID = me->GetGUID(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - destroyPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - summonPortals(); - - if (pInstance) - pInstance->SetData(DATA_GRANDMASTERVORPILEVENT, IN_PROGRESS); - } - - void MoveInLineOfSight(Unit *who) - { - ScriptedAI::MoveInLineOfSight(who); - - if (!Intro && me->IsWithinLOSInMap(who)&& me->IsWithinDistInMap(who, 100) && me->IsHostileTo(who)) - { - DoScriptText(SAY_INTRO, me); - Intro = true; - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOWBOLT_VOLLEY); - ShadowBoltVolley_Timer = 15000 + rand()%15000; - } else ShadowBoltVolley_Timer -= diff; - - if (IsHeroic() && banish_Timer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,30,false); - if (pTarget) - { - DoCast(pTarget, SPELL_BANISH); - banish_Timer = 16000; - } - } else banish_Timer -= diff; - - if (DrawShadows_Timer <= diff) - { - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - if (Player* i_pl = i->getSource()) - if (i_pl->isAlive() && !i_pl->HasAura(SPELL_BANISH)) - i_pl->TeleportTo(me->GetMapId(), VorpilPosition[0],VorpilPosition[1],VorpilPosition[2], 0, TELE_TO_NOT_LEAVE_COMBAT); - - me->GetMap()->CreatureRelocation(me, VorpilPosition[0],VorpilPosition[1],VorpilPosition[2],0.0f); - DoCast(me, SPELL_DRAW_SHADOWS, true); - - DoCast(me, SPELL_RAIN_OF_FIRE); - - ShadowBoltVolley_Timer = 6000; - DrawShadows_Timer = 30000; - } else DrawShadows_Timer -= diff; - - if (summonTraveler_Timer <= diff) - { - spawnVoidTraveler(); - summonTraveler_Timer = 10000; - //enrage at 20% - if ((me->GetHealth()*5) < me->GetMaxHealth()) - summonTraveler_Timer = 5000; - } else summonTraveler_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_grandmaster_vorpil(Creature* pCreature) -{ - return new boss_grandmaster_vorpilAI (pCreature); -} - -void AddSC_boss_grandmaster_vorpil() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_grandmaster_vorpil"; - newscript->GetAI = &GetAI_boss_grandmaster_vorpil; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_voidtraveler"; - newscript->GetAI = &GetAI_mob_voidtraveler; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp deleted file mode 100644 index 14bf249c3b5..00000000000 --- a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/boss_murmur.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Murmur -SD%Complete: 90 -SDComment: Timers may be incorrect -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define EMOTE_SONIC_BOOM -1555036 - -#define SPELL_SONIC_BOOM_CAST DUNGEON_MODE(33923, 38796) -#define SPELL_SONIC_BOOM_EFFECT DUNGEON_MODE(33666, 38795) -#define SPELL_RESONANCE 33657 -#define SPELL_MURMURS_TOUCH DUNGEON_MODE(33711, 38794) -#define SPELL_MAGNETIC_PULL 33689 -#define SPELL_SONIC_SHOCK 38797 -#define SPELL_THUNDERING_STORM 39365 - -struct boss_murmurAI : public ScriptedAI -{ - boss_murmurAI(Creature *c) : ScriptedAI(c) - { - SetCombatMovement(false); - } - - uint32 SonicBoom_Timer; - uint32 MurmursTouch_Timer; - uint32 Resonance_Timer; - uint32 MagneticPull_Timer; - uint32 SonicShock_Timer; - uint32 ThunderingStorm_Timer; - bool SonicBoom; - - void Reset() - { - SonicBoom_Timer = 30000; - MurmursTouch_Timer = 8000 + rand()%12000; - Resonance_Timer = 5000; - MagneticPull_Timer = 15000 + rand()%15000; - ThunderingStorm_Timer = 15000; - SonicShock_Timer = 10000; - SonicBoom = false; - - //database should have `RegenHealth`=0 to prevent regen - uint32 hp = (me->GetMaxHealth()*40)/100; - if (hp) me->SetHealth(hp); - me->ResetPlayerDamageReq(); - } - - void SonicBoomEffect() - { - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit *pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER) - { - //Not do anything without aura, spell can be resisted! - if (pTarget->HasAura(SPELL_SONIC_BOOM_CAST) && me->IsWithinDistInMap(pTarget, 34.0f)) - { - //This will be wrong calculation. Also, comments suggest it must deal damage - pTarget->SetHealth(uint32(pTarget->GetMaxHealth() - pTarget->GetMaxHealth() * 0.8)); - } - } - } - } - - void EnterCombat(Unit * /*who*/) { } - - // Sonic Boom instant damage (needs core fix instead of this) - void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) - { - if (pTarget && pTarget->isAlive() && spell && spell->Id == uint32(SPELL_SONIC_BOOM_EFFECT)) - me->DealDamage(pTarget,(pTarget->GetHealth()*90)/100,NULL,SPELL_DIRECT_DAMAGE,SPELL_SCHOOL_MASK_NATURE,spell); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target or casting - if (!UpdateVictim() || me->IsNonMeleeSpellCasted(false)) - return; - - // Sonic Boom - if (SonicBoom) - { - DoCast(me, SPELL_SONIC_BOOM_EFFECT, true); - SonicBoomEffect(); - - SonicBoom = false; - Resonance_Timer = 1500; - } - if (SonicBoom_Timer <= diff) - { - DoScriptText(EMOTE_SONIC_BOOM, me); - DoCast(me, SPELL_SONIC_BOOM_CAST); - SonicBoom_Timer = 30000; - SonicBoom = true; - return; - } else SonicBoom_Timer -= diff; - - // Murmur's Touch - if (MurmursTouch_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,80,true)) - DoCast(pTarget, SPELL_MURMURS_TOUCH); - MurmursTouch_Timer = 25000 + rand()%10000; - } else MurmursTouch_Timer -= diff; - - // Resonance - if (!SonicBoom && !(me->IsWithinMeleeRange(me->getVictim()))) - { - if (Resonance_Timer <= diff) - { - DoCast(me, SPELL_RESONANCE); - Resonance_Timer = 5000; - } else Resonance_Timer -= diff; - } - - // Magnetic Pull - if (MagneticPull_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - if (pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive()) - { - DoCast(pTarget, SPELL_MAGNETIC_PULL); - MagneticPull_Timer = 15000+rand()%15000; - return; - } - MagneticPull_Timer = 500; - } else MagneticPull_Timer -= diff; - - if (IsHeroic()) - { - // Thundering Storm - if (ThunderingStorm_Timer <= diff) - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) - if (pTarget->isAlive() && !me->IsWithinDist(pTarget, 35, false)) - DoCast(pTarget, SPELL_THUNDERING_STORM, true); - ThunderingStorm_Timer = 15000; - } else ThunderingStorm_Timer -= diff; - - // Sonic Shock - if (SonicShock_Timer <= diff) - { - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM,0,20,false)) - if (pTarget->isAlive()) - DoCast(pTarget, SPELL_SONIC_SHOCK); - SonicShock_Timer = 10000+rand()%10000; - } else SonicShock_Timer -= diff; - } - - // Select nearest most aggro target if top aggro too far - if (!me->isAttackReady()) - return; - if (!me->IsWithinMeleeRange(me->getVictim())) - { - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i != m_threatlist.end(); ++i) - if (Unit *pTarget = Unit::GetUnit((*me),(*i)->getUnitGuid())) - if (pTarget->isAlive() && me->IsWithinMeleeRange(pTarget)) - { - me->TauntApply(pTarget); - break; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_murmur(Creature* pCreature) -{ - return new boss_murmurAI (pCreature); -} - -void AddSC_boss_murmur() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_murmur"; - newscript->GetAI = &GetAI_boss_murmur; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp deleted file mode 100644 index 78340e5e132..00000000000 --- a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Shadow_Labyrinth -SD%Complete: 85 -SDComment: Some cleanup left along with save -SDCategory: Auchindoun, Shadow Labyrinth -EndScriptData */ - -#include "ScriptedPch.h" -#include "shadow_labyrinth.h" - -#define MAX_ENCOUNTER 5 - -#define REFECTORY_DOOR 183296 //door opened when blackheart the inciter dies -#define SCREAMING_HALL_DOOR 183295 //door opened when grandmaster vorpil dies - -/* Shadow Labyrinth encounters: -1 - Ambassador Hellmaw event -2 - Blackheart the Inciter event -3 - Grandmaster Vorpil event -4 - Murmur event -*/ - -struct instance_shadow_labyrinth : public ScriptedInstance -{ - instance_shadow_labyrinth(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - uint64 m_uiRefectoryDoorGUID; - uint64 m_uiScreamingHallDoorGUID; - - uint64 m_uiGrandmasterVorpil; - uint32 m_uiFelOverseerCount; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiRefectoryDoorGUID = 0; - m_uiScreamingHallDoorGUID = 0; - - m_uiGrandmasterVorpil = 0; - m_uiFelOverseerCount = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case REFECTORY_DOOR: - m_uiRefectoryDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[2] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case SCREAMING_HALL_DOOR: - m_uiScreamingHallDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[3] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 18732: - m_uiGrandmasterVorpil = pCreature->GetGUID(); - break; - case 18796: - if (pCreature->isAlive()) - { - ++m_uiFelOverseerCount; - debug_log("TSCR: Shadow Labyrinth: counting %u Fel Overseers.",m_uiFelOverseerCount); - } - break; - } - } - - void SetData(uint32 type, uint32 uiData) - { - switch(type) - { - case TYPE_HELLMAW: - m_auiEncounter[0] = uiData; - break; - - case TYPE_OVERSEER: - if (uiData != DONE) - { - error_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER did not expect other data than DONE"); - return; - } - if (m_uiFelOverseerCount) - { - --m_uiFelOverseerCount; - - if (m_uiFelOverseerCount) - debug_log("TSCR: Shadow Labyrinth: %u Fel Overseers left to kill.",m_uiFelOverseerCount); - else - { - m_auiEncounter[1] = DONE; - debug_log("TSCR: Shadow Labyrinth: TYPE_OVERSEER == DONE"); - } - } - break; - - case DATA_BLACKHEARTTHEINCITEREVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiRefectoryDoorGUID); - m_auiEncounter[2] = uiData; - break; - - case DATA_GRANDMASTERVORPILEVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiScreamingHallDoorGUID); - m_auiEncounter[3] = uiData; - break; - - case DATA_MURMUREVENT: - m_auiEncounter[4] = uiData; - break; - } - - if (uiData == DONE) - { - if (type == TYPE_OVERSEER && m_uiFelOverseerCount != 0) - return; - - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " - << m_auiEncounter[2] << " " << m_auiEncounter[3] << " " << m_auiEncounter[4]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_HELLMAW: return m_auiEncounter[0]; - case TYPE_OVERSEER: return m_auiEncounter[1]; - case DATA_GRANDMASTERVORPILEVENT: return m_auiEncounter[3]; - case DATA_MURMUREVENT: return m_auiEncounter[4]; - } - return false; - } - - uint64 GetData64(uint32 identifier) - { - if (identifier == DATA_GRANDMASTERVORPIL) - return m_uiGrandmasterVorpil; - - return 0; - } - - std::string GetSaveData() - { - return str_data; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_shadow_labyrinth(Map* pMap) -{ - return new instance_shadow_labyrinth(pMap); -} - -void AddSC_instance_shadow_labyrinth() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_shadow_labyrinth"; - newscript->GetInstanceData = &GetInstanceData_instance_shadow_labyrinth; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h b/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h deleted file mode 100644 index a78955368bf..00000000000 --- a/src/server/scripts/Outland/Auchindoun/shadow_labyrinth/shadow_labyrinth.h +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SHADOW_LABYRINTH_H -#define DEF_SHADOW_LABYRINTH_H - -#define TYPE_HELLMAW 1 -#define TYPE_OVERSEER 2 -#define DATA_BLACKHEARTTHEINCITEREVENT 3 -#define DATA_GRANDMASTERVORPILEVENT 4 -#define DATA_MURMUREVENT 5 -#define DATA_GRANDMASTERVORPIL 6 -#endif - diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp new file mode 100644 index 00000000000..69a969adda0 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_fathomlord_karathress.cpp @@ -0,0 +1,746 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Fathomlord_Karathress +SD%Complete: 70 +SDComment: Cyclone workaround +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedEscortAI.h" + +#define SAY_AGGRO -1548021 +#define SAY_GAIN_BLESSING -1548022 +#define SAY_GAIN_ABILITY1 -1548023 +#define SAY_GAIN_ABILITY2 -1548024 +#define SAY_GAIN_ABILITY3 -1548025 +#define SAY_SLAY1 -1548026 +#define SAY_SLAY2 -1548027 +#define SAY_SLAY3 -1548028 +#define SAY_DEATH -1548029 + +//Karathress spells +#define SPELL_CATACLYSMIC_BOLT 38441 +#define SPELL_POWER_OF_SHARKKIS 38455 +#define SPELL_POWER_OF_TIDALVESS 38452 +#define SPELL_POWER_OF_CARIBDIS 38451 +#define SPELL_ENRAGE 24318 +#define SPELL_SEAR_NOVA 38445 +#define SPELL_BLESSING_OF_THE_TIDES 38449 + +//Sharkkis spells +#define SPELL_LEECHING_THROW 29436 +#define SPELL_THE_BEAST_WITHIN 38373 +#define SPELL_MULTISHOT 38366 +#define SPELL_SUMMON_FATHOM_LURKER 38433 +#define SPELL_SUMMON_FATHOM_SPOREBAT 38431 +#define SPELL_PET_ENRAGE 19574 + +//Tidalvess spells +#define SPELL_FROST_SHOCK 38234 +#define SPELL_SPITFIRE_TOTEM 38236 +#define SPELL_POISON_CLEANSING_TOTEM 38306 +// Spell obsolete +// #define SPELL_POISON_CLEANSING_EFFECT 8167 +#define SPELL_EARTHBIND_TOTEM 38304 +#define SPELL_EARTHBIND_TOTEM_EFFECT 6474 +#define SPELL_WINDFURY_WEAPON 38184 + +//Caribdis Spells +#define SPELL_WATER_BOLT_VOLLEY 38335 +#define SPELL_TIDAL_SURGE 38358 +#define SPELL_TIDAL_SURGE_FREEZE 38357 +#define SPELL_HEAL 38330 +#define SPELL_SUMMON_CYCLONE 38337 +#define SPELL_CYCLONE_CYCLONE 29538 + +//Yells and Quotes +#define SAY_GAIN_BLESSING_OF_TIDES "Your overconfidence will be your undoing! Guards, lend me your strength!" +#define SOUND_GAIN_BLESSING_OF_TIDES 11278 +#define SAY_MISC "Alana be'lendor!" //don't know what use this +#define SOUND_MISC 11283 + +//Summoned Unit GUIDs +#define CREATURE_CYCLONE 22104 +#define CREATURE_FATHOM_SPOREBAT 22120 +#define CREATURE_FATHOM_LURKER 22119 +#define CREATURE_SPITFIRE_TOTEM 22091 +#define CREATURE_EARTHBIND_TOTEM 22486 +#define CREATURE_POISON_CLEANSING_TOTEM 22487 + +//entry and position for Seer Olum +#define SEER_OLUM 22820 +#define OLUM_X 446.78f +#define OLUM_Y -542.76f +#define OLUM_Z -7.54773f +#define OLUM_O 0.401581f + +//Fathom-Lord Karathress AI +struct boss_fathomlord_karathressAI : public ScriptedAI +{ + boss_fathomlord_karathressAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Advisors[0] = 0; + Advisors[1] = 0; + Advisors[2] = 0; + } + + ScriptedInstance* pInstance; + + uint32 CataclysmicBolt_Timer; + uint32 Enrage_Timer; + uint32 SearNova_Timer; + + bool BlessingOfTides; + + uint64 Advisors[3]; + + void Reset() + { + CataclysmicBolt_Timer = 10000; + Enrage_Timer = 600000; //10 minutes + SearNova_Timer = 20000+rand()%40000; // 20 - 60 seconds + + BlessingOfTides = false; + + if (pInstance) + { + uint64 RAdvisors[3]; + RAdvisors[0] = pInstance->GetData64(DATA_SHARKKIS); + RAdvisors[1] = pInstance->GetData64(DATA_TIDALVESS); + RAdvisors[2] = pInstance->GetData64(DATA_CARIBDIS); + //Respawn of the 3 Advisors + Creature* pAdvisor = NULL; + for (int i=0; i<3; ++i) + + if (RAdvisors[i]) + { + pAdvisor = (Unit::GetCreature((*me), RAdvisors[i])); + if (pAdvisor && !pAdvisor->isAlive()) + { + pAdvisor->Respawn(); + pAdvisor->AI()->EnterEvadeMode(); + pAdvisor->GetMotionMaster()->MoveTargetedHome(); + } + } + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + } + + void EventSharkkisDeath() + { + DoScriptText(SAY_GAIN_ABILITY1, me); + DoCast(me, SPELL_POWER_OF_SHARKKIS); + } + + void EventTidalvessDeath() + { + DoScriptText(SAY_GAIN_ABILITY2, me); + DoCast(me, SPELL_POWER_OF_TIDALVESS); + } + + void EventCaribdisDeath() + { + DoScriptText(SAY_GAIN_ABILITY3, me); + DoCast(me, SPELL_POWER_OF_CARIBDIS); + } + + void GetAdvisors() + { + if (!pInstance) + return; + + Advisors[0] = pInstance->GetData64(DATA_SHARKKIS); + Advisors[1] = pInstance->GetData64(DATA_TIDALVESS); + Advisors[2] = pInstance->GetData64(DATA_CARIBDIS); + } + + void StartEvent(Unit *who) + { + if (!pInstance) + return; + + GetAdvisors(); + + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); + + //support for quest 10944 + me->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 3600000); + } + + void EnterCombat(Unit * who) + { + StartEvent(who); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + GetAdvisors(); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //CataclysmicBolt_Timer + if (CataclysmicBolt_Timer <= diff) + { + //select a random unit other than the main tank + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); + + //if there aren't other units, cast on the tank + if (!pTarget) + pTarget = me->getVictim(); + + if (pTarget) + DoCast(pTarget, SPELL_CATACLYSMIC_BOLT); + CataclysmicBolt_Timer = 10000; + } else CataclysmicBolt_Timer -= diff; + + //SearNova_Timer + if (SearNova_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SEAR_NOVA); + SearNova_Timer = 20000+rand()%40000; + } else SearNova_Timer -= diff; + + //Enrage_Timer + if (Enrage_Timer <= diff) + { + DoCast(me, SPELL_ENRAGE); + Enrage_Timer = 90000; + } else Enrage_Timer -= diff; + + //Blessing of Tides Trigger + if ((me->GetHealth()*100 / me->GetMaxHealth()) <= 75 && !BlessingOfTides) + { + BlessingOfTides = true; + bool continueTriggering = false; + Creature* Advisor; + for (uint8 i = 0; i < 4; ++i) + if (Advisors[i]) + { + Advisor = (Unit::GetCreature(*me, Advisors[i])); + if (Advisor && Advisor->isAlive()) + { + continueTriggering = true; + break; + } + } + if (continueTriggering) + { + DoCast(me, SPELL_BLESSING_OF_THE_TIDES); + me->MonsterYell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL, NULL); + DoPlaySoundToSet(me, SOUND_GAIN_BLESSING_OF_TIDES); + } + } + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Sharkkis AI +struct boss_fathomguard_sharkkisAI : public ScriptedAI +{ + boss_fathomguard_sharkkisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 LeechingThrow_Timer; + uint32 TheBeastWithin_Timer; + uint32 Multishot_Timer; + uint32 Pet_Timer; + + bool pet; + + uint64 SummonedPet; + + void Reset() + { + LeechingThrow_Timer = 20000; + TheBeastWithin_Timer = 30000; + Multishot_Timer = 15000; + Pet_Timer = 10000; + + pet = false; + + Creature *Pet = Unit::GetCreature(*me, SummonedPet); + if (Pet && Pet->isAlive()) + { + Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + SummonedPet = 0; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //LeechingThrow_Timer + if (LeechingThrow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_LEECHING_THROW); + LeechingThrow_Timer = 20000; + } else LeechingThrow_Timer -= diff; + + //Multishot_Timer + if (Multishot_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MULTISHOT); + Multishot_Timer = 20000; + } else Multishot_Timer -= diff; + + //TheBeastWithin_Timer + if (TheBeastWithin_Timer <= diff) + { + DoCast(me, SPELL_THE_BEAST_WITHIN); + Creature *Pet = Unit::GetCreature(*me, SummonedPet); + if (Pet && Pet->isAlive()) + { + Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); + } + TheBeastWithin_Timer = 30000; + } else TheBeastWithin_Timer -= diff; + + //Pet_Timer + if (Pet_Timer < diff && pet == false) + { + pet = true; + //uint32 spell_id; + uint32 pet_id; + if (!urand(0,1)) + { + //spell_id = SPELL_SUMMON_FATHOM_LURKER; + pet_id = CREATURE_FATHOM_LURKER; + } + else + { + //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; + pet_id = CREATURE_FATHOM_SPOREBAT; + } + //DoCast(me, spell_id, true); + Creature *Pet = DoSpawnCreature(pet_id,0,0,0,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (Pet && pTarget) + { + Pet->AI()->AttackStart(pTarget); + SummonedPet = Pet->GetGUID(); + } + } else Pet_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Tidalvess AI +struct boss_fathomguard_tidalvessAI : public ScriptedAI +{ + boss_fathomguard_tidalvessAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 FrostShock_Timer; + uint32 Spitfire_Timer; + uint32 PoisonCleansing_Timer; + uint32 Earthbind_Timer; + + void Reset() + { + FrostShock_Timer = 25000; + Spitfire_Timer = 60000; + PoisonCleansing_Timer = 30000; + Earthbind_Timer = 45000; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + if (!me->isAlive() && Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventTidalvessDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + DoCast(me, SPELL_WINDFURY_WEAPON); + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + if (!me->HasAura(SPELL_WINDFURY_WEAPON)) + { + DoCast(me, SPELL_WINDFURY_WEAPON); + } + + //FrostShock_Timer + if (FrostShock_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_SHOCK); + FrostShock_Timer = 25000+rand()%5000; + } else FrostShock_Timer -= diff; + + //Spitfire_Timer + if (Spitfire_Timer <= diff) + { + DoCast(me, SPELL_SPITFIRE_TOTEM); + Unit *SpitfireTotem = Unit::GetUnit(*me, CREATURE_SPITFIRE_TOTEM); + if (SpitfireTotem) + { + CAST_CRE(SpitfireTotem)->AI()->AttackStart(me->getVictim()); + } + Spitfire_Timer = 60000; + } else Spitfire_Timer -= diff; + + //PoisonCleansing_Timer + if (PoisonCleansing_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLEANSING_TOTEM); + PoisonCleansing_Timer = 30000; + } else PoisonCleansing_Timer -= diff; + + //Earthbind_Timer + if (Earthbind_Timer <= diff) + { + DoCast(me, SPELL_EARTHBIND_TOTEM); + Earthbind_Timer = 45000; + } else Earthbind_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Fathom-Guard Caribdis AI +struct boss_fathomguard_caribdisAI : public ScriptedAI +{ + boss_fathomguard_caribdisAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 WaterBoltVolley_Timer; + uint32 TidalSurge_Timer; + uint32 Heal_Timer; + uint32 Cyclone_Timer; + + void Reset() + { + WaterBoltVolley_Timer = 35000; + TidalSurge_Timer = 15000+rand()%5000; + Heal_Timer = 55000; + Cyclone_Timer = 30000+rand()%10000; + + if (pInstance) + pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + { + Creature *Karathress = NULL; + Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); + + if (Karathress) + if (!me->isAlive() && Karathress) + CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventCaribdisDeath(); + } + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); + pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + //Only if not incombat check if the event is started + if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) + { + Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); + + if (pTarget) + { + AttackStart(pTarget); + } + } + + //Return since we have no target + if (!UpdateVictim()) + return; + + //someone evaded! + if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) + { + EnterEvadeMode(); + return; + } + + //WaterBoltVolley_Timer + if (WaterBoltVolley_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_WATER_BOLT_VOLLEY); + WaterBoltVolley_Timer = 30000; + } else WaterBoltVolley_Timer -= diff; + + //TidalSurge_Timer + if (TidalSurge_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIDAL_SURGE); + // Hacky way to do it - won't trigger elseways + me->getVictim()->CastSpell(me->getVictim(), SPELL_TIDAL_SURGE_FREEZE, true); + TidalSurge_Timer = 15000+rand()%5000; + } else TidalSurge_Timer -= diff; + + //Cyclone_Timer + if (Cyclone_Timer <= diff) + { + //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work + Cyclone_Timer = 30000+rand()%10000; + Creature *Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000); + if (Cyclone) + { + CAST_CRE(Cyclone)->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); + Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Cyclone->setFaction(me->getFaction()); + Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Cyclone->AI()->AttackStart(pTarget); + } + } + } else Cyclone_Timer -= diff; + + //Heal_Timer + if (Heal_Timer <= diff) + { + // It can be cast on any of the mobs + Unit *pUnit = NULL; + + while (pUnit == NULL || !pUnit->isAlive()) + { + pUnit = selectAdvisorUnit(); + } + + if (pUnit && pUnit->isAlive()) + DoCast(pUnit, SPELL_HEAL); + Heal_Timer = 60000; + } else Heal_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + Unit* selectAdvisorUnit() + { + Unit* pUnit = NULL; + if (pInstance) + { + switch(rand()%4) + { + case 0: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESS)); + break; + case 1: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_SHARKKIS)); + break; + case 2: + pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_TIDALVESS)); + break; + case 3: + pUnit = me; + break; + } + } else pUnit = me; + + return pUnit; + } +}; + +CreatureAI* GetAI_boss_fathomlord_karathress(Creature* pCreature) +{ + return new boss_fathomlord_karathressAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_sharkkis(Creature* pCreature) +{ + return new boss_fathomguard_sharkkisAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_tidalvess(Creature* pCreature) +{ + return new boss_fathomguard_tidalvessAI (pCreature); +} + +CreatureAI* GetAI_boss_fathomguard_caribdis(Creature* pCreature) +{ + return new boss_fathomguard_caribdisAI (pCreature); +} + +void AddSC_boss_fathomlord_karathress() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_fathomlord_karathress"; + newscript->GetAI = &GetAI_boss_fathomlord_karathress; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_sharkkis"; + newscript->GetAI = &GetAI_boss_fathomguard_sharkkis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_tidalvess"; + newscript->GetAI = &GetAI_boss_fathomguard_tidalvess; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_fathomguard_caribdis"; + newscript->GetAI = &GetAI_boss_fathomguard_caribdis; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp new file mode 100644 index 00000000000..923fdf55f80 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp @@ -0,0 +1,379 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hydross_The_Unstable +SD%Complete: 90 +SDComment: Some details and adjustments left to do, probably nothing major. Spawns may be spawned in different way/location. +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define SAY_AGGRO -1548000 +#define SAY_SWITCH_TO_CLEAN -1548001 +#define SAY_CLEAN_SLAY1 -1548002 +#define SAY_CLEAN_SLAY2 -1548003 +#define SAY_CLEAN_DEATH -1548004 +#define SAY_SWITCH_TO_CORRUPT -1548005 +#define SAY_CORRUPT_SLAY1 -1548006 +#define SAY_CORRUPT_SLAY2 -1548007 +#define SAY_CORRUPT_DEATH -1548008 + +#define SWITCH_RADIUS 18 + +#define MODEL_CORRUPT 20609 +#define MODEL_CLEAN 20162 + +#define SPELL_WATER_TOMB 38235 +#define SPELL_MARK_OF_HYDROSS1 38215 +#define SPELL_MARK_OF_HYDROSS2 38216 +#define SPELL_MARK_OF_HYDROSS3 38217 +#define SPELL_MARK_OF_HYDROSS4 38218 +#define SPELL_MARK_OF_HYDROSS5 38231 +#define SPELL_MARK_OF_HYDROSS6 40584 +#define SPELL_MARK_OF_CORRUPTION1 38219 +#define SPELL_MARK_OF_CORRUPTION2 38220 +#define SPELL_MARK_OF_CORRUPTION3 38221 +#define SPELL_MARK_OF_CORRUPTION4 38222 +#define SPELL_MARK_OF_CORRUPTION5 38230 +#define SPELL_MARK_OF_CORRUPTION6 40583 +#define SPELL_VILE_SLUDGE 38246 +#define SPELL_ENRAGE 27680 //this spell need verification +#define SPELL_SUMMON_WATER_ELEMENT 36459 //not in use yet(in use ever?) +#define SPELL_ELEMENTAL_SPAWNIN 25035 +#define SPELL_BLUE_BEAM 40227 //channeled Hydross Beam Helper (not in use yet) + +#define ENTRY_PURE_SPAWN 22035 +#define ENTRY_TAINTED_SPAWN 22036 +#define ENTRY_BEAM_DUMMY 21934 + +#define HYDROSS_X -239.439 +#define HYDROSS_Y -363.481 + +#define SPAWN_X_DIFF1 6.934003 +#define SPAWN_Y_DIFF1 -11.255012 +#define SPAWN_X_DIFF2 -6.934003 +#define SPAWN_Y_DIFF2 11.255012 +#define SPAWN_X_DIFF3 -12.577011 +#define SPAWN_Y_DIFF3 -4.72702 +#define SPAWN_X_DIFF4 12.577011 +#define SPAWN_Y_DIFF4 4.72702 + +struct boss_hydross_the_unstableAI : public ScriptedAI +{ + boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 beams[2]; + uint32 PosCheck_Timer; + uint32 MarkOfHydross_Timer; + uint32 MarkOfCorruption_Timer; + uint32 WaterTomb_Timer; + uint32 VileSludge_Timer; + uint32 MarkOfHydross_Count; + uint32 MarkOfCorruption_Count; + uint32 EnrageTimer; + bool CorruptedForm; + bool beam; + SummonList Summons; + + void Reset() + { + DeSummonBeams(); + beams[0] = 0; + beams[1] = 0; + PosCheck_Timer = 2500; + MarkOfHydross_Timer = 15000; + MarkOfCorruption_Timer = 15000; + WaterTomb_Timer = 7000; + VileSludge_Timer = 7000; + MarkOfHydross_Count = 0; + MarkOfCorruption_Count = 0; + EnrageTimer = 600000; + + CorruptedForm = false; + me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + + me->SetDisplayId(MODEL_CLEAN); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); + beam = false; + Summons.DespawnAll(); + } + + void SummonBeams() + { + Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-258.333,-356.34,22.0499,5.90835,TEMPSUMMON_CORPSE_DESPAWN,0); + if (beamer) + { + beamer->CastSpell(me,SPELL_BLUE_BEAM,true); + beamer->SetDisplayId(11686); //invisible + beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + beams[0]=beamer->GetGUID(); + } + beamer = beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-219.918,-371.308,22.0042,2.73072,TEMPSUMMON_CORPSE_DESPAWN,0); + if (beamer) + { + beamer->CastSpell(me,SPELL_BLUE_BEAM,true); + beamer->SetDisplayId(11686); //invisible + beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + beams[1]=beamer->GetGUID(); + } + } + void DeSummonBeams() + { + for (uint8 i=0; i<2; ++i) + { + Creature* mob = Unit::GetCreature(*me,beams[i]); + if (mob) + { + mob->setDeathState(DEAD); + mob->RemoveCorpse(); + } + } + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + if (CorruptedForm) + { + DoScriptText(RAND(SAY_CORRUPT_SLAY1,SAY_CORRUPT_SLAY2), me); + } + else + { + DoScriptText(RAND(SAY_CLEAN_SLAY1,SAY_CLEAN_SLAY2), me); + } + } + + void JustSummoned(Creature* summoned) + { + if (summoned->GetEntry() == ENTRY_PURE_SPAWN) + { + summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); + Summons.Summon(summoned); + } + if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN) + { + summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); + Summons.Summon(summoned); + } + } + + void SummonedCreatureDespawn(Creature *summon) + { + Summons.Despawn(summon); + } + + void JustDied(Unit * /*victim*/) + { + if (CorruptedForm) + DoScriptText(SAY_CORRUPT_DEATH, me); + else + DoScriptText(SAY_CLEAN_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, DONE); + Summons.DespawnAll(); + } + + void UpdateAI(const uint32 diff) + { + if (!beam) + { + SummonBeams(); + beam=true; + } + //Return since we have no target + if (!UpdateVictim()) + return; + + // corrupted form + if (CorruptedForm) + { + //MarkOfCorruption_Timer + if (MarkOfCorruption_Timer <= diff) + { + if (MarkOfCorruption_Count <= 5) + { + uint32 mark_spell = 0; + + switch (MarkOfCorruption_Count) + { + case 0: mark_spell = SPELL_MARK_OF_CORRUPTION1; break; + case 1: mark_spell = SPELL_MARK_OF_CORRUPTION2; break; + case 2: mark_spell = SPELL_MARK_OF_CORRUPTION3; break; + case 3: mark_spell = SPELL_MARK_OF_CORRUPTION4; break; + case 4: mark_spell = SPELL_MARK_OF_CORRUPTION5; break; + case 5: mark_spell = SPELL_MARK_OF_CORRUPTION6; break; + } + + DoCast(me->getVictim(), mark_spell); + + if (MarkOfCorruption_Count < 5) + ++MarkOfCorruption_Count; + } + + MarkOfCorruption_Timer = 15000; + } else MarkOfCorruption_Timer -= diff; + + //VileSludge_Timer + if (VileSludge_Timer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + DoCast(pTarget, SPELL_VILE_SLUDGE); + + VileSludge_Timer = 15000; + } else VileSludge_Timer -= diff; + + //PosCheck_Timer + if (PosCheck_Timer <= diff) + { + if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) + { + // switch to clean form + me->SetDisplayId(MODEL_CLEAN); + CorruptedForm = false; + MarkOfHydross_Count = 0; + + DoScriptText(SAY_SWITCH_TO_CLEAN, me); + DoResetThreat(); + SummonBeams(); + + // spawn 4 adds + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); + } + + PosCheck_Timer = 2500; + } else PosCheck_Timer -=diff; + } + // clean form + else + { + //MarkOfHydross_Timer + if (MarkOfHydross_Timer <= diff) + { + if (MarkOfHydross_Count <= 5) + { + uint32 mark_spell = NULL; + + switch(MarkOfHydross_Count) + { + case 0: mark_spell = SPELL_MARK_OF_HYDROSS1; break; + case 1: mark_spell = SPELL_MARK_OF_HYDROSS2; break; + case 2: mark_spell = SPELL_MARK_OF_HYDROSS3; break; + case 3: mark_spell = SPELL_MARK_OF_HYDROSS4; break; + case 4: mark_spell = SPELL_MARK_OF_HYDROSS5; break; + case 5: mark_spell = SPELL_MARK_OF_HYDROSS6; break; + } + + DoCast(me->getVictim(), mark_spell); + + if (MarkOfHydross_Count < 5) + ++MarkOfHydross_Count; + } + + MarkOfHydross_Timer = 15000; + } else MarkOfHydross_Timer -= diff; + + //WaterTomb_Timer + if (WaterTomb_Timer <= diff) + { + Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); + if (pTarget) + DoCast(pTarget, SPELL_WATER_TOMB); + + WaterTomb_Timer = 7000; + } else WaterTomb_Timer -= diff; + + //PosCheck_Timer + if (PosCheck_Timer <= diff) + { + if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) + { + // switch to corrupted form + me->SetDisplayId(MODEL_CORRUPT); + MarkOfCorruption_Count = 0; + CorruptedForm = true; + + DoScriptText(SAY_SWITCH_TO_CORRUPT, me); + DoResetThreat(); + DeSummonBeams(); + + // spawn 4 adds + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); + } + + PosCheck_Timer = 2500; + } else PosCheck_Timer -=diff; + } + + //EnrageTimer + if (EnrageTimer <= diff) + { + DoCast(me, SPELL_ENRAGE); + EnrageTimer = 60000; + } else EnrageTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_hydross_the_unstable(Creature* pCreature) +{ + return new boss_hydross_the_unstableAI (pCreature); +} + +void AddSC_boss_hydross_the_unstable() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hydross_the_unstable"; + newscript->GetAI = &GetAI_boss_hydross_the_unstable; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp new file mode 100644 index 00000000000..2f0485d0e6c --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -0,0 +1,1039 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA + */ + +/* ScriptData +SDName: Boss_Lady_Vashj +SD%Complete: 99 +SDComment: Missing blizzlike Shield Generators coords +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedSimpleAI.h" +#include "Spell.h" + +#define SAY_INTRO -1548042 +#define SAY_AGGRO1 -1548043 +#define SAY_AGGRO2 -1548044 +#define SAY_AGGRO3 -1548045 +#define SAY_AGGRO4 -1548046 +#define SAY_PHASE1 -1548047 +#define SAY_PHASE2 -1548048 +#define SAY_PHASE3 -1548049 +#define SAY_BOWSHOT1 -1548050 +#define SAY_BOWSHOT2 -1548051 +#define SAY_SLAY1 -1548052 +#define SAY_SLAY2 -1548053 +#define SAY_SLAY3 -1548054 +#define SAY_DEATH -1548055 + +#define SPELL_SURGE 38044 +#define SPELL_MULTI_SHOT 38310 +#define SPELL_SHOCK_BLAST 38509 +#define SPELL_ENTANGLE 38316 +#define SPELL_STATIC_CHARGE_TRIGGER 38280 +#define SPELL_FORKED_LIGHTNING 40088 +#define SPELL_SHOOT 40873 +#define SPELL_POISON_BOLT 40095 +#define SPELL_TOXIC_SPORES 38575 +#define SPELL_MAGIC_BARRIER 38112 + +#define MIDDLE_X 30.134 +#define MIDDLE_Y -923.65 +#define MIDDLE_Z 42.9 + +#define SPOREBAT_X 30.977156 +#define SPOREBAT_Y -925.297761 +#define SPOREBAT_Z 77.176567 +#define SPOREBAT_O 5.223932 + +#define SHIED_GENERATOR_CHANNEL 19870 +#define ENCHANTED_ELEMENTAL 21958 +#define TAINTED_ELEMENTAL 22009 +#define COILFANG_STRIDER 22056 +#define COILFANG_ELITE 22055 +#define TOXIC_SPOREBAT 22140 +#define TOXIC_SPORES_TRIGGER 22207 + +#define TEXT_NOT_INITIALIZED "Instance script not initialized" +#define TEXT_ALREADY_DEACTIVATED "Already deactivated" + +float ElementPos[8][4] = +{ + {8.3, -835.3, 21.9, 5}, + {53.4, -835.3, 21.9, 4.5}, + {96, -861.9, 21.8, 4}, + {96, -986.4, 21.4, 2.5}, + {54.4, -1010.6, 22, 1.8}, + {9.8, -1012, 21.7, 1.4}, + {-35, -987.6, 21.5, 0.8}, + {-58.9, -901.6, 21.5, 6} +}; + +float ElementWPPos[8][3] = +{ + {71.700752, -883.905884, 41.097168}, + {45.039848, -868.022827, 41.097015}, + {14.585141, -867.894470, 41.097061}, + {-25.415508, -906.737732, 41.097061}, + {-11.801594, -963.405884, 41.097067}, + {14.556657, -979.051514, 41.097137}, + {43.466549, -979.406677, 41.097027}, + {69.945908, -964.663940, 41.097054} +}; + +float SporebatWPPos[8][3] = +{ + {31.6,-896.3,59.1}, + {9.1, -913.9, 56}, + {5.2, -934.4, 52.4}, + {20.7, -946.9, 49.7}, + {41, -941.9, 51}, + {47.7, -927.3, 55}, + {42.2, -912.4, 51.7}, + {27, -905.9, 50} +}; + +float CoilfangElitePos[3][4] = +{ + {28.84, -923.28, 42.9, 6}, + {31.183281, -953.502625, 41.523602, 1.640957}, + {58.895180, -923.124268, 41.545307, 3.152848} +}; + +float CoilfangStriderPos[3][4] = +{ + {66.427010, -948.778503, 41.262245, 2.584220}, + {7.513962, -959.538208, 41.300422, 1.034629}, + {-12.843201, -907.798401, 41.239620, 6.087094} +}; + +float ShieldGeneratorChannelPos[4][4] = +{ + {49.6262, -902.181, 43.0975, 3.95683}, + {10.988, -901.616, 42.5371, 5.4373}, + {10.3859, -944.036, 42.5446, 0.779888}, + {49.3126, -943.398, 42.5501, 2.40174} +}; + +//Lady Vashj AI +struct boss_lady_vashjAI : public ScriptedAI +{ + boss_lady_vashjAI (Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + Intro = false; + JustCreated = true; + c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //set it only once on Creature create (no need do intro if wiped) + } + + ScriptedInstance *pInstance; + + uint64 ShieldGeneratorChannel[4]; + + uint32 AggroTimer; + uint32 ShockBlast_Timer; + uint32 Entangle_Timer; + uint32 StaticCharge_Timer; + uint32 ForkedLightning_Timer; + uint32 Check_Timer; + uint32 EnchantedElemental_Timer; + uint32 TaintedElemental_Timer; + uint32 CoilfangElite_Timer; + uint32 CoilfangStrider_Timer; + uint32 SummonSporebat_Timer; + uint32 SummonSporebat_StaticTimer; + uint8 EnchantedElemental_Pos; + uint8 Phase; + + bool Entangle; + bool Intro; + bool CanAttack; + bool JustCreated; + + void Reset() + { + AggroTimer = 19000; + ShockBlast_Timer = 1+rand()%60000; + Entangle_Timer = 30000; + StaticCharge_Timer = 10000+rand()%15000; + ForkedLightning_Timer = 2000; + Check_Timer = 15000; + EnchantedElemental_Timer = 5000; + TaintedElemental_Timer = 50000; + CoilfangElite_Timer = 45000+rand()%5000; + CoilfangStrider_Timer = 60000+rand()%10000; + SummonSporebat_Timer = 10000; + SummonSporebat_StaticTimer = 30000; + EnchantedElemental_Pos = 0; + Phase = 0; + + Entangle = false; + if (JustCreated) + { + CanAttack = false; + JustCreated = false; + } else CanAttack = true; + + Unit *remo; + for (uint8 i = 0; i < 4; ++i) + { + remo = Unit::GetUnit(*me, ShieldGeneratorChannel[i]); + if (remo) + remo->setDeathState(JUST_DIED); + } + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED); + ShieldGeneratorChannel[0] = 0; + ShieldGeneratorChannel[1] = 0; + ShieldGeneratorChannel[2] = 0; + ShieldGeneratorChannel[3] = 0; + + me->SetCorpseDelay(1000*60*60); + } + + //Called when a tainted elemental dies + void EventTaintedElementalDeath() + { + //the next will spawn 50 seconds after the previous one's death + if (TaintedElemental_Timer > 50000) + TaintedElemental_Timer = 50000; + } + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, DONE); + } + + void StartEvent() + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3,SAY_AGGRO4), me); + + Phase = 1; + + if (pInstance) + pInstance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + { + //remove old tainted cores to prevent cheating in phase 2 + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* i_pl = i->getSource()) + { + i_pl->DestroyItemCount(31088, 1, true); + } + } + } + StartEvent();//this is EnterCombat(), so were are 100% in combat, start the event + + if (Phase != 2) + AttackStart(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (!Intro) + { + Intro = true; + DoScriptText(SAY_INTRO, me); + } + if (!CanAttack) + return; + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) + { + //if (who->HasStealthAura()) + // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + + if (!me->isInCombat())//AttackStart() sets UNIT_FLAG_IN_COMBAT, so this msut be before attacking + StartEvent(); + + if (Phase != 2) + AttackStart(who); + } + } + } + + void CastShootOrMultishot() + { + switch (urand(0,1)) + { + case 0: + //Shoot + //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. + DoCast(me->getVictim(), SPELL_SHOOT); + break; + case 1: + //Multishot + //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. + DoCast(me->getVictim(), SPELL_MULTI_SHOT); + break; + } + if (rand()%3) + { + DoScriptText(RAND(SAY_BOWSHOT1,SAY_BOWSHOT2), me); + } + } + + void UpdateAI(const uint32 diff) + { + if (!CanAttack && Intro) + { + if (AggroTimer <= diff) + { + CanAttack = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + AggroTimer=19000; + }else + { + AggroTimer-=diff; + return; + } + } + //to prevent abuses during phase 2 + if (Phase == 2 && !me->getVictim() && me->isInCombat()) + { + EnterEvadeMode(); + return; + } + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Phase == 1 || Phase == 3) + { + //ShockBlast_Timer + if (ShockBlast_Timer <= diff) + { + //Shock Burst + //Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. + DoCast(me->getVictim(), SPELL_SHOCK_BLAST); + me->TauntApply(me->getVictim()); + + ShockBlast_Timer = 1000+rand()%14000; //random cooldown + } else ShockBlast_Timer -= diff; + + //StaticCharge_Timer + if (StaticCharge_Timer <= diff) + { + //Static Charge + //Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. + Unit *pTarget = NULL; + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true); + + if (pTarget && !pTarget->HasAura(SPELL_STATIC_CHARGE_TRIGGER)) + //cast Static Charge every 2 seconds for 20 seconds + DoCast(pTarget, SPELL_STATIC_CHARGE_TRIGGER); + + StaticCharge_Timer = 10000+rand()%20000; //blizzlike + } else StaticCharge_Timer -= diff; + + //Entangle_Timer + if (Entangle_Timer <= diff) + { + if (!Entangle) + { + //Entangle + //Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. + DoCast(me->getVictim(), SPELL_ENTANGLE); + Entangle = true; + Entangle_Timer = 10000; + } + else + { + CastShootOrMultishot(); + Entangle = false; + Entangle_Timer = 20000+rand()%5000; + } + } else Entangle_Timer -= diff; + + //Phase 1 + if (Phase == 1) + { + //Start phase 2 + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 70) + { + //Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. + Phase = 2; + + me->GetMotionMaster()->Clear(); + DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + + Creature *pCreature; + for (uint8 i = 0; i < 4; ++i) + { + pCreature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0], ShieldGeneratorChannelPos[i][1], ShieldGeneratorChannelPos[i][2], ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + if (pCreature) + ShieldGeneratorChannel[i] = pCreature->GetGUID(); + } + DoScriptText(SAY_PHASE2, me); + } + } + //Phase 3 + else + { + //SummonSporebat_Timer + if (SummonSporebat_Timer <= diff) + { + Creature *Sporebat = NULL; + Sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (Sporebat) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Sporebat->AI()->AttackStart(pTarget); + } + + //summon sporebats faster and faster + if (SummonSporebat_StaticTimer > 1000) + SummonSporebat_StaticTimer -= 1000; + + SummonSporebat_Timer = SummonSporebat_StaticTimer; + + if (SummonSporebat_Timer < 5000) + SummonSporebat_Timer = 5000; + + } else SummonSporebat_Timer -= diff; + } + + //Melee attack + DoMeleeAttackIfReady(); + + //Check_Timer - used to check if somebody is in melee range + if (Check_Timer <= diff) + { + bool InMeleeRange = false; + Unit *pTarget; + std::list t_list = me->getThreatManager().getThreatList(); + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + //if in melee range + if (pTarget && pTarget->IsWithinDistInMap(me, 5)) + { + InMeleeRange = true; + break; + } + } + + //if nobody is in melee range + if (!InMeleeRange) + CastShootOrMultishot(); + + Check_Timer = 5000; + } else Check_Timer -= diff; + } + //Phase 2 + else + { + //ForkedLightning_Timer + if (ForkedLightning_Timer <= diff) + { + //Forked Lightning + //Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (!pTarget) + pTarget = me->getVictim(); + + DoCast(pTarget, SPELL_FORKED_LIGHTNING); + + ForkedLightning_Timer = 2000+rand()%6000; //blizzlike + } else ForkedLightning_Timer -= diff; + + //EnchantedElemental_Timer + if (EnchantedElemental_Timer <= diff) + { + Creature *Elemental; + Elemental = me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (EnchantedElemental_Pos == 7) + EnchantedElemental_Pos = 0; + else + ++EnchantedElemental_Pos; + + EnchantedElemental_Timer = 10000+rand()%5000; + } else EnchantedElemental_Timer -= diff; + + //TaintedElemental_Timer + if (TaintedElemental_Timer <= diff) + { + Creature *Tain_Elemental; + uint32 pos = rand()%8; + Tain_Elemental = me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN, 0); + + TaintedElemental_Timer = 120000; + } else TaintedElemental_Timer -= diff; + + //CoilfangElite_Timer + if (CoilfangElite_Timer <= diff) + { + uint32 pos = rand()%3; + Creature* CoilfangElite = NULL; + CoilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (CoilfangElite) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + CoilfangElite->AI()->AttackStart(pTarget); + else if (me->getVictim()) + CoilfangElite->AI()->AttackStart(me->getVictim()); + } + CoilfangElite_Timer = 45000+rand()%5000; + } else CoilfangElite_Timer -= diff; + + //CoilfangStrider_Timer + if (CoilfangStrider_Timer <= diff) + { + uint32 pos = rand()%3; + Creature* CoilfangStrider = NULL; + CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (CoilfangStrider) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + CoilfangStrider->AI()->AttackStart(pTarget); + else if (me->getVictim()) + CoilfangStrider->AI()->AttackStart(me->getVictim()); + } + CoilfangStrider_Timer = 60000+rand()%10000; + } else CoilfangStrider_Timer -= diff; + + //Check_Timer + if (Check_Timer <= diff) + { + //Start Phase 3 + if (pInstance && pInstance->GetData(DATA_CANSTARTPHASE3)) + { + //set life 50% + me->SetHealth(me->GetMaxHealth()/2); + + me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); + + DoScriptText(SAY_PHASE3, me); + + Phase = 3; + + //return to the tank + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + Check_Timer = 1000; + } else Check_Timer -= diff; + } + } +}; + +//Enchanted Elemental +//If one of them reaches Vashj he will increase her damage done by 5%. +struct mob_enchanted_elementalAI : public ScriptedAI +{ + mob_enchanted_elementalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 move; + uint32 phase; + float x, y, z; + + uint64 VashjGUID; + + void Reset() + { + me->SetSpeed(MOVE_WALK,0.6);//walk + me->SetSpeed(MOVE_RUN,0.6);//run + move = 0; + phase = 1; + + VashjGUID = 0; + + for (int i = 0; i<8; ++i)//search for nearest waypoint (up on stairs) + { + if (!x || !y || !z) + { + x = ElementWPPos[i][0]; + y = ElementWPPos[i][1]; + z = ElementWPPos[i][2]; + } + else + { + if (me->GetDistance(ElementWPPos[i][0],ElementWPPos[i][1],ElementWPPos[i][2]) < me->GetDistance(x,y,z)) + { + x = ElementWPPos[i][0]; + y = ElementWPPos[i][1]; + z = ElementWPPos[i][2]; + } + } + } + if (pInstance) + VashjGUID = pInstance->GetData64(DATA_LADYVASHJ); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!pInstance) + return; + + if (!VashjGUID) + return; + + if (move <= diff) + { + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + if (phase == 1) + me->GetMotionMaster()->MovePoint(0, x, y, z); + if (phase == 1 && me->IsWithinDist3d(x,y,z, 0.1)) + phase = 2; + if (phase == 2) + { + me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + phase = 3; + } + if (phase == 3) + { + me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); + if (me->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) + DoCast(me, SPELL_SURGE); + } + if (Creature *Vashj = Unit::GetCreature(*me, VashjGUID)) + { + if (!Vashj->isInCombat() || CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase != 2 || Vashj->isDead()) + { + //call Unsummon() + me->Kill(me); + } + } + move = 1000; + } else move -= diff; + } +}; + +//Tainted Elemental +//This mob has 7,900 life, doesn't move, and shoots Poison Bolts at one person anywhere in the area, doing 3,000 nature damage and placing a posion doing 2,000 damage every 2 seconds. He will switch targets often, or sometimes just hang on a single player, but there is nothing you can do about it except heal the damage and kill the Tainted Elemental +struct mob_tainted_elementalAI : public ScriptedAI +{ + mob_tainted_elementalAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 PoisonBolt_Timer; + uint32 Despawn_Timer; + + void Reset() + { + PoisonBolt_Timer = 5000+rand()%5000; + Despawn_Timer = 30000; + } + + void JustDied(Unit * /*killer*/) + { + if (pInstance) + { + Creature *Vashj = NULL; + Vashj = (Unit::GetCreature((*me), pInstance->GetData64(DATA_LADYVASHJ))); + + if (Vashj) + CAST_AI(boss_lady_vashjAI, Vashj->AI())->EventTaintedElementalDeath(); + } + } + + void EnterCombat(Unit * who) + { + me->AddThreat(who, 0.1f); + } + + void UpdateAI(const uint32 diff) + { + //PoisonBolt_Timer + if (PoisonBolt_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget && pTarget->IsWithinDistInMap(me, 30)) + DoCast(pTarget, SPELL_POISON_BOLT); + + PoisonBolt_Timer = 5000+rand()%5000; + } else PoisonBolt_Timer -= diff; + + //Despawn_Timer + if (Despawn_Timer <= diff) + { + //call Unsummon() + me->setDeathState(DEAD); + + //to prevent crashes + Despawn_Timer = 1000; + } else Despawn_Timer -= diff; + } +}; + +//Toxic Sporebat +//Toxic Spores: Used in Phase 3 by the Spore Bats, it creates a contaminated green patch of ground, dealing about 2775-3225 nature damage every second to anyone who stands in it. +struct mob_toxic_sporebatAI : public ScriptedAI +{ + mob_toxic_sporebatAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + EnterEvadeMode(); + } + + ScriptedInstance *pInstance; + + uint32 movement_timer; + uint32 ToxicSpore_Timer; + uint32 bolt_timer; + uint32 Check_Timer; + + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->setFaction(14); + movement_timer = 0; + ToxicSpore_Timer = 5000; + bolt_timer = 5500; + Check_Timer = 1000; + } + + void EnterCombat(Unit * /*who*/) + { + + } + + void MoveInLineOfSight(Unit * /*who*/) + { + + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id == 1) + movement_timer = 0; + } + + void UpdateAI (const uint32 diff) + { + //Random movement + if (movement_timer <= diff) + { + uint32 rndpos = rand()%8; + me->GetMotionMaster()->MovePoint(1,SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]); + movement_timer = 6000; + } else movement_timer -= diff; + + //toxic spores + if (bolt_timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + { + Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); + if (trig) + { + trig->setFaction(14); + trig->CastSpell(trig, SPELL_TOXIC_SPORES,true); + } + } + bolt_timer = 10000+rand()%5000; + } + else bolt_timer -= diff; + + //Check_Timer + if (Check_Timer <= diff) + { + if (pInstance) + { + //check if vashj is death + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); + if (!Vashj || (Vashj && !Vashj->isAlive()) || (Vashj && CAST_AI(boss_lady_vashjAI, CAST_CRE(Vashj)->AI())->Phase != 3)) + { + //remove + me->setDeathState(DEAD); + me->RemoveCorpse(); + me->setFaction(35); + } + } + + Check_Timer = 1000; + } else Check_Timer -= diff; + } +}; + +//Coilfang Elite +//It's an elite Naga mob with 170,000 HP. It does about 5000 damage on plate, and has a nasty cleave hitting for about 7500 damage +CreatureAI* GetAI_mob_coilfang_elite(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 31345; //Cleave + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].CooldownRandomAddition = 5000; + ai->Spell[0].First_Cast = 5000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_RANDOM; + + ai->EnterEvadeMode(); + + return ai; +} + +//Coilfang Strider +//It hits plate for about 8000 damage, has a Mind Blast spell doing about 3000 shadow damage, and a Psychic Scream Aura, which fears everybody in a 8 yard range of it every 2-3 seconds , for 5 seconds and increasing their movement speed by 150% during the fear. +CreatureAI* GetAI_mob_coilfang_strider(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = 41374; //Mind Blast + ai->Spell[0].Cooldown = 30000; + ai->Spell[0].CooldownRandomAddition = 10000; + ai->Spell[0].First_Cast = 8000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + //Scream aura not implemented + + ai->EnterEvadeMode(); + + return ai; +} + +struct mob_shield_generator_channelAI : public ScriptedAI +{ + mob_shield_generator_channelAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + uint32 Check_Timer; + bool Casted; + void Reset() + { + Check_Timer = 0; + Casted = false; + me->SetDisplayId(11686); //invisible + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit * /*who*/) {} + + void UpdateAI (const uint32 diff) + { + if (!pInstance) + return; + + if (Check_Timer <= diff) + { + Unit *Vashj = NULL; + Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); + + if (Vashj && Vashj->isAlive()) + { + //start visual channel + if (!Casted || !Vashj->HasAura(SPELL_MAGIC_BARRIER)) + { + DoCast(Vashj, SPELL_MAGIC_BARRIER, true); + Casted = true; + } + } + Check_Timer = 1000; + } else Check_Timer -= diff; + } +}; + +bool ItemUse_item_tainted_core(Player* pPlayer, Item* /*_Item*/, SpellCastTargets const& targets) +{ + ScriptedInstance *pInstance = pPlayer->GetInstanceData(); + + if (!pInstance) + { + pPlayer->GetSession()->SendNotification(TEXT_NOT_INITIALIZED); + return true; + } + + Creature *Vashj = NULL; + Vashj = (Unit::GetCreature((*pPlayer), pInstance->GetData64(DATA_LADYVASHJ))); + if (Vashj && CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase == 2) + { + if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT) + { + uint32 identifier; + uint8 channel_identifier; + switch(targets.getGOTarget()->GetEntry()) + { + case 185052: + identifier = DATA_SHIELDGENERATOR1; + channel_identifier = 0; + break; + case 185053: + identifier = DATA_SHIELDGENERATOR2; + channel_identifier = 1; + break; + case 185051: + identifier = DATA_SHIELDGENERATOR3; + channel_identifier = 2; + break; + case 185054: + identifier = DATA_SHIELDGENERATOR4; + channel_identifier = 3; + break; + default: + return true; + } + + if (pInstance->GetData(identifier)) + { + pPlayer->GetSession()->SendNotification(TEXT_ALREADY_DEACTIVATED); + return true; + } + + //get and remove channel + Unit *Channel = NULL; + Channel = Unit::GetCreature(*Vashj, CAST_AI(boss_lady_vashjAI, Vashj->AI())->ShieldGeneratorChannel[channel_identifier]); + if (Channel) + { + //call Unsummon() + Channel->setDeathState(JUST_DIED); + } + + pInstance->SetData(identifier, 1); + + //remove this item + pPlayer->DestroyItemCount(31088, 1, true); + return true; + } + else if (targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT) + return false; + else if (targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) + { + pPlayer->DestroyItemCount(31088, 1, true); + pPlayer->CastSpell(targets.getUnitTarget(), 38134, true); + return true; + } + } + return true; +} + +CreatureAI* GetAI_boss_lady_vashj(Creature* pCreature) +{ + return new boss_lady_vashjAI (pCreature); +} + +CreatureAI* GetAI_mob_enchanted_elemental(Creature* pCreature) +{ + return new mob_enchanted_elementalAI (pCreature); +} + +CreatureAI* GetAI_mob_tainted_elemental(Creature* pCreature) +{ + return new mob_tainted_elementalAI (pCreature); +} + +CreatureAI* GetAI_mob_toxic_sporebat(Creature* pCreature) +{ + return new mob_toxic_sporebatAI (pCreature); +} + +CreatureAI* GetAI_mob_shield_generator_channel(Creature* pCreature) +{ + return new mob_shield_generator_channelAI (pCreature); +} + +void AddSC_boss_lady_vashj() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lady_vashj"; + newscript->GetAI = &GetAI_boss_lady_vashj; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_enchanted_elemental"; + newscript->GetAI = &GetAI_mob_enchanted_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_tainted_elemental"; + newscript->GetAI = &GetAI_mob_tainted_elemental; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toxic_sporebat"; + newscript->GetAI = &GetAI_mob_toxic_sporebat; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_elite"; + newscript->GetAI = &GetAI_mob_coilfang_elite; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_strider"; + newscript->GetAI = &GetAI_mob_coilfang_strider; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shield_generator_channel"; + newscript->GetAI = &GetAI_mob_shield_generator_channel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "item_tainted_core"; + newscript->pItemUse = &ItemUse_item_tainted_core; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp new file mode 100644 index 00000000000..61c9ed9d527 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -0,0 +1,787 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Leotheras_The_Blind +SD%Complete: 80 +SDComment: Possesion Support +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +// --- Spells used by Leotheras The Blind +#define SPELL_WHIRLWIND 37640 +#define SPELL_CHAOS_BLAST 37674 +#define SPELL_BERSERK 26662 +#define SPELL_INSIDIOUS_WHISPER 37676 +#define SPELL_DUAL_WIELD 42459 + +// --- Spells used in banish phase --- +#define BANISH_BEAM 38909 +#define AURA_BANISH 37833 + +// --- Spells used by Greyheart Spellbinders +#define SPELL_EARTHSHOCK 39076 +#define SPELL_MINDBLAST 37531 + +// --- Spells used by Inner Demons and Creature ID +#define INNER_DEMON_ID 21857 +#define AURA_DEMONIC_ALIGNMENT 37713 +#define SPELL_SHADOWBOLT 39309 +#define SPELL_SOUL_LINK 38007 +#define SPELL_CONSUMING_MADNESS 37749 //not supported by core yet + +//Misc. +#define MODEL_DEMON 20125 +#define MODEL_NIGHTELF 20514 +#define DEMON_FORM 21875 +#define MOB_SPELLBINDER 21806 + +#define SAY_AGGRO -1548009 +#define SAY_SWITCH_TO_DEMON -1548010 +#define SAY_INNER_DEMONS -1548011 +#define SAY_DEMON_SLAY1 -1548012 +#define SAY_DEMON_SLAY2 -1548013 +#define SAY_DEMON_SLAY3 -1548014 +#define SAY_NIGHTELF_SLAY1 -1548015 +#define SAY_NIGHTELF_SLAY2 -1548016 +#define SAY_NIGHTELF_SLAY3 -1548017 +#define SAY_FINAL_FORM -1548018 +#define SAY_FREE -1548019 +#define SAY_DEATH -1548020 + +struct mob_inner_demonAI : public ScriptedAI +{ + mob_inner_demonAI(Creature *c) : ScriptedAI(c) + { + victimGUID = 0; + } + + uint32 ShadowBolt_Timer; + + uint32 Link_Timer; + uint64 victimGUID; + + void Reset() + { + ShadowBolt_Timer = 10000; + Link_Timer = 1000; + } + void JustDied(Unit * /*victim*/) + { + Unit* pUnit = Unit::GetUnit((*me),victimGUID); + if (pUnit && pUnit->HasAura(SPELL_INSIDIOUS_WHISPER)) + pUnit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID()) + { + damage = 0; + DoModifyThreatPercent(done_by, -100); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (!victimGUID) return; + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (me->getVictim()->GetGUID() != victimGUID) + { + DoModifyThreatPercent(me->getVictim(), -100); + Unit* owner = Unit::GetUnit((*me),victimGUID); + if (owner && owner->isAlive()) + { + me->AddThreat(owner,999999); + AttackStart(owner); + } else if (owner && owner->isDead()) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + } + + if (Link_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOUL_LINK, true); + Link_Timer = 1000; + } else Link_Timer -= diff; + + if (!me->HasAura(AURA_DEMONIC_ALIGNMENT)) + DoCast(me, AURA_DEMONIC_ALIGNMENT, true); + + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOWBOLT, false); + ShadowBolt_Timer = 10000; + } else ShadowBolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +//Original Leotheras the Blind AI +struct boss_leotheras_the_blindAI : public ScriptedAI +{ + boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c) + { + c->GetPosition(x,y,z); + pInstance = c->GetInstanceData(); + Demon = 0; + + for (uint8 i = 0; i < 3; ++i)//clear guids + SpellBinderGUID[i] = 0; + } + + ScriptedInstance *pInstance; + + uint32 Whirlwind_Timer; + uint32 ChaosBlast_Timer; + uint32 SwitchToDemon_Timer; + uint32 SwitchToHuman_Timer; + uint32 Berserk_Timer; + uint32 InnerDemons_Timer; + uint32 BanishTimer; + + bool DealDamage; + bool NeedThreatReset; + bool DemonForm; + bool IsFinalForm; + bool EnrageUsed; + float x,y,z; + + uint64 InnderDemon[5]; + uint32 InnerDemon_Count; + uint64 Demon; + uint64 SpellBinderGUID[3]; + + void Reset() + { + CheckChannelers(); + BanishTimer = 1000; + Whirlwind_Timer = 15000; + ChaosBlast_Timer = 1000; + SwitchToDemon_Timer = 45000; + SwitchToHuman_Timer = 60000; + Berserk_Timer = 600000; + InnerDemons_Timer = 30000; + me->SetCanDualWield(true); + DealDamage = true; + DemonForm = false; + IsFinalForm = false; + NeedThreatReset = false; + EnrageUsed = false; + InnerDemon_Count = 0; + me->SetSpeed(MOVE_RUN, 2.0f, true); + me->SetDisplayId(MODEL_NIGHTELF); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + DoCast(me, SPELL_DUAL_WIELD, true); + me->SetCorpseDelay(1000*60*60); + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED); + } + + void CheckChannelers(/*bool DoEvade = true*/) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Creature *add = Unit::GetCreature(*me,SpellBinderGUID[i])) + add->DisappearAndDie(); + + float nx = x; + float ny = y; + float o = 2.4f; + if (i == 0) {nx += 10; ny -= 5; o=2.5f;} + if (i == 1) {nx -= 8; ny -= 7; o=0.9f;} + if (i == 2) {nx -= 3; ny += 9; o=5.0f;} + Creature* binder = me->SummonCreature(MOB_SPELLBINDER,nx,ny,z,o,TEMPSUMMON_DEAD_DESPAWN,0); + if (binder) + SpellBinderGUID[i] = binder->GetGUID(); + + } + } + void MoveInLineOfSight(Unit *who) + { + if (me->HasAura(AURA_BANISH)) + return; + + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius)) + { + // Check first that object is in an angle in front of this one before LoS check + if (me->HasInArc(M_PI/2.0f, who) && me->IsWithinLOSInMap(who)) + { + AttackStart(who); + } + } + } + } + + void StartEvent() + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, IN_PROGRESS); + } + + void CheckBanish() + { + uint8 AliveChannelers = 0; + for (uint8 i = 0; i < 3; ++i) + { + Unit *add = Unit::GetUnit(*me,SpellBinderGUID[i]); + if (add && add->isAlive()) + ++AliveChannelers; + } + + // channelers == 0 remove banish aura + if (AliveChannelers == 0 && me->HasAura(AURA_BANISH)) + { + // removing banish aura + me->RemoveAurasDueToSpell(AURA_BANISH); + + // Leotheras is getting immune again + me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); + + // changing model to bloodelf + me->SetDisplayId(MODEL_NIGHTELF); + + // and reseting equipment + me->LoadEquipment(me->GetEquipmentId()); + + if (pInstance && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + Unit *victim = NULL; + victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); + if (victim) + me->getThreatManager().addThreat(victim, 1); + StartEvent(); + } + } + else if (AliveChannelers != 0 && !me->HasAura(AURA_BANISH)) + { + // channelers != 0 apply banish aura + // removing Leotheras banish immune to apply AURA_BANISH + me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); + DoCast(me, AURA_BANISH); + + // changing model + me->SetDisplayId(MODEL_DEMON); + + // and removing weapons + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + } + } + + //Despawn all Inner Demon summoned + void DespawnDemon() + { + for (uint8 i=0; i<5; ++i) + { + if (InnderDemon[i]) + { + //delete creature + Creature* pCreature = Unit::GetCreature((*me), InnderDemon[i]); + if (pCreature && pCreature->isAlive()) + { + pCreature->ForcedDespawn(); + } + InnderDemon[i] = 0; + } + } + + InnerDemon_Count = 0; + } + + void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core + { + for (uint8 i=0; i<5; ++i) + { + if (InnderDemon[i] > 0) + { + Creature* pUnit = Unit::GetCreature((*me), InnderDemon[i]); + if (pUnit && pUnit->isAlive()) + { + Unit* pUnit_pTarget = Unit::GetUnit(*pUnit, CAST_AI(mob_inner_demonAI, pUnit->AI())->victimGUID); + if (pUnit_pTarget && pUnit_pTarget->isAlive()) + { + pUnit->CastSpell(pUnit_pTarget, SPELL_CONSUMING_MADNESS, true); + DoModifyThreatPercent(pUnit_pTarget, -100); + } + } + } + } + } + + void KilledUnit(Unit * victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + if (DemonForm) + { + DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); + } + else + { + DoScriptText(RAND(SAY_NIGHTELF_SLAY1,SAY_NIGHTELF_SLAY2,SAY_NIGHTELF_SLAY3), me); + } + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + //despawn copy + if (Demon) + { + if (Creature* pDemon = Unit::GetCreature(*me, Demon)) + pDemon->ForcedDespawn(); + } + if (pInstance) + pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + if (me->HasAura(AURA_BANISH)) + return; + + me->LoadEquipment(me->GetEquipmentId()); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (me->HasAura(AURA_BANISH) || !UpdateVictim()) + { + if (BanishTimer <= diff) + { + CheckBanish();//no need to check every update tick + BanishTimer = 1000; + } else BanishTimer -= diff; + return; + } + if (me->HasAura(SPELL_WHIRLWIND)) + if (Whirlwind_Timer <= diff) + { + Unit *newTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (newTarget) + { + DoResetThreat(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,newTarget->GetPositionX(),newTarget->GetPositionY(),newTarget->GetPositionZ()); + } + Whirlwind_Timer = 2000; + } else Whirlwind_Timer -= diff; + + // reseting after changing forms and after ending whirlwind + if (NeedThreatReset && !me->HasAura(SPELL_WHIRLWIND)) + { + // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding) + if (DemonForm) + InnerDemons_Timer = 30000; + else + Whirlwind_Timer = 15000; + + NeedThreatReset = false; + DoResetThreat(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(me->getVictim()); + } + + //Enrage_Timer (10 min) + if (Berserk_Timer < diff && !EnrageUsed) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_BERSERK); + EnrageUsed = true; + } else Berserk_Timer -= diff; + + if (!DemonForm) + { + //Whirldind Timer + if (!me->HasAura(SPELL_WHIRLWIND)) + { + if (Whirlwind_Timer <= diff) + { + DoCast(me, SPELL_WHIRLWIND); + // while whirlwinding this variable is used to countdown target's change + Whirlwind_Timer = 2000; + NeedThreatReset = true; + } else Whirlwind_Timer -= diff; + } + //Switch_Timer + + if (!IsFinalForm) + if (SwitchToDemon_Timer <= diff) + { + //switch to demon form + me->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0); + me->SetDisplayId(MODEL_DEMON); + DoScriptText(SAY_SWITCH_TO_DEMON, me); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); + me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); + DemonForm = true; + NeedThreatReset = true; + SwitchToDemon_Timer = 45000; + } else SwitchToDemon_Timer -= diff; + DoMeleeAttackIfReady(); + } + else + { + //ChaosBlast_Timer + if (!me->getVictim()) + return; + if (me->IsWithinDist(me->getVictim(), 30)) + me->StopMoving(); + if (ChaosBlast_Timer <= diff) + { + // will cast only when in range of spell + if (me->IsWithinDist(me->getVictim(), 30)) + { + //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); + int damage = 100; + me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); + } + ChaosBlast_Timer = 3000; + } else ChaosBlast_Timer -= diff; + //Summon Inner Demon + if (InnerDemons_Timer <= diff) + { + std::list& ThreatList = me->getThreatManager().getThreatList(); + std::vector TargetList; + for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) + { + Unit *tempTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->getVictim()->GetGUID() && TargetList.size()<5) + TargetList.push_back(tempTarget); + } + //SpellEntry *spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); + for (std::vector::const_iterator itr = TargetList.begin(); itr != TargetList.end(); ++itr) + { + if ((*itr) && (*itr)->isAlive()) + { + Creature * demon = me->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (demon) + { + demon->AI()->AttackStart((*itr)); + CAST_AI(mob_inner_demonAI, demon->AI())->victimGUID = (*itr)->GetGUID(); + + (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); + + if (InnerDemon_Count > 4) + InnerDemon_Count = 0; + + //Safe storing of creatures + InnderDemon[InnerDemon_Count] = demon->GetGUID(); + + //Update demon count + ++InnerDemon_Count; + } + } + } + DoScriptText(SAY_INNER_DEMONS, me); + + InnerDemons_Timer = 999999; + } else InnerDemons_Timer -= diff; + + //Switch_Timer + if (SwitchToHuman_Timer <= diff) + { + //switch to nightelf form + me->SetDisplayId(MODEL_NIGHTELF); + me->LoadEquipment(me->GetEquipmentId()); + + CastConsumingMadness(); + DespawnDemon(); + + DemonForm = false; + NeedThreatReset = true; + + SwitchToHuman_Timer = 60000; + } else SwitchToHuman_Timer -= diff; + } + + if (!IsFinalForm && (me->GetHealth()*100 / me->GetMaxHealth()) < 15) + { + //at this point he divides himself in two parts + CastConsumingMadness(); + DespawnDemon(); + Creature *Copy = NULL; + Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000); + if (Copy) + { + Demon = Copy->GetGUID(); + if (me->getVictim()) + Copy->AI()->AttackStart(me->getVictim()); + } + //set nightelf final form + IsFinalForm = true; + DemonForm = false; + + DoScriptText(SAY_FINAL_FORM, me); + me->SetDisplayId(MODEL_NIGHTELF); + me->LoadEquipment(me->GetEquipmentId()); + } + } +}; + +//Leotheras the Blind Demon Form AI +struct boss_leotheras_the_blind_demonformAI : public ScriptedAI +{ + boss_leotheras_the_blind_demonformAI(Creature *c) : ScriptedAI(c) {} + + uint32 ChaosBlast_Timer; + bool DealDamage; + + void Reset() + { + ChaosBlast_Timer = 1000; + DealDamage = true; + } + + void StartEvent() + { + DoScriptText(SAY_FREE, me); + } + + void KilledUnit(Unit * victim) + { + if (victim->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) + DoCast(me, 8149, true); + } + + void EnterCombat(Unit * /*who*/) + { + StartEvent(); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + //ChaosBlast_Timer + if (me->IsWithinDist(me->getVictim(), 30)) + me->StopMoving(); + + if (ChaosBlast_Timer <= diff) + { + // will cast only when in range od spell + if (me->IsWithinDist(me->getVictim(), 30)) + { + //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); + int damage = 100; + me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); + ChaosBlast_Timer = 3000; + } + } else ChaosBlast_Timer -= diff; + + //Do NOT deal any melee damage to the target. + } +}; +struct mob_greyheart_spellbinderAI : public ScriptedAI +{ + mob_greyheart_spellbinderAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + leotherasGUID = 0; + AddedBanish = false; + } + + ScriptedInstance *pInstance; + + uint64 leotherasGUID; + + uint32 Mindblast_Timer; + uint32 Earthshock_Timer; + + bool AddedBanish; + + void Reset() + { + Mindblast_Timer = 3000 + rand()%5000; + Earthshock_Timer = 5000 + rand()%5000; + + if (pInstance) + { + pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, 0); + Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); + if (leotheras && leotheras->isAlive()) + CAST_AI(boss_leotheras_the_blindAI, leotheras->AI())->CheckChannelers(/*false*/); + } + } + + void EnterCombat(Unit * who) + { + me->InterruptNonMeleeSpells(false); + if (pInstance) + pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID()); + } + + void JustRespawned() + { + AddedBanish = false; + Reset(); + } + + void CastChanneling() + { + if (!me->isInCombat() && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + { + if (leotherasGUID) + { + Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); + if (leotheras && leotheras->isAlive()) + DoCast(leotheras, BANISH_BEAM); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (pInstance) + { + if (!leotherasGUID) + leotherasGUID = pInstance->GetData64(DATA_LEOTHERAS); + + if (!me->isInCombat() && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + Unit *victim = NULL; + victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); + if (victim) + AttackStart(victim); + } + } + + if (!UpdateVictim()) + { + CastChanneling(); + return; + } + + if (pInstance && !pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) + { + EnterEvadeMode(); + return; + } + + if (Mindblast_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (pTarget)DoCast(pTarget, SPELL_MINDBLAST); + + Mindblast_Timer = 10000 + rand()%5000; + } else Mindblast_Timer -= diff; + + if (Earthshock_Timer <= diff) + { + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) + { + if (Player* i_pl = itr->getSource()) + { + bool isCasting = false; + for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) + if (i_pl->GetCurrentSpell(i)) + isCasting = true; + + if (isCasting) + { + DoCast(i_pl, SPELL_EARTHSHOCK); + break; + } + } + } + Earthshock_Timer = 8000 + rand()%7000; + } else Earthshock_Timer -= diff; + DoMeleeAttackIfReady(); + } + + void JustDied(Unit * /*killer*/) {} +}; +CreatureAI* GetAI_boss_leotheras_the_blind(Creature* pCreature) +{ + return new boss_leotheras_the_blindAI (pCreature); +} + +CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature* pCreature) +{ + return new boss_leotheras_the_blind_demonformAI (pCreature); +} + +CreatureAI* GetAI_mob_greyheart_spellbinder(Creature* pCreature) +{ + return new mob_greyheart_spellbinderAI (pCreature); +} + +CreatureAI* GetAI_mob_inner_demon(Creature* pCreature) +{ + return new mob_inner_demonAI (pCreature); +} +void AddSC_boss_leotheras_the_blind() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_leotheras_the_blind"; + newscript->GetAI = &GetAI_boss_leotheras_the_blind; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_leotheras_the_blind_demonform"; + newscript->GetAI = &GetAI_boss_leotheras_the_blind_demonform; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_greyheart_spellbinder"; + newscript->GetAI = &GetAI_mob_greyheart_spellbinder; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_inner_demon"; + newscript->GetAI = &GetAI_mob_inner_demon; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp new file mode 100644 index 00000000000..b1c0c10bcce --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp @@ -0,0 +1,458 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: boss_the_lurker_below +SD%Complete: 80 +SDComment: Coilfang Frenzy, find out how could we fishing in the strangepool +SDCategory: The Lurker Below +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" +#include "ScriptedSimpleAI.h" +#include "Spell.h" + +#define SPELL_SPOUT 37433 +#define SPELL_SPOUT_ANIM 42835 +#define SPELL_SPOUT_BREATH 37431 +#define SPELL_KNOCKBACK 19813 +#define SPELL_GEYSER 37478 +#define SPELL_WHIRL 37660 +#define SPELL_WATERBOLT 37138 +#define SPELL_SUBMERGE 37550 +#define SPELL_EMERGE 20568 + +#define EMOTE_SPOUT "The Lurker Below takes a deep breath." + +#define SPOUT_DIST 100 + +#define MOB_COILFANG_GUARDIAN 21873 +#define MOB_COILFANG_AMBUSHER 21865 + +//Ambusher spells +#define SPELL_SPREAD_SHOT 37790 +#define SPELL_SHOOT 37770 + +//Guardian spells +#define SPELL_ARCINGSMASH 38761 // Wrong SpellId. Can't find the right one. +#define SPELL_HAMSTRING 26211 + +float AddPos[9][3] = +{ + {2.8553810, -459.823914, -19.182686}, //MOVE_AMBUSHER_1 X, Y, Z + {12.400000, -466.042267, -19.182686}, //MOVE_AMBUSHER_2 X, Y, Z + {51.366653, -460.836060, -19.182686}, //MOVE_AMBUSHER_3 X, Y, Z + {62.597980, -457.433044, -19.182686}, //MOVE_AMBUSHER_4 X, Y, Z + {77.607452, -384.302765, -19.182686}, //MOVE_AMBUSHER_5 X, Y, Z + {63.897900, -378.984924, -19.182686}, //MOVE_AMBUSHER_6 X, Y, Z + {34.447250, -387.333618, -19.182686}, //MOVE_GUARDIAN_1 X, Y, Z + {14.388216, -423.468018, -19.625271}, //MOVE_GUARDIAN_2 X, Y, Z + {42.471519, -445.115295, -19.769423} //MOVE_GUARDIAN_3 X, Y, Z +}; + +struct boss_the_lurker_belowAI : public Scripted_NoMovementAI +{ + boss_the_lurker_belowAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + SpellEntry *TempSpell = GET_SPELL(SPELL_SPOUT_ANIM); + if (TempSpell) + { + TempSpell->Effect[0] = 0;//remove all spell effect, only anim is needed + TempSpell->Effect[1] = 0; + TempSpell->Effect[2] = 0; + } + } + + ScriptedInstance* pInstance; + SummonList Summons; + + bool Spawned; + bool Submerged; + bool InRange; + bool CanStartEvent; + uint32 RotTimer; + uint32 SpoutAnimTimer; + uint32 WaterboltTimer; + uint32 SpoutTimer; + uint32 WhirlTimer; + uint32 PhaseTimer; + uint32 GeyserTimer; + uint32 CheckTimer; + uint32 WaitTimer; + uint32 WaitTimer2; + + bool CheckCanStart()//check if players fished + { + if (pInstance && pInstance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) + return false; + return true; + } + void Reset() + { + me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); + SpoutAnimTimer = 1000; + RotTimer = 0; + WaterboltTimer = 15000;//give time to get in range when fight starts + SpoutTimer = 45000; + WhirlTimer = 18000;//after avery spout + PhaseTimer = 120000; + GeyserTimer = rand()%5000 + 15000; + CheckTimer = 15000;//give time to get in range when fight starts + WaitTimer = 60000;//never reached + WaitTimer2 = 60000;//never reached + + Submerged = true;//will be false at combat start + Spawned = false; + InRange = false; + CanStartEvent = false; + + Summons.DespawnAll(); + + if (pInstance) + { + pInstance->SetData(DATA_THELURKERBELOWEVENT, NOT_STARTED); + pInstance->SetData(DATA_STRANGE_POOL, NOT_STARTED); + } + DoCast(me, SPELL_SUBMERGE);//submerge anim + me->SetVisibility(VISIBILITY_OFF);//we start invis under water, submerged + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_THELURKERBELOWEVENT, DONE); + + Summons.DespawnAll(); + } + + void EnterCombat(Unit * who) + { + if (pInstance) + pInstance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS); + Scripted_NoMovementAI::EnterCombat(who); + } + + void MoveInLineOfSight(Unit *who) + { + if (!CanStartEvent)//boss is invisible, don't attack + return; + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) + { + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius)) + { + AttackStart(who); + } + } + } + + void MovementInform(uint32 type, uint32 /*id*/) + { + if (type == ROTATE_MOTION_TYPE) + me->SetReactState(REACT_AGGRESSIVE); + } + + void UpdateAI(const uint32 diff) + { + if (!CanStartEvent)//boss is invisible, don't attack + { + if (CheckCanStart()) + { + if (Submerged) + { + me->SetVisibility(VISIBILITY_ON); + Submerged = false; + WaitTimer2 = 500; + } + if (!Submerged && WaitTimer2 <= diff)//wait 500ms before emerge anim + { + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); + DoCast(me, SPELL_EMERGE, false); + WaitTimer2 = 60000;//never reached + WaitTimer = 3000; + } else WaitTimer2 -= diff; + + if (WaitTimer <= diff)//wait 3secs for emerge anim, then attack + { + WaitTimer = 3000; + CanStartEvent=true;//fresh fished from pool + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } else WaitTimer -= diff; + } + return; + } + + if (me->getThreatManager().getThreatList().empty())//check if should evade + { + if (me->isInCombat()) + EnterEvadeMode(); + return; + } + if (!Submerged) + { + if (PhaseTimer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUBMERGE); + PhaseTimer = 60000;//60secs submerged + Submerged = true; + } else PhaseTimer-=diff; + + if (SpoutTimer <= diff) + { + me->MonsterTextEmote(EMOTE_SPOUT,0,true); + me->SetReactState(REACT_PASSIVE); + me->GetMotionMaster()->MoveRotate(20000, rand()%2 ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); + SpoutTimer = 45000; + WhirlTimer = 20000;//whirl directly after spout + RotTimer = 20000; + return; + } else SpoutTimer -= diff; + + //Whirl directly after a Spout and at random times + if (WhirlTimer <= diff) + { + WhirlTimer = 18000; + DoCast(me, SPELL_WHIRL); + } else WhirlTimer -= diff; + + if (CheckTimer <= diff)//check if there are players in melee range + { + InRange = false; + Map* pMap = me->GetMap(); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + if (!PlayerList.isEmpty()) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (me->IsWithinMeleeRange(i->getSource())) + InRange = true; + } + } + CheckTimer = 2000; + } else CheckTimer -= diff; + + if (RotTimer) + { + Map* pMap = me->GetMap(); + if (pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource() && i->getSource()->isAlive() && me->HasInArc((double)diff/20000*(double)M_PI*2,i->getSource()) && me->IsWithinDist(i->getSource(), SPOUT_DIST) && !i->getSource()->IsInWater()) + DoCast(i->getSource(), SPELL_SPOUT, true);//only knock back palyers in arc, in 100yards, not in water + } + } + + if (SpoutAnimTimer <= diff) + { + DoCast(me, SPELL_SPOUT_ANIM, true); + SpoutAnimTimer = 1000; + } else SpoutAnimTimer -= diff; + + if (RotTimer <= diff) + { + RotTimer = 0; + } else RotTimer -= diff; + return; + } + + if (GeyserTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); + if (!pTarget && me->getVictim()) + pTarget = me->getVictim(); + if (pTarget) + DoCast(pTarget, SPELL_GEYSER, true); + GeyserTimer = rand()%5000 + 15000; + } else GeyserTimer -= diff; + + if (!InRange)//if on players in melee range cast Waterbolt + { + if (WaterboltTimer <= diff) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + if (!pTarget && me->getVictim()) + pTarget = me->getVictim(); + if (pTarget) + DoCast(pTarget, SPELL_WATERBOLT, true); + WaterboltTimer = 3000; + } else WaterboltTimer -= diff; + } + + if (!UpdateCombatState()) + return; + + DoMeleeAttackIfReady(); + + }else//submerged + { + if (PhaseTimer <= diff) + { + Submerged = false; + me->InterruptNonMeleeSpells(false);//shouldn't be any + me->RemoveAllAuras(); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); + DoCast(me, SPELL_EMERGE, true); + Spawned = false; + SpoutTimer = 3000; // directly cast Spout after emerging! + PhaseTimer = 120000; + return; + } else PhaseTimer-=diff; + + if (me->getThreatManager().getThreatList().empty())//check if should evade + { + EnterEvadeMode(); + return; + } + if (!me->isInCombat()) + DoZoneInCombat(); + + if (!Spawned) + { + me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + //spawn adds + for (uint8 i = 0; i < 9; ++i) + { + Creature* Summoned; + if (i < 6) + Summoned = me->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + else Summoned = me->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + + if (Summoned) + Summons.Summon(Summoned); + } + Spawned = true; + } + } + } + }; + +CreatureAI* GetAI_mob_coilfang_guardian(Creature* pCreature) +{ + SimpleAI* ai = new SimpleAI (pCreature); + + ai->Spell[0].Enabled = true; + ai->Spell[0].Spell_Id = SPELL_ARCINGSMASH; + ai->Spell[0].Cooldown = 15000; + ai->Spell[0].First_Cast = 5000; + ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; + + ai->Spell[1].Enabled = true; + ai->Spell[1].Spell_Id = SPELL_HAMSTRING; + ai->Spell[1].Cooldown = 10000; + ai->Spell[1].First_Cast = 2000; + ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; + + return ai; +} + +struct mob_coilfang_ambusherAI : public Scripted_NoMovementAI +{ + mob_coilfang_ambusherAI(Creature *c) : Scripted_NoMovementAI(c) + { + SpellEntry *TempSpell = GET_SPELL(SPELL_SHOOT); + if (TempSpell) + TempSpell->Effect[0] = 2;//change spell effect from weapon % dmg to simple phisical dmg + } + + uint32 MultiShotTimer; + uint32 ShootBowTimer; + + void Reset() + { + MultiShotTimer = 10000; + ShootBowTimer = 4000; + + } + + void EnterCombat(Unit * /*who*/) + { + + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who) && me->IsWithinDistInMap(who, 45)) + { + AttackStart(who); + } + } + + void UpdateAI(const uint32 diff) + { + if (MultiShotTimer <= diff) + { + if (me->getVictim()) + DoCast(me->getVictim(), SPELL_SPREAD_SHOT, true); + + MultiShotTimer = 10000+rand()%10000; + ShootBowTimer += 1500;//add global cooldown + } else MultiShotTimer -= diff; + + if (ShootBowTimer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + int bp0 = 1100; + if (pTarget) + me->CastCustomSpell(pTarget,SPELL_SHOOT,&bp0,NULL,NULL,true); + ShootBowTimer = 4000+rand()%5000; + MultiShotTimer += 1500;//add global cooldown + } else ShootBowTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_coilfang_ambusher(Creature* pCreature) +{ + return new mob_coilfang_ambusherAI (pCreature); +} + +CreatureAI* GetAI_boss_the_lurker_below(Creature* pCreature) +{ + return new boss_the_lurker_belowAI (pCreature); +} + +void AddSC_boss_the_lurker_below() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_lurker_below"; + newscript->GetAI = &GetAI_boss_the_lurker_below; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_guardian"; + newscript->GetAI = &GetAI_mob_coilfang_guardian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_ambusher"; + newscript->GetAI = &GetAI_mob_coilfang_ambusher; + newscript->RegisterSelf(); +} + + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp new file mode 100644 index 00000000000..14c87aee141 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_morogrim_tidewalker.cpp @@ -0,0 +1,369 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Morogrim_Tidewalker +SD%Complete: 90 +SDComment: Water globules don't explode properly, remove hacks +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define SAY_AGGRO -1548030 +#define SAY_SUMMON1 -1548031 +#define SAY_SUMMON2 -1548032 +#define SAY_SUMMON_BUBL1 -1548033 +#define SAY_SUMMON_BUBL2 -1548034 +#define SAY_SLAY1 -1548035 +#define SAY_SLAY2 -1548036 +#define SAY_SLAY3 -1548037 +#define SAY_DEATH -1548038 +#define EMOTE_WATERY_GRAVE -1548039 +#define EMOTE_EARTHQUAKE -1548040 +#define EMOTE_WATERY_GLOBULES -1548041 + +#define SPELL_TIDAL_WAVE 37730 +#define SPELL_WATERY_GRAVE 38049 +#define SPELL_EARTHQUAKE 37764 +#define SPELL_WATERY_GRAVE_EXPLOSION 37852 + +#define WATERY_GRAVE_X1 334.64 +#define WATERY_GRAVE_Y1 -728.89 +#define WATERY_GRAVE_Z1 -14.42 +#define WATERY_GRAVE_X2 365.51 +#define WATERY_GRAVE_Y2 -737.14 +#define WATERY_GRAVE_Z2 -14.44 +#define WATERY_GRAVE_X3 366.19 +#define WATERY_GRAVE_Y3 -709.59 +#define WATERY_GRAVE_Z3 -14.36 +#define WATERY_GRAVE_X4 372.93 +#define WATERY_GRAVE_Y4 -690.96 +#define WATERY_GRAVE_Z4 -14.44 + +#define SPELL_WATERY_GRAVE_1 38023 +#define SPELL_WATERY_GRAVE_2 38024 +#define SPELL_WATERY_GRAVE_3 38025 +#define SPELL_WATERY_GRAVE_4 37850 + +#define SPELL_SUMMON_WATER_GLOBULE_1 37854 +#define SPELL_SUMMON_WATER_GLOBULE_2 37858 +#define SPELL_SUMMON_WATER_GLOBULE_3 37860 +#define SPELL_SUMMON_WATER_GLOBULE_4 37861 + +/*#define SPELL_SUMMON_MURLOC_A6 39813 +#define SPELL_SUMMON_MURLOC_A7 39814 +#define SPELL_SUMMON_MURLOC_A8 39815 +#define SPELL_SUMMON_MURLOC_A9 39816 +#define SPELL_SUMMON_MURLOC_A10 39817 + +#define SPELL_SUMMON_MURLOC_B6 39818 +#define SPELL_SUMMON_MURLOC_B7 39819 +#define SPELL_SUMMON_MURLOC_B8 39820 +#define SPELL_SUMMON_MURLOC_B9 39821 +#define SPELL_SUMMON_MURLOC_B10 39822*/ + +float MurlocCords[10][5] = +{ + {21920, 424.36, -715.4, -7.14, 0.124}, + {21920, 425.13, -719.3, -7.14, 0.124}, + {21920, 425.05, -724.23, -7.14, 0.124}, + {21920, 424.91, -728.68, -7.14, 0.124}, + {21920, 424.84, -732.18, -7.14, 0.124}, + {21920, 321.05, -734.2, -13.15, 0.124}, + {21920, 321.05, -729.4, -13.15, 0.124}, + {21920, 321.05, -724.03, -13.15, 0.124}, + {21920, 321.05, -718.73, -13.15, 0.124}, + {21920, 321.05, -714.24, -13.15, 0.124} +}; + +//Creatures +#define WATER_GLOBULE 21913 +#define TIDEWALKER_LURKER 21920 + +//Morogrim Tidewalker AI +struct boss_morogrim_tidewalkerAI : public ScriptedAI +{ + boss_morogrim_tidewalkerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + Map::PlayerList const *PlayerList; + + uint32 TidalWave_Timer; + uint32 WateryGrave_Timer; + uint32 Earthquake_Timer; + uint32 WateryGlobules_Timer; + uint32 globulespell[4]; + int8 Playercount; + int8 counter; + + bool Earthquake; + bool Phase2; + + void Reset() + { + TidalWave_Timer = 10000; + WateryGrave_Timer = 30000; + Earthquake_Timer = 40000; + WateryGlobules_Timer = 0; + globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1; + globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2; + globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3; + globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4; + + Earthquake = false; + Phase2 = false; + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); + } + + void StartEvent() + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + PlayerList = &me->GetMap()->GetPlayers(); + Playercount = PlayerList->getSize(); + StartEvent(); + } + + void ApplyWateryGrave(Unit* pPlayer, uint8 i) + { + switch(i) + { + case 0: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_1, true); break; + case 1: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_2, true); break; + case 2: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_3, true); break; + case 3: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_4, true); break; + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Earthquake_Timer + if (Earthquake_Timer <= diff) + { + if (!Earthquake) + { + DoCast(me->getVictim(), SPELL_EARTHQUAKE); + Earthquake = true; + Earthquake_Timer = 10000; + } + else + { + DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); + + for (uint8 i = 0; i < 10; ++i) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + Creature* Murloc = me->SummonCreature(MurlocCords[i][0],MurlocCords[i][1],MurlocCords[i][2],MurlocCords[i][3],MurlocCords[i][4], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); + if (pTarget && Murloc) + Murloc->AI()->AttackStart(pTarget); + } + DoScriptText(EMOTE_EARTHQUAKE, me); + Earthquake = false; + Earthquake_Timer = 40000+rand()%5000; + } + } else Earthquake_Timer -= diff; + + //TidalWave_Timer + if (TidalWave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_TIDAL_WAVE); + TidalWave_Timer = 20000; + } else TidalWave_Timer -= diff; + + if (!Phase2) + { + //WateryGrave_Timer + if (WateryGrave_Timer <= diff) + { + //Teleport 4 players under the waterfalls + Unit *pTarget; + using std::set; + setlist; + set::const_iterator itr; + for (uint8 i = 0; i < 4; ++i) + { + counter = 0; + do + { + pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only + if (counter < Playercount) + break; + if (pTarget) + itr = list.find(pTarget->GetGUID()); + ++counter; + } while (itr != list.end()); + + if (pTarget) + { + list.insert(pTarget->GetGUID()); + ApplyWateryGrave(pTarget, i); + } + } + + DoScriptText(RAND(SAY_SUMMON_BUBL1,SAY_SUMMON_BUBL2), me); + + DoScriptText(EMOTE_WATERY_GRAVE, me); + WateryGrave_Timer = 30000; + } else WateryGrave_Timer -= diff; + + //Start Phase2 + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) + Phase2 = true; + } + else + { + //WateryGlobules_Timer + if (WateryGlobules_Timer <= diff) + { + Unit* pGlobuleTarget; + using std::set; + setglobulelist; + set::const_iterator itr; + for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD + { + counter = 0; + do { + pGlobuleTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); + if (pGlobuleTarget) + itr = globulelist.find(pGlobuleTarget->GetGUID()); + if (counter > Playercount) + break; + ++counter; + } while (itr != globulelist.end()); + if (pGlobuleTarget) + globulelist.insert(pGlobuleTarget->GetGUID()); + pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true); + } + DoScriptText(EMOTE_WATERY_GLOBULES, me); + WateryGlobules_Timer = 25000; + } else WateryGlobules_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +//Water Globule AI +#define SPELL_GLOBULE_EXPLOSION 37871 + +struct mob_water_globuleAI : public ScriptedAI +{ + mob_water_globuleAI(Creature *c) : ScriptedAI(c) {} + + uint32 Check_Timer; + + void Reset() + { + Check_Timer = 1000; + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + } + + void EnterCombat(Unit * /*who*/) {} + + void MoveInLineOfSight(Unit *who) + { + if (!who || me->getVictim()) + return; + + if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) + { + //no attack radius check - it attacks the first target that moves in his los + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Check_Timer <= diff) + { + if (me->IsWithinDistInMap(me->getVictim(), 5)) + { + DoCast(me->getVictim(), SPELL_GLOBULE_EXPLOSION); + + //despawn + me->ForcedDespawn(); + return; + } + Check_Timer = 500; + } else Check_Timer -= diff; + + //do NOT deal any melee damage to the target. + } +}; + +CreatureAI* GetAI_boss_morogrim_tidewalker(Creature* pCreature) +{ + return new boss_morogrim_tidewalkerAI (pCreature); +} +CreatureAI* GetAI_mob_water_globule(Creature* pCreature) +{ + return new mob_water_globuleAI (pCreature); +} + +void AddSC_boss_morogrim_tidewalker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_morogrim_tidewalker"; + newscript->GetAI = &GetAI_boss_morogrim_tidewalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_water_globule"; + newscript->GetAI = &GetAI_mob_water_globule; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp new file mode 100644 index 00000000000..c80afae15c7 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/instance_serpent_shrine.cpp @@ -0,0 +1,398 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Serpent_Shrine +SD%Complete: 100 +SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Serpent Shrine Scripts +SDCategory: Coilfang Resevoir, Serpent Shrine Cavern +EndScriptData */ + +#include "ScriptedPch.h" +#include "serpent_shrine.h" + +#define MAX_ENCOUNTER 6 +#define SPELL_SCALDINGWATER 37284 +#define MOB_COILFANG_FRENZY 21508 +#define TRASHMOB_COILFANG_PRIESTESS 21220 //6*2 +#define TRASHMOB_COILFANG_SHATTERER 21301 //6*3 + +#define MIN_KILLS 30 + +//NOTE: there are 6 platforms +//there should be 3 shatterers and 2 priestess on all platforms, total of 30 elites, else it won't work! +//delete all other elites not on platforms! these mobs should only be on those platforms nowhere else. + +/* Serpentshrine cavern encounters: +0 - Hydross The Unstable event +1 - Leotheras The Blind Event +2 - The Lurker Below Event +3 - Fathom-Lord Karathress Event +4 - Morogrim Tidewalker Event +5 - Lady Vashj Event +*/ + +bool GOHello_go_bridge_console(Player* /*pPlayer*/, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + + if (!pInstance) + return false; + + if (pInstance) + pInstance->SetData(DATA_CONTROL_CONSOLE, DONE); + + return true; +} + +struct instance_serpentshrine_cavern : public ScriptedInstance +{ + instance_serpentshrine_cavern(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 LurkerBelow; + uint64 Sharkkis; + uint64 Tidalvess; + uint64 Caribdis; + uint64 LadyVashj; + uint64 Karathress; + uint64 KarathressEvent_Starter; + uint64 LeotherasTheBlind; + uint64 LeotherasEventStarter; + + uint64 ControlConsole; + uint64 BridgePart[3]; + uint32 StrangePool; + uint32 FishingTimer; + uint32 LurkerSubEvent; + uint32 WaterCheckTimer; + uint32 FrenzySpawnTimer; + uint32 Water; + uint32 TrashCount; + + bool ShieldGeneratorDeactivated[4]; + uint32 m_auiEncounter[MAX_ENCOUNTER]; + bool DoSpawnFrenzy; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + LurkerBelow = 0; + Sharkkis = 0; + Tidalvess = 0; + Caribdis = 0; + LadyVashj = 0; + Karathress = 0; + KarathressEvent_Starter = 0; + LeotherasTheBlind = 0; + LeotherasEventStarter = 0; + + ControlConsole = 0; + BridgePart[0] = 0; + BridgePart[1] = 0; + BridgePart[2] = 0; + StrangePool = 0; + Water = WATERSTATE_FRENZY; + + ShieldGeneratorDeactivated[0] = false; + ShieldGeneratorDeactivated[1] = false; + ShieldGeneratorDeactivated[2] = false; + ShieldGeneratorDeactivated[3] = false; + FishingTimer = 1000; + LurkerSubEvent = 0; + WaterCheckTimer = 500; + FrenzySpawnTimer = 2000; + DoSpawnFrenzy = false; + TrashCount = 0; + + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void Update (uint32 diff) + { + //Lurker Fishing event + if (LurkerSubEvent == LURKER_FISHING) + { + if (FishingTimer <= diff) + { + LurkerSubEvent = LURKER_HOOKED; + SetData(DATA_STRANGE_POOL, IN_PROGRESS);//just fished, signal Lurker script to emerge and start fight, we use IN_PROGRESS so it won't get saved and lurker will be alway invis at start if server restarted + } else FishingTimer -= diff; + } + //Water checks + if (WaterCheckTimer <= diff) + { + if (TrashCount >= MIN_KILLS) + Water = WATERSTATE_SCALDING; + else + Water = WATERSTATE_FRENZY; + + Map::PlayerList const &PlayerList = instance->GetPlayers(); + if (PlayerList.isEmpty()) + return; + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer->isAlive() && /*i->getSource()->GetPositionZ() <= -21.434931f*/pPlayer->IsInWater()) + { + if (Water == WATERSTATE_SCALDING) + { + + if (!pPlayer->HasAura(SPELL_SCALDINGWATER)) + { + pPlayer->CastSpell(pPlayer, SPELL_SCALDINGWATER,true); + } + } else if (Water == WATERSTATE_FRENZY) + { + //spawn frenzy + if (DoSpawnFrenzy) + { + if (Creature* frenzy = pPlayer->SummonCreature(MOB_COILFANG_FRENZY,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ(),pPlayer->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,2000)) + { + frenzy->Attack(pPlayer,false); + frenzy->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); + } + DoSpawnFrenzy = false; + } + } + } + if (!pPlayer->IsInWater()) + pPlayer->RemoveAurasDueToSpell(SPELL_SCALDINGWATER); + } + + } + WaterCheckTimer = 500;//remove stress from core + } else WaterCheckTimer -= diff; + if (FrenzySpawnTimer <= diff) + { + DoSpawnFrenzy = true; + FrenzySpawnTimer = 2000; + } else FrenzySpawnTimer -= diff; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 184568: + ControlConsole = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184203: + BridgePart[0] = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184204: + BridgePart[1] = pGo->GetGUID(); + pGo->setActive(true); + break; + + case 184205: + BridgePart[2] = pGo->GetGUID(); + pGo->setActive(true); + break; + case GAMEOBJECT_FISHINGNODE_ENTRY://no way checking if fish is hooked, so we create a timed event + if (LurkerSubEvent == LURKER_NOT_STARTED) + { + FishingTimer = 10000+rand()%30000;//random time before lurker emerges + LurkerSubEvent = LURKER_FISHING; + } + break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 21212: LadyVashj = pCreature->GetGUID(); break; + case 21214: Karathress = pCreature->GetGUID(); break; + case 21966: Sharkkis = pCreature->GetGUID(); break; + case 21217: LurkerBelow = pCreature->GetGUID(); break; + case 21965: Tidalvess = pCreature->GetGUID(); break; + case 21964: Caribdis = pCreature->GetGUID(); break; + case 21215: LeotherasTheBlind = pCreature->GetGUID(); break; + /*case TRASHMOB_COILFANG_PRIESTESS: + case TRASHMOB_COILFANG_SHATTERER: + if (pCreature->isAlive()) + ++TrashCount; + break;*/ + } + } + + void SetData64(uint32 type, uint64 data) + { + if (type == DATA_KARATHRESSEVENT_STARTER) + KarathressEvent_Starter = data; + if (type == DATA_LEOTHERAS_EVENT_STARTER) + LeotherasEventStarter = data; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_THELURKERBELOW: return LurkerBelow; + case DATA_SHARKKIS: return Sharkkis; + case DATA_TIDALVESS: return Tidalvess; + case DATA_CARIBDIS: return Caribdis; + case DATA_LADYVASHJ: return LadyVashj; + case DATA_KARATHRESS: return Karathress; + case DATA_KARATHRESSEVENT_STARTER: return KarathressEvent_Starter; + case DATA_LEOTHERAS: return LeotherasTheBlind; + case DATA_LEOTHERAS_EVENT_STARTER: return LeotherasEventStarter; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_STRANGE_POOL: + { + StrangePool = data; + if (data == NOT_STARTED) + LurkerSubEvent = LURKER_NOT_STARTED; + } + break; + case DATA_CONTROL_CONSOLE: + if (data == DONE) + { + HandleGameObject(BridgePart[0], true); + HandleGameObject(BridgePart[0], true); + HandleGameObject(BridgePart[0], true); + } + ControlConsole = data;break; + case DATA_TRASH : + { + if (data == 1 && TrashCount < MIN_KILLS) + ++TrashCount;//+1 died + SaveToDB(); + break; + } + case DATA_WATER : Water = data;break; + case DATA_HYDROSSTHEUNSTABLEEVENT: m_auiEncounter[0] = data; break; + case DATA_LEOTHERASTHEBLINDEVENT: m_auiEncounter[1] = data; break; + case DATA_THELURKERBELOWEVENT: m_auiEncounter[2] = data; break; + case DATA_KARATHRESSEVENT: m_auiEncounter[3] = data; break; + case DATA_MOROGRIMTIDEWALKEREVENT: m_auiEncounter[4] = data; break; + //Lady Vashj + case DATA_LADYVASHJEVENT: + if (data == NOT_STARTED) + { + ShieldGeneratorDeactivated[0] = false; + ShieldGeneratorDeactivated[1] = false; + ShieldGeneratorDeactivated[2] = false; + ShieldGeneratorDeactivated[3] = false; + } + m_auiEncounter[5] = data; break; + case DATA_SHIELDGENERATOR1:ShieldGeneratorDeactivated[0] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR2:ShieldGeneratorDeactivated[1] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR3:ShieldGeneratorDeactivated[2] = (data) ? true : false; break; + case DATA_SHIELDGENERATOR4:ShieldGeneratorDeactivated[3] = (data) ? true : false; break; + } + + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_HYDROSSTHEUNSTABLEEVENT: return m_auiEncounter[0]; + case DATA_LEOTHERASTHEBLINDEVENT: return m_auiEncounter[1]; + case DATA_THELURKERBELOWEVENT: return m_auiEncounter[2]; + case DATA_KARATHRESSEVENT: return m_auiEncounter[3]; + case DATA_MOROGRIMTIDEWALKEREVENT: return m_auiEncounter[4]; + //Lady Vashj + case DATA_LADYVASHJEVENT: return m_auiEncounter[5]; + case DATA_SHIELDGENERATOR1: return ShieldGeneratorDeactivated[0]; + case DATA_SHIELDGENERATOR2: return ShieldGeneratorDeactivated[1]; + case DATA_SHIELDGENERATOR3: return ShieldGeneratorDeactivated[2]; + case DATA_SHIELDGENERATOR4: return ShieldGeneratorDeactivated[3]; + case DATA_CANSTARTPHASE3: + if (ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3])return 1;break; + case DATA_STRANGE_POOL: return StrangePool; + case DATA_WATER: return Water; + } + return 0; + } + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << TrashCount; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + >> m_auiEncounter[4] >> m_auiEncounter[5] >> TrashCount; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_serpentshrine_cavern(Map* pMap) +{ + return new instance_serpentshrine_cavern(pMap); +} + +void AddSC_instance_serpentshrine_cavern() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "instance_serpent_shrine"; + newscript->GetInstanceData = &GetInstanceData_instance_serpentshrine_cavern; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_bridge_console"; + newscript->pGOHello = &GOHello_go_bridge_console; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h new file mode 100644 index 00000000000..adfa39dc7e0 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/serpent_shrine.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SERPENT_SHRINE_H +#define DEF_SERPENT_SHRINE_H +enum LurkerEventState +{ + LURKER_NOT_STARTED = 0, + LURKER_FISHING = 1, + LURKER_HOOKED = 2 +}; +enum WaterEventState +{ + WATERSTATE_NONE = 0, + WATERSTATE_FRENZY = 1, + WATERSTATE_SCALDING = 2 +}; +#define DATA_CANSTARTPHASE3 1 +#define DATA_CARIBDIS 2 +#define DATA_HYDROSSTHEUNSTABLEEVENT 3 +#define DATA_KARATHRESS 4 +#define DATA_KARATHRESSEVENT 5 +#define DATA_KARATHRESSEVENT_STARTER 6 +#define DATA_LADYVASHJ 7 +#define DATA_LADYVASHJEVENT 8 +#define DATA_LEOTHERASTHEBLINDEVENT 9 +#define DATA_MOROGRIMTIDEWALKEREVENT 10 +#define DATA_SHARKKIS 11 +#define DATA_SHIELDGENERATOR1 12 +#define DATA_SHIELDGENERATOR2 13 +#define DATA_SHIELDGENERATOR3 14 +#define DATA_SHIELDGENERATOR4 15 +#define DATA_THELURKERBELOW 16 +#define DATA_THELURKERBELOWEVENT 17 +#define DATA_TIDALVESS 18 +#define DATA_FATHOMLORDKARATHRESSEVENT 19 +#define DATA_LEOTHERAS 20 +#define DATA_LEOTHERAS_EVENT_STARTER 21 +#define DATA_CONTROL_CONSOLE 22 +#define DATA_STRANGE_POOL 23 +#define DATA_WATER 24 +#define DATA_TRASH 25 +#endif + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp new file mode 100644 index 00000000000..8e1b438bdc5 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_hydromancer_thespia.cpp @@ -0,0 +1,187 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Hydromancer_Thespia +SD%Complete: 80 +SDComment: Needs additional adjustments (when instance script is adjusted) +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +/* ContentData +boss_hydromancer_thespia +mob_coilfang_waterelemental +EndContentData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_SUMMON -1545000 +#define SAY_AGGRO_1 -1545001 +#define SAY_AGGRO_2 -1545002 +#define SAY_AGGRO_3 -1545003 +#define SAY_SLAY_1 -1545004 +#define SAY_SLAY_2 -1545005 +#define SAY_DEAD -1545006 + +#define SPELL_LIGHTNING_CLOUD 25033 +#define SPELL_LUNG_BURST 31481 +#define SPELL_ENVELOPING_WINDS 31718 + +struct boss_thespiaAI : public ScriptedAI +{ + boss_thespiaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 LightningCloud_Timer; + uint32 LungBurst_Timer; + uint32 EnvelopingWinds_Timer; + + void Reset() + { + LightningCloud_Timer = 15000; + LungBurst_Timer = 7000; + EnvelopingWinds_Timer = 9000; + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, NOT_STARTED); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEAD, me); + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (pInstance) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //LightningCloud_Timer + if (LightningCloud_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LIGHTNING_CLOUD); + + //cast twice in Heroic mode + if (IsHeroic()) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LIGHTNING_CLOUD); + + LightningCloud_Timer = 15000+rand()%10000; + } else LightningCloud_Timer -=diff; + + //LungBurst_Timer + if (LungBurst_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_LUNG_BURST); + LungBurst_Timer = 7000+rand()%5000; + } else LungBurst_Timer -=diff; + + //EnvelopingWinds_Timer + if (EnvelopingWinds_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ENVELOPING_WINDS); + + //cast twice in Heroic mode + if (IsHeroic()) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_ENVELOPING_WINDS); + EnvelopingWinds_Timer = 10000+rand()%5000; + } else EnvelopingWinds_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +#define SPELL_WATER_BOLT_VOLLEY 34449 +#define H_SPELL_WATER_BOLT_VOLLEY 37924 + +struct mob_coilfang_waterelementalAI : public ScriptedAI +{ + mob_coilfang_waterelementalAI(Creature *c) : ScriptedAI(c) {} + + uint32 WaterBoltVolley_Timer; + + void Reset() + { + WaterBoltVolley_Timer = 3000+rand()%3000; + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (WaterBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_WATER_BOLT_VOLLEY); + WaterBoltVolley_Timer = 7000+rand()%5000; + } else WaterBoltVolley_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_thespiaAI(Creature* pCreature) +{ + return new boss_thespiaAI (pCreature); +} + +CreatureAI* GetAI_mob_coilfang_waterelementalAI(Creature* pCreature) +{ + return new mob_coilfang_waterelementalAI (pCreature); +} + +void AddSC_boss_hydromancer_thespia() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_hydromancer_thespia"; + newscript->GetAI = &GetAI_boss_thespiaAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coilfang_waterelemental"; + newscript->GetAI = &GetAI_mob_coilfang_waterelementalAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp new file mode 100644 index 00000000000..f2da4058e44 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp @@ -0,0 +1,264 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Mekgineer_Steamrigger +SD%Complete: 60 +SDComment: Mechanics' interrrupt heal doesn't work very well, also a proper movement needs to be implemented -> summon further away and move towards pTarget to repair. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +/* ContentData +boss_mekgineer_steamrigger +mob_steamrigger_mechanic +EndContentData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_MECHANICS -1545007 +#define SAY_AGGRO_1 -1545008 +#define SAY_AGGRO_2 -1545009 +#define SAY_AGGRO_3 -1545010 +#define SAY_AGGRO_4 -1545011 +#define SAY_SLAY_1 -1545012 +#define SAY_SLAY_2 -1545013 +#define SAY_SLAY_3 -1545014 +#define SAY_DEATH -1545015 + +#define SPELL_SUPER_SHRINK_RAY 31485 +#define SPELL_SAW_BLADE 31486 +#define SPELL_ELECTRIFIED_NET 35107 +#define H_SPELL_ENRAGE 1 //corrent enrage spell not known + +#define ENTRY_STREAMRIGGER_MECHANIC 17951 + +struct boss_mekgineer_steamriggerAI : public ScriptedAI +{ + boss_mekgineer_steamriggerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Shrink_Timer; + uint32 Saw_Blade_Timer; + uint32 Electrified_Net_Timer; + bool Summon75; + bool Summon50; + bool Summon25; + + void Reset() + { + Shrink_Timer = 20000; + Saw_Blade_Timer = 15000; + Electrified_Net_Timer = 10000; + + Summon75 = false; + Summon50 = false; + Summon25 = false; + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, NOT_STARTED); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, DONE); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (pInstance) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, IN_PROGRESS); + } + + //no known summon spells exist + void SummonMechanichs() + { + DoScriptText(SAY_MECHANICS, me); + + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + + if (rand()%2) + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,-7,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + if (rand()%2) + DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,7,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Shrink_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SUPER_SHRINK_RAY); + Shrink_Timer = 20000; + } else Shrink_Timer -= diff; + + if (Saw_Blade_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_SAW_BLADE); + else + DoCast(me->getVictim(), SPELL_SAW_BLADE); + + Saw_Blade_Timer = 15000; + } else Saw_Blade_Timer -= diff; + + if (Electrified_Net_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ELECTRIFIED_NET); + Electrified_Net_Timer = 10000; + } + else Electrified_Net_Timer -= diff; + + if (!Summon75) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 75) + { + SummonMechanichs(); + Summon75 = true; + } + } + + if (!Summon50) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) + { + SummonMechanichs(); + Summon50 = true; + } + } + + if (!Summon25) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) + { + SummonMechanichs(); + Summon25 = true; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_mekgineer_steamrigger(Creature* pCreature) +{ + return new boss_mekgineer_steamriggerAI (pCreature); +} + +#define SPELL_DISPEL_MAGIC 17201 +#define SPELL_REPAIR 31532 +#define H_SPELL_REPAIR 37936 + +#define MAX_REPAIR_RANGE (13.0f) //we should be at least at this range for repair +#define MIN_REPAIR_RANGE (7.0f) //we can stop movement at this range to repair but not required + +struct mob_steamrigger_mechanicAI : public ScriptedAI +{ + mob_steamrigger_mechanicAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Repair_Timer; + + void Reset() + { + Repair_Timer = 2000; + } + + void MoveInLineOfSight(Unit* /*who*/) + { + //react only if attacked + } + + void EnterCombat(Unit * /*who*/) { } + + void UpdateAI(const uint32 diff) + { + if (Repair_Timer <= diff) + { + if (pInstance && pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER) && pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) + { + if (Unit* pMekgineer = Unit::GetUnit((*me), pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER))) + { + if (me->IsWithinDistInMap(pMekgineer, MAX_REPAIR_RANGE)) + { + //are we already channeling? Doesn't work very well, find better check? + if (!me->GetUInt32Value(UNIT_CHANNEL_SPELL)) + { + //me->GetMotionMaster()->MovementExpired(); + //me->GetMotionMaster()->MoveIdle(); + + DoCast(me, SPELL_REPAIR, true); + } + Repair_Timer = 5000; + } + else + { + //me->GetMotionMaster()->MovementExpired(); + //me->GetMotionMaster()->MoveFollow(pMekgineer,0,0); + } + } + } else Repair_Timer = 5000; + } else Repair_Timer -= diff; + + if (!UpdateVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_steamrigger_mechanic(Creature* pCreature) +{ + return new mob_steamrigger_mechanicAI (pCreature); +} + +void AddSC_boss_mekgineer_steamrigger() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_mekgineer_steamrigger"; + newscript->GetAI = &GetAI_boss_mekgineer_steamrigger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_steamrigger_mechanic"; + newscript->GetAI = &GetAI_mob_steamrigger_mechanic; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_warlord_kalithresh.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_warlord_kalithresh.cpp new file mode 100644 index 00000000000..f46956dda81 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/boss_warlord_kalithresh.cpp @@ -0,0 +1,204 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warlord_Kalithres +SD%Complete: 65 +SDComment: Contains workarounds regarding warlord's rage spells not acting as expected. Both scripts here require review and fine tuning. +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define SAY_INTRO -1545016 +#define SAY_REGEN -1545017 +#define SAY_AGGRO1 -1545018 +#define SAY_AGGRO2 -1545019 +#define SAY_AGGRO3 -1545020 +#define SAY_SLAY1 -1545021 +#define SAY_SLAY2 -1545022 +#define SAY_DEATH -1545023 + +#define SPELL_SPELL_REFLECTION 31534 +#define SPELL_IMPALE 39061 +#define SPELL_WARLORDS_RAGE 37081 +#define SPELL_WARLORDS_RAGE_NAGA 31543 + +#define SPELL_WARLORDS_RAGE_PROC 36453 + +struct mob_naga_distillerAI : public ScriptedAI +{ + mob_naga_distillerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + //hack, due to really weird spell behaviour :( + if (pInstance) + { + if (pInstance->GetData(TYPE_DISTILLER) == IN_PROGRESS) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + } + + void EnterCombat(Unit * /*who*/) { } + + void StartRageGen(Unit * /*caster*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + DoCast(me, SPELL_WARLORDS_RAGE_NAGA, true); + + if (pInstance) + pInstance->SetData(TYPE_DISTILLER,IN_PROGRESS); + } + + void DamageTaken(Unit * /*done_by*/, uint32 &damage) + { + if (me->GetHealth() <= damage) + if (pInstance) + pInstance->SetData(TYPE_DISTILLER,DONE); + } +}; + +struct boss_warlord_kalithreshAI : public ScriptedAI +{ + boss_warlord_kalithreshAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 Reflection_Timer; + uint32 Impale_Timer; + uint32 Rage_Timer; + bool CanRage; + + void Reset() + { + Reflection_Timer = 10000; + Impale_Timer = 7000+rand()%7000; + Rage_Timer = 45000; + CanRage = false; + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, NOT_STARTED); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void SpellHit(Unit * /*caster*/, const SpellEntry *spell) + { + //hack :( + if (spell->Id == SPELL_WARLORDS_RAGE_PROC) + if (pInstance) + if (pInstance->GetData(TYPE_DISTILLER) == DONE) + me->RemoveAurasDueToSpell(SPELL_WARLORDS_RAGE_PROC); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(TYPE_WARLORD_KALITHRESH, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Rage_Timer <= diff) + { + if (Creature* distiller = me->FindNearestCreature(17954, 100.0f)) + { + DoScriptText(SAY_REGEN, me); + DoCast(me, SPELL_WARLORDS_RAGE); + CAST_AI(mob_naga_distillerAI, distiller->AI())->StartRageGen(me); + } + Rage_Timer = 3000+rand()%15000; + } else Rage_Timer -= diff; + + //Reflection_Timer + if (Reflection_Timer <= diff) + { + DoCast(me, SPELL_SPELL_REFLECTION); + Reflection_Timer = 15000+rand()%10000; + } else Reflection_Timer -= diff; + + //Impale_Timer + if (Impale_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_IMPALE); + + Impale_Timer = 7500+rand()%5000; + } else Impale_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_naga_distiller(Creature* pCreature) +{ + return new mob_naga_distillerAI (pCreature); +} + +CreatureAI* GetAI_boss_warlord_kalithresh(Creature* pCreature) +{ + return new boss_warlord_kalithreshAI (pCreature); +} + +void AddSC_boss_warlord_kalithresh() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_naga_distiller"; + newscript->GetAI = &GetAI_mob_naga_distiller; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_warlord_kalithresh"; + newscript->GetAI = &GetAI_boss_warlord_kalithresh; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp new file mode 100644 index 00000000000..188a23738f5 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/instance_steam_vault.cpp @@ -0,0 +1,231 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Steam_Vault +SD%Complete: 80 +SDComment: Instance script and access panel GO +SDCategory: Coilfang Resevoir, The Steamvault +EndScriptData */ + +#include "ScriptedPch.h" +#include "steam_vault.h" + +#define MAX_ENCOUNTER 4 + +#define MAIN_CHAMBERS_DOOR 183049 +#define ACCESS_PANEL_HYDRO 184125 +#define ACCESS_PANEL_MEK 184126 + +/* Steam Vaults encounters: +1 - Hydromancer Thespia Event +2 - Mekgineer Steamrigger Event +3 - Warlord Kalithresh Event +*/ + +bool GOHello_go_main_chambers_access_panel(Player* /*pPlayer*/, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + + if (!pInstance) + return false; + + if (pGo->GetEntry() == ACCESS_PANEL_HYDRO && (pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == DONE || pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL)) + pInstance->SetData(TYPE_HYDROMANCER_THESPIA,SPECIAL); + + if (pGo->GetEntry() == ACCESS_PANEL_MEK && (pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == DONE || pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL)) + pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER,SPECIAL); + + return true; +} + +struct instance_steam_vault : public ScriptedInstance +{ + instance_steam_vault(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 ThespiaGUID; + uint64 MekgineerGUID; + uint64 KalithreshGUID; + + uint64 MainChambersDoor; + uint64 AccessPanelHydro; + uint64 AccessPanelMek; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + ThespiaGUID = 0; + MekgineerGUID = 0; + KalithreshGUID = 0; + MainChambersDoor = 0; + AccessPanelHydro = 0; + AccessPanelMek = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17797: ThespiaGUID = pCreature->GetGUID(); break; + case 17796: MekgineerGUID = pCreature->GetGUID(); break; + case 17798: KalithreshGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case MAIN_CHAMBERS_DOOR: MainChambersDoor = pGo->GetGUID(); break; + case ACCESS_PANEL_HYDRO: AccessPanelHydro = pGo->GetGUID(); break; + case ACCESS_PANEL_MEK: AccessPanelMek = pGo->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_HYDROMANCER_THESPIA: + if (data == SPECIAL) + { + HandleGameObject(AccessPanelHydro, true); + + if (GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL) + HandleGameObject(MainChambersDoor, true); + + debug_log("TSCR: Instance Steamvault: Access panel used."); + } + m_auiEncounter[0] = data; + break; + case TYPE_MEKGINEER_STEAMRIGGER: + if (data == SPECIAL) + { + HandleGameObject(AccessPanelMek, true); + + if (GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL) + HandleGameObject(MainChambersDoor, true); + + debug_log("TSCR: Instance Steamvault: Access panel used."); + } + m_auiEncounter[1] = data; + break; + case TYPE_WARLORD_KALITHRESH: + m_auiEncounter[2] = data; + break; + case TYPE_DISTILLER: + m_auiEncounter[3] = data; + break; + } + + if (data == DONE || data == SPECIAL) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_HYDROMANCER_THESPIA: + return m_auiEncounter[0]; + case TYPE_MEKGINEER_STEAMRIGGER: + return m_auiEncounter[1]; + case TYPE_WARLORD_KALITHRESH: + return m_auiEncounter[2]; + case TYPE_DISTILLER: + return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THESPIA: + return ThespiaGUID; + case DATA_MEKGINEERSTEAMRIGGER: + return MekgineerGUID; + case DATA_KALITRESH: + return KalithreshGUID; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_steam_vault(Map* pMap) +{ + return new instance_steam_vault(pMap); +} + +void AddSC_instance_steam_vault() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_main_chambers_access_panel"; + newscript->pGOHello = &GOHello_go_main_chambers_access_panel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "instance_steam_vault"; + newscript->GetInstanceData = &GetInstanceData_instance_steam_vault; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h new file mode 100644 index 00000000000..4b407ac4816 --- /dev/null +++ b/src/server/scripts/Outland/CoilfangReservoir/SteamVault/steam_vault.h @@ -0,0 +1,17 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_STEAM_VAULT_H +#define DEF_STEAM_VAULT_H + +#define TYPE_HYDROMANCER_THESPIA 1 +#define TYPE_MEKGINEER_STEAMRIGGER 2 +#define TYPE_WARLORD_KALITHRESH 3 +#define TYPE_DISTILLER 4 + +#define DATA_MEKGINEERSTEAMRIGGER 5 +#define DATA_KALITRESH 6 +#define DATA_THESPIA 7 +#endif + diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp deleted file mode 100644 index 69a969adda0..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_fathomlord_karathress.cpp +++ /dev/null @@ -1,746 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Fathomlord_Karathress -SD%Complete: 70 -SDComment: Cyclone workaround -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedEscortAI.h" - -#define SAY_AGGRO -1548021 -#define SAY_GAIN_BLESSING -1548022 -#define SAY_GAIN_ABILITY1 -1548023 -#define SAY_GAIN_ABILITY2 -1548024 -#define SAY_GAIN_ABILITY3 -1548025 -#define SAY_SLAY1 -1548026 -#define SAY_SLAY2 -1548027 -#define SAY_SLAY3 -1548028 -#define SAY_DEATH -1548029 - -//Karathress spells -#define SPELL_CATACLYSMIC_BOLT 38441 -#define SPELL_POWER_OF_SHARKKIS 38455 -#define SPELL_POWER_OF_TIDALVESS 38452 -#define SPELL_POWER_OF_CARIBDIS 38451 -#define SPELL_ENRAGE 24318 -#define SPELL_SEAR_NOVA 38445 -#define SPELL_BLESSING_OF_THE_TIDES 38449 - -//Sharkkis spells -#define SPELL_LEECHING_THROW 29436 -#define SPELL_THE_BEAST_WITHIN 38373 -#define SPELL_MULTISHOT 38366 -#define SPELL_SUMMON_FATHOM_LURKER 38433 -#define SPELL_SUMMON_FATHOM_SPOREBAT 38431 -#define SPELL_PET_ENRAGE 19574 - -//Tidalvess spells -#define SPELL_FROST_SHOCK 38234 -#define SPELL_SPITFIRE_TOTEM 38236 -#define SPELL_POISON_CLEANSING_TOTEM 38306 -// Spell obsolete -// #define SPELL_POISON_CLEANSING_EFFECT 8167 -#define SPELL_EARTHBIND_TOTEM 38304 -#define SPELL_EARTHBIND_TOTEM_EFFECT 6474 -#define SPELL_WINDFURY_WEAPON 38184 - -//Caribdis Spells -#define SPELL_WATER_BOLT_VOLLEY 38335 -#define SPELL_TIDAL_SURGE 38358 -#define SPELL_TIDAL_SURGE_FREEZE 38357 -#define SPELL_HEAL 38330 -#define SPELL_SUMMON_CYCLONE 38337 -#define SPELL_CYCLONE_CYCLONE 29538 - -//Yells and Quotes -#define SAY_GAIN_BLESSING_OF_TIDES "Your overconfidence will be your undoing! Guards, lend me your strength!" -#define SOUND_GAIN_BLESSING_OF_TIDES 11278 -#define SAY_MISC "Alana be'lendor!" //don't know what use this -#define SOUND_MISC 11283 - -//Summoned Unit GUIDs -#define CREATURE_CYCLONE 22104 -#define CREATURE_FATHOM_SPOREBAT 22120 -#define CREATURE_FATHOM_LURKER 22119 -#define CREATURE_SPITFIRE_TOTEM 22091 -#define CREATURE_EARTHBIND_TOTEM 22486 -#define CREATURE_POISON_CLEANSING_TOTEM 22487 - -//entry and position for Seer Olum -#define SEER_OLUM 22820 -#define OLUM_X 446.78f -#define OLUM_Y -542.76f -#define OLUM_Z -7.54773f -#define OLUM_O 0.401581f - -//Fathom-Lord Karathress AI -struct boss_fathomlord_karathressAI : public ScriptedAI -{ - boss_fathomlord_karathressAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Advisors[0] = 0; - Advisors[1] = 0; - Advisors[2] = 0; - } - - ScriptedInstance* pInstance; - - uint32 CataclysmicBolt_Timer; - uint32 Enrage_Timer; - uint32 SearNova_Timer; - - bool BlessingOfTides; - - uint64 Advisors[3]; - - void Reset() - { - CataclysmicBolt_Timer = 10000; - Enrage_Timer = 600000; //10 minutes - SearNova_Timer = 20000+rand()%40000; // 20 - 60 seconds - - BlessingOfTides = false; - - if (pInstance) - { - uint64 RAdvisors[3]; - RAdvisors[0] = pInstance->GetData64(DATA_SHARKKIS); - RAdvisors[1] = pInstance->GetData64(DATA_TIDALVESS); - RAdvisors[2] = pInstance->GetData64(DATA_CARIBDIS); - //Respawn of the 3 Advisors - Creature* pAdvisor = NULL; - for (int i=0; i<3; ++i) - - if (RAdvisors[i]) - { - pAdvisor = (Unit::GetCreature((*me), RAdvisors[i])); - if (pAdvisor && !pAdvisor->isAlive()) - { - pAdvisor->Respawn(); - pAdvisor->AI()->EnterEvadeMode(); - pAdvisor->GetMotionMaster()->MoveTargetedHome(); - } - } - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - } - - void EventSharkkisDeath() - { - DoScriptText(SAY_GAIN_ABILITY1, me); - DoCast(me, SPELL_POWER_OF_SHARKKIS); - } - - void EventTidalvessDeath() - { - DoScriptText(SAY_GAIN_ABILITY2, me); - DoCast(me, SPELL_POWER_OF_TIDALVESS); - } - - void EventCaribdisDeath() - { - DoScriptText(SAY_GAIN_ABILITY3, me); - DoCast(me, SPELL_POWER_OF_CARIBDIS); - } - - void GetAdvisors() - { - if (!pInstance) - return; - - Advisors[0] = pInstance->GetData64(DATA_SHARKKIS); - Advisors[1] = pInstance->GetData64(DATA_TIDALVESS); - Advisors[2] = pInstance->GetData64(DATA_CARIBDIS); - } - - void StartEvent(Unit *who) - { - if (!pInstance) - return; - - GetAdvisors(); - - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_FATHOMLORDKARATHRESSEVENT, DONE); - - //support for quest 10944 - me->SummonCreature(SEER_OLUM, OLUM_X, OLUM_Y, OLUM_Z, OLUM_O, TEMPSUMMON_TIMED_DESPAWN, 3600000); - } - - void EnterCombat(Unit * who) - { - StartEvent(who); - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - GetAdvisors(); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //CataclysmicBolt_Timer - if (CataclysmicBolt_Timer <= diff) - { - //select a random unit other than the main tank - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1); - - //if there aren't other units, cast on the tank - if (!pTarget) - pTarget = me->getVictim(); - - if (pTarget) - DoCast(pTarget, SPELL_CATACLYSMIC_BOLT); - CataclysmicBolt_Timer = 10000; - } else CataclysmicBolt_Timer -= diff; - - //SearNova_Timer - if (SearNova_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SEAR_NOVA); - SearNova_Timer = 20000+rand()%40000; - } else SearNova_Timer -= diff; - - //Enrage_Timer - if (Enrage_Timer <= diff) - { - DoCast(me, SPELL_ENRAGE); - Enrage_Timer = 90000; - } else Enrage_Timer -= diff; - - //Blessing of Tides Trigger - if ((me->GetHealth()*100 / me->GetMaxHealth()) <= 75 && !BlessingOfTides) - { - BlessingOfTides = true; - bool continueTriggering = false; - Creature* Advisor; - for (uint8 i = 0; i < 4; ++i) - if (Advisors[i]) - { - Advisor = (Unit::GetCreature(*me, Advisors[i])); - if (Advisor && Advisor->isAlive()) - { - continueTriggering = true; - break; - } - } - if (continueTriggering) - { - DoCast(me, SPELL_BLESSING_OF_THE_TIDES); - me->MonsterYell(SAY_GAIN_BLESSING_OF_TIDES, LANG_UNIVERSAL, NULL); - DoPlaySoundToSet(me, SOUND_GAIN_BLESSING_OF_TIDES); - } - } - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Sharkkis AI -struct boss_fathomguard_sharkkisAI : public ScriptedAI -{ - boss_fathomguard_sharkkisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 LeechingThrow_Timer; - uint32 TheBeastWithin_Timer; - uint32 Multishot_Timer; - uint32 Pet_Timer; - - bool pet; - - uint64 SummonedPet; - - void Reset() - { - LeechingThrow_Timer = 20000; - TheBeastWithin_Timer = 30000; - Multishot_Timer = 15000; - Pet_Timer = 10000; - - pet = false; - - Creature *Pet = Unit::GetCreature(*me, SummonedPet); - if (Pet && Pet->isAlive()) - { - Pet->DealDamage(Pet, Pet->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - } - - SummonedPet = 0; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventSharkkisDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //LeechingThrow_Timer - if (LeechingThrow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_LEECHING_THROW); - LeechingThrow_Timer = 20000; - } else LeechingThrow_Timer -= diff; - - //Multishot_Timer - if (Multishot_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MULTISHOT); - Multishot_Timer = 20000; - } else Multishot_Timer -= diff; - - //TheBeastWithin_Timer - if (TheBeastWithin_Timer <= diff) - { - DoCast(me, SPELL_THE_BEAST_WITHIN); - Creature *Pet = Unit::GetCreature(*me, SummonedPet); - if (Pet && Pet->isAlive()) - { - Pet->CastSpell(Pet, SPELL_PET_ENRAGE, true); - } - TheBeastWithin_Timer = 30000; - } else TheBeastWithin_Timer -= diff; - - //Pet_Timer - if (Pet_Timer < diff && pet == false) - { - pet = true; - //uint32 spell_id; - uint32 pet_id; - if (!urand(0,1)) - { - //spell_id = SPELL_SUMMON_FATHOM_LURKER; - pet_id = CREATURE_FATHOM_LURKER; - } - else - { - //spell_id = SPELL_SUMMON_FATHOM_SPOREBAT; - pet_id = CREATURE_FATHOM_SPOREBAT; - } - //DoCast(me, spell_id, true); - Creature *Pet = DoSpawnCreature(pet_id,0,0,0,0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (Pet && pTarget) - { - Pet->AI()->AttackStart(pTarget); - SummonedPet = Pet->GetGUID(); - } - } else Pet_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Tidalvess AI -struct boss_fathomguard_tidalvessAI : public ScriptedAI -{ - boss_fathomguard_tidalvessAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 FrostShock_Timer; - uint32 Spitfire_Timer; - uint32 PoisonCleansing_Timer; - uint32 Earthbind_Timer; - - void Reset() - { - FrostShock_Timer = 25000; - Spitfire_Timer = 60000; - PoisonCleansing_Timer = 30000; - Earthbind_Timer = 45000; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - if (!me->isAlive() && Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventTidalvessDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - DoCast(me, SPELL_WINDFURY_WEAPON); - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - if (!me->HasAura(SPELL_WINDFURY_WEAPON)) - { - DoCast(me, SPELL_WINDFURY_WEAPON); - } - - //FrostShock_Timer - if (FrostShock_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_SHOCK); - FrostShock_Timer = 25000+rand()%5000; - } else FrostShock_Timer -= diff; - - //Spitfire_Timer - if (Spitfire_Timer <= diff) - { - DoCast(me, SPELL_SPITFIRE_TOTEM); - Unit *SpitfireTotem = Unit::GetUnit(*me, CREATURE_SPITFIRE_TOTEM); - if (SpitfireTotem) - { - CAST_CRE(SpitfireTotem)->AI()->AttackStart(me->getVictim()); - } - Spitfire_Timer = 60000; - } else Spitfire_Timer -= diff; - - //PoisonCleansing_Timer - if (PoisonCleansing_Timer <= diff) - { - DoCast(me, SPELL_POISON_CLEANSING_TOTEM); - PoisonCleansing_Timer = 30000; - } else PoisonCleansing_Timer -= diff; - - //Earthbind_Timer - if (Earthbind_Timer <= diff) - { - DoCast(me, SPELL_EARTHBIND_TOTEM); - Earthbind_Timer = 45000; - } else Earthbind_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Fathom-Guard Caribdis AI -struct boss_fathomguard_caribdisAI : public ScriptedAI -{ - boss_fathomguard_caribdisAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 WaterBoltVolley_Timer; - uint32 TidalSurge_Timer; - uint32 Heal_Timer; - uint32 Cyclone_Timer; - - void Reset() - { - WaterBoltVolley_Timer = 35000; - TidalSurge_Timer = 15000+rand()%5000; - Heal_Timer = 55000; - Cyclone_Timer = 30000+rand()%10000; - - if (pInstance) - pInstance->SetData(DATA_KARATHRESSEVENT, NOT_STARTED); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - { - Creature *Karathress = NULL; - Karathress = (Unit::GetCreature((*me), pInstance->GetData64(DATA_KARATHRESS))); - - if (Karathress) - if (!me->isAlive() && Karathress) - CAST_AI(boss_fathomlord_karathressAI, Karathress->AI())->EventCaribdisDeath(); - } - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - pInstance->SetData64(DATA_KARATHRESSEVENT_STARTER, who->GetGUID()); - pInstance->SetData(DATA_KARATHRESSEVENT, IN_PROGRESS); - } - } - - void UpdateAI(const uint32 diff) - { - //Only if not incombat check if the event is started - if (!me->isInCombat() && pInstance && pInstance->GetData(DATA_KARATHRESSEVENT)) - { - Unit *pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESSEVENT_STARTER)); - - if (pTarget) - { - AttackStart(pTarget); - } - } - - //Return since we have no target - if (!UpdateVictim()) - return; - - //someone evaded! - if (pInstance && !pInstance->GetData(DATA_KARATHRESSEVENT)) - { - EnterEvadeMode(); - return; - } - - //WaterBoltVolley_Timer - if (WaterBoltVolley_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_WATER_BOLT_VOLLEY); - WaterBoltVolley_Timer = 30000; - } else WaterBoltVolley_Timer -= diff; - - //TidalSurge_Timer - if (TidalSurge_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIDAL_SURGE); - // Hacky way to do it - won't trigger elseways - me->getVictim()->CastSpell(me->getVictim(), SPELL_TIDAL_SURGE_FREEZE, true); - TidalSurge_Timer = 15000+rand()%5000; - } else TidalSurge_Timer -= diff; - - //Cyclone_Timer - if (Cyclone_Timer <= diff) - { - //DoCast(me, SPELL_SUMMON_CYCLONE); // Doesn't work - Cyclone_Timer = 30000+rand()%10000; - Creature *Cyclone = me->SummonCreature(CREATURE_CYCLONE, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), (rand()%5), TEMPSUMMON_TIMED_DESPAWN, 15000); - if (Cyclone) - { - CAST_CRE(Cyclone)->SetFloatValue(OBJECT_FIELD_SCALE_X, 3.0f); - Cyclone->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Cyclone->setFaction(me->getFaction()); - Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_CYCLONE, true); - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Cyclone->AI()->AttackStart(pTarget); - } - } - } else Cyclone_Timer -= diff; - - //Heal_Timer - if (Heal_Timer <= diff) - { - // It can be cast on any of the mobs - Unit *pUnit = NULL; - - while (pUnit == NULL || !pUnit->isAlive()) - { - pUnit = selectAdvisorUnit(); - } - - if (pUnit && pUnit->isAlive()) - DoCast(pUnit, SPELL_HEAL); - Heal_Timer = 60000; - } else Heal_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - Unit* selectAdvisorUnit() - { - Unit* pUnit = NULL; - if (pInstance) - { - switch(rand()%4) - { - case 0: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_KARATHRESS)); - break; - case 1: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_SHARKKIS)); - break; - case 2: - pUnit = Unit::GetUnit((*me), pInstance->GetData64(DATA_TIDALVESS)); - break; - case 3: - pUnit = me; - break; - } - } else pUnit = me; - - return pUnit; - } -}; - -CreatureAI* GetAI_boss_fathomlord_karathress(Creature* pCreature) -{ - return new boss_fathomlord_karathressAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_sharkkis(Creature* pCreature) -{ - return new boss_fathomguard_sharkkisAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_tidalvess(Creature* pCreature) -{ - return new boss_fathomguard_tidalvessAI (pCreature); -} - -CreatureAI* GetAI_boss_fathomguard_caribdis(Creature* pCreature) -{ - return new boss_fathomguard_caribdisAI (pCreature); -} - -void AddSC_boss_fathomlord_karathress() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_fathomlord_karathress"; - newscript->GetAI = &GetAI_boss_fathomlord_karathress; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_sharkkis"; - newscript->GetAI = &GetAI_boss_fathomguard_sharkkis; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_tidalvess"; - newscript->GetAI = &GetAI_boss_fathomguard_tidalvess; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_fathomguard_caribdis"; - newscript->GetAI = &GetAI_boss_fathomguard_caribdis; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp deleted file mode 100644 index 923fdf55f80..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_hydross_the_unstable.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hydross_The_Unstable -SD%Complete: 90 -SDComment: Some details and adjustments left to do, probably nothing major. Spawns may be spawned in different way/location. -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define SAY_AGGRO -1548000 -#define SAY_SWITCH_TO_CLEAN -1548001 -#define SAY_CLEAN_SLAY1 -1548002 -#define SAY_CLEAN_SLAY2 -1548003 -#define SAY_CLEAN_DEATH -1548004 -#define SAY_SWITCH_TO_CORRUPT -1548005 -#define SAY_CORRUPT_SLAY1 -1548006 -#define SAY_CORRUPT_SLAY2 -1548007 -#define SAY_CORRUPT_DEATH -1548008 - -#define SWITCH_RADIUS 18 - -#define MODEL_CORRUPT 20609 -#define MODEL_CLEAN 20162 - -#define SPELL_WATER_TOMB 38235 -#define SPELL_MARK_OF_HYDROSS1 38215 -#define SPELL_MARK_OF_HYDROSS2 38216 -#define SPELL_MARK_OF_HYDROSS3 38217 -#define SPELL_MARK_OF_HYDROSS4 38218 -#define SPELL_MARK_OF_HYDROSS5 38231 -#define SPELL_MARK_OF_HYDROSS6 40584 -#define SPELL_MARK_OF_CORRUPTION1 38219 -#define SPELL_MARK_OF_CORRUPTION2 38220 -#define SPELL_MARK_OF_CORRUPTION3 38221 -#define SPELL_MARK_OF_CORRUPTION4 38222 -#define SPELL_MARK_OF_CORRUPTION5 38230 -#define SPELL_MARK_OF_CORRUPTION6 40583 -#define SPELL_VILE_SLUDGE 38246 -#define SPELL_ENRAGE 27680 //this spell need verification -#define SPELL_SUMMON_WATER_ELEMENT 36459 //not in use yet(in use ever?) -#define SPELL_ELEMENTAL_SPAWNIN 25035 -#define SPELL_BLUE_BEAM 40227 //channeled Hydross Beam Helper (not in use yet) - -#define ENTRY_PURE_SPAWN 22035 -#define ENTRY_TAINTED_SPAWN 22036 -#define ENTRY_BEAM_DUMMY 21934 - -#define HYDROSS_X -239.439 -#define HYDROSS_Y -363.481 - -#define SPAWN_X_DIFF1 6.934003 -#define SPAWN_Y_DIFF1 -11.255012 -#define SPAWN_X_DIFF2 -6.934003 -#define SPAWN_Y_DIFF2 11.255012 -#define SPAWN_X_DIFF3 -12.577011 -#define SPAWN_Y_DIFF3 -4.72702 -#define SPAWN_X_DIFF4 12.577011 -#define SPAWN_Y_DIFF4 4.72702 - -struct boss_hydross_the_unstableAI : public ScriptedAI -{ - boss_hydross_the_unstableAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 beams[2]; - uint32 PosCheck_Timer; - uint32 MarkOfHydross_Timer; - uint32 MarkOfCorruption_Timer; - uint32 WaterTomb_Timer; - uint32 VileSludge_Timer; - uint32 MarkOfHydross_Count; - uint32 MarkOfCorruption_Count; - uint32 EnrageTimer; - bool CorruptedForm; - bool beam; - SummonList Summons; - - void Reset() - { - DeSummonBeams(); - beams[0] = 0; - beams[1] = 0; - PosCheck_Timer = 2500; - MarkOfHydross_Timer = 15000; - MarkOfCorruption_Timer = 15000; - WaterTomb_Timer = 7000; - VileSludge_Timer = 7000; - MarkOfHydross_Count = 0; - MarkOfCorruption_Count = 0; - EnrageTimer = 600000; - - CorruptedForm = false; - me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - - me->SetDisplayId(MODEL_CLEAN); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, NOT_STARTED); - beam = false; - Summons.DespawnAll(); - } - - void SummonBeams() - { - Creature* beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-258.333,-356.34,22.0499,5.90835,TEMPSUMMON_CORPSE_DESPAWN,0); - if (beamer) - { - beamer->CastSpell(me,SPELL_BLUE_BEAM,true); - beamer->SetDisplayId(11686); //invisible - beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - beams[0]=beamer->GetGUID(); - } - beamer = beamer = me->SummonCreature(ENTRY_BEAM_DUMMY,-219.918,-371.308,22.0042,2.73072,TEMPSUMMON_CORPSE_DESPAWN,0); - if (beamer) - { - beamer->CastSpell(me,SPELL_BLUE_BEAM,true); - beamer->SetDisplayId(11686); //invisible - beamer->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - beams[1]=beamer->GetGUID(); - } - } - void DeSummonBeams() - { - for (uint8 i=0; i<2; ++i) - { - Creature* mob = Unit::GetCreature(*me,beams[i]); - if (mob) - { - mob->setDeathState(DEAD); - mob->RemoveCorpse(); - } - } - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - if (CorruptedForm) - { - DoScriptText(RAND(SAY_CORRUPT_SLAY1,SAY_CORRUPT_SLAY2), me); - } - else - { - DoScriptText(RAND(SAY_CLEAN_SLAY1,SAY_CLEAN_SLAY2), me); - } - } - - void JustSummoned(Creature* summoned) - { - if (summoned->GetEntry() == ENTRY_PURE_SPAWN) - { - summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); - Summons.Summon(summoned); - } - if (summoned->GetEntry() == ENTRY_TAINTED_SPAWN) - { - summoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - summoned->CastSpell(summoned,SPELL_ELEMENTAL_SPAWNIN,true); - Summons.Summon(summoned); - } - } - - void SummonedCreatureDespawn(Creature *summon) - { - Summons.Despawn(summon); - } - - void JustDied(Unit * /*victim*/) - { - if (CorruptedForm) - DoScriptText(SAY_CORRUPT_DEATH, me); - else - DoScriptText(SAY_CLEAN_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_HYDROSSTHEUNSTABLEEVENT, DONE); - Summons.DespawnAll(); - } - - void UpdateAI(const uint32 diff) - { - if (!beam) - { - SummonBeams(); - beam=true; - } - //Return since we have no target - if (!UpdateVictim()) - return; - - // corrupted form - if (CorruptedForm) - { - //MarkOfCorruption_Timer - if (MarkOfCorruption_Timer <= diff) - { - if (MarkOfCorruption_Count <= 5) - { - uint32 mark_spell = 0; - - switch (MarkOfCorruption_Count) - { - case 0: mark_spell = SPELL_MARK_OF_CORRUPTION1; break; - case 1: mark_spell = SPELL_MARK_OF_CORRUPTION2; break; - case 2: mark_spell = SPELL_MARK_OF_CORRUPTION3; break; - case 3: mark_spell = SPELL_MARK_OF_CORRUPTION4; break; - case 4: mark_spell = SPELL_MARK_OF_CORRUPTION5; break; - case 5: mark_spell = SPELL_MARK_OF_CORRUPTION6; break; - } - - DoCast(me->getVictim(), mark_spell); - - if (MarkOfCorruption_Count < 5) - ++MarkOfCorruption_Count; - } - - MarkOfCorruption_Timer = 15000; - } else MarkOfCorruption_Timer -= diff; - - //VileSludge_Timer - if (VileSludge_Timer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - DoCast(pTarget, SPELL_VILE_SLUDGE); - - VileSludge_Timer = 15000; - } else VileSludge_Timer -= diff; - - //PosCheck_Timer - if (PosCheck_Timer <= diff) - { - if (me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) - { - // switch to clean form - me->SetDisplayId(MODEL_CLEAN); - CorruptedForm = false; - MarkOfHydross_Count = 0; - - DoScriptText(SAY_SWITCH_TO_CLEAN, me); - DoResetThreat(); - SummonBeams(); - - // spawn 4 adds - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_PURE_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - me->SetMeleeDamageSchool(SPELL_SCHOOL_FROST); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, false); - } - - PosCheck_Timer = 2500; - } else PosCheck_Timer -=diff; - } - // clean form - else - { - //MarkOfHydross_Timer - if (MarkOfHydross_Timer <= diff) - { - if (MarkOfHydross_Count <= 5) - { - uint32 mark_spell = NULL; - - switch(MarkOfHydross_Count) - { - case 0: mark_spell = SPELL_MARK_OF_HYDROSS1; break; - case 1: mark_spell = SPELL_MARK_OF_HYDROSS2; break; - case 2: mark_spell = SPELL_MARK_OF_HYDROSS3; break; - case 3: mark_spell = SPELL_MARK_OF_HYDROSS4; break; - case 4: mark_spell = SPELL_MARK_OF_HYDROSS5; break; - case 5: mark_spell = SPELL_MARK_OF_HYDROSS6; break; - } - - DoCast(me->getVictim(), mark_spell); - - if (MarkOfHydross_Count < 5) - ++MarkOfHydross_Count; - } - - MarkOfHydross_Timer = 15000; - } else MarkOfHydross_Timer -= diff; - - //WaterTomb_Timer - if (WaterTomb_Timer <= diff) - { - Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - if (pTarget) - DoCast(pTarget, SPELL_WATER_TOMB); - - WaterTomb_Timer = 7000; - } else WaterTomb_Timer -= diff; - - //PosCheck_Timer - if (PosCheck_Timer <= diff) - { - if (!me->IsWithinDist2d(HYDROSS_X, HYDROSS_Y, SWITCH_RADIUS)) - { - // switch to corrupted form - me->SetDisplayId(MODEL_CORRUPT); - MarkOfCorruption_Count = 0; - CorruptedForm = true; - - DoScriptText(SAY_SWITCH_TO_CORRUPT, me); - DoResetThreat(); - DeSummonBeams(); - - // spawn 4 adds - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF1, SPAWN_Y_DIFF1, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF2, SPAWN_Y_DIFF2, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF3, SPAWN_Y_DIFF3, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - DoSpawnCreature(ENTRY_TAINTED_SPAWN, SPAWN_X_DIFF4, SPAWN_Y_DIFF4, 3, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - me->SetMeleeDamageSchool(SPELL_SCHOOL_NATURE); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_NATURE, true); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FROST, false); - } - - PosCheck_Timer = 2500; - } else PosCheck_Timer -=diff; - } - - //EnrageTimer - if (EnrageTimer <= diff) - { - DoCast(me, SPELL_ENRAGE); - EnrageTimer = 60000; - } else EnrageTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_hydross_the_unstable(Creature* pCreature) -{ - return new boss_hydross_the_unstableAI (pCreature); -} - -void AddSC_boss_hydross_the_unstable() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_hydross_the_unstable"; - newscript->GetAI = &GetAI_boss_hydross_the_unstable; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp deleted file mode 100644 index 2f0485d0e6c..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lady_vashj.cpp +++ /dev/null @@ -1,1039 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307USA - */ - -/* ScriptData -SDName: Boss_Lady_Vashj -SD%Complete: 99 -SDComment: Missing blizzlike Shield Generators coords -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedSimpleAI.h" -#include "Spell.h" - -#define SAY_INTRO -1548042 -#define SAY_AGGRO1 -1548043 -#define SAY_AGGRO2 -1548044 -#define SAY_AGGRO3 -1548045 -#define SAY_AGGRO4 -1548046 -#define SAY_PHASE1 -1548047 -#define SAY_PHASE2 -1548048 -#define SAY_PHASE3 -1548049 -#define SAY_BOWSHOT1 -1548050 -#define SAY_BOWSHOT2 -1548051 -#define SAY_SLAY1 -1548052 -#define SAY_SLAY2 -1548053 -#define SAY_SLAY3 -1548054 -#define SAY_DEATH -1548055 - -#define SPELL_SURGE 38044 -#define SPELL_MULTI_SHOT 38310 -#define SPELL_SHOCK_BLAST 38509 -#define SPELL_ENTANGLE 38316 -#define SPELL_STATIC_CHARGE_TRIGGER 38280 -#define SPELL_FORKED_LIGHTNING 40088 -#define SPELL_SHOOT 40873 -#define SPELL_POISON_BOLT 40095 -#define SPELL_TOXIC_SPORES 38575 -#define SPELL_MAGIC_BARRIER 38112 - -#define MIDDLE_X 30.134 -#define MIDDLE_Y -923.65 -#define MIDDLE_Z 42.9 - -#define SPOREBAT_X 30.977156 -#define SPOREBAT_Y -925.297761 -#define SPOREBAT_Z 77.176567 -#define SPOREBAT_O 5.223932 - -#define SHIED_GENERATOR_CHANNEL 19870 -#define ENCHANTED_ELEMENTAL 21958 -#define TAINTED_ELEMENTAL 22009 -#define COILFANG_STRIDER 22056 -#define COILFANG_ELITE 22055 -#define TOXIC_SPOREBAT 22140 -#define TOXIC_SPORES_TRIGGER 22207 - -#define TEXT_NOT_INITIALIZED "Instance script not initialized" -#define TEXT_ALREADY_DEACTIVATED "Already deactivated" - -float ElementPos[8][4] = -{ - {8.3, -835.3, 21.9, 5}, - {53.4, -835.3, 21.9, 4.5}, - {96, -861.9, 21.8, 4}, - {96, -986.4, 21.4, 2.5}, - {54.4, -1010.6, 22, 1.8}, - {9.8, -1012, 21.7, 1.4}, - {-35, -987.6, 21.5, 0.8}, - {-58.9, -901.6, 21.5, 6} -}; - -float ElementWPPos[8][3] = -{ - {71.700752, -883.905884, 41.097168}, - {45.039848, -868.022827, 41.097015}, - {14.585141, -867.894470, 41.097061}, - {-25.415508, -906.737732, 41.097061}, - {-11.801594, -963.405884, 41.097067}, - {14.556657, -979.051514, 41.097137}, - {43.466549, -979.406677, 41.097027}, - {69.945908, -964.663940, 41.097054} -}; - -float SporebatWPPos[8][3] = -{ - {31.6,-896.3,59.1}, - {9.1, -913.9, 56}, - {5.2, -934.4, 52.4}, - {20.7, -946.9, 49.7}, - {41, -941.9, 51}, - {47.7, -927.3, 55}, - {42.2, -912.4, 51.7}, - {27, -905.9, 50} -}; - -float CoilfangElitePos[3][4] = -{ - {28.84, -923.28, 42.9, 6}, - {31.183281, -953.502625, 41.523602, 1.640957}, - {58.895180, -923.124268, 41.545307, 3.152848} -}; - -float CoilfangStriderPos[3][4] = -{ - {66.427010, -948.778503, 41.262245, 2.584220}, - {7.513962, -959.538208, 41.300422, 1.034629}, - {-12.843201, -907.798401, 41.239620, 6.087094} -}; - -float ShieldGeneratorChannelPos[4][4] = -{ - {49.6262, -902.181, 43.0975, 3.95683}, - {10.988, -901.616, 42.5371, 5.4373}, - {10.3859, -944.036, 42.5446, 0.779888}, - {49.3126, -943.398, 42.5501, 2.40174} -}; - -//Lady Vashj AI -struct boss_lady_vashjAI : public ScriptedAI -{ - boss_lady_vashjAI (Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - Intro = false; - JustCreated = true; - c->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); //set it only once on Creature create (no need do intro if wiped) - } - - ScriptedInstance *pInstance; - - uint64 ShieldGeneratorChannel[4]; - - uint32 AggroTimer; - uint32 ShockBlast_Timer; - uint32 Entangle_Timer; - uint32 StaticCharge_Timer; - uint32 ForkedLightning_Timer; - uint32 Check_Timer; - uint32 EnchantedElemental_Timer; - uint32 TaintedElemental_Timer; - uint32 CoilfangElite_Timer; - uint32 CoilfangStrider_Timer; - uint32 SummonSporebat_Timer; - uint32 SummonSporebat_StaticTimer; - uint8 EnchantedElemental_Pos; - uint8 Phase; - - bool Entangle; - bool Intro; - bool CanAttack; - bool JustCreated; - - void Reset() - { - AggroTimer = 19000; - ShockBlast_Timer = 1+rand()%60000; - Entangle_Timer = 30000; - StaticCharge_Timer = 10000+rand()%15000; - ForkedLightning_Timer = 2000; - Check_Timer = 15000; - EnchantedElemental_Timer = 5000; - TaintedElemental_Timer = 50000; - CoilfangElite_Timer = 45000+rand()%5000; - CoilfangStrider_Timer = 60000+rand()%10000; - SummonSporebat_Timer = 10000; - SummonSporebat_StaticTimer = 30000; - EnchantedElemental_Pos = 0; - Phase = 0; - - Entangle = false; - if (JustCreated) - { - CanAttack = false; - JustCreated = false; - } else CanAttack = true; - - Unit *remo; - for (uint8 i = 0; i < 4; ++i) - { - remo = Unit::GetUnit(*me, ShieldGeneratorChannel[i]); - if (remo) - remo->setDeathState(JUST_DIED); - } - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, NOT_STARTED); - ShieldGeneratorChannel[0] = 0; - ShieldGeneratorChannel[1] = 0; - ShieldGeneratorChannel[2] = 0; - ShieldGeneratorChannel[3] = 0; - - me->SetCorpseDelay(1000*60*60); - } - - //Called when a tainted elemental dies - void EventTaintedElementalDeath() - { - //the next will spawn 50 seconds after the previous one's death - if (TaintedElemental_Timer > 50000) - TaintedElemental_Timer = 50000; - } - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, DONE); - } - - void StartEvent() - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3,SAY_AGGRO4), me); - - Phase = 1; - - if (pInstance) - pInstance->SetData(DATA_LADYVASHJEVENT, IN_PROGRESS); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - { - //remove old tainted cores to prevent cheating in phase 2 - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* i_pl = i->getSource()) - { - i_pl->DestroyItemCount(31088, 1, true); - } - } - } - StartEvent();//this is EnterCombat(), so were are 100% in combat, start the event - - if (Phase != 2) - AttackStart(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (!Intro) - { - Intro = true; - DoScriptText(SAY_INTRO, me); - } - if (!CanAttack) - return; - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->GetDistanceZ(who) <= CREATURE_Z_ATTACK_RANGE && me->IsWithinLOSInMap(who)) - { - //if (who->HasStealthAura()) - // who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - - if (!me->isInCombat())//AttackStart() sets UNIT_FLAG_IN_COMBAT, so this msut be before attacking - StartEvent(); - - if (Phase != 2) - AttackStart(who); - } - } - } - - void CastShootOrMultishot() - { - switch (urand(0,1)) - { - case 0: - //Shoot - //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits her target for 4097-5543 Physical damage. - DoCast(me->getVictim(), SPELL_SHOOT); - break; - case 1: - //Multishot - //Used in Phases 1 and 3 after Entangle or while having nobody in melee range. A shot that hits 1 person and 4 people around him for 6475-7525 physical damage. - DoCast(me->getVictim(), SPELL_MULTI_SHOT); - break; - } - if (rand()%3) - { - DoScriptText(RAND(SAY_BOWSHOT1,SAY_BOWSHOT2), me); - } - } - - void UpdateAI(const uint32 diff) - { - if (!CanAttack && Intro) - { - if (AggroTimer <= diff) - { - CanAttack = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - AggroTimer=19000; - }else - { - AggroTimer-=diff; - return; - } - } - //to prevent abuses during phase 2 - if (Phase == 2 && !me->getVictim() && me->isInCombat()) - { - EnterEvadeMode(); - return; - } - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Phase == 1 || Phase == 3) - { - //ShockBlast_Timer - if (ShockBlast_Timer <= diff) - { - //Shock Burst - //Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. - DoCast(me->getVictim(), SPELL_SHOCK_BLAST); - me->TauntApply(me->getVictim()); - - ShockBlast_Timer = 1000+rand()%14000; //random cooldown - } else ShockBlast_Timer -= diff; - - //StaticCharge_Timer - if (StaticCharge_Timer <= diff) - { - //Static Charge - //Used on random people (only 1 person at any given time) in Phases 1 and 3, it's a debuff doing 2775 to 3225 Nature damage to the target and everybody in about 5 yards around it, every 1 seconds for 30 seconds. It can be removed by Cloak of Shadows, Iceblock, Divine Shield, etc, but not by Cleanse or Dispel Magic. - Unit *pTarget = NULL; - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 200, true); - - if (pTarget && !pTarget->HasAura(SPELL_STATIC_CHARGE_TRIGGER)) - //cast Static Charge every 2 seconds for 20 seconds - DoCast(pTarget, SPELL_STATIC_CHARGE_TRIGGER); - - StaticCharge_Timer = 10000+rand()%20000; //blizzlike - } else StaticCharge_Timer -= diff; - - //Entangle_Timer - if (Entangle_Timer <= diff) - { - if (!Entangle) - { - //Entangle - //Used in Phases 1 and 3, it casts Entangling Roots on everybody in a 15 yard radius of Vashj, immobilzing them for 10 seconds and dealing 500 damage every 2 seconds. It's not a magic effect so it cannot be dispelled, but is removed by various buffs such as Cloak of Shadows or Blessing of Freedom. - DoCast(me->getVictim(), SPELL_ENTANGLE); - Entangle = true; - Entangle_Timer = 10000; - } - else - { - CastShootOrMultishot(); - Entangle = false; - Entangle_Timer = 20000+rand()%5000; - } - } else Entangle_Timer -= diff; - - //Phase 1 - if (Phase == 1) - { - //Start phase 2 - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 70) - { - //Phase 2 begins when Vashj hits 70%. She will run to the middle of her platform and surround herself in a shield making her invulerable. - Phase = 2; - - me->GetMotionMaster()->Clear(); - DoTeleportTo(MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - - Creature *pCreature; - for (uint8 i = 0; i < 4; ++i) - { - pCreature = me->SummonCreature(SHIED_GENERATOR_CHANNEL, ShieldGeneratorChannelPos[i][0], ShieldGeneratorChannelPos[i][1], ShieldGeneratorChannelPos[i][2], ShieldGeneratorChannelPos[i][3], TEMPSUMMON_CORPSE_DESPAWN, 0); - if (pCreature) - ShieldGeneratorChannel[i] = pCreature->GetGUID(); - } - DoScriptText(SAY_PHASE2, me); - } - } - //Phase 3 - else - { - //SummonSporebat_Timer - if (SummonSporebat_Timer <= diff) - { - Creature *Sporebat = NULL; - Sporebat = me->SummonCreature(TOXIC_SPOREBAT, SPOREBAT_X, SPOREBAT_Y, SPOREBAT_Z, SPOREBAT_O, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (Sporebat) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Sporebat->AI()->AttackStart(pTarget); - } - - //summon sporebats faster and faster - if (SummonSporebat_StaticTimer > 1000) - SummonSporebat_StaticTimer -= 1000; - - SummonSporebat_Timer = SummonSporebat_StaticTimer; - - if (SummonSporebat_Timer < 5000) - SummonSporebat_Timer = 5000; - - } else SummonSporebat_Timer -= diff; - } - - //Melee attack - DoMeleeAttackIfReady(); - - //Check_Timer - used to check if somebody is in melee range - if (Check_Timer <= diff) - { - bool InMeleeRange = false; - Unit *pTarget; - std::list t_list = me->getThreatManager().getThreatList(); - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - //if in melee range - if (pTarget && pTarget->IsWithinDistInMap(me, 5)) - { - InMeleeRange = true; - break; - } - } - - //if nobody is in melee range - if (!InMeleeRange) - CastShootOrMultishot(); - - Check_Timer = 5000; - } else Check_Timer -= diff; - } - //Phase 2 - else - { - //ForkedLightning_Timer - if (ForkedLightning_Timer <= diff) - { - //Forked Lightning - //Used constantly in Phase 2, it shoots out completely randomly targeted bolts of lightning which hit everybody in a roughtly 60 degree cone in front of Vashj for 2313-2687 nature damage. - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (!pTarget) - pTarget = me->getVictim(); - - DoCast(pTarget, SPELL_FORKED_LIGHTNING); - - ForkedLightning_Timer = 2000+rand()%6000; //blizzlike - } else ForkedLightning_Timer -= diff; - - //EnchantedElemental_Timer - if (EnchantedElemental_Timer <= diff) - { - Creature *Elemental; - Elemental = me->SummonCreature(ENCHANTED_ELEMENTAL, ElementPos[EnchantedElemental_Pos][0], ElementPos[EnchantedElemental_Pos][1], ElementPos[EnchantedElemental_Pos][2], ElementPos[EnchantedElemental_Pos][3], TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (EnchantedElemental_Pos == 7) - EnchantedElemental_Pos = 0; - else - ++EnchantedElemental_Pos; - - EnchantedElemental_Timer = 10000+rand()%5000; - } else EnchantedElemental_Timer -= diff; - - //TaintedElemental_Timer - if (TaintedElemental_Timer <= diff) - { - Creature *Tain_Elemental; - uint32 pos = rand()%8; - Tain_Elemental = me->SummonCreature(TAINTED_ELEMENTAL, ElementPos[pos][0], ElementPos[pos][1], ElementPos[pos][2], ElementPos[pos][3], TEMPSUMMON_DEAD_DESPAWN, 0); - - TaintedElemental_Timer = 120000; - } else TaintedElemental_Timer -= diff; - - //CoilfangElite_Timer - if (CoilfangElite_Timer <= diff) - { - uint32 pos = rand()%3; - Creature* CoilfangElite = NULL; - CoilfangElite = me->SummonCreature(COILFANG_ELITE, CoilfangElitePos[pos][0], CoilfangElitePos[pos][1], CoilfangElitePos[pos][2], CoilfangElitePos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (CoilfangElite) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - CoilfangElite->AI()->AttackStart(pTarget); - else if (me->getVictim()) - CoilfangElite->AI()->AttackStart(me->getVictim()); - } - CoilfangElite_Timer = 45000+rand()%5000; - } else CoilfangElite_Timer -= diff; - - //CoilfangStrider_Timer - if (CoilfangStrider_Timer <= diff) - { - uint32 pos = rand()%3; - Creature* CoilfangStrider = NULL; - CoilfangStrider = me->SummonCreature(COILFANG_STRIDER, CoilfangStriderPos[pos][0], CoilfangStriderPos[pos][1], CoilfangStriderPos[pos][2], CoilfangStriderPos[pos][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (CoilfangStrider) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - CoilfangStrider->AI()->AttackStart(pTarget); - else if (me->getVictim()) - CoilfangStrider->AI()->AttackStart(me->getVictim()); - } - CoilfangStrider_Timer = 60000+rand()%10000; - } else CoilfangStrider_Timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - //Start Phase 3 - if (pInstance && pInstance->GetData(DATA_CANSTARTPHASE3)) - { - //set life 50% - me->SetHealth(me->GetMaxHealth()/2); - - me->RemoveAurasDueToSpell(SPELL_MAGIC_BARRIER); - - DoScriptText(SAY_PHASE3, me); - - Phase = 3; - - //return to the tank - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - Check_Timer = 1000; - } else Check_Timer -= diff; - } - } -}; - -//Enchanted Elemental -//If one of them reaches Vashj he will increase her damage done by 5%. -struct mob_enchanted_elementalAI : public ScriptedAI -{ - mob_enchanted_elementalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 move; - uint32 phase; - float x, y, z; - - uint64 VashjGUID; - - void Reset() - { - me->SetSpeed(MOVE_WALK,0.6);//walk - me->SetSpeed(MOVE_RUN,0.6);//run - move = 0; - phase = 1; - - VashjGUID = 0; - - for (int i = 0; i<8; ++i)//search for nearest waypoint (up on stairs) - { - if (!x || !y || !z) - { - x = ElementWPPos[i][0]; - y = ElementWPPos[i][1]; - z = ElementWPPos[i][2]; - } - else - { - if (me->GetDistance(ElementWPPos[i][0],ElementWPPos[i][1],ElementWPPos[i][2]) < me->GetDistance(x,y,z)) - { - x = ElementWPPos[i][0]; - y = ElementWPPos[i][1]; - z = ElementWPPos[i][2]; - } - } - } - if (pInstance) - VashjGUID = pInstance->GetData64(DATA_LADYVASHJ); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!pInstance) - return; - - if (!VashjGUID) - return; - - if (move <= diff) - { - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - if (phase == 1) - me->GetMotionMaster()->MovePoint(0, x, y, z); - if (phase == 1 && me->IsWithinDist3d(x,y,z, 0.1)) - phase = 2; - if (phase == 2) - { - me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - phase = 3; - } - if (phase == 3) - { - me->GetMotionMaster()->MovePoint(0, MIDDLE_X, MIDDLE_Y, MIDDLE_Z); - if (me->IsWithinDist3d(MIDDLE_X, MIDDLE_Y, MIDDLE_Z, 3)) - DoCast(me, SPELL_SURGE); - } - if (Creature *Vashj = Unit::GetCreature(*me, VashjGUID)) - { - if (!Vashj->isInCombat() || CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase != 2 || Vashj->isDead()) - { - //call Unsummon() - me->Kill(me); - } - } - move = 1000; - } else move -= diff; - } -}; - -//Tainted Elemental -//This mob has 7,900 life, doesn't move, and shoots Poison Bolts at one person anywhere in the area, doing 3,000 nature damage and placing a posion doing 2,000 damage every 2 seconds. He will switch targets often, or sometimes just hang on a single player, but there is nothing you can do about it except heal the damage and kill the Tainted Elemental -struct mob_tainted_elementalAI : public ScriptedAI -{ - mob_tainted_elementalAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 PoisonBolt_Timer; - uint32 Despawn_Timer; - - void Reset() - { - PoisonBolt_Timer = 5000+rand()%5000; - Despawn_Timer = 30000; - } - - void JustDied(Unit * /*killer*/) - { - if (pInstance) - { - Creature *Vashj = NULL; - Vashj = (Unit::GetCreature((*me), pInstance->GetData64(DATA_LADYVASHJ))); - - if (Vashj) - CAST_AI(boss_lady_vashjAI, Vashj->AI())->EventTaintedElementalDeath(); - } - } - - void EnterCombat(Unit * who) - { - me->AddThreat(who, 0.1f); - } - - void UpdateAI(const uint32 diff) - { - //PoisonBolt_Timer - if (PoisonBolt_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget && pTarget->IsWithinDistInMap(me, 30)) - DoCast(pTarget, SPELL_POISON_BOLT); - - PoisonBolt_Timer = 5000+rand()%5000; - } else PoisonBolt_Timer -= diff; - - //Despawn_Timer - if (Despawn_Timer <= diff) - { - //call Unsummon() - me->setDeathState(DEAD); - - //to prevent crashes - Despawn_Timer = 1000; - } else Despawn_Timer -= diff; - } -}; - -//Toxic Sporebat -//Toxic Spores: Used in Phase 3 by the Spore Bats, it creates a contaminated green patch of ground, dealing about 2775-3225 nature damage every second to anyone who stands in it. -struct mob_toxic_sporebatAI : public ScriptedAI -{ - mob_toxic_sporebatAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - EnterEvadeMode(); - } - - ScriptedInstance *pInstance; - - uint32 movement_timer; - uint32 ToxicSpore_Timer; - uint32 bolt_timer; - uint32 Check_Timer; - - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->setFaction(14); - movement_timer = 0; - ToxicSpore_Timer = 5000; - bolt_timer = 5500; - Check_Timer = 1000; - } - - void EnterCombat(Unit * /*who*/) - { - - } - - void MoveInLineOfSight(Unit * /*who*/) - { - - } - - void MovementInform(uint32 type, uint32 id) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id == 1) - movement_timer = 0; - } - - void UpdateAI (const uint32 diff) - { - //Random movement - if (movement_timer <= diff) - { - uint32 rndpos = rand()%8; - me->GetMotionMaster()->MovePoint(1,SporebatWPPos[rndpos][0], SporebatWPPos[rndpos][1], SporebatWPPos[rndpos][2]); - movement_timer = 6000; - } else movement_timer -= diff; - - //toxic spores - if (bolt_timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - { - Creature* trig = me->SummonCreature(TOXIC_SPORES_TRIGGER,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN,30000); - if (trig) - { - trig->setFaction(14); - trig->CastSpell(trig, SPELL_TOXIC_SPORES,true); - } - } - bolt_timer = 10000+rand()%5000; - } - else bolt_timer -= diff; - - //Check_Timer - if (Check_Timer <= diff) - { - if (pInstance) - { - //check if vashj is death - Unit *Vashj = NULL; - Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); - if (!Vashj || (Vashj && !Vashj->isAlive()) || (Vashj && CAST_AI(boss_lady_vashjAI, CAST_CRE(Vashj)->AI())->Phase != 3)) - { - //remove - me->setDeathState(DEAD); - me->RemoveCorpse(); - me->setFaction(35); - } - } - - Check_Timer = 1000; - } else Check_Timer -= diff; - } -}; - -//Coilfang Elite -//It's an elite Naga mob with 170,000 HP. It does about 5000 damage on plate, and has a nasty cleave hitting for about 7500 damage -CreatureAI* GetAI_mob_coilfang_elite(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = 31345; //Cleave - ai->Spell[0].Cooldown = 15000; - ai->Spell[0].CooldownRandomAddition = 5000; - ai->Spell[0].First_Cast = 5000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_RANDOM; - - ai->EnterEvadeMode(); - - return ai; -} - -//Coilfang Strider -//It hits plate for about 8000 damage, has a Mind Blast spell doing about 3000 shadow damage, and a Psychic Scream Aura, which fears everybody in a 8 yard range of it every 2-3 seconds , for 5 seconds and increasing their movement speed by 150% during the fear. -CreatureAI* GetAI_mob_coilfang_strider(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = 41374; //Mind Blast - ai->Spell[0].Cooldown = 30000; - ai->Spell[0].CooldownRandomAddition = 10000; - ai->Spell[0].First_Cast = 8000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - //Scream aura not implemented - - ai->EnterEvadeMode(); - - return ai; -} - -struct mob_shield_generator_channelAI : public ScriptedAI -{ - mob_shield_generator_channelAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - uint32 Check_Timer; - bool Casted; - void Reset() - { - Check_Timer = 0; - Casted = false; - me->SetDisplayId(11686); //invisible - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit * /*who*/) {} - - void UpdateAI (const uint32 diff) - { - if (!pInstance) - return; - - if (Check_Timer <= diff) - { - Unit *Vashj = NULL; - Vashj = Unit::GetUnit((*me), pInstance->GetData64(DATA_LADYVASHJ)); - - if (Vashj && Vashj->isAlive()) - { - //start visual channel - if (!Casted || !Vashj->HasAura(SPELL_MAGIC_BARRIER)) - { - DoCast(Vashj, SPELL_MAGIC_BARRIER, true); - Casted = true; - } - } - Check_Timer = 1000; - } else Check_Timer -= diff; - } -}; - -bool ItemUse_item_tainted_core(Player* pPlayer, Item* /*_Item*/, SpellCastTargets const& targets) -{ - ScriptedInstance *pInstance = pPlayer->GetInstanceData(); - - if (!pInstance) - { - pPlayer->GetSession()->SendNotification(TEXT_NOT_INITIALIZED); - return true; - } - - Creature *Vashj = NULL; - Vashj = (Unit::GetCreature((*pPlayer), pInstance->GetData64(DATA_LADYVASHJ))); - if (Vashj && CAST_AI(boss_lady_vashjAI, Vashj->AI())->Phase == 2) - { - if (targets.getGOTarget() && targets.getGOTarget()->GetTypeId() == TYPEID_GAMEOBJECT) - { - uint32 identifier; - uint8 channel_identifier; - switch(targets.getGOTarget()->GetEntry()) - { - case 185052: - identifier = DATA_SHIELDGENERATOR1; - channel_identifier = 0; - break; - case 185053: - identifier = DATA_SHIELDGENERATOR2; - channel_identifier = 1; - break; - case 185051: - identifier = DATA_SHIELDGENERATOR3; - channel_identifier = 2; - break; - case 185054: - identifier = DATA_SHIELDGENERATOR4; - channel_identifier = 3; - break; - default: - return true; - } - - if (pInstance->GetData(identifier)) - { - pPlayer->GetSession()->SendNotification(TEXT_ALREADY_DEACTIVATED); - return true; - } - - //get and remove channel - Unit *Channel = NULL; - Channel = Unit::GetCreature(*Vashj, CAST_AI(boss_lady_vashjAI, Vashj->AI())->ShieldGeneratorChannel[channel_identifier]); - if (Channel) - { - //call Unsummon() - Channel->setDeathState(JUST_DIED); - } - - pInstance->SetData(identifier, 1); - - //remove this item - pPlayer->DestroyItemCount(31088, 1, true); - return true; - } - else if (targets.getUnitTarget()->GetTypeId() == TYPEID_UNIT) - return false; - else if (targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER) - { - pPlayer->DestroyItemCount(31088, 1, true); - pPlayer->CastSpell(targets.getUnitTarget(), 38134, true); - return true; - } - } - return true; -} - -CreatureAI* GetAI_boss_lady_vashj(Creature* pCreature) -{ - return new boss_lady_vashjAI (pCreature); -} - -CreatureAI* GetAI_mob_enchanted_elemental(Creature* pCreature) -{ - return new mob_enchanted_elementalAI (pCreature); -} - -CreatureAI* GetAI_mob_tainted_elemental(Creature* pCreature) -{ - return new mob_tainted_elementalAI (pCreature); -} - -CreatureAI* GetAI_mob_toxic_sporebat(Creature* pCreature) -{ - return new mob_toxic_sporebatAI (pCreature); -} - -CreatureAI* GetAI_mob_shield_generator_channel(Creature* pCreature) -{ - return new mob_shield_generator_channelAI (pCreature); -} - -void AddSC_boss_lady_vashj() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_lady_vashj"; - newscript->GetAI = &GetAI_boss_lady_vashj; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_enchanted_elemental"; - newscript->GetAI = &GetAI_mob_enchanted_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_tainted_elemental"; - newscript->GetAI = &GetAI_mob_tainted_elemental; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_toxic_sporebat"; - newscript->GetAI = &GetAI_mob_toxic_sporebat; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_elite"; - newscript->GetAI = &GetAI_mob_coilfang_elite; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_strider"; - newscript->GetAI = &GetAI_mob_coilfang_strider; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shield_generator_channel"; - newscript->GetAI = &GetAI_mob_shield_generator_channel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "item_tainted_core"; - newscript->pItemUse = &ItemUse_item_tainted_core; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp deleted file mode 100644 index 61c9ed9d527..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_leotheras_the_blind.cpp +++ /dev/null @@ -1,787 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Leotheras_The_Blind -SD%Complete: 80 -SDComment: Possesion Support -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -// --- Spells used by Leotheras The Blind -#define SPELL_WHIRLWIND 37640 -#define SPELL_CHAOS_BLAST 37674 -#define SPELL_BERSERK 26662 -#define SPELL_INSIDIOUS_WHISPER 37676 -#define SPELL_DUAL_WIELD 42459 - -// --- Spells used in banish phase --- -#define BANISH_BEAM 38909 -#define AURA_BANISH 37833 - -// --- Spells used by Greyheart Spellbinders -#define SPELL_EARTHSHOCK 39076 -#define SPELL_MINDBLAST 37531 - -// --- Spells used by Inner Demons and Creature ID -#define INNER_DEMON_ID 21857 -#define AURA_DEMONIC_ALIGNMENT 37713 -#define SPELL_SHADOWBOLT 39309 -#define SPELL_SOUL_LINK 38007 -#define SPELL_CONSUMING_MADNESS 37749 //not supported by core yet - -//Misc. -#define MODEL_DEMON 20125 -#define MODEL_NIGHTELF 20514 -#define DEMON_FORM 21875 -#define MOB_SPELLBINDER 21806 - -#define SAY_AGGRO -1548009 -#define SAY_SWITCH_TO_DEMON -1548010 -#define SAY_INNER_DEMONS -1548011 -#define SAY_DEMON_SLAY1 -1548012 -#define SAY_DEMON_SLAY2 -1548013 -#define SAY_DEMON_SLAY3 -1548014 -#define SAY_NIGHTELF_SLAY1 -1548015 -#define SAY_NIGHTELF_SLAY2 -1548016 -#define SAY_NIGHTELF_SLAY3 -1548017 -#define SAY_FINAL_FORM -1548018 -#define SAY_FREE -1548019 -#define SAY_DEATH -1548020 - -struct mob_inner_demonAI : public ScriptedAI -{ - mob_inner_demonAI(Creature *c) : ScriptedAI(c) - { - victimGUID = 0; - } - - uint32 ShadowBolt_Timer; - - uint32 Link_Timer; - uint64 victimGUID; - - void Reset() - { - ShadowBolt_Timer = 10000; - Link_Timer = 1000; - } - void JustDied(Unit * /*victim*/) - { - Unit* pUnit = Unit::GetUnit((*me),victimGUID); - if (pUnit && pUnit->HasAura(SPELL_INSIDIOUS_WHISPER)) - pUnit->RemoveAurasDueToSpell(SPELL_INSIDIOUS_WHISPER); - } - - void DamageTaken(Unit *done_by, uint32 &damage) - { - if (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID()) - { - damage = 0; - DoModifyThreatPercent(done_by, -100); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (!victimGUID) return; - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (me->getVictim()->GetGUID() != victimGUID) - { - DoModifyThreatPercent(me->getVictim(), -100); - Unit* owner = Unit::GetUnit((*me),victimGUID); - if (owner && owner->isAlive()) - { - me->AddThreat(owner,999999); - AttackStart(owner); - } else if (owner && owner->isDead()) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - return; - } - } - - if (Link_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOUL_LINK, true); - Link_Timer = 1000; - } else Link_Timer -= diff; - - if (!me->HasAura(AURA_DEMONIC_ALIGNMENT)) - DoCast(me, AURA_DEMONIC_ALIGNMENT, true); - - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOWBOLT, false); - ShadowBolt_Timer = 10000; - } else ShadowBolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -//Original Leotheras the Blind AI -struct boss_leotheras_the_blindAI : public ScriptedAI -{ - boss_leotheras_the_blindAI(Creature *c) : ScriptedAI(c) - { - c->GetPosition(x,y,z); - pInstance = c->GetInstanceData(); - Demon = 0; - - for (uint8 i = 0; i < 3; ++i)//clear guids - SpellBinderGUID[i] = 0; - } - - ScriptedInstance *pInstance; - - uint32 Whirlwind_Timer; - uint32 ChaosBlast_Timer; - uint32 SwitchToDemon_Timer; - uint32 SwitchToHuman_Timer; - uint32 Berserk_Timer; - uint32 InnerDemons_Timer; - uint32 BanishTimer; - - bool DealDamage; - bool NeedThreatReset; - bool DemonForm; - bool IsFinalForm; - bool EnrageUsed; - float x,y,z; - - uint64 InnderDemon[5]; - uint32 InnerDemon_Count; - uint64 Demon; - uint64 SpellBinderGUID[3]; - - void Reset() - { - CheckChannelers(); - BanishTimer = 1000; - Whirlwind_Timer = 15000; - ChaosBlast_Timer = 1000; - SwitchToDemon_Timer = 45000; - SwitchToHuman_Timer = 60000; - Berserk_Timer = 600000; - InnerDemons_Timer = 30000; - me->SetCanDualWield(true); - DealDamage = true; - DemonForm = false; - IsFinalForm = false; - NeedThreatReset = false; - EnrageUsed = false; - InnerDemon_Count = 0; - me->SetSpeed(MOVE_RUN, 2.0f, true); - me->SetDisplayId(MODEL_NIGHTELF); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - DoCast(me, SPELL_DUAL_WIELD, true); - me->SetCorpseDelay(1000*60*60); - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, NOT_STARTED); - } - - void CheckChannelers(/*bool DoEvade = true*/) - { - for (uint8 i = 0; i < 3; ++i) - { - if (Creature *add = Unit::GetCreature(*me,SpellBinderGUID[i])) - add->DisappearAndDie(); - - float nx = x; - float ny = y; - float o = 2.4f; - if (i == 0) {nx += 10; ny -= 5; o=2.5f;} - if (i == 1) {nx -= 8; ny -= 7; o=0.9f;} - if (i == 2) {nx -= 3; ny += 9; o=5.0f;} - Creature* binder = me->SummonCreature(MOB_SPELLBINDER,nx,ny,z,o,TEMPSUMMON_DEAD_DESPAWN,0); - if (binder) - SpellBinderGUID[i] = binder->GetGUID(); - - } - } - void MoveInLineOfSight(Unit *who) - { - if (me->HasAura(AURA_BANISH)) - return; - - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius)) - { - // Check first that object is in an angle in front of this one before LoS check - if (me->HasInArc(M_PI/2.0f, who) && me->IsWithinLOSInMap(who)) - { - AttackStart(who); - } - } - } - } - - void StartEvent() - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, IN_PROGRESS); - } - - void CheckBanish() - { - uint8 AliveChannelers = 0; - for (uint8 i = 0; i < 3; ++i) - { - Unit *add = Unit::GetUnit(*me,SpellBinderGUID[i]); - if (add && add->isAlive()) - ++AliveChannelers; - } - - // channelers == 0 remove banish aura - if (AliveChannelers == 0 && me->HasAura(AURA_BANISH)) - { - // removing banish aura - me->RemoveAurasDueToSpell(AURA_BANISH); - - // Leotheras is getting immune again - me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, true); - - // changing model to bloodelf - me->SetDisplayId(MODEL_NIGHTELF); - - // and reseting equipment - me->LoadEquipment(me->GetEquipmentId()); - - if (pInstance && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - Unit *victim = NULL; - victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); - if (victim) - me->getThreatManager().addThreat(victim, 1); - StartEvent(); - } - } - else if (AliveChannelers != 0 && !me->HasAura(AURA_BANISH)) - { - // channelers != 0 apply banish aura - // removing Leotheras banish immune to apply AURA_BANISH - me->ApplySpellImmune(AURA_BANISH, IMMUNITY_MECHANIC, MECHANIC_BANISH, false); - DoCast(me, AURA_BANISH); - - // changing model - me->SetDisplayId(MODEL_DEMON); - - // and removing weapons - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - } - } - - //Despawn all Inner Demon summoned - void DespawnDemon() - { - for (uint8 i=0; i<5; ++i) - { - if (InnderDemon[i]) - { - //delete creature - Creature* pCreature = Unit::GetCreature((*me), InnderDemon[i]); - if (pCreature && pCreature->isAlive()) - { - pCreature->ForcedDespawn(); - } - InnderDemon[i] = 0; - } - } - - InnerDemon_Count = 0; - } - - void CastConsumingMadness() //remove this once SPELL_INSIDIOUS_WHISPER is supported by core - { - for (uint8 i=0; i<5; ++i) - { - if (InnderDemon[i] > 0) - { - Creature* pUnit = Unit::GetCreature((*me), InnderDemon[i]); - if (pUnit && pUnit->isAlive()) - { - Unit* pUnit_pTarget = Unit::GetUnit(*pUnit, CAST_AI(mob_inner_demonAI, pUnit->AI())->victimGUID); - if (pUnit_pTarget && pUnit_pTarget->isAlive()) - { - pUnit->CastSpell(pUnit_pTarget, SPELL_CONSUMING_MADNESS, true); - DoModifyThreatPercent(pUnit_pTarget, -100); - } - } - } - } - } - - void KilledUnit(Unit * victim) - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - if (DemonForm) - { - DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); - } - else - { - DoScriptText(RAND(SAY_NIGHTELF_SLAY1,SAY_NIGHTELF_SLAY2,SAY_NIGHTELF_SLAY3), me); - } - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - //despawn copy - if (Demon) - { - if (Creature* pDemon = Unit::GetCreature(*me, Demon)) - pDemon->ForcedDespawn(); - } - if (pInstance) - pInstance->SetData(DATA_LEOTHERASTHEBLINDEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - if (me->HasAura(AURA_BANISH)) - return; - - me->LoadEquipment(me->GetEquipmentId()); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (me->HasAura(AURA_BANISH) || !UpdateVictim()) - { - if (BanishTimer <= diff) - { - CheckBanish();//no need to check every update tick - BanishTimer = 1000; - } else BanishTimer -= diff; - return; - } - if (me->HasAura(SPELL_WHIRLWIND)) - if (Whirlwind_Timer <= diff) - { - Unit *newTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (newTarget) - { - DoResetThreat(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0,newTarget->GetPositionX(),newTarget->GetPositionY(),newTarget->GetPositionZ()); - } - Whirlwind_Timer = 2000; - } else Whirlwind_Timer -= diff; - - // reseting after changing forms and after ending whirlwind - if (NeedThreatReset && !me->HasAura(SPELL_WHIRLWIND)) - { - // when changing forms seting timers (or when ending whirlwind - to avoid adding new variable i use Whirlwind_Timer to countdown 2s while whirlwinding) - if (DemonForm) - InnerDemons_Timer = 30000; - else - Whirlwind_Timer = 15000; - - NeedThreatReset = false; - DoResetThreat(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(me->getVictim()); - } - - //Enrage_Timer (10 min) - if (Berserk_Timer < diff && !EnrageUsed) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_BERSERK); - EnrageUsed = true; - } else Berserk_Timer -= diff; - - if (!DemonForm) - { - //Whirldind Timer - if (!me->HasAura(SPELL_WHIRLWIND)) - { - if (Whirlwind_Timer <= diff) - { - DoCast(me, SPELL_WHIRLWIND); - // while whirlwinding this variable is used to countdown target's change - Whirlwind_Timer = 2000; - NeedThreatReset = true; - } else Whirlwind_Timer -= diff; - } - //Switch_Timer - - if (!IsFinalForm) - if (SwitchToDemon_Timer <= diff) - { - //switch to demon form - me->RemoveAurasDueToSpell(SPELL_WHIRLWIND,0); - me->SetDisplayId(MODEL_DEMON); - DoScriptText(SAY_SWITCH_TO_DEMON, me); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0); - me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0); - DemonForm = true; - NeedThreatReset = true; - SwitchToDemon_Timer = 45000; - } else SwitchToDemon_Timer -= diff; - DoMeleeAttackIfReady(); - } - else - { - //ChaosBlast_Timer - if (!me->getVictim()) - return; - if (me->IsWithinDist(me->getVictim(), 30)) - me->StopMoving(); - if (ChaosBlast_Timer <= diff) - { - // will cast only when in range of spell - if (me->IsWithinDist(me->getVictim(), 30)) - { - //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); - int damage = 100; - me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); - } - ChaosBlast_Timer = 3000; - } else ChaosBlast_Timer -= diff; - //Summon Inner Demon - if (InnerDemons_Timer <= diff) - { - std::list& ThreatList = me->getThreatManager().getThreatList(); - std::vector TargetList; - for (std::list::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) - { - Unit *tempTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->getVictim()->GetGUID() && TargetList.size()<5) - TargetList.push_back(tempTarget); - } - //SpellEntry *spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); - for (std::vector::const_iterator itr = TargetList.begin(); itr != TargetList.end(); ++itr) - { - if ((*itr) && (*itr)->isAlive()) - { - Creature * demon = me->SummonCreature(INNER_DEMON_ID, (*itr)->GetPositionX()+10, (*itr)->GetPositionY()+10, (*itr)->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (demon) - { - demon->AI()->AttackStart((*itr)); - CAST_AI(mob_inner_demonAI, demon->AI())->victimGUID = (*itr)->GetGUID(); - - (*itr)->AddAura(SPELL_INSIDIOUS_WHISPER, *itr); - - if (InnerDemon_Count > 4) - InnerDemon_Count = 0; - - //Safe storing of creatures - InnderDemon[InnerDemon_Count] = demon->GetGUID(); - - //Update demon count - ++InnerDemon_Count; - } - } - } - DoScriptText(SAY_INNER_DEMONS, me); - - InnerDemons_Timer = 999999; - } else InnerDemons_Timer -= diff; - - //Switch_Timer - if (SwitchToHuman_Timer <= diff) - { - //switch to nightelf form - me->SetDisplayId(MODEL_NIGHTELF); - me->LoadEquipment(me->GetEquipmentId()); - - CastConsumingMadness(); - DespawnDemon(); - - DemonForm = false; - NeedThreatReset = true; - - SwitchToHuman_Timer = 60000; - } else SwitchToHuman_Timer -= diff; - } - - if (!IsFinalForm && (me->GetHealth()*100 / me->GetMaxHealth()) < 15) - { - //at this point he divides himself in two parts - CastConsumingMadness(); - DespawnDemon(); - Creature *Copy = NULL; - Copy = DoSpawnCreature(DEMON_FORM, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 6000); - if (Copy) - { - Demon = Copy->GetGUID(); - if (me->getVictim()) - Copy->AI()->AttackStart(me->getVictim()); - } - //set nightelf final form - IsFinalForm = true; - DemonForm = false; - - DoScriptText(SAY_FINAL_FORM, me); - me->SetDisplayId(MODEL_NIGHTELF); - me->LoadEquipment(me->GetEquipmentId()); - } - } -}; - -//Leotheras the Blind Demon Form AI -struct boss_leotheras_the_blind_demonformAI : public ScriptedAI -{ - boss_leotheras_the_blind_demonformAI(Creature *c) : ScriptedAI(c) {} - - uint32 ChaosBlast_Timer; - bool DealDamage; - - void Reset() - { - ChaosBlast_Timer = 1000; - DealDamage = true; - } - - void StartEvent() - { - DoScriptText(SAY_FREE, me); - } - - void KilledUnit(Unit * victim) - { - if (victim->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(RAND(SAY_DEMON_SLAY1,SAY_DEMON_SLAY2,SAY_DEMON_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - //invisibility (blizzlike, at the end of the fight he doesn't die, he disappears) - DoCast(me, 8149, true); - } - - void EnterCombat(Unit * /*who*/) - { - StartEvent(); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - //ChaosBlast_Timer - if (me->IsWithinDist(me->getVictim(), 30)) - me->StopMoving(); - - if (ChaosBlast_Timer <= diff) - { - // will cast only when in range od spell - if (me->IsWithinDist(me->getVictim(), 30)) - { - //DoCast(me->getVictim(), SPELL_CHAOS_BLAST, true); - int damage = 100; - me->CastCustomSpell(me->getVictim(), SPELL_CHAOS_BLAST, &damage, NULL, NULL, false, NULL, NULL, me->GetGUID()); - ChaosBlast_Timer = 3000; - } - } else ChaosBlast_Timer -= diff; - - //Do NOT deal any melee damage to the target. - } -}; -struct mob_greyheart_spellbinderAI : public ScriptedAI -{ - mob_greyheart_spellbinderAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - leotherasGUID = 0; - AddedBanish = false; - } - - ScriptedInstance *pInstance; - - uint64 leotherasGUID; - - uint32 Mindblast_Timer; - uint32 Earthshock_Timer; - - bool AddedBanish; - - void Reset() - { - Mindblast_Timer = 3000 + rand()%5000; - Earthshock_Timer = 5000 + rand()%5000; - - if (pInstance) - { - pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, 0); - Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); - if (leotheras && leotheras->isAlive()) - CAST_AI(boss_leotheras_the_blindAI, leotheras->AI())->CheckChannelers(/*false*/); - } - } - - void EnterCombat(Unit * who) - { - me->InterruptNonMeleeSpells(false); - if (pInstance) - pInstance->SetData64(DATA_LEOTHERAS_EVENT_STARTER, who->GetGUID()); - } - - void JustRespawned() - { - AddedBanish = false; - Reset(); - } - - void CastChanneling() - { - if (!me->isInCombat() && !me->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) - { - if (leotherasGUID) - { - Creature *leotheras = Unit::GetCreature(*me, leotherasGUID); - if (leotheras && leotheras->isAlive()) - DoCast(leotheras, BANISH_BEAM); - } - } - } - - void UpdateAI(const uint32 diff) - { - if (pInstance) - { - if (!leotherasGUID) - leotherasGUID = pInstance->GetData64(DATA_LEOTHERAS); - - if (!me->isInCombat() && pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - Unit *victim = NULL; - victim = Unit::GetUnit(*me, pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)); - if (victim) - AttackStart(victim); - } - } - - if (!UpdateVictim()) - { - CastChanneling(); - return; - } - - if (pInstance && !pInstance->GetData64(DATA_LEOTHERAS_EVENT_STARTER)) - { - EnterEvadeMode(); - return; - } - - if (Mindblast_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (pTarget)DoCast(pTarget, SPELL_MINDBLAST); - - Mindblast_Timer = 10000 + rand()%5000; - } else Mindblast_Timer -= diff; - - if (Earthshock_Timer <= diff) - { - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr) - { - if (Player* i_pl = itr->getSource()) - { - bool isCasting = false; - for (uint8 i = 0; i < CURRENT_MAX_SPELL; ++i) - if (i_pl->GetCurrentSpell(i)) - isCasting = true; - - if (isCasting) - { - DoCast(i_pl, SPELL_EARTHSHOCK); - break; - } - } - } - Earthshock_Timer = 8000 + rand()%7000; - } else Earthshock_Timer -= diff; - DoMeleeAttackIfReady(); - } - - void JustDied(Unit * /*killer*/) {} -}; -CreatureAI* GetAI_boss_leotheras_the_blind(Creature* pCreature) -{ - return new boss_leotheras_the_blindAI (pCreature); -} - -CreatureAI* GetAI_boss_leotheras_the_blind_demonform(Creature* pCreature) -{ - return new boss_leotheras_the_blind_demonformAI (pCreature); -} - -CreatureAI* GetAI_mob_greyheart_spellbinder(Creature* pCreature) -{ - return new mob_greyheart_spellbinderAI (pCreature); -} - -CreatureAI* GetAI_mob_inner_demon(Creature* pCreature) -{ - return new mob_inner_demonAI (pCreature); -} -void AddSC_boss_leotheras_the_blind() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_leotheras_the_blind"; - newscript->GetAI = &GetAI_boss_leotheras_the_blind; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_leotheras_the_blind_demonform"; - newscript->GetAI = &GetAI_boss_leotheras_the_blind_demonform; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_greyheart_spellbinder"; - newscript->GetAI = &GetAI_mob_greyheart_spellbinder; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_inner_demon"; - newscript->GetAI = &GetAI_mob_inner_demon; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp deleted file mode 100644 index b1c0c10bcce..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_lurker_below.cpp +++ /dev/null @@ -1,458 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: boss_the_lurker_below -SD%Complete: 80 -SDComment: Coilfang Frenzy, find out how could we fishing in the strangepool -SDCategory: The Lurker Below -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" -#include "ScriptedSimpleAI.h" -#include "Spell.h" - -#define SPELL_SPOUT 37433 -#define SPELL_SPOUT_ANIM 42835 -#define SPELL_SPOUT_BREATH 37431 -#define SPELL_KNOCKBACK 19813 -#define SPELL_GEYSER 37478 -#define SPELL_WHIRL 37660 -#define SPELL_WATERBOLT 37138 -#define SPELL_SUBMERGE 37550 -#define SPELL_EMERGE 20568 - -#define EMOTE_SPOUT "The Lurker Below takes a deep breath." - -#define SPOUT_DIST 100 - -#define MOB_COILFANG_GUARDIAN 21873 -#define MOB_COILFANG_AMBUSHER 21865 - -//Ambusher spells -#define SPELL_SPREAD_SHOT 37790 -#define SPELL_SHOOT 37770 - -//Guardian spells -#define SPELL_ARCINGSMASH 38761 // Wrong SpellId. Can't find the right one. -#define SPELL_HAMSTRING 26211 - -float AddPos[9][3] = -{ - {2.8553810, -459.823914, -19.182686}, //MOVE_AMBUSHER_1 X, Y, Z - {12.400000, -466.042267, -19.182686}, //MOVE_AMBUSHER_2 X, Y, Z - {51.366653, -460.836060, -19.182686}, //MOVE_AMBUSHER_3 X, Y, Z - {62.597980, -457.433044, -19.182686}, //MOVE_AMBUSHER_4 X, Y, Z - {77.607452, -384.302765, -19.182686}, //MOVE_AMBUSHER_5 X, Y, Z - {63.897900, -378.984924, -19.182686}, //MOVE_AMBUSHER_6 X, Y, Z - {34.447250, -387.333618, -19.182686}, //MOVE_GUARDIAN_1 X, Y, Z - {14.388216, -423.468018, -19.625271}, //MOVE_GUARDIAN_2 X, Y, Z - {42.471519, -445.115295, -19.769423} //MOVE_GUARDIAN_3 X, Y, Z -}; - -struct boss_the_lurker_belowAI : public Scripted_NoMovementAI -{ - boss_the_lurker_belowAI(Creature *c) : Scripted_NoMovementAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - SpellEntry *TempSpell = GET_SPELL(SPELL_SPOUT_ANIM); - if (TempSpell) - { - TempSpell->Effect[0] = 0;//remove all spell effect, only anim is needed - TempSpell->Effect[1] = 0; - TempSpell->Effect[2] = 0; - } - } - - ScriptedInstance* pInstance; - SummonList Summons; - - bool Spawned; - bool Submerged; - bool InRange; - bool CanStartEvent; - uint32 RotTimer; - uint32 SpoutAnimTimer; - uint32 WaterboltTimer; - uint32 SpoutTimer; - uint32 WhirlTimer; - uint32 PhaseTimer; - uint32 GeyserTimer; - uint32 CheckTimer; - uint32 WaitTimer; - uint32 WaitTimer2; - - bool CheckCanStart()//check if players fished - { - if (pInstance && pInstance->GetData(DATA_STRANGE_POOL) == NOT_STARTED) - return false; - return true; - } - void Reset() - { - me->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); - SpoutAnimTimer = 1000; - RotTimer = 0; - WaterboltTimer = 15000;//give time to get in range when fight starts - SpoutTimer = 45000; - WhirlTimer = 18000;//after avery spout - PhaseTimer = 120000; - GeyserTimer = rand()%5000 + 15000; - CheckTimer = 15000;//give time to get in range when fight starts - WaitTimer = 60000;//never reached - WaitTimer2 = 60000;//never reached - - Submerged = true;//will be false at combat start - Spawned = false; - InRange = false; - CanStartEvent = false; - - Summons.DespawnAll(); - - if (pInstance) - { - pInstance->SetData(DATA_THELURKERBELOWEVENT, NOT_STARTED); - pInstance->SetData(DATA_STRANGE_POOL, NOT_STARTED); - } - DoCast(me, SPELL_SUBMERGE);//submerge anim - me->SetVisibility(VISIBILITY_OFF);//we start invis under water, submerged - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_THELURKERBELOWEVENT, DONE); - - Summons.DespawnAll(); - } - - void EnterCombat(Unit * who) - { - if (pInstance) - pInstance->SetData(DATA_THELURKERBELOWEVENT, IN_PROGRESS); - Scripted_NoMovementAI::EnterCombat(who); - } - - void MoveInLineOfSight(Unit *who) - { - if (!CanStartEvent)//boss is invisible, don't attack - return; - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who))) - { - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius)) - { - AttackStart(who); - } - } - } - - void MovementInform(uint32 type, uint32 /*id*/) - { - if (type == ROTATE_MOTION_TYPE) - me->SetReactState(REACT_AGGRESSIVE); - } - - void UpdateAI(const uint32 diff) - { - if (!CanStartEvent)//boss is invisible, don't attack - { - if (CheckCanStart()) - { - if (Submerged) - { - me->SetVisibility(VISIBILITY_ON); - Submerged = false; - WaitTimer2 = 500; - } - if (!Submerged && WaitTimer2 <= diff)//wait 500ms before emerge anim - { - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); - DoCast(me, SPELL_EMERGE, false); - WaitTimer2 = 60000;//never reached - WaitTimer = 3000; - } else WaitTimer2 -= diff; - - if (WaitTimer <= diff)//wait 3secs for emerge anim, then attack - { - WaitTimer = 3000; - CanStartEvent=true;//fresh fished from pool - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } else WaitTimer -= diff; - } - return; - } - - if (me->getThreatManager().getThreatList().empty())//check if should evade - { - if (me->isInCombat()) - EnterEvadeMode(); - return; - } - if (!Submerged) - { - if (PhaseTimer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SUBMERGE); - PhaseTimer = 60000;//60secs submerged - Submerged = true; - } else PhaseTimer-=diff; - - if (SpoutTimer <= diff) - { - me->MonsterTextEmote(EMOTE_SPOUT,0,true); - me->SetReactState(REACT_PASSIVE); - me->GetMotionMaster()->MoveRotate(20000, rand()%2 ? ROTATE_DIRECTION_LEFT : ROTATE_DIRECTION_RIGHT); - SpoutTimer = 45000; - WhirlTimer = 20000;//whirl directly after spout - RotTimer = 20000; - return; - } else SpoutTimer -= diff; - - //Whirl directly after a Spout and at random times - if (WhirlTimer <= diff) - { - WhirlTimer = 18000; - DoCast(me, SPELL_WHIRL); - } else WhirlTimer -= diff; - - if (CheckTimer <= diff)//check if there are players in melee range - { - InRange = false; - Map* pMap = me->GetMap(); - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (!PlayerList.isEmpty()) - { - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (me->IsWithinMeleeRange(i->getSource())) - InRange = true; - } - } - CheckTimer = 2000; - } else CheckTimer -= diff; - - if (RotTimer) - { - Map* pMap = me->GetMap(); - if (pMap->IsDungeon()) - { - Map::PlayerList const &PlayerList = pMap->GetPlayers(); - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (i->getSource() && i->getSource()->isAlive() && me->HasInArc((double)diff/20000*(double)M_PI*2,i->getSource()) && me->IsWithinDist(i->getSource(), SPOUT_DIST) && !i->getSource()->IsInWater()) - DoCast(i->getSource(), SPELL_SPOUT, true);//only knock back palyers in arc, in 100yards, not in water - } - } - - if (SpoutAnimTimer <= diff) - { - DoCast(me, SPELL_SPOUT_ANIM, true); - SpoutAnimTimer = 1000; - } else SpoutAnimTimer -= diff; - - if (RotTimer <= diff) - { - RotTimer = 0; - } else RotTimer -= diff; - return; - } - - if (GeyserTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1); - if (!pTarget && me->getVictim()) - pTarget = me->getVictim(); - if (pTarget) - DoCast(pTarget, SPELL_GEYSER, true); - GeyserTimer = rand()%5000 + 15000; - } else GeyserTimer -= diff; - - if (!InRange)//if on players in melee range cast Waterbolt - { - if (WaterboltTimer <= diff) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - if (!pTarget && me->getVictim()) - pTarget = me->getVictim(); - if (pTarget) - DoCast(pTarget, SPELL_WATERBOLT, true); - WaterboltTimer = 3000; - } else WaterboltTimer -= diff; - } - - if (!UpdateCombatState()) - return; - - DoMeleeAttackIfReady(); - - }else//submerged - { - if (PhaseTimer <= diff) - { - Submerged = false; - me->InterruptNonMeleeSpells(false);//shouldn't be any - me->RemoveAllAuras(); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->RemoveFlag(UNIT_NPC_EMOTESTATE,EMOTE_STATE_SUBMERGED); - DoCast(me, SPELL_EMERGE, true); - Spawned = false; - SpoutTimer = 3000; // directly cast Spout after emerging! - PhaseTimer = 120000; - return; - } else PhaseTimer-=diff; - - if (me->getThreatManager().getThreatList().empty())//check if should evade - { - EnterEvadeMode(); - return; - } - if (!me->isInCombat()) - DoZoneInCombat(); - - if (!Spawned) - { - me->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - //spawn adds - for (uint8 i = 0; i < 9; ++i) - { - Creature* Summoned; - if (i < 6) - Summoned = me->SummonCreature(MOB_COILFANG_AMBUSHER,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - else Summoned = me->SummonCreature(MOB_COILFANG_GUARDIAN,AddPos[i][0],AddPos[i][1],AddPos[i][2], 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - - if (Summoned) - Summons.Summon(Summoned); - } - Spawned = true; - } - } - } - }; - -CreatureAI* GetAI_mob_coilfang_guardian(Creature* pCreature) -{ - SimpleAI* ai = new SimpleAI (pCreature); - - ai->Spell[0].Enabled = true; - ai->Spell[0].Spell_Id = SPELL_ARCINGSMASH; - ai->Spell[0].Cooldown = 15000; - ai->Spell[0].First_Cast = 5000; - ai->Spell[0].Cast_Target_Type = CAST_HOSTILE_TARGET; - - ai->Spell[1].Enabled = true; - ai->Spell[1].Spell_Id = SPELL_HAMSTRING; - ai->Spell[1].Cooldown = 10000; - ai->Spell[1].First_Cast = 2000; - ai->Spell[1].Cast_Target_Type = CAST_HOSTILE_TARGET; - - return ai; -} - -struct mob_coilfang_ambusherAI : public Scripted_NoMovementAI -{ - mob_coilfang_ambusherAI(Creature *c) : Scripted_NoMovementAI(c) - { - SpellEntry *TempSpell = GET_SPELL(SPELL_SHOOT); - if (TempSpell) - TempSpell->Effect[0] = 2;//change spell effect from weapon % dmg to simple phisical dmg - } - - uint32 MultiShotTimer; - uint32 ShootBowTimer; - - void Reset() - { - MultiShotTimer = 10000; - ShootBowTimer = 4000; - - } - - void EnterCombat(Unit * /*who*/) - { - - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who) && me->IsWithinDistInMap(who, 45)) - { - AttackStart(who); - } - } - - void UpdateAI(const uint32 diff) - { - if (MultiShotTimer <= diff) - { - if (me->getVictim()) - DoCast(me->getVictim(), SPELL_SPREAD_SHOT, true); - - MultiShotTimer = 10000+rand()%10000; - ShootBowTimer += 1500;//add global cooldown - } else MultiShotTimer -= diff; - - if (ShootBowTimer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - int bp0 = 1100; - if (pTarget) - me->CastCustomSpell(pTarget,SPELL_SHOOT,&bp0,NULL,NULL,true); - ShootBowTimer = 4000+rand()%5000; - MultiShotTimer += 1500;//add global cooldown - } else ShootBowTimer -= diff; - } -}; - -CreatureAI* GetAI_mob_coilfang_ambusher(Creature* pCreature) -{ - return new mob_coilfang_ambusherAI (pCreature); -} - -CreatureAI* GetAI_boss_the_lurker_below(Creature* pCreature) -{ - return new boss_the_lurker_belowAI (pCreature); -} - -void AddSC_boss_the_lurker_below() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_lurker_below"; - newscript->GetAI = &GetAI_boss_the_lurker_below; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_guardian"; - newscript->GetAI = &GetAI_mob_coilfang_guardian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_ambusher"; - newscript->GetAI = &GetAI_mob_coilfang_ambusher; - newscript->RegisterSelf(); -} - - diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp deleted file mode 100644 index 14c87aee141..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/boss_morogrim_tidewalker.cpp +++ /dev/null @@ -1,369 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Morogrim_Tidewalker -SD%Complete: 90 -SDComment: Water globules don't explode properly, remove hacks -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define SAY_AGGRO -1548030 -#define SAY_SUMMON1 -1548031 -#define SAY_SUMMON2 -1548032 -#define SAY_SUMMON_BUBL1 -1548033 -#define SAY_SUMMON_BUBL2 -1548034 -#define SAY_SLAY1 -1548035 -#define SAY_SLAY2 -1548036 -#define SAY_SLAY3 -1548037 -#define SAY_DEATH -1548038 -#define EMOTE_WATERY_GRAVE -1548039 -#define EMOTE_EARTHQUAKE -1548040 -#define EMOTE_WATERY_GLOBULES -1548041 - -#define SPELL_TIDAL_WAVE 37730 -#define SPELL_WATERY_GRAVE 38049 -#define SPELL_EARTHQUAKE 37764 -#define SPELL_WATERY_GRAVE_EXPLOSION 37852 - -#define WATERY_GRAVE_X1 334.64 -#define WATERY_GRAVE_Y1 -728.89 -#define WATERY_GRAVE_Z1 -14.42 -#define WATERY_GRAVE_X2 365.51 -#define WATERY_GRAVE_Y2 -737.14 -#define WATERY_GRAVE_Z2 -14.44 -#define WATERY_GRAVE_X3 366.19 -#define WATERY_GRAVE_Y3 -709.59 -#define WATERY_GRAVE_Z3 -14.36 -#define WATERY_GRAVE_X4 372.93 -#define WATERY_GRAVE_Y4 -690.96 -#define WATERY_GRAVE_Z4 -14.44 - -#define SPELL_WATERY_GRAVE_1 38023 -#define SPELL_WATERY_GRAVE_2 38024 -#define SPELL_WATERY_GRAVE_3 38025 -#define SPELL_WATERY_GRAVE_4 37850 - -#define SPELL_SUMMON_WATER_GLOBULE_1 37854 -#define SPELL_SUMMON_WATER_GLOBULE_2 37858 -#define SPELL_SUMMON_WATER_GLOBULE_3 37860 -#define SPELL_SUMMON_WATER_GLOBULE_4 37861 - -/*#define SPELL_SUMMON_MURLOC_A6 39813 -#define SPELL_SUMMON_MURLOC_A7 39814 -#define SPELL_SUMMON_MURLOC_A8 39815 -#define SPELL_SUMMON_MURLOC_A9 39816 -#define SPELL_SUMMON_MURLOC_A10 39817 - -#define SPELL_SUMMON_MURLOC_B6 39818 -#define SPELL_SUMMON_MURLOC_B7 39819 -#define SPELL_SUMMON_MURLOC_B8 39820 -#define SPELL_SUMMON_MURLOC_B9 39821 -#define SPELL_SUMMON_MURLOC_B10 39822*/ - -float MurlocCords[10][5] = -{ - {21920, 424.36, -715.4, -7.14, 0.124}, - {21920, 425.13, -719.3, -7.14, 0.124}, - {21920, 425.05, -724.23, -7.14, 0.124}, - {21920, 424.91, -728.68, -7.14, 0.124}, - {21920, 424.84, -732.18, -7.14, 0.124}, - {21920, 321.05, -734.2, -13.15, 0.124}, - {21920, 321.05, -729.4, -13.15, 0.124}, - {21920, 321.05, -724.03, -13.15, 0.124}, - {21920, 321.05, -718.73, -13.15, 0.124}, - {21920, 321.05, -714.24, -13.15, 0.124} -}; - -//Creatures -#define WATER_GLOBULE 21913 -#define TIDEWALKER_LURKER 21920 - -//Morogrim Tidewalker AI -struct boss_morogrim_tidewalkerAI : public ScriptedAI -{ - boss_morogrim_tidewalkerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - Map::PlayerList const *PlayerList; - - uint32 TidalWave_Timer; - uint32 WateryGrave_Timer; - uint32 Earthquake_Timer; - uint32 WateryGlobules_Timer; - uint32 globulespell[4]; - int8 Playercount; - int8 counter; - - bool Earthquake; - bool Phase2; - - void Reset() - { - TidalWave_Timer = 10000; - WateryGrave_Timer = 30000; - Earthquake_Timer = 40000; - WateryGlobules_Timer = 0; - globulespell[0] = SPELL_SUMMON_WATER_GLOBULE_1; - globulespell[1] = SPELL_SUMMON_WATER_GLOBULE_2; - globulespell[2] = SPELL_SUMMON_WATER_GLOBULE_3; - globulespell[3] = SPELL_SUMMON_WATER_GLOBULE_4; - - Earthquake = false; - Phase2 = false; - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, NOT_STARTED); - } - - void StartEvent() - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, IN_PROGRESS); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_MOROGRIMTIDEWALKEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - PlayerList = &me->GetMap()->GetPlayers(); - Playercount = PlayerList->getSize(); - StartEvent(); - } - - void ApplyWateryGrave(Unit* pPlayer, uint8 i) - { - switch(i) - { - case 0: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_1, true); break; - case 1: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_2, true); break; - case 2: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_3, true); break; - case 3: pPlayer->CastSpell(pPlayer, SPELL_WATERY_GRAVE_4, true); break; - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Earthquake_Timer - if (Earthquake_Timer <= diff) - { - if (!Earthquake) - { - DoCast(me->getVictim(), SPELL_EARTHQUAKE); - Earthquake = true; - Earthquake_Timer = 10000; - } - else - { - DoScriptText(RAND(SAY_SUMMON1,SAY_SUMMON2), me); - - for (uint8 i = 0; i < 10; ++i) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - Creature* Murloc = me->SummonCreature(MurlocCords[i][0],MurlocCords[i][1],MurlocCords[i][2],MurlocCords[i][3],MurlocCords[i][4], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000); - if (pTarget && Murloc) - Murloc->AI()->AttackStart(pTarget); - } - DoScriptText(EMOTE_EARTHQUAKE, me); - Earthquake = false; - Earthquake_Timer = 40000+rand()%5000; - } - } else Earthquake_Timer -= diff; - - //TidalWave_Timer - if (TidalWave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_TIDAL_WAVE); - TidalWave_Timer = 20000; - } else TidalWave_Timer -= diff; - - if (!Phase2) - { - //WateryGrave_Timer - if (WateryGrave_Timer <= diff) - { - //Teleport 4 players under the waterfalls - Unit *pTarget; - using std::set; - setlist; - set::const_iterator itr; - for (uint8 i = 0; i < 4; ++i) - { - counter = 0; - do - { - pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 50, true); //target players only - if (counter < Playercount) - break; - if (pTarget) - itr = list.find(pTarget->GetGUID()); - ++counter; - } while (itr != list.end()); - - if (pTarget) - { - list.insert(pTarget->GetGUID()); - ApplyWateryGrave(pTarget, i); - } - } - - DoScriptText(RAND(SAY_SUMMON_BUBL1,SAY_SUMMON_BUBL2), me); - - DoScriptText(EMOTE_WATERY_GRAVE, me); - WateryGrave_Timer = 30000; - } else WateryGrave_Timer -= diff; - - //Start Phase2 - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) - Phase2 = true; - } - else - { - //WateryGlobules_Timer - if (WateryGlobules_Timer <= diff) - { - Unit* pGlobuleTarget; - using std::set; - setglobulelist; - set::const_iterator itr; - for (uint8 g = 0; g < 4; g++) //one unit can't cast more than one spell per update, so some players have to cast for us XD - { - counter = 0; - do { - pGlobuleTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 50, true); - if (pGlobuleTarget) - itr = globulelist.find(pGlobuleTarget->GetGUID()); - if (counter > Playercount) - break; - ++counter; - } while (itr != globulelist.end()); - if (pGlobuleTarget) - globulelist.insert(pGlobuleTarget->GetGUID()); - pGlobuleTarget->CastSpell(pGlobuleTarget, globulespell[g], true); - } - DoScriptText(EMOTE_WATERY_GLOBULES, me); - WateryGlobules_Timer = 25000; - } else WateryGlobules_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -//Water Globule AI -#define SPELL_GLOBULE_EXPLOSION 37871 - -struct mob_water_globuleAI : public ScriptedAI -{ - mob_water_globuleAI(Creature *c) : ScriptedAI(c) {} - - uint32 Check_Timer; - - void Reset() - { - Check_Timer = 1000; - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - } - - void EnterCombat(Unit * /*who*/) {} - - void MoveInLineOfSight(Unit *who) - { - if (!who || me->getVictim()) - return; - - if (who->isTargetableForAttack() && who->isInAccessiblePlaceFor(me) && me->IsHostileTo(who)) - { - //no attack radius check - it attacks the first target that moves in his los - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Check_Timer <= diff) - { - if (me->IsWithinDistInMap(me->getVictim(), 5)) - { - DoCast(me->getVictim(), SPELL_GLOBULE_EXPLOSION); - - //despawn - me->ForcedDespawn(); - return; - } - Check_Timer = 500; - } else Check_Timer -= diff; - - //do NOT deal any melee damage to the target. - } -}; - -CreatureAI* GetAI_boss_morogrim_tidewalker(Creature* pCreature) -{ - return new boss_morogrim_tidewalkerAI (pCreature); -} -CreatureAI* GetAI_mob_water_globule(Creature* pCreature) -{ - return new mob_water_globuleAI (pCreature); -} - -void AddSC_boss_morogrim_tidewalker() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_morogrim_tidewalker"; - newscript->GetAI = &GetAI_boss_morogrim_tidewalker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_water_globule"; - newscript->GetAI = &GetAI_mob_water_globule; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp deleted file mode 100644 index c80afae15c7..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/instance_serpent_shrine.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Serpent_Shrine -SD%Complete: 100 -SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Serpent Shrine Scripts -SDCategory: Coilfang Resevoir, Serpent Shrine Cavern -EndScriptData */ - -#include "ScriptedPch.h" -#include "serpent_shrine.h" - -#define MAX_ENCOUNTER 6 -#define SPELL_SCALDINGWATER 37284 -#define MOB_COILFANG_FRENZY 21508 -#define TRASHMOB_COILFANG_PRIESTESS 21220 //6*2 -#define TRASHMOB_COILFANG_SHATTERER 21301 //6*3 - -#define MIN_KILLS 30 - -//NOTE: there are 6 platforms -//there should be 3 shatterers and 2 priestess on all platforms, total of 30 elites, else it won't work! -//delete all other elites not on platforms! these mobs should only be on those platforms nowhere else. - -/* Serpentshrine cavern encounters: -0 - Hydross The Unstable event -1 - Leotheras The Blind Event -2 - The Lurker Below Event -3 - Fathom-Lord Karathress Event -4 - Morogrim Tidewalker Event -5 - Lady Vashj Event -*/ - -bool GOHello_go_bridge_console(Player* /*pPlayer*/, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - - if (!pInstance) - return false; - - if (pInstance) - pInstance->SetData(DATA_CONTROL_CONSOLE, DONE); - - return true; -} - -struct instance_serpentshrine_cavern : public ScriptedInstance -{ - instance_serpentshrine_cavern(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 LurkerBelow; - uint64 Sharkkis; - uint64 Tidalvess; - uint64 Caribdis; - uint64 LadyVashj; - uint64 Karathress; - uint64 KarathressEvent_Starter; - uint64 LeotherasTheBlind; - uint64 LeotherasEventStarter; - - uint64 ControlConsole; - uint64 BridgePart[3]; - uint32 StrangePool; - uint32 FishingTimer; - uint32 LurkerSubEvent; - uint32 WaterCheckTimer; - uint32 FrenzySpawnTimer; - uint32 Water; - uint32 TrashCount; - - bool ShieldGeneratorDeactivated[4]; - uint32 m_auiEncounter[MAX_ENCOUNTER]; - bool DoSpawnFrenzy; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - LurkerBelow = 0; - Sharkkis = 0; - Tidalvess = 0; - Caribdis = 0; - LadyVashj = 0; - Karathress = 0; - KarathressEvent_Starter = 0; - LeotherasTheBlind = 0; - LeotherasEventStarter = 0; - - ControlConsole = 0; - BridgePart[0] = 0; - BridgePart[1] = 0; - BridgePart[2] = 0; - StrangePool = 0; - Water = WATERSTATE_FRENZY; - - ShieldGeneratorDeactivated[0] = false; - ShieldGeneratorDeactivated[1] = false; - ShieldGeneratorDeactivated[2] = false; - ShieldGeneratorDeactivated[3] = false; - FishingTimer = 1000; - LurkerSubEvent = 0; - WaterCheckTimer = 500; - FrenzySpawnTimer = 2000; - DoSpawnFrenzy = false; - TrashCount = 0; - - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void Update (uint32 diff) - { - //Lurker Fishing event - if (LurkerSubEvent == LURKER_FISHING) - { - if (FishingTimer <= diff) - { - LurkerSubEvent = LURKER_HOOKED; - SetData(DATA_STRANGE_POOL, IN_PROGRESS);//just fished, signal Lurker script to emerge and start fight, we use IN_PROGRESS so it won't get saved and lurker will be alway invis at start if server restarted - } else FishingTimer -= diff; - } - //Water checks - if (WaterCheckTimer <= diff) - { - if (TrashCount >= MIN_KILLS) - Water = WATERSTATE_SCALDING; - else - Water = WATERSTATE_FRENZY; - - Map::PlayerList const &PlayerList = instance->GetPlayers(); - if (PlayerList.isEmpty()) - return; - for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) - { - if (Player* pPlayer = i->getSource()) - { - if (pPlayer->isAlive() && /*i->getSource()->GetPositionZ() <= -21.434931f*/pPlayer->IsInWater()) - { - if (Water == WATERSTATE_SCALDING) - { - - if (!pPlayer->HasAura(SPELL_SCALDINGWATER)) - { - pPlayer->CastSpell(pPlayer, SPELL_SCALDINGWATER,true); - } - } else if (Water == WATERSTATE_FRENZY) - { - //spawn frenzy - if (DoSpawnFrenzy) - { - if (Creature* frenzy = pPlayer->SummonCreature(MOB_COILFANG_FRENZY,pPlayer->GetPositionX(),pPlayer->GetPositionY(),pPlayer->GetPositionZ(),pPlayer->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,2000)) - { - frenzy->Attack(pPlayer,false); - frenzy->AddUnitMovementFlag(MOVEMENTFLAG_SWIMMING | MOVEMENTFLAG_LEVITATING); - } - DoSpawnFrenzy = false; - } - } - } - if (!pPlayer->IsInWater()) - pPlayer->RemoveAurasDueToSpell(SPELL_SCALDINGWATER); - } - - } - WaterCheckTimer = 500;//remove stress from core - } else WaterCheckTimer -= diff; - if (FrenzySpawnTimer <= diff) - { - DoSpawnFrenzy = true; - FrenzySpawnTimer = 2000; - } else FrenzySpawnTimer -= diff; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 184568: - ControlConsole = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184203: - BridgePart[0] = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184204: - BridgePart[1] = pGo->GetGUID(); - pGo->setActive(true); - break; - - case 184205: - BridgePart[2] = pGo->GetGUID(); - pGo->setActive(true); - break; - case GAMEOBJECT_FISHINGNODE_ENTRY://no way checking if fish is hooked, so we create a timed event - if (LurkerSubEvent == LURKER_NOT_STARTED) - { - FishingTimer = 10000+rand()%30000;//random time before lurker emerges - LurkerSubEvent = LURKER_FISHING; - } - break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 21212: LadyVashj = pCreature->GetGUID(); break; - case 21214: Karathress = pCreature->GetGUID(); break; - case 21966: Sharkkis = pCreature->GetGUID(); break; - case 21217: LurkerBelow = pCreature->GetGUID(); break; - case 21965: Tidalvess = pCreature->GetGUID(); break; - case 21964: Caribdis = pCreature->GetGUID(); break; - case 21215: LeotherasTheBlind = pCreature->GetGUID(); break; - /*case TRASHMOB_COILFANG_PRIESTESS: - case TRASHMOB_COILFANG_SHATTERER: - if (pCreature->isAlive()) - ++TrashCount; - break;*/ - } - } - - void SetData64(uint32 type, uint64 data) - { - if (type == DATA_KARATHRESSEVENT_STARTER) - KarathressEvent_Starter = data; - if (type == DATA_LEOTHERAS_EVENT_STARTER) - LeotherasEventStarter = data; - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_THELURKERBELOW: return LurkerBelow; - case DATA_SHARKKIS: return Sharkkis; - case DATA_TIDALVESS: return Tidalvess; - case DATA_CARIBDIS: return Caribdis; - case DATA_LADYVASHJ: return LadyVashj; - case DATA_KARATHRESS: return Karathress; - case DATA_KARATHRESSEVENT_STARTER: return KarathressEvent_Starter; - case DATA_LEOTHERAS: return LeotherasTheBlind; - case DATA_LEOTHERAS_EVENT_STARTER: return LeotherasEventStarter; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_STRANGE_POOL: - { - StrangePool = data; - if (data == NOT_STARTED) - LurkerSubEvent = LURKER_NOT_STARTED; - } - break; - case DATA_CONTROL_CONSOLE: - if (data == DONE) - { - HandleGameObject(BridgePart[0], true); - HandleGameObject(BridgePart[0], true); - HandleGameObject(BridgePart[0], true); - } - ControlConsole = data;break; - case DATA_TRASH : - { - if (data == 1 && TrashCount < MIN_KILLS) - ++TrashCount;//+1 died - SaveToDB(); - break; - } - case DATA_WATER : Water = data;break; - case DATA_HYDROSSTHEUNSTABLEEVENT: m_auiEncounter[0] = data; break; - case DATA_LEOTHERASTHEBLINDEVENT: m_auiEncounter[1] = data; break; - case DATA_THELURKERBELOWEVENT: m_auiEncounter[2] = data; break; - case DATA_KARATHRESSEVENT: m_auiEncounter[3] = data; break; - case DATA_MOROGRIMTIDEWALKEREVENT: m_auiEncounter[4] = data; break; - //Lady Vashj - case DATA_LADYVASHJEVENT: - if (data == NOT_STARTED) - { - ShieldGeneratorDeactivated[0] = false; - ShieldGeneratorDeactivated[1] = false; - ShieldGeneratorDeactivated[2] = false; - ShieldGeneratorDeactivated[3] = false; - } - m_auiEncounter[5] = data; break; - case DATA_SHIELDGENERATOR1:ShieldGeneratorDeactivated[0] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR2:ShieldGeneratorDeactivated[1] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR3:ShieldGeneratorDeactivated[2] = (data) ? true : false; break; - case DATA_SHIELDGENERATOR4:ShieldGeneratorDeactivated[3] = (data) ? true : false; break; - } - - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_HYDROSSTHEUNSTABLEEVENT: return m_auiEncounter[0]; - case DATA_LEOTHERASTHEBLINDEVENT: return m_auiEncounter[1]; - case DATA_THELURKERBELOWEVENT: return m_auiEncounter[2]; - case DATA_KARATHRESSEVENT: return m_auiEncounter[3]; - case DATA_MOROGRIMTIDEWALKEREVENT: return m_auiEncounter[4]; - //Lady Vashj - case DATA_LADYVASHJEVENT: return m_auiEncounter[5]; - case DATA_SHIELDGENERATOR1: return ShieldGeneratorDeactivated[0]; - case DATA_SHIELDGENERATOR2: return ShieldGeneratorDeactivated[1]; - case DATA_SHIELDGENERATOR3: return ShieldGeneratorDeactivated[2]; - case DATA_SHIELDGENERATOR4: return ShieldGeneratorDeactivated[3]; - case DATA_CANSTARTPHASE3: - if (ShieldGeneratorDeactivated[0] && ShieldGeneratorDeactivated[1] && ShieldGeneratorDeactivated[2] && ShieldGeneratorDeactivated[3])return 1;break; - case DATA_STRANGE_POOL: return StrangePool; - case DATA_WATER: return Water; - } - return 0; - } - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << TrashCount; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> TrashCount; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_serpentshrine_cavern(Map* pMap) -{ - return new instance_serpentshrine_cavern(pMap); -} - -void AddSC_instance_serpentshrine_cavern() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "instance_serpent_shrine"; - newscript->GetInstanceData = &GetInstanceData_instance_serpentshrine_cavern; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_bridge_console"; - newscript->pGOHello = &GOHello_go_bridge_console; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h b/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h deleted file mode 100644 index adfa39dc7e0..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/serpent_shrine/serpent_shrine.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SERPENT_SHRINE_H -#define DEF_SERPENT_SHRINE_H -enum LurkerEventState -{ - LURKER_NOT_STARTED = 0, - LURKER_FISHING = 1, - LURKER_HOOKED = 2 -}; -enum WaterEventState -{ - WATERSTATE_NONE = 0, - WATERSTATE_FRENZY = 1, - WATERSTATE_SCALDING = 2 -}; -#define DATA_CANSTARTPHASE3 1 -#define DATA_CARIBDIS 2 -#define DATA_HYDROSSTHEUNSTABLEEVENT 3 -#define DATA_KARATHRESS 4 -#define DATA_KARATHRESSEVENT 5 -#define DATA_KARATHRESSEVENT_STARTER 6 -#define DATA_LADYVASHJ 7 -#define DATA_LADYVASHJEVENT 8 -#define DATA_LEOTHERASTHEBLINDEVENT 9 -#define DATA_MOROGRIMTIDEWALKEREVENT 10 -#define DATA_SHARKKIS 11 -#define DATA_SHIELDGENERATOR1 12 -#define DATA_SHIELDGENERATOR2 13 -#define DATA_SHIELDGENERATOR3 14 -#define DATA_SHIELDGENERATOR4 15 -#define DATA_THELURKERBELOW 16 -#define DATA_THELURKERBELOWEVENT 17 -#define DATA_TIDALVESS 18 -#define DATA_FATHOMLORDKARATHRESSEVENT 19 -#define DATA_LEOTHERAS 20 -#define DATA_LEOTHERAS_EVENT_STARTER 21 -#define DATA_CONTROL_CONSOLE 22 -#define DATA_STRANGE_POOL 23 -#define DATA_WATER 24 -#define DATA_TRASH 25 -#endif - diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp deleted file mode 100644 index 8e1b438bdc5..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_hydromancer_thespia.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Hydromancer_Thespia -SD%Complete: 80 -SDComment: Needs additional adjustments (when instance script is adjusted) -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -/* ContentData -boss_hydromancer_thespia -mob_coilfang_waterelemental -EndContentData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_SUMMON -1545000 -#define SAY_AGGRO_1 -1545001 -#define SAY_AGGRO_2 -1545002 -#define SAY_AGGRO_3 -1545003 -#define SAY_SLAY_1 -1545004 -#define SAY_SLAY_2 -1545005 -#define SAY_DEAD -1545006 - -#define SPELL_LIGHTNING_CLOUD 25033 -#define SPELL_LUNG_BURST 31481 -#define SPELL_ENVELOPING_WINDS 31718 - -struct boss_thespiaAI : public ScriptedAI -{ - boss_thespiaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 LightningCloud_Timer; - uint32 LungBurst_Timer; - uint32 EnvelopingWinds_Timer; - - void Reset() - { - LightningCloud_Timer = 15000; - LungBurst_Timer = 7000; - EnvelopingWinds_Timer = 9000; - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, NOT_STARTED); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEAD, me); - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (pInstance) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //LightningCloud_Timer - if (LightningCloud_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LIGHTNING_CLOUD); - - //cast twice in Heroic mode - if (IsHeroic()) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LIGHTNING_CLOUD); - - LightningCloud_Timer = 15000+rand()%10000; - } else LightningCloud_Timer -=diff; - - //LungBurst_Timer - if (LungBurst_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_LUNG_BURST); - LungBurst_Timer = 7000+rand()%5000; - } else LungBurst_Timer -=diff; - - //EnvelopingWinds_Timer - if (EnvelopingWinds_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ENVELOPING_WINDS); - - //cast twice in Heroic mode - if (IsHeroic()) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_ENVELOPING_WINDS); - EnvelopingWinds_Timer = 10000+rand()%5000; - } else EnvelopingWinds_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -#define SPELL_WATER_BOLT_VOLLEY 34449 -#define H_SPELL_WATER_BOLT_VOLLEY 37924 - -struct mob_coilfang_waterelementalAI : public ScriptedAI -{ - mob_coilfang_waterelementalAI(Creature *c) : ScriptedAI(c) {} - - uint32 WaterBoltVolley_Timer; - - void Reset() - { - WaterBoltVolley_Timer = 3000+rand()%3000; - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (WaterBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_WATER_BOLT_VOLLEY); - WaterBoltVolley_Timer = 7000+rand()%5000; - } else WaterBoltVolley_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_thespiaAI(Creature* pCreature) -{ - return new boss_thespiaAI (pCreature); -} - -CreatureAI* GetAI_mob_coilfang_waterelementalAI(Creature* pCreature) -{ - return new mob_coilfang_waterelementalAI (pCreature); -} - -void AddSC_boss_hydromancer_thespia() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_hydromancer_thespia"; - newscript->GetAI = &GetAI_boss_thespiaAI; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_coilfang_waterelemental"; - newscript->GetAI = &GetAI_mob_coilfang_waterelementalAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp deleted file mode 100644 index f2da4058e44..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_mekgineer_steamrigger.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Mekgineer_Steamrigger -SD%Complete: 60 -SDComment: Mechanics' interrrupt heal doesn't work very well, also a proper movement needs to be implemented -> summon further away and move towards pTarget to repair. -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -/* ContentData -boss_mekgineer_steamrigger -mob_steamrigger_mechanic -EndContentData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_MECHANICS -1545007 -#define SAY_AGGRO_1 -1545008 -#define SAY_AGGRO_2 -1545009 -#define SAY_AGGRO_3 -1545010 -#define SAY_AGGRO_4 -1545011 -#define SAY_SLAY_1 -1545012 -#define SAY_SLAY_2 -1545013 -#define SAY_SLAY_3 -1545014 -#define SAY_DEATH -1545015 - -#define SPELL_SUPER_SHRINK_RAY 31485 -#define SPELL_SAW_BLADE 31486 -#define SPELL_ELECTRIFIED_NET 35107 -#define H_SPELL_ENRAGE 1 //corrent enrage spell not known - -#define ENTRY_STREAMRIGGER_MECHANIC 17951 - -struct boss_mekgineer_steamriggerAI : public ScriptedAI -{ - boss_mekgineer_steamriggerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Shrink_Timer; - uint32 Saw_Blade_Timer; - uint32 Electrified_Net_Timer; - bool Summon75; - bool Summon50; - bool Summon25; - - void Reset() - { - Shrink_Timer = 20000; - Saw_Blade_Timer = 15000; - Electrified_Net_Timer = 10000; - - Summon75 = false; - Summon50 = false; - Summon25 = false; - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, NOT_STARTED); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, DONE); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2,SAY_SLAY_3), me); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (pInstance) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER, IN_PROGRESS); - } - - //no known summon spells exist - void SummonMechanichs() - { - DoScriptText(SAY_MECHANICS, me); - - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,-5,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - - if (rand()%2) - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,5,-7,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - if (rand()%2) - DoSpawnCreature(ENTRY_STREAMRIGGER_MECHANIC,7,-5,0,0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 240000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Shrink_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SUPER_SHRINK_RAY); - Shrink_Timer = 20000; - } else Shrink_Timer -= diff; - - if (Saw_Blade_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_SAW_BLADE); - else - DoCast(me->getVictim(), SPELL_SAW_BLADE); - - Saw_Blade_Timer = 15000; - } else Saw_Blade_Timer -= diff; - - if (Electrified_Net_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ELECTRIFIED_NET); - Electrified_Net_Timer = 10000; - } - else Electrified_Net_Timer -= diff; - - if (!Summon75) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 75) - { - SummonMechanichs(); - Summon75 = true; - } - } - - if (!Summon50) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) - { - SummonMechanichs(); - Summon50 = true; - } - } - - if (!Summon25) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 25) - { - SummonMechanichs(); - Summon25 = true; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_mekgineer_steamrigger(Creature* pCreature) -{ - return new boss_mekgineer_steamriggerAI (pCreature); -} - -#define SPELL_DISPEL_MAGIC 17201 -#define SPELL_REPAIR 31532 -#define H_SPELL_REPAIR 37936 - -#define MAX_REPAIR_RANGE (13.0f) //we should be at least at this range for repair -#define MIN_REPAIR_RANGE (7.0f) //we can stop movement at this range to repair but not required - -struct mob_steamrigger_mechanicAI : public ScriptedAI -{ - mob_steamrigger_mechanicAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Repair_Timer; - - void Reset() - { - Repair_Timer = 2000; - } - - void MoveInLineOfSight(Unit* /*who*/) - { - //react only if attacked - } - - void EnterCombat(Unit * /*who*/) { } - - void UpdateAI(const uint32 diff) - { - if (Repair_Timer <= diff) - { - if (pInstance && pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER) && pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == IN_PROGRESS) - { - if (Unit* pMekgineer = Unit::GetUnit((*me), pInstance->GetData64(DATA_MEKGINEERSTEAMRIGGER))) - { - if (me->IsWithinDistInMap(pMekgineer, MAX_REPAIR_RANGE)) - { - //are we already channeling? Doesn't work very well, find better check? - if (!me->GetUInt32Value(UNIT_CHANNEL_SPELL)) - { - //me->GetMotionMaster()->MovementExpired(); - //me->GetMotionMaster()->MoveIdle(); - - DoCast(me, SPELL_REPAIR, true); - } - Repair_Timer = 5000; - } - else - { - //me->GetMotionMaster()->MovementExpired(); - //me->GetMotionMaster()->MoveFollow(pMekgineer,0,0); - } - } - } else Repair_Timer = 5000; - } else Repair_Timer -= diff; - - if (!UpdateVictim()) - return; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_steamrigger_mechanic(Creature* pCreature) -{ - return new mob_steamrigger_mechanicAI (pCreature); -} - -void AddSC_boss_mekgineer_steamrigger() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_mekgineer_steamrigger"; - newscript->GetAI = &GetAI_boss_mekgineer_steamrigger; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_steamrigger_mechanic"; - newscript->GetAI = &GetAI_mob_steamrigger_mechanic; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp deleted file mode 100644 index f46956dda81..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/boss_warlord_kalithresh.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warlord_Kalithres -SD%Complete: 65 -SDComment: Contains workarounds regarding warlord's rage spells not acting as expected. Both scripts here require review and fine tuning. -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define SAY_INTRO -1545016 -#define SAY_REGEN -1545017 -#define SAY_AGGRO1 -1545018 -#define SAY_AGGRO2 -1545019 -#define SAY_AGGRO3 -1545020 -#define SAY_SLAY1 -1545021 -#define SAY_SLAY2 -1545022 -#define SAY_DEATH -1545023 - -#define SPELL_SPELL_REFLECTION 31534 -#define SPELL_IMPALE 39061 -#define SPELL_WARLORDS_RAGE 37081 -#define SPELL_WARLORDS_RAGE_NAGA 31543 - -#define SPELL_WARLORDS_RAGE_PROC 36453 - -struct mob_naga_distillerAI : public ScriptedAI -{ - mob_naga_distillerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - //hack, due to really weird spell behaviour :( - if (pInstance) - { - if (pInstance->GetData(TYPE_DISTILLER) == IN_PROGRESS) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - } - - void EnterCombat(Unit * /*who*/) { } - - void StartRageGen(Unit * /*caster*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - DoCast(me, SPELL_WARLORDS_RAGE_NAGA, true); - - if (pInstance) - pInstance->SetData(TYPE_DISTILLER,IN_PROGRESS); - } - - void DamageTaken(Unit * /*done_by*/, uint32 &damage) - { - if (me->GetHealth() <= damage) - if (pInstance) - pInstance->SetData(TYPE_DISTILLER,DONE); - } -}; - -struct boss_warlord_kalithreshAI : public ScriptedAI -{ - boss_warlord_kalithreshAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 Reflection_Timer; - uint32 Impale_Timer; - uint32 Rage_Timer; - bool CanRage; - - void Reset() - { - Reflection_Timer = 10000; - Impale_Timer = 7000+rand()%7000; - Rage_Timer = 45000; - CanRage = false; - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, NOT_STARTED); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void SpellHit(Unit * /*caster*/, const SpellEntry *spell) - { - //hack :( - if (spell->Id == SPELL_WARLORDS_RAGE_PROC) - if (pInstance) - if (pInstance->GetData(TYPE_DISTILLER) == DONE) - me->RemoveAurasDueToSpell(SPELL_WARLORDS_RAGE_PROC); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(TYPE_WARLORD_KALITHRESH, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Rage_Timer <= diff) - { - if (Creature* distiller = me->FindNearestCreature(17954, 100.0f)) - { - DoScriptText(SAY_REGEN, me); - DoCast(me, SPELL_WARLORDS_RAGE); - CAST_AI(mob_naga_distillerAI, distiller->AI())->StartRageGen(me); - } - Rage_Timer = 3000+rand()%15000; - } else Rage_Timer -= diff; - - //Reflection_Timer - if (Reflection_Timer <= diff) - { - DoCast(me, SPELL_SPELL_REFLECTION); - Reflection_Timer = 15000+rand()%10000; - } else Reflection_Timer -= diff; - - //Impale_Timer - if (Impale_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_IMPALE); - - Impale_Timer = 7500+rand()%5000; - } else Impale_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_naga_distiller(Creature* pCreature) -{ - return new mob_naga_distillerAI (pCreature); -} - -CreatureAI* GetAI_boss_warlord_kalithresh(Creature* pCreature) -{ - return new boss_warlord_kalithreshAI (pCreature); -} - -void AddSC_boss_warlord_kalithresh() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "mob_naga_distiller"; - newscript->GetAI = &GetAI_mob_naga_distiller; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_warlord_kalithresh"; - newscript->GetAI = &GetAI_boss_warlord_kalithresh; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp deleted file mode 100644 index 188a23738f5..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/instance_steam_vault.cpp +++ /dev/null @@ -1,231 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Steam_Vault -SD%Complete: 80 -SDComment: Instance script and access panel GO -SDCategory: Coilfang Resevoir, The Steamvault -EndScriptData */ - -#include "ScriptedPch.h" -#include "steam_vault.h" - -#define MAX_ENCOUNTER 4 - -#define MAIN_CHAMBERS_DOOR 183049 -#define ACCESS_PANEL_HYDRO 184125 -#define ACCESS_PANEL_MEK 184126 - -/* Steam Vaults encounters: -1 - Hydromancer Thespia Event -2 - Mekgineer Steamrigger Event -3 - Warlord Kalithresh Event -*/ - -bool GOHello_go_main_chambers_access_panel(Player* /*pPlayer*/, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - - if (!pInstance) - return false; - - if (pGo->GetEntry() == ACCESS_PANEL_HYDRO && (pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == DONE || pInstance->GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL)) - pInstance->SetData(TYPE_HYDROMANCER_THESPIA,SPECIAL); - - if (pGo->GetEntry() == ACCESS_PANEL_MEK && (pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == DONE || pInstance->GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL)) - pInstance->SetData(TYPE_MEKGINEER_STEAMRIGGER,SPECIAL); - - return true; -} - -struct instance_steam_vault : public ScriptedInstance -{ - instance_steam_vault(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 ThespiaGUID; - uint64 MekgineerGUID; - uint64 KalithreshGUID; - - uint64 MainChambersDoor; - uint64 AccessPanelHydro; - uint64 AccessPanelMek; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - ThespiaGUID = 0; - MekgineerGUID = 0; - KalithreshGUID = 0; - MainChambersDoor = 0; - AccessPanelHydro = 0; - AccessPanelMek = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17797: ThespiaGUID = pCreature->GetGUID(); break; - case 17796: MekgineerGUID = pCreature->GetGUID(); break; - case 17798: KalithreshGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case MAIN_CHAMBERS_DOOR: MainChambersDoor = pGo->GetGUID(); break; - case ACCESS_PANEL_HYDRO: AccessPanelHydro = pGo->GetGUID(); break; - case ACCESS_PANEL_MEK: AccessPanelMek = pGo->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_HYDROMANCER_THESPIA: - if (data == SPECIAL) - { - HandleGameObject(AccessPanelHydro, true); - - if (GetData(TYPE_MEKGINEER_STEAMRIGGER) == SPECIAL) - HandleGameObject(MainChambersDoor, true); - - debug_log("TSCR: Instance Steamvault: Access panel used."); - } - m_auiEncounter[0] = data; - break; - case TYPE_MEKGINEER_STEAMRIGGER: - if (data == SPECIAL) - { - HandleGameObject(AccessPanelMek, true); - - if (GetData(TYPE_HYDROMANCER_THESPIA) == SPECIAL) - HandleGameObject(MainChambersDoor, true); - - debug_log("TSCR: Instance Steamvault: Access panel used."); - } - m_auiEncounter[1] = data; - break; - case TYPE_WARLORD_KALITHRESH: - m_auiEncounter[2] = data; - break; - case TYPE_DISTILLER: - m_auiEncounter[3] = data; - break; - } - - if (data == DONE || data == SPECIAL) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_HYDROMANCER_THESPIA: - return m_auiEncounter[0]; - case TYPE_MEKGINEER_STEAMRIGGER: - return m_auiEncounter[1]; - case TYPE_WARLORD_KALITHRESH: - return m_auiEncounter[2]; - case TYPE_DISTILLER: - return m_auiEncounter[3]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THESPIA: - return ThespiaGUID; - case DATA_MEKGINEERSTEAMRIGGER: - return MekgineerGUID; - case DATA_KALITRESH: - return KalithreshGUID; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_steam_vault(Map* pMap) -{ - return new instance_steam_vault(pMap); -} - -void AddSC_instance_steam_vault() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "go_main_chambers_access_panel"; - newscript->pGOHello = &GOHello_go_main_chambers_access_panel; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "instance_steam_vault"; - newscript->GetInstanceData = &GetInstanceData_instance_steam_vault; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h b/src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h deleted file mode 100644 index 4b407ac4816..00000000000 --- a/src/server/scripts/Outland/CoilfangReservoir/steam_vault/steam_vault.h +++ /dev/null @@ -1,17 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_STEAM_VAULT_H -#define DEF_STEAM_VAULT_H - -#define TYPE_HYDROMANCER_THESPIA 1 -#define TYPE_MEKGINEER_STEAMRIGGER 2 -#define TYPE_WARLORD_KALITHRESH 3 -#define TYPE_DISTILLER 4 - -#define DATA_MEKGINEERSTEAMRIGGER 5 -#define DATA_KALITRESH 6 -#define DATA_THESPIA 7 -#endif - diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h new file mode 100644 index 00000000000..b845c66823f --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/blood_furnace.h @@ -0,0 +1,29 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BLOOD_FURNACE_H +#define DEF_BLOOD_FURNACE_H + +#define DATA_THE_MAKER 1 +#define DATA_BROGGOK 2 +#define DATA_KELIDAN_THE_MAKER 3 +#define TYPE_THE_MAKER_EVENT 4 +#define TYPE_BROGGOK_EVENT 5 +#define TYPE_KELIDAN_THE_BREAKER_EVENT 6 +#define DATA_DOOR1 7 +#define DATA_DOOR2 8 +#define DATA_DOOR3 9 +#define DATA_DOOR4 10 +#define DATA_DOOR5 11 +#define DATA_DOOR6 12 +#define DATA_PRISON_CELL1 13 +#define DATA_PRISON_CELL2 14 +#define DATA_PRISON_CELL3 15 +#define DATA_PRISON_CELL4 16 +#define DATA_PRISON_CELL5 17 +#define DATA_PRISON_CELL6 18 +#define DATA_PRISON_CELL7 19 +#define DATA_PRISON_CELL8 20 +#endif + diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp new file mode 100644 index 00000000000..d5fb9bdba49 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_broggok.cpp @@ -0,0 +1,131 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Broggok +SD%Complete: 70 +SDComment: pre-event not made +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eEnums +{ + SAY_AGGRO = -1542008, + + SPELL_SLIME_SPRAY = 30913, + SPELL_POISON_CLOUD = 30916, + SPELL_POISON_BOLT = 30917, + + SPELL_POISON = 30914 +}; + +struct boss_broggokAI : public ScriptedAI +{ + boss_broggokAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AcidSpray_Timer; + uint32 PoisonSpawn_Timer; + uint32 PoisonBolt_Timer; + + void Reset() + { + AcidSpray_Timer = 10000; + PoisonSpawn_Timer = 5000; + PoisonBolt_Timer = 7000; + if (pInstance) + { + pInstance->SetData(TYPE_BROGGOK_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); + } + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + if (pInstance) + { + pInstance->SetData(TYPE_BROGGOK_EVENT, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), false); + } + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(16); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->CastSpell(summoned,SPELL_POISON,false,0,0,me->GetGUID()); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AcidSpray_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SLIME_SPRAY); + AcidSpray_Timer = 4000+rand()%8000; + } else AcidSpray_Timer -=diff; + + if (PoisonBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POISON_BOLT); + PoisonBolt_Timer = 4000+rand()%8000; + } else PoisonBolt_Timer -=diff; + + if (PoisonSpawn_Timer <= diff) + { + DoCast(me, SPELL_POISON_CLOUD); + PoisonSpawn_Timer = 20000; + } else PoisonSpawn_Timer -=diff; + + DoMeleeAttackIfReady(); + } + + void JustDied(Unit* /*who*/) + { + if (pInstance) + { + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR5), true); + pInstance->SetData(TYPE_BROGGOK_EVENT, DONE); + } + } + +}; + +CreatureAI* GetAI_boss_broggok(Creature* pCreature) +{ + return new boss_broggokAI (pCreature); +} + +void AddSC_boss_broggok() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_broggok"; + newscript->GetAI = &GetAI_boss_broggok; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp new file mode 100644 index 00000000000..a44ad9cc3c8 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_kelidan_the_breaker.cpp @@ -0,0 +1,356 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kelidan_The_Breaker +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +/* ContentData +boss_kelidan_the_breaker +mob_shadowmoon_channeler +EndContentData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eKelidan +{ + SAY_WAKE = -1542000, + SAY_ADD_AGGRO_1 = -1542001, + SAY_ADD_AGGRO_2 = -1542002, + SAY_ADD_AGGRO_3 = -1542003, + SAY_KILL_1 = -1542004, + SAY_KILL_2 = -1542005, + SAY_NOVA = -1542006, + SAY_DIE = -1542007, + + SPELL_CORRUPTION = 30938, + SPELL_EVOCATION = 30935, + + SPELL_FIRE_NOVA = 33132, + H_SPELL_FIRE_NOVA = 37371, + + SPELL_SHADOW_BOLT_VOLLEY = 28599, + H_SPELL_SHADOW_BOLT_VOLLEY = 40070, + + SPELL_BURNING_NOVA = 30940, + SPELL_VORTEX = 37370, + + ENTRY_KELIDAN = 17377, + ENTRY_CHANNELER = 17653 +}; + +const float ShadowmoonChannelers[5][4]= +{ + {302,-87,-24.4,0.157}, + {321,-63.5,-24.6,4.887}, + {346,-74.5,-24.6,3.595}, + {344,-103.5,-24.5,2.356}, + {316,-109,-24.6,1.257} +}; + +struct boss_kelidan_the_breakerAI : public ScriptedAI +{ + boss_kelidan_the_breakerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + for (uint8 i=0; i<5; ++i) + Channelers[i] = 0; + } + + ScriptedInstance* pInstance; + + uint32 ShadowVolley_Timer; + uint32 BurningNova_Timer; + uint32 Firenova_Timer; + uint32 Corruption_Timer; + uint32 check_Timer; + bool Firenova; + bool addYell; + uint64 Channelers[5]; + + void Reset() + { + ShadowVolley_Timer = 1000; + BurningNova_Timer = 15000; + Corruption_Timer = 5000; + check_Timer = 0; + Firenova = false; + addYell = false; + SummonChannelers(); + if (pInstance) + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + DoScriptText(SAY_WAKE, me); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoStartMovement(who); + if (pInstance) + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, IN_PROGRESS); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void ChannelerEngaged(Unit* who) + { + if (who && !addYell) + { + addYell = true; + DoScriptText(RAND(SAY_ADD_AGGRO_1,SAY_ADD_AGGRO_2,SAY_ADD_AGGRO_3), me); + } + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (who && channeler && !channeler->isInCombat()) + channeler->AI()->AttackStart(who); + } + } + + void ChannelerDied(Unit* killer) + { + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (channeler && channeler->isAlive()) + return; + } + + if (killer) + me->AI()->AttackStart(killer); + } + + uint64 GetChanneled(Creature *channeler1) + { + SummonChannelers(); + if (!channeler1) return NULL; + uint8 i; + for (i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (channeler && channeler->GetGUID() == channeler1->GetGUID()) + break; + } + return Channelers[(i+2)%5]; + } + + void SummonChannelers() + { + for (uint8 i=0; i<5; ++i) + { + Creature *channeler = Unit::GetCreature(*me, Channelers[i]); + if (!channeler || channeler->isDead()) + channeler = me->SummonCreature(ENTRY_CHANNELER,ShadowmoonChannelers[i][0],ShadowmoonChannelers[i][1],ShadowmoonChannelers[i][2],ShadowmoonChannelers[i][3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,300000); + if (channeler) + Channelers[i] = channeler->GetGUID(); + else + Channelers[i] = 0; + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR1), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR6), true); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (check_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + DoCast(me, SPELL_EVOCATION); + check_Timer = 5000; + } else check_Timer -= diff; + return; + } + + if (Firenova) + { + if (Firenova_Timer <= diff) + { + DoCast(me, SPELL_FIRE_NOVA, true); + Firenova = false; + ShadowVolley_Timer = 2000; + } else Firenova_Timer -=diff; + + return; + } + + if (ShadowVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); + ShadowVolley_Timer = 5000+rand()%8000; + } else ShadowVolley_Timer -=diff; + + if (Corruption_Timer <= diff) + { + DoCast(me, SPELL_CORRUPTION); + Corruption_Timer = 30000+rand()%20000; + } else Corruption_Timer -=diff; + + if (BurningNova_Timer <= diff) + { + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + + DoScriptText(SAY_NOVA, me); + + if (SpellEntry *nova = GET_SPELL(SPELL_BURNING_NOVA)) + { + if (Aura * aura = Aura::TryCreate(nova, me, me)) + aura->ApplyForTargets(); + } + + if (IsHeroic()) + DoTeleportAll(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); + + BurningNova_Timer = 20000+rand()%8000; + Firenova_Timer= 5000; + Firenova = true; + } else BurningNova_Timer -=diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_boss_kelidan_the_breaker(Creature* pCreature) +{ + return new boss_kelidan_the_breakerAI (pCreature); +} + +/*###### +## mob_shadowmoon_channeler +######*/ + +enum eShadowmoon +{ + SPELL_SHADOW_BOLT = 12739, + H_SPELL_SHADOW_BOLT = 15472, + + SPELL_MARK_OF_SHADOW = 30937, + SPELL_CHANNELING = 39123 +}; + +struct mob_shadowmoon_channelerAI : public ScriptedAI +{ + mob_shadowmoon_channelerAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 ShadowBolt_Timer; + uint32 MarkOfShadow_Timer; + uint32 check_Timer; + + void Reset() + { + ShadowBolt_Timer = 1000+rand()%1000; + MarkOfShadow_Timer = 5000+rand()%2000; + check_Timer = 0; + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + } + + void EnterCombat(Unit* who) + { + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerEngaged(who); + if (me->IsNonMeleeSpellCasted(false)) + me->InterruptNonMeleeSpells(true); + DoStartMovement(who); + } + + void JustDied(Unit* Killer) + { + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerDied(Killer); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (check_Timer <= diff) + { + if (!me->IsNonMeleeSpellCasted(false)) + if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) + { + uint64 channeler = CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->GetChanneled(me); + if (Unit *channeled = Unit::GetUnit(*me, channeler)) + DoCast(channeled, SPELL_CHANNELING); + } + check_Timer = 5000; + } else check_Timer -= diff; + return; + } + + if (MarkOfShadow_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MARK_OF_SHADOW); + MarkOfShadow_Timer = 15000+rand()%5000; + } else MarkOfShadow_Timer -=diff; + + if (ShadowBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_BOLT); + ShadowBolt_Timer = 5000+rand()%1000; + } else ShadowBolt_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_shadowmoon_channeler(Creature* pCreature) +{ + return new mob_shadowmoon_channelerAI (pCreature); +} + +void AddSC_boss_kelidan_the_breaker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_kelidan_the_breaker"; + newscript->GetAI = &GetAI_boss_kelidan_the_breaker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shadowmoon_channeler"; + newscript->GetAI = &GetAI_mob_shadowmoon_channeler; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp new file mode 100644 index 00000000000..45219b6509b --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/boss_the_maker.cpp @@ -0,0 +1,152 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_The_Maker +SD%Complete: 80 +SDComment: Mind control no support +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +enum eEnums +{ + SAY_AGGRO_1 = -1542009, + SAY_AGGRO_2 = -1542010, + SAY_AGGRO_3 = -1542011, + SAY_KILL_1 = -1542012, + SAY_KILL_2 = -1542013, + SAY_DIE = -1542014, + + SPELL_ACID_SPRAY = 38153, // heroic 38973 ??? 38153 + SPELL_EXPLODING_BREAKER = 30925, + SPELL_KNOCKDOWN = 20276, + SPELL_DOMINATION = 25772 // ??? +}; + +struct boss_the_makerAI : public ScriptedAI +{ + boss_the_makerAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 AcidSpray_Timer; + uint32 ExplodingBreaker_Timer; + uint32 Domination_Timer; + uint32 Knockdown_Timer; + + void Reset() + { + AcidSpray_Timer = 15000; + ExplodingBreaker_Timer = 6000; + Domination_Timer = 120000; + Knockdown_Timer = 10000; + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, NOT_STARTED); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, IN_PROGRESS); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), false); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_THE_MAKER_EVENT, DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); + pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR3), true); + + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AcidSpray_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ACID_SPRAY); + AcidSpray_Timer = 15000+rand()%8000; + } else AcidSpray_Timer -=diff; + + if (ExplodingBreaker_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_EXPLODING_BREAKER); + ExplodingBreaker_Timer = 4000+rand()%8000; + } else ExplodingBreaker_Timer -=diff; + + /* // Disabled until Core Support for mind control + if (domination_timer_timer <= diff) + { + Unit *pTarget; + pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + + DoCast(pTarget, SPELL_DOMINATION); + + domination_timer = 120000; + } else domination_timer -=diff; + */ + + if (Knockdown_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKDOWN); + Knockdown_Timer = 4000+rand()%8000; + } else Knockdown_Timer -=diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_the_makerAI(Creature* pCreature) +{ + return new boss_the_makerAI (pCreature); +} + +void AddSC_boss_the_maker() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_the_maker"; + newscript->GetAI = &GetAI_boss_the_makerAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp new file mode 100644 index 00000000000..3a2eb8ba5ee --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/BloodFurnace/instance_blood_furnace.cpp @@ -0,0 +1,232 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Blood_Furnace +SD%Complete: 85 +SDComment: +SDCategory: Hellfire Citadel, Blood Furnace +EndScriptData */ + +#include "ScriptedPch.h" +#include "blood_furnace.h" + +#define ENTRY_SEWER1 181823 +#define ENTRY_SEWER2 181766 +#define MAX_ENCOUNTER 3 + +struct instance_blood_furnace : public ScriptedInstance +{ + instance_blood_furnace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 The_MakerGUID; + uint64 BroggokGUID; + uint64 Kelidan_The_BreakerGUID; + + uint64 Door1GUID; + uint64 Door2GUID; + uint64 Door3GUID; + uint64 Door4GUID; + uint64 Door5GUID; + uint64 Door6GUID; + + uint64 PrisonCell1GUID; + uint64 PrisonCell2GUID; + uint64 PrisonCell3GUID; + uint64 PrisonCell4GUID; + uint64 PrisonCell5GUID; + uint64 PrisonCell6GUID; + uint64 PrisonCell7GUID; + uint64 PrisonCell8GUID; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string str_data; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + The_MakerGUID = 0; + BroggokGUID = 0; + Kelidan_The_BreakerGUID = 0; + + Door1GUID = 0; + Door2GUID = 0; + Door3GUID = 0; + Door4GUID = 0; + Door5GUID = 0; + Door6GUID = 0; + + PrisonCell1GUID = 0; + PrisonCell2GUID = 0; + PrisonCell3GUID = 0; + PrisonCell4GUID = 0; + PrisonCell5GUID = 0; + PrisonCell6GUID = 0; + PrisonCell7GUID = 0; + PrisonCell8GUID = 0; + } + + void OnCreatureCreate(Creature* pCreature, bool add) + { + if (!add) + return; + + switch(pCreature->GetEntry()) + { + case 17381: The_MakerGUID = pCreature->GetGUID(); break; + case 17380: BroggokGUID = pCreature->GetGUID(); break; + case 17377: Kelidan_The_BreakerGUID = pCreature->GetGUID(); break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool add) + { + if (!add) + return; + + if (pGo->GetEntry() == 181766) //Final exit door + Door1GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181811) //The Maker Front door + Door2GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181812) //The Maker Rear door + Door3GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181822) //Broggok Front door + Door4GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181819) //Broggok Rear door + Door5GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181823) //Kelidan exit door + Door6GUID = pGo->GetGUID(); + + if (pGo->GetEntry() == 181813) //The Maker prison cell front right + PrisonCell1GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181814) //The Maker prison cell back right + PrisonCell2GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181816) //The Maker prison cell front left + PrisonCell3GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181815) //The Maker prison cell back left + PrisonCell4GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181821) //Broggok prison cell front right + PrisonCell5GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181818) //Broggok prison cell back right + PrisonCell6GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181820) //Broggok prison cell front left + PrisonCell7GUID = pGo->GetGUID(); + if (pGo->GetEntry() == 181817) //Broggok prison cell back left + PrisonCell8GUID = pGo->GetGUID(); + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_THE_MAKER: return The_MakerGUID; + case DATA_BROGGOK: return BroggokGUID; + case DATA_KELIDAN_THE_MAKER: return Kelidan_The_BreakerGUID; + case DATA_DOOR1: return Door1GUID; + case DATA_DOOR2: return Door2GUID; + case DATA_DOOR3: return Door3GUID; + case DATA_DOOR4: return Door4GUID; + case DATA_DOOR5: return Door5GUID; + case DATA_DOOR6: return Door6GUID; + case DATA_PRISON_CELL1: return PrisonCell1GUID; + case DATA_PRISON_CELL2: return PrisonCell2GUID; + case DATA_PRISON_CELL3: return PrisonCell3GUID; + case DATA_PRISON_CELL4: return PrisonCell4GUID; + case DATA_PRISON_CELL5: return PrisonCell5GUID; + case DATA_PRISON_CELL6: return PrisonCell6GUID; + case DATA_PRISON_CELL7: return PrisonCell7GUID; + case DATA_PRISON_CELL8: return PrisonCell8GUID; + } + + return 0; + } + + void SetData(uint32 /*type*/, uint32 data) + { + switch(data) + { + case TYPE_THE_MAKER_EVENT: m_auiEncounter[0] = data; break; + case TYPE_BROGGOK_EVENT: m_auiEncounter[1] = data; break; + case TYPE_KELIDAN_THE_BREAKER_EVENT: m_auiEncounter[2] = data; break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2]; + + str_data = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 data) + { + switch(data) + { + case TYPE_THE_MAKER_EVENT: return m_auiEncounter[0]; + case TYPE_BROGGOK_EVENT: return m_auiEncounter[1]; + case TYPE_KELIDAN_THE_BREAKER_EVENT: return m_auiEncounter[2]; + } + + return 0; + } + + const char* Save() + { + return str_data.c_str(); + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(in); + + std::istringstream loadStream(in); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS || m_auiEncounter[i] == FAIL) + m_auiEncounter[i] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_blood_furnace(Map* pMap) +{ + return new instance_blood_furnace(pMap); +} + +void AddSC_instance_blood_furnace() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_blood_furnace"; + newscript->GetInstanceData = &GetInstanceData_instance_blood_furnace; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp new file mode 100644 index 00000000000..d6c0b2fd401 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_omor_the_unscarred.cpp @@ -0,0 +1,206 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Omar_The_Unscarred +SD%Complete: 90 +SDComment: Temporary solution for orbital/shadow whip-ability. Needs more core support before making it more proper. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1543009 +#define SAY_AGGRO_2 -1543010 +#define SAY_AGGRO_3 -1543011 +#define SAY_SUMMON -1543012 +#define SAY_CURSE -1543013 +#define SAY_KILL_1 -1543014 +#define SAY_DIE -1543015 +#define SAY_WIPE -1543016 + +#define SPELL_ORBITAL_STRIKE 30637 +#define SPELL_SHADOW_WHIP 30638 +#define SPELL_TREACHEROUS_AURA 30695 +#define H_SPELL_BANE_OF_TREACHERY 37566 +#define SPELL_DEMONIC_SHIELD 31901 +#define SPELL_SHADOW_BOLT 30686 +#define H_SPELL_SHADOW_BOLT 39297 +#define SPELL_SUMMON_FIENDISH_HOUND 30707 + +struct boss_omor_the_unscarredAI : public ScriptedAI +{ + boss_omor_the_unscarredAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + } + + uint32 OrbitalStrike_Timer; + uint32 ShadowWhip_Timer; + uint32 Aura_Timer; + uint32 DemonicShield_Timer; + uint32 Shadowbolt_Timer; + uint32 Summon_Timer; + uint32 SummonedCount; + uint64 PlayerGUID; + bool CanPullBack; + + void Reset() + { + DoScriptText(SAY_WIPE, me); + + OrbitalStrike_Timer = 25000; + ShadowWhip_Timer = 2000; + Aura_Timer = 10000; + DemonicShield_Timer = 1000; + Shadowbolt_Timer = 2000; + Summon_Timer = 10000; + SummonedCount = 0; + PlayerGUID = 0; + CanPullBack = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(SAY_KILL_1, me); + } + + void JustSummoned(Creature* summoned) + { + DoScriptText(SAY_SUMMON, me); + + if (Unit* random = SelectUnit(SELECT_TARGET_RANDOM,0)) + summoned->AI()->AttackStart(random); + + ++SummonedCount; + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //only two may be wrong, perhaps increase timer and spawn periodically instead. + if (SummonedCount < 2) + { + if (Summon_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_SUMMON_FIENDISH_HOUND); + Summon_Timer = 15000+rand()%15000; + } else Summon_Timer -= diff; + } + + if (CanPullBack) + { + if (ShadowWhip_Timer <= diff) + { + if (Player* temp = Unit::GetPlayer(PlayerGUID)) + { + //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) + if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) + { + me->InterruptNonMeleeSpells(false); + DoCast(temp, SPELL_SHADOW_WHIP); + } + } + PlayerGUID = 0; + ShadowWhip_Timer = 2000; + CanPullBack = false; + } else ShadowWhip_Timer -= diff; + } + else if (OrbitalStrike_Timer <= diff) + { + Unit* temp = NULL; + if (me->IsWithinMeleeRange(me->getVictim())) + temp = me->getVictim(); + else temp = SelectUnit(SELECT_TARGET_RANDOM,0); + + if (temp && temp->GetTypeId() == TYPEID_PLAYER) + { + DoCast(temp, SPELL_ORBITAL_STRIKE); + OrbitalStrike_Timer = 14000+rand()%2000; + PlayerGUID = temp->GetGUID(); + + if (PlayerGUID) + CanPullBack = true; + } + } else OrbitalStrike_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) + { + if (DemonicShield_Timer <= diff) + { + DoCast(me, SPELL_DEMONIC_SHIELD); + DemonicShield_Timer = 15000; + } else DemonicShield_Timer -= diff; + } + + if (Aura_Timer <= diff) + { + DoScriptText(SAY_CURSE, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoCast(pTarget, SPELL_TREACHEROUS_AURA); + Aura_Timer = 8000+rand()%8000; + } + } else Aura_Timer -= diff; + + if (Shadowbolt_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + if (pTarget) + pTarget = me->getVictim(); + + DoCast(pTarget, SPELL_SHADOW_BOLT); + Shadowbolt_Timer = 4000+rand()%2500; + } + } else Shadowbolt_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_omor_the_unscarredAI(Creature* pCreature) +{ + return new boss_omor_the_unscarredAI (pCreature); +} + +void AddSC_boss_omor_the_unscarred() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_omor_the_unscarred"; + newscript->GetAI = &GetAI_boss_omor_the_unscarredAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp new file mode 100644 index 00000000000..181911f77a4 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp @@ -0,0 +1,467 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +Name: Boss_Vazruden_the_Herald +%Complete: 90 +Comment: +Category: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SPELL_FIREBALL DUNGEON_MODE(34653, 36920) +#define SPELL_CONE_OF_FIRE DUNGEON_MODE(30926, 36921) +#define SPELL_SUMMON_LIQUID_FIRE DUNGEON_MODE(23971, 30928) +#define SPELL_BELLOWING_ROAR 39427 +#define SPELL_REVENGE DUNGEON_MODE(19130, 40392) +#define SPELL_KIDNEY_SHOT 30621 +#define SPELL_FIRE_NOVA_VISUAL 19823 + +#define ENTRY_HELLFIRE_SENTRY 17517 +#define ENTRY_VAZRUDEN_HERALD 17307 +#define ENTRY_VAZRUDEN 17537 +#define ENTRY_NAZAN 17536 +#define ENTRY_LIQUID_FIRE 22515 +#define ENTRY_REINFORCED_FEL_IRON_CHEST DUNGEON_MODE(185168, 185169) + +#define SAY_INTRO -1543017 +#define SAY_WIPE -1543018 +#define SAY_AGGRO_1 -1543019 +#define SAY_AGGRO_2 -1543020 +#define SAY_AGGRO_3 -1543021 +#define SAY_KILL_1 -1543022 +#define SAY_KILL_2 -1543023 +#define SAY_DIE -1543024 +#define EMOTE -1543025 + +#define PATH_ENTRY 2081 + +const float VazrudenMiddle[3] = {-1406.5, 1746.5, 81.2}; +const float VazrudenRing[2][3] = +{ + {-1430, 1705, 112}, + {-1377, 1760, 112} +}; + +struct boss_nazanAI : public ScriptedAI +{ + boss_nazanAI(Creature *c) : ScriptedAI(c) + { + VazrudenGUID = 0; + flight = true; + } + + uint32 Fireball_Timer; + uint32 ConeOfFire_Timer; + uint32 BellowingRoar_Timer; + uint32 Fly_Timer; + uint32 Turn_Timer; + uint32 UnsummonCheck; + bool flight; + uint64 VazrudenGUID; + SpellEntry *liquid_fire; + + void Reset() + { + Fireball_Timer = 4000; + Fly_Timer = 45000; + Turn_Timer = 0; + UnsummonCheck = 5000; + } + + void EnterCombat(Unit* /*who*/) {} + + void JustSummoned(Creature *summoned) + { + if (summoned && summoned->GetEntry() == ENTRY_LIQUID_FIRE) + { + summoned->SetLevel(me->getLevel()); + summoned->setFaction(me->getFaction()); + summoned->CastSpell(summoned,SPELL_SUMMON_LIQUID_FIRE,true); + summoned->CastSpell(summoned,SPELL_FIRE_NOVA_VISUAL,true); + } + } + + void SpellHitTarget(Unit *pTarget, const SpellEntry* entry) + { + if (pTarget && entry->Id == uint32(SPELL_FIREBALL)) + me->SummonCreature(ENTRY_LIQUID_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),pTarget->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,30000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (UnsummonCheck < diff && me->isAlive()) + me->DisappearAndDie(); + else + UnsummonCheck -= diff; + return; + } + + if (Fireball_Timer <= diff) + { + if (Unit *victim = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(victim, SPELL_FIREBALL, true); + Fireball_Timer = urand(4000,7000); + } else Fireball_Timer -= diff; + + if (flight) // phase 1 - the flight + { + Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); + if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) + { + flight = false; + BellowingRoar_Timer = 6000; + ConeOfFire_Timer = 12000; + me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + me->GetMotionMaster()->Clear(); + if (Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) + me->AI()->AttackStart(victim); + DoStartMovement(me->getVictim()); + DoScriptText(EMOTE, me); + return; + } else Fly_Timer -= diff; + + if (Turn_Timer <= diff) + { + uint32 waypoint = (Fly_Timer/10000)%2; + if (me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) + me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); + Turn_Timer = 10000; + } else Turn_Timer -= diff; + } + else // phase 2 - land fight + { + if (ConeOfFire_Timer <= diff) + { + DoCast(me, SPELL_CONE_OF_FIRE); + ConeOfFire_Timer = 12000; + Fireball_Timer = 4000; + } else ConeOfFire_Timer -= diff; + + if (IsHeroic()) + if (BellowingRoar_Timer <= diff) + { + DoCast(me, SPELL_BELLOWING_ROAR); + BellowingRoar_Timer = 45000; + } else BellowingRoar_Timer -= diff; + + DoMeleeAttackIfReady(); + } + } +}; + +struct boss_vazrudenAI : public ScriptedAI +{ + boss_vazrudenAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Revenge_Timer; + bool WipeSaid; + uint32 UnsummonCheck; + + void Reset() + { + Revenge_Timer = 4000; + UnsummonCheck = 2000; + WipeSaid = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void KilledUnit(Unit* who) + { + if (who && who->GetEntry() != ENTRY_VAZRUDEN) + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* who) + { + if (who && who != me) + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + { + if (UnsummonCheck < diff && me->isAlive()) + { + if (!WipeSaid) + { + DoScriptText(SAY_WIPE, me); + WipeSaid = true; + } + me->DisappearAndDie(); + } else UnsummonCheck -= diff; + return; + } + + if (Revenge_Timer <= diff) + { + if (Unit *victim = me->getVictim()) + DoCast(victim, SPELL_REVENGE); + Revenge_Timer = 5000; + } else Revenge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_vazruden_the_heraldAI : public ScriptedAI +{ + boss_vazruden_the_heraldAI(Creature *c) : ScriptedAI(c) + { + summoned = false; + sentryDown = false; + NazanGUID = 0; + VazrudenGUID = 0; + } + + uint32 phase; + uint32 waypoint; + uint32 check; + bool sentryDown; + uint64 NazanGUID; + uint64 VazrudenGUID; + bool summoned; + + void Reset() + { + phase = 0; + waypoint = 0; + check = 0; + UnsummonAdds(); + me->GetMotionMaster()->MovePath(PATH_ENTRY, true); + } + + void UnsummonAdds() + { + if (summoned) + { + Creature *Nazan = Unit::GetCreature(*me, NazanGUID); + if (!Nazan) + Nazan = me->FindNearestCreature(ENTRY_NAZAN, 5000); + if (Nazan) + { + Nazan->DisappearAndDie(); + NazanGUID = 0; + } + + Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); + if (!Vazruden) + Vazruden = me->FindNearestCreature(ENTRY_VAZRUDEN, 5000); + if (Vazruden) + { + Vazruden->DisappearAndDie(); + VazrudenGUID = 0; + } + summoned = false; + me->clearUnitState(UNIT_STAT_ROOT); + me->SetVisibility(VISIBILITY_ON); + } + } + + void SummonAdds() + { + if (!summoned) + { + if (Creature* Vazruden = me->SummonCreature(ENTRY_VAZRUDEN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) + VazrudenGUID = Vazruden->GetGUID(); + if (Creature* Nazan = me->SummonCreature(ENTRY_NAZAN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) + NazanGUID = Nazan->GetGUID(); + summoned = true; + me->SetVisibility(VISIBILITY_OFF); + me->addUnitState(UNIT_STAT_ROOT); + } + } + + void EnterCombat(Unit * /*who*/) + { + if (phase == 0) + { + phase = 1; + check = 0; + DoScriptText(SAY_INTRO, me); + } + } + + void JustSummoned(Creature *summoned) + { + if (!summoned) return; + Unit *victim = me->getVictim(); + if (summoned->GetEntry() == ENTRY_NAZAN) + { + CAST_AI(boss_nazanAI, summoned->AI())->VazrudenGUID = VazrudenGUID; + summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); + summoned->SetSpeed(MOVE_FLIGHT, 2.5); + if (victim) + AttackStartNoMove(victim); + } + else if (victim) + summoned->AI()->AttackStart(victim); + } + + void SentryDownBy(Unit* killer) + { + if (sentryDown) + { + AttackStartNoMove(killer); + sentryDown = false; + } + else + sentryDown = true; + } + + void UpdateAI(const uint32 diff) + { + switch(phase) + { + case 0: // circle around the platform + return; + break; + case 1: // go to the middle and begin the fight + if (check <= diff) + { + if (!me->IsWithinDist3d(VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],5)) + { + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2]); + check = 1000; + } + else + { + SummonAdds(); + phase = 2; + return; + } + } else check -= diff; + break; + default: // adds do the job now + if (check <= diff) + { + Creature *Nazan = Unit::GetCreature(*me, NazanGUID); + Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); + if (Nazan && Nazan->isAlive() || Vazruden && Vazruden->isAlive()) + { + if (Nazan && Nazan->getVictim() || Vazruden && Vazruden->getVictim()) + return; + else + { + UnsummonAdds(); + EnterEvadeMode(); + return; + } + } + else + { + me->SummonGameObject(ENTRY_REINFORCED_FEL_IRON_CHEST,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,0,0,0,0,0); + me->SetLootRecipient(NULL); // don't think this is necessary.. + me->Kill(me); + } + check = 2000; + } else check -= diff; + break; + } + } +}; + +struct mob_hellfire_sentryAI : public ScriptedAI +{ + mob_hellfire_sentryAI(Creature *c) : ScriptedAI(c) {} + + uint32 KidneyShot_Timer; + + void Reset() + { + KidneyShot_Timer = urand(3000,7000); + } + + void EnterCombat(Unit* /*who*/) {} + + void JustDied(Unit* who) + { + if (Creature *herald = me->FindNearestCreature(ENTRY_VAZRUDEN_HERALD,150)) + CAST_AI(boss_vazruden_the_heraldAI, herald->AI())->SentryDownBy(who); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (KidneyShot_Timer <= diff) + { + if (Unit *victim = me->getVictim()) + DoCast(victim, SPELL_KIDNEY_SHOT); + KidneyShot_Timer = 20000; + } else KidneyShot_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_vazruden_the_herald(Creature* pCreature) +{ + return new boss_vazruden_the_heraldAI (pCreature); +} + +CreatureAI* GetAI_boss_vazruden(Creature* pCreature) +{ + return new boss_vazrudenAI (pCreature); +} + +CreatureAI* GetAI_boss_nazan(Creature* pCreature) +{ + return new boss_nazanAI (pCreature); +} + +CreatureAI* GetAI_mob_hellfire_sentry(Creature* pCreature) +{ + return new mob_hellfire_sentryAI (pCreature); +} + +void AddSC_boss_vazruden_the_herald() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vazruden_the_herald"; + newscript->GetAI = &GetAI_boss_vazruden_the_herald; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_vazruden"; + newscript->GetAI = &GetAI_boss_vazruden; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_nazan"; + newscript->GetAI = &GetAI_boss_nazan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_hellfire_sentry"; + newscript->GetAI = &GetAI_mob_hellfire_sentry; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_watchkeeper_gargolmar.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_watchkeeper_gargolmar.cpp new file mode 100644 index 00000000000..f0e813d3890 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_watchkeeper_gargolmar.cpp @@ -0,0 +1,156 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Watchkeeper_Gargolmar +SD%Complete: 80 +SDComment: Missing adds to heal him. Surge should be used on pTarget furthest away, not random. +SDCategory: Hellfire Citadel, Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_TAUNT -1543000 +#define SAY_HEAL -1543001 +#define SAY_SURGE -1543002 +#define SAY_AGGRO_1 -1543003 +#define SAY_AGGRO_2 -1543004 +#define SAY_AGGRO_3 -1543005 +#define SAY_KILL_1 -1543006 +#define SAY_KILL_2 -1543007 +#define SAY_DIE -1543008 + +#define SPELL_MORTAL_WOUND 30641 +#define H_SPELL_MORTAL_WOUND 36814 +#define SPELL_SURGE 34645 +#define SPELL_RETALIATION 22857 + +struct boss_watchkeeper_gargolmarAI : public ScriptedAI +{ + boss_watchkeeper_gargolmarAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Surge_Timer; + uint32 MortalWound_Timer; + uint32 Retaliation_Timer; + + bool HasTaunted; + bool YelledForHeal; + + void Reset() + { + Surge_Timer = 5000; + MortalWound_Timer = 4000; + Retaliation_Timer = 0; + + HasTaunted = false; + YelledForHeal = false; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void MoveInLineOfSight(Unit* who) + { + if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (!HasTaunted && me->IsWithinDistInMap(who, 60.0f)) + { + DoScriptText(SAY_TAUNT, me); + HasTaunted = true; + } + } + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (MortalWound_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MORTAL_WOUND); + MortalWound_Timer = 5000+rand()%8000; + } else MortalWound_Timer -= diff; + + if (Surge_Timer <= diff) + { + DoScriptText(SAY_SURGE, me); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SURGE); + + Surge_Timer = 5000+rand()%8000; + } else Surge_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) + { + if (Retaliation_Timer <= diff) + { + DoCast(me, SPELL_RETALIATION); + Retaliation_Timer = 30000; + } else Retaliation_Timer -= diff; + } + + if (!YelledForHeal) + { + if ((me->GetHealth()*100) / me->GetMaxHealth() < 40) + { + DoScriptText(SAY_HEAL, me); + YelledForHeal = true; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_watchkeeper_gargolmarAI(Creature* pCreature) +{ + return new boss_watchkeeper_gargolmarAI (pCreature); +} + +void AddSC_boss_watchkeeper_gargolmar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_watchkeeper_gargolmar"; + newscript->GetAI = &GetAI_boss_watchkeeper_gargolmarAI; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/hellfire_ramparts.h b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/hellfire_ramparts.h new file mode 100644 index 00000000000..599aa237774 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/hellfire_ramparts.h @@ -0,0 +1,16 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_RAMPARTS_H +#define DEF_RAMPARTS_H + +#define MAX_ENCOUNTER 2 + +enum eTypes +{ + TYPE_VAZRUDEN = 1, + TYPE_NAZAN = 2 +}; + +#endif diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/instance_hellfire_ramparts.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/instance_hellfire_ramparts.cpp new file mode 100644 index 00000000000..29c58675e9c --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/instance_hellfire_ramparts.cpp @@ -0,0 +1,84 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Hellfire_Ramparts +SD%Complete: 50 +SDComment: +SDCategory: Hellfire Ramparts +EndScriptData */ + +#include "ScriptedPch.h" +#include "hellfire_ramparts.h" + +struct instance_ramparts : public ScriptedInstance +{ + instance_ramparts(Map* pMap) : ScriptedInstance(pMap) {Initialize();} + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 m_uiChestNGUID; + uint64 m_uiChestHGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + m_uiChestNGUID = 0; + m_uiChestHGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 185168: m_uiChestNGUID = pGo->GetGUID(); break; + case 185169: m_uiChestHGUID = pGo->GetGUID(); break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + debug_log("TSCR: Instance Ramparts: SetData received for type %u with data %u",uiType,uiData); + + switch(uiType) + { + case TYPE_VAZRUDEN: + if (uiData == DONE && m_auiEncounter[1] == DONE) + DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); + m_auiEncounter[0] = uiData; + break; + case TYPE_NAZAN: + if (uiData == DONE && m_auiEncounter[0] == DONE) + DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); + m_auiEncounter[1] = uiData; + break; + } + } +}; + +InstanceData* GetInstanceData_instance_ramparts(Map* pMap) +{ + return new instance_ramparts(pMap); +} + +void AddSC_instance_ramparts() +{ + Script* pNewScript; + pNewScript = new Script; + pNewScript->Name = "instance_ramparts"; + pNewScript->GetInstanceData = &GetInstanceData_instance_ramparts; + pNewScript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp new file mode 100644 index 00000000000..5fb381f4065 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/boss_magtheridon.cpp @@ -0,0 +1,570 @@ +/* Copyright(C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +*(at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Magtheridon +SD%Complete: 60 +SDComment: In Development +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "magtheridons_lair.h" + +struct Yell +{ + int32 id; +}; + +static Yell RandomTaunt[]= +{ + {-1544000}, + {-1544001}, + {-1544002}, + {-1544003}, + {-1544004}, + {-1544005}, +}; + +#define SAY_FREED -1544006 +#define SAY_AGGRO -1544007 +#define SAY_BANISH -1544008 +#define SAY_CHAMBER_DESTROY -1544009 +#define SAY_PLAYER_KILLED -1544010 +#define SAY_DEATH -1544011 + +#define EMOTE_BERSERK -1544012 +#define EMOTE_BLASTNOVA -1544013 +#define EMOTE_BEGIN -1544014 + +#define MOB_MAGTHERIDON 17257 +#define MOB_ROOM 17516 +#define MOB_CHANNELLER 17256 +#define MOB_ABYSSAL 17454 + +#define SPELL_BLASTNOVA 30616 +#define SPELL_CLEAVE 30619 +#define SPELL_QUAKE_TRIGGER 30657 // must be cast with 30561 as the proc spell +#define SPELL_QUAKE_KNOCKBACK 30571 +#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 +#define SPELL_BLAZE_TRAP 30542 +#define SPELL_DEBRIS_KNOCKDOWN 36449 +#define SPELL_DEBRIS_VISUAL 30632 +#define SPELL_DEBRIS_DAMAGE 30631 // core bug, does not support target 8 +#define SPELL_CAMERA_SHAKE 36455 +#define SPELL_BERSERK 27680 + +#define SPELL_SHADOW_CAGE 30168 +#define SPELL_SHADOW_GRASP 30410 +#define SPELL_SHADOW_GRASP_VISUAL 30166 +#define SPELL_MIND_EXHAUSTION 44032 //Casted by the cubes when channeling ends + +#define SPELL_SHADOW_CAGE_C 30205 +#define SPELL_SHADOW_GRASP_C 30207 + +#define SPELL_SHADOW_BOLT_VOLLEY 30510 +#define SPELL_DARK_MENDING 30528 +#define SPELL_FEAR 30530 //39176 +#define SPELL_BURNING_ABYSSAL 30511 +#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 + +#define SPELL_FIRE_BLAST 37110 + +// count of clickers needed to interrupt blast nova +#define CLICKERS_COUNT 5 + +typedef std::map CubeMap; + +struct mob_abyssalAI : public ScriptedAI +{ + mob_abyssalAI(Creature *c) : ScriptedAI(c) + { + trigger = 0; + Despawn_Timer = 60000; + } + + uint32 FireBlast_Timer; + uint32 Despawn_Timer; + uint32 trigger; + + void Reset() + { + FireBlast_Timer = 6000; + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (trigger == 2 && spell->Id == SPELL_BLAZE_TARGET) + { + DoCast(me, SPELL_BLAZE_TRAP, true); + me->SetVisibility(VISIBILITY_OFF); + Despawn_Timer = 130000; + } + } + + void SetTrigger(uint32 _trigger) + { + trigger = _trigger; + me->SetDisplayId(11686); + if (trigger == 1) //debris + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(me, SPELL_DEBRIS_VISUAL, true); + FireBlast_Timer = 5000; + Despawn_Timer = 10000; + } + } + + void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} + void AttackStart(Unit *who) {if (!trigger) ScriptedAI::AttackStart(who);} + void MoveInLineOfSight(Unit *who) {if (!trigger) ScriptedAI::MoveInLineOfSight(who);} + + void UpdateAI(const uint32 diff) + { + if (trigger) + { + if (trigger == 1) + { + if (FireBlast_Timer <= diff) + { + DoCast(me, SPELL_DEBRIS_DAMAGE, true); + trigger = 3; + } else FireBlast_Timer -= diff; + } + return; + } + + if (Despawn_Timer <= diff) + { + me->ForcedDespawn(); + } else Despawn_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (FireBlast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FIRE_BLAST); + FireBlast_Timer = 5000+rand()%10000; + } else FireBlast_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +struct boss_magtheridonAI : public ScriptedAI +{ + boss_magtheridonAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + + // target 7, random target with certain entry spell, need core fix + SpellEntry *TempSpell; + TempSpell = GET_SPELL(SPELL_BLAZE_TARGET); + if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 6) + { + TempSpell->EffectImplicitTargetA[0] = 6; + TempSpell->EffectImplicitTargetB[0] = 0; + } + TempSpell = GET_SPELL(SPELL_QUAKE_TRIGGER); + if (TempSpell && TempSpell->EffectTriggerSpell[0] != SPELL_QUAKE_KNOCKBACK) + { + TempSpell->EffectTriggerSpell[0] = SPELL_QUAKE_KNOCKBACK; + } + } + + CubeMap Cube; + + ScriptedInstance* pInstance; + + uint32 Berserk_Timer; + uint32 Quake_Timer; + uint32 Cleave_Timer; + uint32 BlastNova_Timer; + uint32 Blaze_Timer; + uint32 Debris_Timer; + uint32 RandChat_Timer; + + bool Phase3; + bool NeedCheckCube; + + void Reset() + { + Berserk_Timer = 1320000; + Quake_Timer = 40000; + Debris_Timer = 10000; + Blaze_Timer = 10000+rand()%20000; + BlastNova_Timer = 60000; + Cleave_Timer = 15000; + RandChat_Timer = 90000; + + Phase3 = false; + NeedCheckCube = false; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + me->addUnitState(UNIT_STAT_STUNNED); + DoCast(me, SPELL_SHADOW_CAGE_C, true); + } + + void JustReachedHome() + { + if (pInstance) + { + pInstance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED); + pInstance->SetData(DATA_COLLAPSE, false); + } + } + + void SetClicker(uint64 cubeGUID, uint64 clickerGUID) + { + // to avoid multiclicks from 1 cube + if (uint64 guid = Cube[cubeGUID]) + DebuffClicker(Unit::GetUnit(*me, guid)); + Cube[cubeGUID] = clickerGUID; + NeedCheckCube = true; + } + + //function to interrupt channeling and debuff clicker with mind exh(used if second person clicks with same cube or after dispeling/ending shadow grasp DoT) + void DebuffClicker(Unit *clicker) + { + if (!clicker || !clicker->isAlive()) + return; + + clicker->RemoveAurasDueToSpell(SPELL_SHADOW_GRASP); // cannot interrupt triggered spells + clicker->InterruptNonMeleeSpells(false); + clicker->CastSpell(clicker, SPELL_MIND_EXHAUSTION, true); + } + + void NeedCheckCubeStatus() + { + uint32 ClickerNum = 0; + // now checking if every clicker has debuff from manticron(it is dispelable atm rev 6110 : S) + // if not - apply mind exhaustion and delete from clicker's list + for (CubeMap::iterator i = Cube.begin(); i != Cube.end(); ++i) + { + Unit *clicker = Unit::GetUnit(*me, (*i).second); + if (!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP)) + { + DebuffClicker(clicker); + (*i).second = 0; + } else ++ClickerNum; + } + + // if 5 clickers from other cubes apply shadow cage + if (ClickerNum >= CLICKERS_COUNT && !me->HasAura(SPELL_SHADOW_CAGE)) + { + DoScriptText(SAY_BANISH, me); + DoCast(me, SPELL_SHADOW_CAGE, true); + } + else if (ClickerNum < CLICKERS_COUNT && me->HasAura(SPELL_SHADOW_CAGE)) + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); + + if (!ClickerNum) NeedCheckCube = false; + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(SAY_PLAYER_KILLED, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + pInstance->SetData(DATA_MAGTHERIDON_EVENT, DONE); + + DoScriptText(SAY_DEATH, me); + } + + void MoveInLineOfSight(Unit* /*who*/) {} + + void AttackStart(Unit *who) + { + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + ScriptedAI::AttackStart(who); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS); + DoZoneInCombat(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); + + DoScriptText(SAY_FREED, me); + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) + { + if (RandChat_Timer <= diff) + { + DoScriptText(RandomTaunt[rand()%6].id, me); + RandChat_Timer = 90000; + } else RandChat_Timer -= diff; + } + + if (!UpdateVictim()) + return; + + if (NeedCheckCube) NeedCheckCubeStatus(); + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + DoScriptText(EMOTE_BERSERK, me); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CLEAVE); + Cleave_Timer = 10000; + } else Cleave_Timer -= diff; + + if (BlastNova_Timer <= diff) + { + // to avoid earthquake interruption + if (!me->hasUnitState(UNIT_STAT_STUNNED)) + { + DoScriptText(EMOTE_BLASTNOVA, me); + DoCast(me, SPELL_BLASTNOVA); + BlastNova_Timer = 60000; + } + } else BlastNova_Timer -= diff; + + if (Quake_Timer <= diff) + { + // to avoid blastnova interruption + if (!me->IsNonMeleeSpellCasted(false)) + { + DoCast(me, SPELL_QUAKE_TRIGGER, true); + Quake_Timer = 50000; + } + } else Quake_Timer -= diff; + + if (Blaze_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (summon) + { + CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(2); + DoCast(summon, SPELL_BLAZE_TARGET, true); + summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } + Blaze_Timer = 20000 + rand()%20000; + } else Blaze_Timer -= diff; + + if (!Phase3 && me->GetHealth()*10 < me->GetMaxHealth()*3 + && !me->IsNonMeleeSpellCasted(false) // blast nova + && !me->hasUnitState(UNIT_STAT_STUNNED)) // shadow cage and earthquake + { + Phase3 = true; + DoScriptText(SAY_CHAMBER_DESTROY, me); + DoCast(me, SPELL_CAMERA_SHAKE, true); + DoCast(me, SPELL_DEBRIS_KNOCKDOWN, true); + + if (pInstance) + pInstance->SetData(DATA_COLLAPSE, true); + } + + if (Phase3) + { + if (Debris_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + float x, y, z; + pTarget->GetPosition(x, y, z); + Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); + if (summon) CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(1); + } + Debris_Timer = 10000; + } else Debris_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_hellfire_channelerAI : public ScriptedAI +{ + mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c) + { + pInstance =me->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 ShadowBoltVolley_Timer; + uint32 DarkMending_Timer; + uint32 Fear_Timer; + uint32 Infernal_Timer; + + uint32 Check_Timer; + + void Reset() + { + ShadowBoltVolley_Timer = 8000 + rand()%2000; + DarkMending_Timer = 10000; + Fear_Timer = 15000 + rand()%5000; + Infernal_Timer = 10000 + rand()%40000; + + Check_Timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS); + + me->InterruptNonMeleeSpells(false); + DoZoneInCombat(); + } + + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED); + + DoCast(me, SPELL_SHADOW_GRASP_C, false); + } + + void JustSummoned(Creature *summon) + { + summon->AI()->AttackStart(me->getVictim()); + } + + void DamageTaken(Unit*, uint32 &damage) + { + if (damage >= me->GetHealth()) + DoCast(me, SPELL_SOUL_TRANSFER, true); + } + + void JustDied(Unit* /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_CHANNELER_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ShadowBoltVolley_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); + ShadowBoltVolley_Timer = 10000 + rand()%10000; + } else ShadowBoltVolley_Timer -= diff; + + if (DarkMending_Timer <= diff) + { + if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) + DoCast(me, SPELL_DARK_MENDING); + DarkMending_Timer = 10000 +(rand() % 10000); + } else DarkMending_Timer -= diff; + + if (Fear_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_FEAR); + Fear_Timer = 25000 + rand()%15000; + } else Fear_Timer -= diff; + + if (Infernal_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BURNING_ABYSSAL, true); + Infernal_Timer = 30000 + rand()%10000; + } else Infernal_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Manticron Cube +bool GOHello_go_Manticron_Cube(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = pGo->GetInstanceData(); + if (!pInstance) + return true; + if (pInstance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) return true; + Creature *Magtheridon =Unit::GetCreature(*pGo, pInstance->GetData64(DATA_MAGTHERIDON)); + if (!Magtheridon || !Magtheridon->isAlive()) return true; + + // if exhausted or already channeling return + if (pPlayer->HasAura(SPELL_MIND_EXHAUSTION) || pPlayer->HasAura(SPELL_SHADOW_GRASP)) + return true; + + pPlayer->InterruptNonMeleeSpells(false); + pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP, true); + pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP_VISUAL, false); + CAST_AI(boss_magtheridonAI, Magtheridon->AI())->SetClicker(pGo->GetGUID(), pPlayer->GetGUID()); + return true; +} + +CreatureAI* GetAI_boss_magtheridon(Creature* pCreature) +{ + return new boss_magtheridonAI(pCreature); +} + +CreatureAI* GetAI_mob_hellfire_channeler(Creature* pCreature) +{ + return new mob_hellfire_channelerAI(pCreature); +} + +CreatureAI* GetAI_mob_abyssalAI(Creature* pCreature) +{ + return new mob_abyssalAI(pCreature); +} + +void AddSC_boss_magtheridon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_magtheridon"; + newscript->GetAI = &GetAI_boss_magtheridon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_hellfire_channeler"; + newscript->GetAI = &GetAI_mob_hellfire_channeler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_manticron_cube"; + newscript->pGOHello = &GOHello_go_Manticron_Cube; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_abyssal"; + newscript->GetAI = &GetAI_mob_abyssalAI; + newscript->RegisterSelf(); + +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp new file mode 100644 index 00000000000..d5b459a1fa1 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/instance_magtheridons_lair.cpp @@ -0,0 +1,254 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Magtheridons_Lair +SD%Complete: 100 +SDComment: +SDCategory: Hellfire Citadel, Magtheridon's lair +EndScriptData */ + +#include "ScriptedPch.h" +#include "magtheridons_lair.h" + +#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 +#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 + +#define CHAMBER_CENTER_X -15.14 +#define CHAMBER_CENTER_Y 1.8 +#define CHAMBER_CENTER_Z -0.4 + +#define MAX_ENCOUNTER 2 + +#define EMOTE_BONDS_WEAKEN "'s bonds begin to weaken!" + +struct instance_magtheridons_lair : public ScriptedInstance +{ + instance_magtheridons_lair(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + } + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 MagtheridonGUID; + std::set ChannelerGUID; + uint64 DoorGUID; + std::set ColumnGUID; + + uint32 CageTimer; + uint32 RespawnTimer; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + MagtheridonGUID = 0; + ChannelerGUID.clear(); + DoorGUID = 0; + ColumnGUID.clear(); + + CageTimer = 0; + RespawnTimer = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 17257: + MagtheridonGUID = pCreature->GetGUID(); + break; + case 17256: + ChannelerGUID.insert(pCreature->GetGUID()); + break; + } + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case 181713: + pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 0); + break; + case 183847: + DoorGUID = pGo->GetGUID(); + break; + case 184653: // hall + case 184634: // six columns + case 184635: + case 184636: + case 184637: + case 184638: + case 184639: + ColumnGUID.insert(pGo->GetGUID()); + break; + } + } + + uint64 GetData64(uint32 type) + { + switch(type) + { + case DATA_MAGTHERIDON: + return MagtheridonGUID; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_MAGTHERIDON_EVENT: + m_auiEncounter[0] = data; + if (data == NOT_STARTED) + RespawnTimer = 10000; + if (data != IN_PROGRESS) + HandleGameObject(DoorGUID, true); + break; + case DATA_CHANNELER_EVENT: + switch(data) + { + case NOT_STARTED: // Reset all channelers once one is reset. + if (m_auiEncounter[1] != NOT_STARTED) + { + m_auiEncounter[1] = NOT_STARTED; + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + if (Creature *Channeler = instance->GetCreature(*i)) + { + if (Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); + } + } + CageTimer = 0; + HandleGameObject(DoorGUID, true); + } + break; + case IN_PROGRESS: // Event start. + if (m_auiEncounter[1] != IN_PROGRESS) + { + m_auiEncounter[1] = IN_PROGRESS; + // Let all five channelers aggro. + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + Creature *Channeler = instance->GetCreature(*i); + if (Channeler && Channeler->isAlive()) + Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); + } + // Release Magtheridon after two minutes. + Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); + if (Magtheridon && Magtheridon->isAlive()) + { + Magtheridon->MonsterTextEmote(EMOTE_BONDS_WEAKEN, 0); + CageTimer = 120000; + } + HandleGameObject(DoorGUID, false); + } + break; + case DONE: // Add buff and check if all channelers are dead. + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + Creature *Channeler = instance->GetCreature(*i); + if (Channeler && Channeler->isAlive()) + { + //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); + data = IN_PROGRESS; + break; + } + } + break; + } + m_auiEncounter[1] = data; + break; + case DATA_COLLAPSE: + // true - collapse / false - reset + for (std::set::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) + DoUseDoorOrButton(*i); + break; + default: + break; + } + } + + uint32 GetData(uint32 type) + { + if (type == DATA_MAGTHERIDON_EVENT) + return m_auiEncounter[0]; + return 0; + } + + void Update(uint32 diff) + { + if (CageTimer) + { + if (CageTimer <= diff) + { + Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); + if (Magtheridon && Magtheridon->isAlive()) + { + Magtheridon->clearUnitState(UNIT_STAT_STUNNED); + Magtheridon->AI()->AttackStart(Magtheridon->SelectNearestTarget(999)); + } + CageTimer = 0; + } else CageTimer -= diff; + } + + if (RespawnTimer) + { + if (RespawnTimer <= diff) + { + for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) + { + if (Creature *Channeler = instance->GetCreature(*i)) + { + if (Channeler->isAlive()) + Channeler->AI()->EnterEvadeMode(); + else + Channeler->Respawn(); + } + } + RespawnTimer = 0; + } else RespawnTimer -= diff; + } + } +}; + +InstanceData* GetInstanceData_instance_magtheridons_lair(Map* pMap) +{ + return new instance_magtheridons_lair(pMap); +} + +void AddSC_instance_magtheridons_lair() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_magtheridons_lair"; + newscript->GetInstanceData = &GetInstanceData_instance_magtheridons_lair; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h new file mode 100644 index 00000000000..1b3e525fc54 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/MagtheridonsLair/magtheridons_lair.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_MAGTHERIDONS_LAIR_H +#define DEF_MAGTHERIDONS_LAIR_H + +#define DATA_MAGTHERIDON_EVENT 1 +#define DATA_MAGTHERIDON 3 +#define DATA_CHANNELER_EVENT 2 +#define DATA_COLLAPSE 6 +#define DATA_CHANNELER 9 +#endif + diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp new file mode 100644 index 00000000000..e3ded52edc9 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp @@ -0,0 +1,396 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Grand_Warlock_Nethekurse +SD%Complete: 75 +SDComment: encounter not fully completed. missing part where boss kill minions. +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_grand_warlock_nethekurse +mob_fel_orc_convert +mob_lesser_shadow_fissure +EndContentData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +struct Say +{ + int32 id; +}; + +static Say PeonAttacked[]= +{ + {-1540001}, + {-1540002}, + {-1540003}, + {-1540004}, +}; +static Say PeonDies[]= +{ + {-1540005}, + {-1540006}, + {-1540007}, + {-1540008}, +}; + +#define SAY_INTRO -1540000 +#define SAY_TAUNT_1 -1540009 +#define SAY_TAUNT_2 -1540010 +#define SAY_TAUNT_3 -1540011 +#define SAY_AGGRO_1 -1540012 +#define SAY_AGGRO_2 -1540013 +#define SAY_AGGRO_3 -1540014 +#define SAY_SLAY_1 -1540015 +#define SAY_SLAY_2 -1540016 +#define SAY_DIE -1540017 + +#define SPELL_DEATH_COIL 30500 +#define SPELL_DARK_SPIN 30502 // core bug spell attack caster :D +#define SPELL_SHADOW_FISSURE 30496 // Summon the ShadowFissure NPC + +#define SPELL_SHADOW_CLEAVE 30495 +#define H_SPELL_SHADOW_SLAM 35953 + +#define SPELL_HEMORRHAGE 30478 + +#define SPELL_CONSUMPTION 30497 +#define SPELL_TEMPORARY_VISUAL 39312 // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should + +struct boss_grand_warlock_nethekurseAI : public ScriptedAI +{ + boss_grand_warlock_nethekurseAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + bool IntroOnce; + bool IsIntroEvent; + bool IsMainEvent; + bool SpinOnce; + //bool HasTaunted; + bool Phase; + + uint32 PeonEngagedCount; + uint32 PeonKilledCount; + + uint32 IntroEvent_Timer; + uint32 DeathCoil_Timer; + uint32 ShadowFissure_Timer; + uint32 Cleave_Timer; + + void Reset() + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + IsIntroEvent = false; + IntroOnce = false; + IsMainEvent = false; + //HasTaunted = false; + SpinOnce = false; + Phase = false; + + PeonEngagedCount = 0; + PeonKilledCount = 0; + + IntroEvent_Timer = 90000; //how long before getting bored and kills his minions? + DeathCoil_Timer = 20000; + ShadowFissure_Timer = 8000; + Cleave_Timer = 5000; + } + + void DoYellForPeonAggro() + { + if (PeonEngagedCount >= 4) + return; + + DoScriptText(PeonAttacked[PeonEngagedCount].id, me); + ++PeonEngagedCount; + } + + void DoYellForPeonDeath() + { + if (PeonKilledCount >= 4) + return; + + DoScriptText(PeonDies[PeonKilledCount].id, me); + ++PeonKilledCount; + + if (PeonKilledCount == 4) + { + IsIntroEvent = false; + IsMainEvent = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void DoTauntPeons() + { + DoScriptText(RAND(SAY_TAUNT_1,SAY_TAUNT_2,SAY_TAUNT_3), me); + + //TODO: kill the peons first + IsIntroEvent = false; + PeonEngagedCount = 4; + PeonKilledCount = 4; + IsMainEvent = true; + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackStart(Unit* who) + { + if (IsIntroEvent || !IsMainEvent) + return; + + if (me->Attack(who, true)) + { + if (Phase) + DoStartNoMovement(who); + else + DoStartMovement(who); + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!IntroOnce && me->IsWithinDistInMap(who, 50.0f)) + { + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + DoScriptText(SAY_INTRO, me); + IntroOnce = true; + IsIntroEvent = true; + + if (pInstance) + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + + if (IsIntroEvent || !IsMainEvent) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); + } + + void JustSummoned(Creature *summoned) + { + summoned->setFaction(16); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //triggered spell of consumption does not properly show it's SpellVisual, wrong spellid? + summoned->CastSpell(summoned,SPELL_TEMPORARY_VISUAL,true); + summoned->CastSpell(summoned,SPELL_CONSUMPTION,false,0,0,me->GetGUID()); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DIE, me); + + if (!pInstance) + return; + + pInstance->SetData(TYPE_NETHEKURSE,DONE); + pInstance->HandleGameObject(pInstance->GetData64(DATA_NETHEKURSE_DOOR), true); + } + + void UpdateAI(const uint32 diff) + { + if (IsIntroEvent) + { + if (!pInstance) + return; + + if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) + { + if (IntroEvent_Timer <= diff) + DoTauntPeons(); + else + IntroEvent_Timer -= diff; + } + } + + if (!UpdateVictim()) + return; + + if (!IsMainEvent) + return; + + if (Phase) + { + if (!SpinOnce) + { + DoCast(me->getVictim(), SPELL_DARK_SPIN); + SpinOnce = true; + } + + if (Cleave_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SHADOW_CLEAVE); + Cleave_Timer = 6000+rand()%2500; + } else Cleave_Timer -= diff; + } + else + { + if (ShadowFissure_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_SHADOW_FISSURE); + ShadowFissure_Timer = urand(7500,15000); + } else ShadowFissure_Timer -= diff; + + if (DeathCoil_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + DoCast(pTarget, SPELL_DEATH_COIL); + DeathCoil_Timer = urand(15000,20000); + } else DeathCoil_Timer -= diff; + + if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) + Phase = true; + + DoMeleeAttackIfReady(); + } + } +}; + +struct mob_fel_orc_convertAI : public ScriptedAI +{ + mob_fel_orc_convertAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + uint32 Hemorrhage_Timer; + + void Reset() + { + me->SetNoCallAssistance(true); //we don't want any assistance (WE R HEROZ!) + Hemorrhage_Timer = 3000; + } + + void MoveInLineOfSight(Unit * /*who*/) + { + } + + void EnterCombat(Unit* /*who*/) + { + if (pInstance) + { + if (pInstance->GetData64(DATA_NETHEKURSE)) + { + Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE)); + if (pKurse && me->IsWithinDist(pKurse, 45.0f)) + { + CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonAggro(); + + if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) + return; + else + pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); + } + } + } + } + + void JustDied(Unit* /*Killer*/) + { + if (pInstance) + { + if (pInstance->GetData(TYPE_NETHEKURSE) != IN_PROGRESS) + return; + if (pInstance->GetData64(DATA_NETHEKURSE)) + if (Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE))) + CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonDeath(); + } + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Hemorrhage_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_HEMORRHAGE); + Hemorrhage_Timer = 15000; + } else Hemorrhage_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//NOTE: this Creature are also summoned by other spells, for different creatures +struct mob_lesser_shadow_fissureAI : public ScriptedAI +{ + mob_lesser_shadow_fissureAI(Creature *c) : ScriptedAI(c) {} + + void Reset() { } + void MoveInLineOfSight(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void EnterCombat(Unit* /*who*/) {} +}; + +CreatureAI* GetAI_boss_grand_warlock_nethekurse(Creature* pCreature) +{ + return new boss_grand_warlock_nethekurseAI (pCreature); +} + +CreatureAI* GetAI_mob_fel_orc_convert(Creature* pCreature) +{ + return new mob_fel_orc_convertAI (pCreature); +} + +CreatureAI* GetAI_mob_lesser_shadow_fissure(Creature* pCreature) +{ + return new mob_lesser_shadow_fissureAI (pCreature); +} + +void AddSC_boss_grand_warlock_nethekurse() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_grand_warlock_nethekurse"; + newscript->GetAI = &GetAI_boss_grand_warlock_nethekurse; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_orc_convert"; + newscript->GetAI = &GetAI_mob_fel_orc_convert; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lesser_shadow_fissure"; + newscript->GetAI = &GetAI_mob_lesser_shadow_fissure; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp new file mode 100644 index 00000000000..6fa1c9efe33 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp @@ -0,0 +1,404 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warbringer_Omrogg +SD%Complete: 85 +SDComment: Heroic enabled. Spell timing may need additional tweaks +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +mob_omrogg_heads +boss_warbringer_omrogg +EndContentData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +enum eEnums +{ + YELL_DIE_L = -1540039, + YELL_DIE_R = -1540040, + EMOTE_ENRAGE = -1540041, + + SPELL_BLAST_WAVE = 30600, + SPELL_FEAR = 30584, + SPELL_THUNDERCLAP = 30633, + + SPELL_BURNING_MAUL = 30598, + H_SPELL_BURNING_MAUL = 36056, + + NPC_LEFT_HEAD = 19523, + NPC_RIGHT_HEAD = 19524 +}; + +struct Yell +{ + int32 id; + uint32 creature; +}; + +static Yell GoCombat[]= +{ + {-1540018, NPC_LEFT_HEAD}, + {-1540019, NPC_LEFT_HEAD}, + {-1540020, NPC_LEFT_HEAD}, +}; +static Yell GoCombatDelay[]= +{ + {-1540021, NPC_RIGHT_HEAD}, + {-1540022, NPC_RIGHT_HEAD}, + {-1540023, NPC_RIGHT_HEAD}, +}; + +static Yell Threat[]= +{ + {-1540024, NPC_LEFT_HEAD}, + {-1540025, NPC_RIGHT_HEAD}, + {-1540026, NPC_LEFT_HEAD}, + {-1540027, NPC_LEFT_HEAD}, +}; +static Yell ThreatDelay1[]= +{ + {-1540028, NPC_RIGHT_HEAD}, + {-1540029, NPC_LEFT_HEAD}, + {-1540030, NPC_RIGHT_HEAD}, + {-1540031, NPC_RIGHT_HEAD}, +}; +static Yell ThreatDelay2[]= +{ + {-1540032, NPC_LEFT_HEAD}, + {-1540033, NPC_RIGHT_HEAD}, + {-1540034, NPC_LEFT_HEAD}, + {-1540035, NPC_LEFT_HEAD}, +}; + +static Yell Killing[]= +{ + {-1540036, NPC_LEFT_HEAD}, + {-1540037, NPC_RIGHT_HEAD}, +}; +static Yell KillingDelay[]= +{ + {-1540038, NPC_RIGHT_HEAD}, + {-1000000, NPC_LEFT_HEAD}, +}; + +struct mob_omrogg_headsAI : public ScriptedAI +{ + mob_omrogg_headsAI(Creature *c) : ScriptedAI(c) {} + + bool DeathYell; + uint32 Death_Timer; + + void Reset() + { + Death_Timer = 4000; + DeathYell = false; + } + void EnterCombat(Unit* /*who*/) {} + + void DoDeathYell() + { + DeathYell = true; + } + + void UpdateAI(const uint32 diff) + { + if (!DeathYell) + return; + + if (Death_Timer <= diff) + { + DoScriptText(YELL_DIE_R, me); + Death_Timer = false; + me->setDeathState(JUST_DIED); + } else Death_Timer -= diff; + } +}; + +struct boss_warbringer_omroggAI : public ScriptedAI +{ + boss_warbringer_omroggAI(Creature *c) : ScriptedAI(c) + { + LeftHeadGUID = 0; + RightHeadGUID = 0; + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint64 LeftHeadGUID; + uint64 RightHeadGUID; + int iaggro; + int ithreat; + int ikilling; + + bool AggroYell; + bool ThreatYell; + bool ThreatYell2; + bool KillingYell; + + uint32 Delay_Timer; + uint32 BlastWave_Timer; + uint32 BlastCount; + uint32 Fear_Timer; + uint32 BurningMaul_Timer; + uint32 ThunderClap_Timer; + uint32 ResetThreat_Timer; + + void Reset() + { + if (Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) + { + pLeftHead->setDeathState(JUST_DIED); + LeftHeadGUID = 0; + } + + if (Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID)) + { + pRightHead->setDeathState(JUST_DIED); + RightHeadGUID = 0; + } + + AggroYell = false; + ThreatYell = false; + ThreatYell2 = false; + KillingYell = false; + + Delay_Timer = 4000; + BlastWave_Timer = 0; + BlastCount = 0; + Fear_Timer = 8000; + BurningMaul_Timer = 25000; + ThunderClap_Timer = 15000; + ResetThreat_Timer = 30000; + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, NOT_STARTED); //End boss can use this later. O'mrogg must be defeated(DONE) or he will come to aid. + } + + void DoYellForThreat() + { + Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit *pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + ithreat = rand()%4; + + Unit *source = (pLeftHead->GetEntry() == Threat[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(Threat[ithreat].id, source); + + Delay_Timer = 3500; + ThreatYell = true; + } + + void EnterCombat(Unit * /*who*/) + { + me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); + + if (Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) + { + iaggro = rand()%3; + + DoScriptText(GoCombat[iaggro].id, pLeftHead); + + Delay_Timer = 3500; + AggroYell = true; + } + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, IN_PROGRESS); + } + + void JustSummoned(Creature *summoned) + { + if (summoned->GetEntry() == NPC_LEFT_HEAD) + LeftHeadGUID = summoned->GetGUID(); + + if (summoned->GetEntry() == NPC_RIGHT_HEAD) + RightHeadGUID = summoned->GetGUID(); + + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + summoned->SetVisibility(VISIBILITY_OFF); + } + + void KilledUnit(Unit* /*victim*/) + { + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + ikilling = rand()%2; + + Unit *source = (pLeftHead->GetEntry() == Killing[ikilling].creature ? pLeftHead : pRightHead); + + switch(ikilling) + { + case 0: + DoScriptText(Killing[ikilling].id, source); + Delay_Timer = 3500; + KillingYell = true; + break; + case 1: + DoScriptText(Killing[ikilling].id, source); + KillingYell = false; + break; + } + } + + void JustDied(Unit* /*Killer*/) + { + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + DoScriptText(YELL_DIE_L, pLeftHead); + + CAST_AI(mob_omrogg_headsAI, CAST_CRE(pRightHead)->AI())->DoDeathYell(); + + if (pInstance) + pInstance->SetData(TYPE_OMROGG, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (Delay_Timer <= diff) + { + Delay_Timer = 3500; + + Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); + Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); + + if (!pLeftHead || !pRightHead) + return; + + if (AggroYell) + { + DoScriptText(GoCombatDelay[iaggro].id, pRightHead); + AggroYell = false; + } + + if (ThreatYell2) + { + Unit *source = (pLeftHead->GetEntry() == ThreatDelay2[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(ThreatDelay2[ithreat].id, source); + ThreatYell2 = false; + } + + if (ThreatYell) + { + Unit *source = (pLeftHead->GetEntry() == ThreatDelay1[ithreat].creature ? pLeftHead : pRightHead); + + DoScriptText(ThreatDelay1[ithreat].id, source); + ThreatYell = false; + ThreatYell2 = true; + } + + if (KillingYell) + { + Unit *source = (pLeftHead->GetEntry() == KillingDelay[ikilling].creature ? pLeftHead : pRightHead); + + DoScriptText(KillingDelay[ikilling].id, source); + KillingYell = false; + } + } else Delay_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (BlastCount && BlastWave_Timer <= diff) + { + DoCast(me, SPELL_BLAST_WAVE); + BlastWave_Timer = 5000; + ++BlastCount; + + if (BlastCount == 3) + BlastCount = 0; + } else BlastWave_Timer -= diff; + + if (BurningMaul_Timer <= diff) + { + DoScriptText(EMOTE_ENRAGE, me); + DoCast(me, SPELL_BURNING_MAUL); + BurningMaul_Timer = 40000; + BlastWave_Timer = 16000; + BlastCount = 1; + } else BurningMaul_Timer -= diff; + + if (ResetThreat_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + { + DoYellForThreat(); + DoResetThreat(); + me->AddThreat(pTarget, 0.0f); + } + ResetThreat_Timer = 25000+rand()%15000; + } else ResetThreat_Timer -= diff; + + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 15000+rand()%20000; + } else Fear_Timer -= diff; + + if (ThunderClap_Timer <= diff) + { + DoCast(me, SPELL_THUNDERCLAP); + ThunderClap_Timer = 15000+rand()%15000; + } else ThunderClap_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_warbringer_omrogg(Creature* pCreature) +{ + return new boss_warbringer_omroggAI (pCreature); +} + +CreatureAI* GetAI_mob_omrogg_heads(Creature* pCreature) +{ + return new mob_omrogg_headsAI (pCreature); +} + +void AddSC_boss_warbringer_omrogg() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_warbringer_omrogg"; + newscript->GetAI = &GetAI_boss_warbringer_omrogg; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_omrogg_heads"; + newscript->GetAI = &GetAI_mob_omrogg_heads; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp new file mode 100644 index 00000000000..b108077518a --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp @@ -0,0 +1,288 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Warchief_Kargath_Bladefist +SD%Complete: 90 +SDComment: +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +/* ContentData +boss_warchief_kargath_bladefist +EndContentData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO1 -1540042 +#define SAY_AGGRO2 -1540043 +#define SAY_AGGRO3 -1540044 +#define SAY_SLAY1 -1540045 +#define SAY_SLAY2 -1540046 +#define SAY_DEATH -1540047 + +#define SPELL_BLADE_DANCE 30739 +#define H_SPELL_CHARGE 25821 + +#define TARGET_NUM 5 + +#define MOB_SHATTERED_ASSASSIN 17695 +#define MOB_HEARTHEN_GUARD 17621 +#define MOB_SHARPSHOOTER_GUARD 17622 +#define MOB_REAVER_GUARD 17623 + +float AssassEntrance[3] = {275.136,-84.29,2.3}; // y -8 +float AssassExit[3] = {184.233,-84.29,2.3}; // y -8 +float AddsEntrance[3] = {306.036,-84.29,1.93}; + +struct boss_warchief_kargath_bladefistAI : public ScriptedAI +{ + boss_warchief_kargath_bladefistAI(Creature *c) : ScriptedAI(c) + { + } + + std::vector adds; + std::vector assassins; + + uint32 Charge_timer; + uint32 Blade_Dance_Timer; + uint32 Summon_Assistant_Timer; + uint32 resetcheck_timer; + uint32 Wait_Timer; + + uint32 Assassins_Timer; + + uint32 summoned; + bool InBlade; + + uint32 target_num; + + void Reset() + { + removeAdds(); + + me->SetSpeed(MOVE_RUN,2); + me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); + + summoned = 2; + InBlade = false; + Wait_Timer = 0; + + Charge_timer = 0; + Blade_Dance_Timer = 45000; + Summon_Assistant_Timer = 30000; + Assassins_Timer = 5000; + resetcheck_timer = 5000; + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); + } + + void JustSummoned(Creature *summoned) + { + switch(summoned->GetEntry()) + { + case MOB_HEARTHEN_GUARD: + case MOB_SHARPSHOOTER_GUARD: + case MOB_REAVER_GUARD: + summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0)); + adds.push_back(summoned->GetGUID()); + break; + case MOB_SHATTERED_ASSASSIN: + assassins.push_back(summoned->GetGUID()); + break; + } + } + + void KilledUnit(Unit* victim) + { + if (victim->GetTypeId() == TYPEID_PLAYER) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + removeAdds(); + } + + void MovementInform(uint32 type, uint32 id) + { + if (InBlade) + { + if (type != POINT_MOTION_TYPE) + return; + + if (id != 1) + return; + + if (target_num > 0) // to prevent loops + { + Wait_Timer = 1; + DoCast(me, SPELL_BLADE_DANCE, true); + target_num--; + } + } + } + + void removeAdds() + { + for (std::vector::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) + { + Unit* temp = Unit::GetUnit((*me),*itr); + if (temp && temp->isAlive()) + { + (*temp).GetMotionMaster()->Clear(true); + me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CAST_CRE(temp)->RemoveCorpse(); + } + } + adds.clear(); + + for (std::vector::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) + { + Unit* temp = Unit::GetUnit((*me),*itr); + if (temp && temp->isAlive()) + { + (*temp).GetMotionMaster()->Clear(true); + me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + CAST_CRE(temp)->RemoveCorpse(); + } + } + assassins.clear(); + } + void SpawnAssassin() + { + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]+8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]-8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]+8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]-8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Assassins_Timer) + if (Assassins_Timer <= diff) + { + SpawnAssassin(); + Assassins_Timer = 0; + } else Assassins_Timer -= diff; + + if (InBlade) + { + if (Wait_Timer) + if (Wait_Timer <= diff) + { + if (target_num <= 0) + { + // stop bladedance + InBlade = false; + me->SetSpeed(MOVE_RUN,2); + me->GetMotionMaster()->MoveChase(me->getVictim()); + Blade_Dance_Timer = 30000; + Wait_Timer = 0; + if (IsHeroic()) + Charge_timer = 5000; + } + else + { + //move in bladedance + float x,y,randx,randy; + randx = (rand()%40); + randy = (rand()%40); + x = 210+ randx ; + y = -60- randy ; + me->GetMotionMaster()->MovePoint(1,x,y,me->GetPositionZ()); + Wait_Timer = 0; + } + } else Wait_Timer -= diff; + } + else + { + if (Blade_Dance_Timer) + if (Blade_Dance_Timer <= diff) + { + target_num = TARGET_NUM; + Wait_Timer = 1; + InBlade = true; + Blade_Dance_Timer = 0; + me->SetSpeed(MOVE_RUN,4); + return; + } else Blade_Dance_Timer -= diff; + + if (Charge_timer) + if (Charge_timer <= diff) + { + DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), H_SPELL_CHARGE); + Charge_timer = 0; + } else Charge_timer -= diff; + + if (Summon_Assistant_Timer <= diff) + { + for (uint8 i = 0; i < summoned; ++i) + { + switch (urand(0,2)) + { + case 0: me->SummonCreature(MOB_HEARTHEN_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + case 1: me->SummonCreature(MOB_SHARPSHOOTER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + case 2: me->SummonCreature(MOB_REAVER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; + } + } + if (urand(0,9) < 2) + ++summoned; + Summon_Assistant_Timer = urand(25000,35000); + } else Summon_Assistant_Timer -= diff; + + DoMeleeAttackIfReady(); + } + + if (resetcheck_timer <= diff) + { + uint32 tempx,tempy; + tempx = uint32(me->GetPositionX()); + tempy = uint32(me->GetPositionY()); + if (tempx > 255 || tempx < 205) + { + EnterEvadeMode(); + return; + } + resetcheck_timer = 5000; + } else resetcheck_timer -= diff; + } +}; + +CreatureAI* GetAI_boss_warchief_kargath_bladefist(Creature* pCreature) +{ + return new boss_warchief_kargath_bladefistAI (pCreature); +} + +void AddSC_boss_warchief_kargath_bladefist() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_warchief_kargath_bladefist"; + newscript->GetAI = &GetAI_boss_warchief_kargath_bladefist; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp new file mode 100644 index 00000000000..c29df4d6411 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp @@ -0,0 +1,114 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Shattered_Halls +SD%Complete: 50 +SDComment: currently missing info about door. instance not complete +SDCategory: Hellfire Citadel, Shattered Halls +EndScriptData */ + +#include "ScriptedPch.h" +#include "shattered_halls.h" + +#define MAX_ENCOUNTER 2 + +#define DOOR_NETHEKURSE 1 + +struct instance_shattered_halls : public ScriptedInstance +{ + instance_shattered_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint64 nethekurseGUID; + uint64 nethekurseDoorGUID; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + nethekurseGUID = 0; + nethekurseDoorGUID = 0; + } + + void OnGameObjectCreate(GameObject* pGo, bool /*add*/) + { + switch(pGo->GetEntry()) + { + case DOOR_NETHEKURSE: nethekurseDoorGUID = pGo->GetGUID(); break; + } + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 16807: nethekurseGUID = pCreature->GetGUID(); break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_NETHEKURSE: + m_auiEncounter[0] = data; + break; + case TYPE_OMROGG: + m_auiEncounter[1] = data; + break; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_NETHEKURSE: + return m_auiEncounter[0]; + case TYPE_OMROGG: + return m_auiEncounter[1]; + } + return 0; + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case DATA_NETHEKURSE: + return nethekurseGUID; + case DATA_NETHEKURSE_DOOR: + return nethekurseDoorGUID; + } + return 0; + } +}; + +InstanceData* GetInstanceData_instance_shattered_halls(Map* pMap) +{ + return new instance_shattered_halls(pMap); +} + +void AddSC_instance_shattered_halls() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_shattered_halls"; + newscript->GetInstanceData = &GetInstanceData_instance_shattered_halls; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h new file mode 100644 index 00000000000..cbfa23ec4e0 --- /dev/null +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h @@ -0,0 +1,14 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_SHATTERED_H +#define DEF_SHATTERED_H + +#define TYPE_NETHEKURSE 1 +#define DATA_NETHEKURSE 2 +#define DATA_NETHEKURSE_DOOR 3 + +#define TYPE_OMROGG 4 +#endif + diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h deleted file mode 100644 index b845c66823f..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/blood_furnace.h +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_BLOOD_FURNACE_H -#define DEF_BLOOD_FURNACE_H - -#define DATA_THE_MAKER 1 -#define DATA_BROGGOK 2 -#define DATA_KELIDAN_THE_MAKER 3 -#define TYPE_THE_MAKER_EVENT 4 -#define TYPE_BROGGOK_EVENT 5 -#define TYPE_KELIDAN_THE_BREAKER_EVENT 6 -#define DATA_DOOR1 7 -#define DATA_DOOR2 8 -#define DATA_DOOR3 9 -#define DATA_DOOR4 10 -#define DATA_DOOR5 11 -#define DATA_DOOR6 12 -#define DATA_PRISON_CELL1 13 -#define DATA_PRISON_CELL2 14 -#define DATA_PRISON_CELL3 15 -#define DATA_PRISON_CELL4 16 -#define DATA_PRISON_CELL5 17 -#define DATA_PRISON_CELL6 18 -#define DATA_PRISON_CELL7 19 -#define DATA_PRISON_CELL8 20 -#endif - diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp deleted file mode 100644 index d5fb9bdba49..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_broggok.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Broggok -SD%Complete: 70 -SDComment: pre-event not made -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eEnums -{ - SAY_AGGRO = -1542008, - - SPELL_SLIME_SPRAY = 30913, - SPELL_POISON_CLOUD = 30916, - SPELL_POISON_BOLT = 30917, - - SPELL_POISON = 30914 -}; - -struct boss_broggokAI : public ScriptedAI -{ - boss_broggokAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AcidSpray_Timer; - uint32 PoisonSpawn_Timer; - uint32 PoisonBolt_Timer; - - void Reset() - { - AcidSpray_Timer = 10000; - PoisonSpawn_Timer = 5000; - PoisonBolt_Timer = 7000; - if (pInstance) - { - pInstance->SetData(TYPE_BROGGOK_EVENT, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); - } - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - if (pInstance) - { - pInstance->SetData(TYPE_BROGGOK_EVENT, IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), false); - } - } - - void JustSummoned(Creature *summoned) - { - summoned->setFaction(16); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->CastSpell(summoned,SPELL_POISON,false,0,0,me->GetGUID()); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AcidSpray_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SLIME_SPRAY); - AcidSpray_Timer = 4000+rand()%8000; - } else AcidSpray_Timer -=diff; - - if (PoisonBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POISON_BOLT); - PoisonBolt_Timer = 4000+rand()%8000; - } else PoisonBolt_Timer -=diff; - - if (PoisonSpawn_Timer <= diff) - { - DoCast(me, SPELL_POISON_CLOUD); - PoisonSpawn_Timer = 20000; - } else PoisonSpawn_Timer -=diff; - - DoMeleeAttackIfReady(); - } - - void JustDied(Unit* /*who*/) - { - if (pInstance) - { - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR4), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR5), true); - pInstance->SetData(TYPE_BROGGOK_EVENT, DONE); - } - } - -}; - -CreatureAI* GetAI_boss_broggok(Creature* pCreature) -{ - return new boss_broggokAI (pCreature); -} - -void AddSC_boss_broggok() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_broggok"; - newscript->GetAI = &GetAI_boss_broggok; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp deleted file mode 100644 index a44ad9cc3c8..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_kelidan_the_breaker.cpp +++ /dev/null @@ -1,356 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kelidan_The_Breaker -SD%Complete: 100 -SDComment: -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -/* ContentData -boss_kelidan_the_breaker -mob_shadowmoon_channeler -EndContentData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eKelidan -{ - SAY_WAKE = -1542000, - SAY_ADD_AGGRO_1 = -1542001, - SAY_ADD_AGGRO_2 = -1542002, - SAY_ADD_AGGRO_3 = -1542003, - SAY_KILL_1 = -1542004, - SAY_KILL_2 = -1542005, - SAY_NOVA = -1542006, - SAY_DIE = -1542007, - - SPELL_CORRUPTION = 30938, - SPELL_EVOCATION = 30935, - - SPELL_FIRE_NOVA = 33132, - H_SPELL_FIRE_NOVA = 37371, - - SPELL_SHADOW_BOLT_VOLLEY = 28599, - H_SPELL_SHADOW_BOLT_VOLLEY = 40070, - - SPELL_BURNING_NOVA = 30940, - SPELL_VORTEX = 37370, - - ENTRY_KELIDAN = 17377, - ENTRY_CHANNELER = 17653 -}; - -const float ShadowmoonChannelers[5][4]= -{ - {302,-87,-24.4,0.157}, - {321,-63.5,-24.6,4.887}, - {346,-74.5,-24.6,3.595}, - {344,-103.5,-24.5,2.356}, - {316,-109,-24.6,1.257} -}; - -struct boss_kelidan_the_breakerAI : public ScriptedAI -{ - boss_kelidan_the_breakerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - for (uint8 i=0; i<5; ++i) - Channelers[i] = 0; - } - - ScriptedInstance* pInstance; - - uint32 ShadowVolley_Timer; - uint32 BurningNova_Timer; - uint32 Firenova_Timer; - uint32 Corruption_Timer; - uint32 check_Timer; - bool Firenova; - bool addYell; - uint64 Channelers[5]; - - void Reset() - { - ShadowVolley_Timer = 1000; - BurningNova_Timer = 15000; - Corruption_Timer = 5000; - check_Timer = 0; - Firenova = false; - addYell = false; - SummonChannelers(); - if (pInstance) - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - DoScriptText(SAY_WAKE, me); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - DoStartMovement(who); - if (pInstance) - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, IN_PROGRESS); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void ChannelerEngaged(Unit* who) - { - if (who && !addYell) - { - addYell = true; - DoScriptText(RAND(SAY_ADD_AGGRO_1,SAY_ADD_AGGRO_2,SAY_ADD_AGGRO_3), me); - } - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (who && channeler && !channeler->isInCombat()) - channeler->AI()->AttackStart(who); - } - } - - void ChannelerDied(Unit* killer) - { - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (channeler && channeler->isAlive()) - return; - } - - if (killer) - me->AI()->AttackStart(killer); - } - - uint64 GetChanneled(Creature *channeler1) - { - SummonChannelers(); - if (!channeler1) return NULL; - uint8 i; - for (i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (channeler && channeler->GetGUID() == channeler1->GetGUID()) - break; - } - return Channelers[(i+2)%5]; - } - - void SummonChannelers() - { - for (uint8 i=0; i<5; ++i) - { - Creature *channeler = Unit::GetCreature(*me, Channelers[i]); - if (!channeler || channeler->isDead()) - channeler = me->SummonCreature(ENTRY_CHANNELER,ShadowmoonChannelers[i][0],ShadowmoonChannelers[i][1],ShadowmoonChannelers[i][2],ShadowmoonChannelers[i][3],TEMPSUMMON_CORPSE_TIMED_DESPAWN,300000); - if (channeler) - Channelers[i] = channeler->GetGUID(); - else - Channelers[i] = 0; - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_KELIDAN_THE_BREAKER_EVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR1), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR6), true); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (check_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - DoCast(me, SPELL_EVOCATION); - check_Timer = 5000; - } else check_Timer -= diff; - return; - } - - if (Firenova) - { - if (Firenova_Timer <= diff) - { - DoCast(me, SPELL_FIRE_NOVA, true); - Firenova = false; - ShadowVolley_Timer = 2000; - } else Firenova_Timer -=diff; - - return; - } - - if (ShadowVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); - ShadowVolley_Timer = 5000+rand()%8000; - } else ShadowVolley_Timer -=diff; - - if (Corruption_Timer <= diff) - { - DoCast(me, SPELL_CORRUPTION); - Corruption_Timer = 30000+rand()%20000; - } else Corruption_Timer -=diff; - - if (BurningNova_Timer <= diff) - { - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - - DoScriptText(SAY_NOVA, me); - - if (SpellEntry *nova = GET_SPELL(SPELL_BURNING_NOVA)) - { - if (Aura * aura = Aura::TryCreate(nova, me, me)) - aura->ApplyForTargets(); - } - - if (IsHeroic()) - DoTeleportAll(me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation()); - - BurningNova_Timer = 20000+rand()%8000; - Firenova_Timer= 5000; - Firenova = true; - } else BurningNova_Timer -=diff; - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_boss_kelidan_the_breaker(Creature* pCreature) -{ - return new boss_kelidan_the_breakerAI (pCreature); -} - -/*###### -## mob_shadowmoon_channeler -######*/ - -enum eShadowmoon -{ - SPELL_SHADOW_BOLT = 12739, - H_SPELL_SHADOW_BOLT = 15472, - - SPELL_MARK_OF_SHADOW = 30937, - SPELL_CHANNELING = 39123 -}; - -struct mob_shadowmoon_channelerAI : public ScriptedAI -{ - mob_shadowmoon_channelerAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 ShadowBolt_Timer; - uint32 MarkOfShadow_Timer; - uint32 check_Timer; - - void Reset() - { - ShadowBolt_Timer = 1000+rand()%1000; - MarkOfShadow_Timer = 5000+rand()%2000; - check_Timer = 0; - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - } - - void EnterCombat(Unit* who) - { - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerEngaged(who); - if (me->IsNonMeleeSpellCasted(false)) - me->InterruptNonMeleeSpells(true); - DoStartMovement(who); - } - - void JustDied(Unit* Killer) - { - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->ChannelerDied(Killer); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (check_Timer <= diff) - { - if (!me->IsNonMeleeSpellCasted(false)) - if (Creature *Kelidan = me->FindNearestCreature(ENTRY_KELIDAN, 100)) - { - uint64 channeler = CAST_AI(boss_kelidan_the_breakerAI, Kelidan->AI())->GetChanneled(me); - if (Unit *channeled = Unit::GetUnit(*me, channeler)) - DoCast(channeled, SPELL_CHANNELING); - } - check_Timer = 5000; - } else check_Timer -= diff; - return; - } - - if (MarkOfShadow_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_MARK_OF_SHADOW); - MarkOfShadow_Timer = 15000+rand()%5000; - } else MarkOfShadow_Timer -=diff; - - if (ShadowBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_BOLT); - ShadowBolt_Timer = 5000+rand()%1000; - } else ShadowBolt_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_shadowmoon_channeler(Creature* pCreature) -{ - return new mob_shadowmoon_channelerAI (pCreature); -} - -void AddSC_boss_kelidan_the_breaker() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_kelidan_the_breaker"; - newscript->GetAI = &GetAI_boss_kelidan_the_breaker; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_shadowmoon_channeler"; - newscript->GetAI = &GetAI_mob_shadowmoon_channeler; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp deleted file mode 100644 index 45219b6509b..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/boss_the_maker.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_The_Maker -SD%Complete: 80 -SDComment: Mind control no support -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -enum eEnums -{ - SAY_AGGRO_1 = -1542009, - SAY_AGGRO_2 = -1542010, - SAY_AGGRO_3 = -1542011, - SAY_KILL_1 = -1542012, - SAY_KILL_2 = -1542013, - SAY_DIE = -1542014, - - SPELL_ACID_SPRAY = 38153, // heroic 38973 ??? 38153 - SPELL_EXPLODING_BREAKER = 30925, - SPELL_KNOCKDOWN = 20276, - SPELL_DOMINATION = 25772 // ??? -}; - -struct boss_the_makerAI : public ScriptedAI -{ - boss_the_makerAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 AcidSpray_Timer; - uint32 ExplodingBreaker_Timer; - uint32 Domination_Timer; - uint32 Knockdown_Timer; - - void Reset() - { - AcidSpray_Timer = 15000; - ExplodingBreaker_Timer = 6000; - Domination_Timer = 120000; - Knockdown_Timer = 10000; - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, NOT_STARTED); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, IN_PROGRESS); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), false); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_THE_MAKER_EVENT, DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR2), true); - pInstance->HandleGameObject(pInstance->GetData64(DATA_DOOR3), true); - - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AcidSpray_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ACID_SPRAY); - AcidSpray_Timer = 15000+rand()%8000; - } else AcidSpray_Timer -=diff; - - if (ExplodingBreaker_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_EXPLODING_BREAKER); - ExplodingBreaker_Timer = 4000+rand()%8000; - } else ExplodingBreaker_Timer -=diff; - - /* // Disabled until Core Support for mind control - if (domination_timer_timer <= diff) - { - Unit *pTarget; - pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - - DoCast(pTarget, SPELL_DOMINATION); - - domination_timer = 120000; - } else domination_timer -=diff; - */ - - if (Knockdown_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKDOWN); - Knockdown_Timer = 4000+rand()%8000; - } else Knockdown_Timer -=diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_the_makerAI(Creature* pCreature) -{ - return new boss_the_makerAI (pCreature); -} - -void AddSC_boss_the_maker() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_the_maker"; - newscript->GetAI = &GetAI_boss_the_makerAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp b/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp deleted file mode 100644 index 3a2eb8ba5ee..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/blood_furnace/instance_blood_furnace.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Blood_Furnace -SD%Complete: 85 -SDComment: -SDCategory: Hellfire Citadel, Blood Furnace -EndScriptData */ - -#include "ScriptedPch.h" -#include "blood_furnace.h" - -#define ENTRY_SEWER1 181823 -#define ENTRY_SEWER2 181766 -#define MAX_ENCOUNTER 3 - -struct instance_blood_furnace : public ScriptedInstance -{ - instance_blood_furnace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 The_MakerGUID; - uint64 BroggokGUID; - uint64 Kelidan_The_BreakerGUID; - - uint64 Door1GUID; - uint64 Door2GUID; - uint64 Door3GUID; - uint64 Door4GUID; - uint64 Door5GUID; - uint64 Door6GUID; - - uint64 PrisonCell1GUID; - uint64 PrisonCell2GUID; - uint64 PrisonCell3GUID; - uint64 PrisonCell4GUID; - uint64 PrisonCell5GUID; - uint64 PrisonCell6GUID; - uint64 PrisonCell7GUID; - uint64 PrisonCell8GUID; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string str_data; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - The_MakerGUID = 0; - BroggokGUID = 0; - Kelidan_The_BreakerGUID = 0; - - Door1GUID = 0; - Door2GUID = 0; - Door3GUID = 0; - Door4GUID = 0; - Door5GUID = 0; - Door6GUID = 0; - - PrisonCell1GUID = 0; - PrisonCell2GUID = 0; - PrisonCell3GUID = 0; - PrisonCell4GUID = 0; - PrisonCell5GUID = 0; - PrisonCell6GUID = 0; - PrisonCell7GUID = 0; - PrisonCell8GUID = 0; - } - - void OnCreatureCreate(Creature* pCreature, bool add) - { - if (!add) - return; - - switch(pCreature->GetEntry()) - { - case 17381: The_MakerGUID = pCreature->GetGUID(); break; - case 17380: BroggokGUID = pCreature->GetGUID(); break; - case 17377: Kelidan_The_BreakerGUID = pCreature->GetGUID(); break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool add) - { - if (!add) - return; - - if (pGo->GetEntry() == 181766) //Final exit door - Door1GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181811) //The Maker Front door - Door2GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181812) //The Maker Rear door - Door3GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181822) //Broggok Front door - Door4GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181819) //Broggok Rear door - Door5GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181823) //Kelidan exit door - Door6GUID = pGo->GetGUID(); - - if (pGo->GetEntry() == 181813) //The Maker prison cell front right - PrisonCell1GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181814) //The Maker prison cell back right - PrisonCell2GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181816) //The Maker prison cell front left - PrisonCell3GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181815) //The Maker prison cell back left - PrisonCell4GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181821) //Broggok prison cell front right - PrisonCell5GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181818) //Broggok prison cell back right - PrisonCell6GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181820) //Broggok prison cell front left - PrisonCell7GUID = pGo->GetGUID(); - if (pGo->GetEntry() == 181817) //Broggok prison cell back left - PrisonCell8GUID = pGo->GetGUID(); - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_THE_MAKER: return The_MakerGUID; - case DATA_BROGGOK: return BroggokGUID; - case DATA_KELIDAN_THE_MAKER: return Kelidan_The_BreakerGUID; - case DATA_DOOR1: return Door1GUID; - case DATA_DOOR2: return Door2GUID; - case DATA_DOOR3: return Door3GUID; - case DATA_DOOR4: return Door4GUID; - case DATA_DOOR5: return Door5GUID; - case DATA_DOOR6: return Door6GUID; - case DATA_PRISON_CELL1: return PrisonCell1GUID; - case DATA_PRISON_CELL2: return PrisonCell2GUID; - case DATA_PRISON_CELL3: return PrisonCell3GUID; - case DATA_PRISON_CELL4: return PrisonCell4GUID; - case DATA_PRISON_CELL5: return PrisonCell5GUID; - case DATA_PRISON_CELL6: return PrisonCell6GUID; - case DATA_PRISON_CELL7: return PrisonCell7GUID; - case DATA_PRISON_CELL8: return PrisonCell8GUID; - } - - return 0; - } - - void SetData(uint32 /*type*/, uint32 data) - { - switch(data) - { - case TYPE_THE_MAKER_EVENT: m_auiEncounter[0] = data; break; - case TYPE_BROGGOK_EVENT: m_auiEncounter[1] = data; break; - case TYPE_KELIDAN_THE_BREAKER_EVENT: m_auiEncounter[2] = data; break; - } - - if (data == DONE) - { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2]; - - str_data = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } - } - - uint32 GetData(uint32 data) - { - switch(data) - { - case TYPE_THE_MAKER_EVENT: return m_auiEncounter[0]; - case TYPE_BROGGOK_EVENT: return m_auiEncounter[1]; - case TYPE_KELIDAN_THE_BREAKER_EVENT: return m_auiEncounter[2]; - } - - return 0; - } - - const char* Save() - { - return str_data.c_str(); - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - - OUT_LOAD_INST_DATA(in); - - std::istringstream loadStream(in); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; - - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS || m_auiEncounter[i] == FAIL) - m_auiEncounter[i] = NOT_STARTED; - - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_blood_furnace(Map* pMap) -{ - return new instance_blood_furnace(pMap); -} - -void AddSC_instance_blood_furnace() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_blood_furnace"; - newscript->GetInstanceData = &GetInstanceData_instance_blood_furnace; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp deleted file mode 100644 index d6c0b2fd401..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_omor_the_unscarred.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Omar_The_Unscarred -SD%Complete: 90 -SDComment: Temporary solution for orbital/shadow whip-ability. Needs more core support before making it more proper. -SDCategory: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1543009 -#define SAY_AGGRO_2 -1543010 -#define SAY_AGGRO_3 -1543011 -#define SAY_SUMMON -1543012 -#define SAY_CURSE -1543013 -#define SAY_KILL_1 -1543014 -#define SAY_DIE -1543015 -#define SAY_WIPE -1543016 - -#define SPELL_ORBITAL_STRIKE 30637 -#define SPELL_SHADOW_WHIP 30638 -#define SPELL_TREACHEROUS_AURA 30695 -#define H_SPELL_BANE_OF_TREACHERY 37566 -#define SPELL_DEMONIC_SHIELD 31901 -#define SPELL_SHADOW_BOLT 30686 -#define H_SPELL_SHADOW_BOLT 39297 -#define SPELL_SUMMON_FIENDISH_HOUND 30707 - -struct boss_omor_the_unscarredAI : public ScriptedAI -{ - boss_omor_the_unscarredAI(Creature *c) : ScriptedAI(c) - { - SetCombatMovement(false); - } - - uint32 OrbitalStrike_Timer; - uint32 ShadowWhip_Timer; - uint32 Aura_Timer; - uint32 DemonicShield_Timer; - uint32 Shadowbolt_Timer; - uint32 Summon_Timer; - uint32 SummonedCount; - uint64 PlayerGUID; - bool CanPullBack; - - void Reset() - { - DoScriptText(SAY_WIPE, me); - - OrbitalStrike_Timer = 25000; - ShadowWhip_Timer = 2000; - Aura_Timer = 10000; - DemonicShield_Timer = 1000; - Shadowbolt_Timer = 2000; - Summon_Timer = 10000; - SummonedCount = 0; - PlayerGUID = 0; - CanPullBack = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(SAY_KILL_1, me); - } - - void JustSummoned(Creature* summoned) - { - DoScriptText(SAY_SUMMON, me); - - if (Unit* random = SelectUnit(SELECT_TARGET_RANDOM,0)) - summoned->AI()->AttackStart(random); - - ++SummonedCount; - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //only two may be wrong, perhaps increase timer and spawn periodically instead. - if (SummonedCount < 2) - { - if (Summon_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_SUMMON_FIENDISH_HOUND); - Summon_Timer = 15000+rand()%15000; - } else Summon_Timer -= diff; - } - - if (CanPullBack) - { - if (ShadowWhip_Timer <= diff) - { - if (Player* temp = Unit::GetPlayer(PlayerGUID)) - { - //if unit dosen't have this flag, then no pulling back (script will attempt cast, even if orbital strike was resisted) - if (temp->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)) - { - me->InterruptNonMeleeSpells(false); - DoCast(temp, SPELL_SHADOW_WHIP); - } - } - PlayerGUID = 0; - ShadowWhip_Timer = 2000; - CanPullBack = false; - } else ShadowWhip_Timer -= diff; - } - else if (OrbitalStrike_Timer <= diff) - { - Unit* temp = NULL; - if (me->IsWithinMeleeRange(me->getVictim())) - temp = me->getVictim(); - else temp = SelectUnit(SELECT_TARGET_RANDOM,0); - - if (temp && temp->GetTypeId() == TYPEID_PLAYER) - { - DoCast(temp, SPELL_ORBITAL_STRIKE); - OrbitalStrike_Timer = 14000+rand()%2000; - PlayerGUID = temp->GetGUID(); - - if (PlayerGUID) - CanPullBack = true; - } - } else OrbitalStrike_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) - { - if (DemonicShield_Timer <= diff) - { - DoCast(me, SPELL_DEMONIC_SHIELD); - DemonicShield_Timer = 15000; - } else DemonicShield_Timer -= diff; - } - - if (Aura_Timer <= diff) - { - DoScriptText(SAY_CURSE, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoCast(pTarget, SPELL_TREACHEROUS_AURA); - Aura_Timer = 8000+rand()%8000; - } - } else Aura_Timer -= diff; - - if (Shadowbolt_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - if (pTarget) - pTarget = me->getVictim(); - - DoCast(pTarget, SPELL_SHADOW_BOLT); - Shadowbolt_Timer = 4000+rand()%2500; - } - } else Shadowbolt_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_omor_the_unscarredAI(Creature* pCreature) -{ - return new boss_omor_the_unscarredAI (pCreature); -} - -void AddSC_boss_omor_the_unscarred() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_omor_the_unscarred"; - newscript->GetAI = &GetAI_boss_omor_the_unscarredAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp deleted file mode 100644 index 181911f77a4..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_vazruden_the_herald.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -Name: Boss_Vazruden_the_Herald -%Complete: 90 -Comment: -Category: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SPELL_FIREBALL DUNGEON_MODE(34653, 36920) -#define SPELL_CONE_OF_FIRE DUNGEON_MODE(30926, 36921) -#define SPELL_SUMMON_LIQUID_FIRE DUNGEON_MODE(23971, 30928) -#define SPELL_BELLOWING_ROAR 39427 -#define SPELL_REVENGE DUNGEON_MODE(19130, 40392) -#define SPELL_KIDNEY_SHOT 30621 -#define SPELL_FIRE_NOVA_VISUAL 19823 - -#define ENTRY_HELLFIRE_SENTRY 17517 -#define ENTRY_VAZRUDEN_HERALD 17307 -#define ENTRY_VAZRUDEN 17537 -#define ENTRY_NAZAN 17536 -#define ENTRY_LIQUID_FIRE 22515 -#define ENTRY_REINFORCED_FEL_IRON_CHEST DUNGEON_MODE(185168, 185169) - -#define SAY_INTRO -1543017 -#define SAY_WIPE -1543018 -#define SAY_AGGRO_1 -1543019 -#define SAY_AGGRO_2 -1543020 -#define SAY_AGGRO_3 -1543021 -#define SAY_KILL_1 -1543022 -#define SAY_KILL_2 -1543023 -#define SAY_DIE -1543024 -#define EMOTE -1543025 - -#define PATH_ENTRY 2081 - -const float VazrudenMiddle[3] = {-1406.5, 1746.5, 81.2}; -const float VazrudenRing[2][3] = -{ - {-1430, 1705, 112}, - {-1377, 1760, 112} -}; - -struct boss_nazanAI : public ScriptedAI -{ - boss_nazanAI(Creature *c) : ScriptedAI(c) - { - VazrudenGUID = 0; - flight = true; - } - - uint32 Fireball_Timer; - uint32 ConeOfFire_Timer; - uint32 BellowingRoar_Timer; - uint32 Fly_Timer; - uint32 Turn_Timer; - uint32 UnsummonCheck; - bool flight; - uint64 VazrudenGUID; - SpellEntry *liquid_fire; - - void Reset() - { - Fireball_Timer = 4000; - Fly_Timer = 45000; - Turn_Timer = 0; - UnsummonCheck = 5000; - } - - void EnterCombat(Unit* /*who*/) {} - - void JustSummoned(Creature *summoned) - { - if (summoned && summoned->GetEntry() == ENTRY_LIQUID_FIRE) - { - summoned->SetLevel(me->getLevel()); - summoned->setFaction(me->getFaction()); - summoned->CastSpell(summoned,SPELL_SUMMON_LIQUID_FIRE,true); - summoned->CastSpell(summoned,SPELL_FIRE_NOVA_VISUAL,true); - } - } - - void SpellHitTarget(Unit *pTarget, const SpellEntry* entry) - { - if (pTarget && entry->Id == uint32(SPELL_FIREBALL)) - me->SummonCreature(ENTRY_LIQUID_FIRE,pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(),pTarget->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,30000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (UnsummonCheck < diff && me->isAlive()) - me->DisappearAndDie(); - else - UnsummonCheck -= diff; - return; - } - - if (Fireball_Timer <= diff) - { - if (Unit *victim = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(victim, SPELL_FIREBALL, true); - Fireball_Timer = urand(4000,7000); - } else Fireball_Timer -= diff; - - if (flight) // phase 1 - the flight - { - Creature *Vazruden = Unit::GetCreature(*me,VazrudenGUID); - if (Fly_Timer < diff || !(Vazruden && Vazruden->isAlive() && (Vazruden->GetHealth()*5 > Vazruden->GetMaxHealth()))) - { - flight = false; - BellowingRoar_Timer = 6000; - ConeOfFire_Timer = 12000; - me->RemoveUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - me->AddUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - me->GetMotionMaster()->Clear(); - if (Unit *victim = SelectUnit(SELECT_TARGET_NEAREST,0)) - me->AI()->AttackStart(victim); - DoStartMovement(me->getVictim()); - DoScriptText(EMOTE, me); - return; - } else Fly_Timer -= diff; - - if (Turn_Timer <= diff) - { - uint32 waypoint = (Fly_Timer/10000)%2; - if (me->IsWithinDist3d(VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2], 5)) - me->GetMotionMaster()->MovePoint(0,VazrudenRing[waypoint][0],VazrudenRing[waypoint][1],VazrudenRing[waypoint][2]); - Turn_Timer = 10000; - } else Turn_Timer -= diff; - } - else // phase 2 - land fight - { - if (ConeOfFire_Timer <= diff) - { - DoCast(me, SPELL_CONE_OF_FIRE); - ConeOfFire_Timer = 12000; - Fireball_Timer = 4000; - } else ConeOfFire_Timer -= diff; - - if (IsHeroic()) - if (BellowingRoar_Timer <= diff) - { - DoCast(me, SPELL_BELLOWING_ROAR); - BellowingRoar_Timer = 45000; - } else BellowingRoar_Timer -= diff; - - DoMeleeAttackIfReady(); - } - } -}; - -struct boss_vazrudenAI : public ScriptedAI -{ - boss_vazrudenAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Revenge_Timer; - bool WipeSaid; - uint32 UnsummonCheck; - - void Reset() - { - Revenge_Timer = 4000; - UnsummonCheck = 2000; - WipeSaid = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void KilledUnit(Unit* who) - { - if (who && who->GetEntry() != ENTRY_VAZRUDEN) - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* who) - { - if (who && who != me) - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - { - if (UnsummonCheck < diff && me->isAlive()) - { - if (!WipeSaid) - { - DoScriptText(SAY_WIPE, me); - WipeSaid = true; - } - me->DisappearAndDie(); - } else UnsummonCheck -= diff; - return; - } - - if (Revenge_Timer <= diff) - { - if (Unit *victim = me->getVictim()) - DoCast(victim, SPELL_REVENGE); - Revenge_Timer = 5000; - } else Revenge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_vazruden_the_heraldAI : public ScriptedAI -{ - boss_vazruden_the_heraldAI(Creature *c) : ScriptedAI(c) - { - summoned = false; - sentryDown = false; - NazanGUID = 0; - VazrudenGUID = 0; - } - - uint32 phase; - uint32 waypoint; - uint32 check; - bool sentryDown; - uint64 NazanGUID; - uint64 VazrudenGUID; - bool summoned; - - void Reset() - { - phase = 0; - waypoint = 0; - check = 0; - UnsummonAdds(); - me->GetMotionMaster()->MovePath(PATH_ENTRY, true); - } - - void UnsummonAdds() - { - if (summoned) - { - Creature *Nazan = Unit::GetCreature(*me, NazanGUID); - if (!Nazan) - Nazan = me->FindNearestCreature(ENTRY_NAZAN, 5000); - if (Nazan) - { - Nazan->DisappearAndDie(); - NazanGUID = 0; - } - - Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); - if (!Vazruden) - Vazruden = me->FindNearestCreature(ENTRY_VAZRUDEN, 5000); - if (Vazruden) - { - Vazruden->DisappearAndDie(); - VazrudenGUID = 0; - } - summoned = false; - me->clearUnitState(UNIT_STAT_ROOT); - me->SetVisibility(VISIBILITY_ON); - } - } - - void SummonAdds() - { - if (!summoned) - { - if (Creature* Vazruden = me->SummonCreature(ENTRY_VAZRUDEN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) - VazrudenGUID = Vazruden->GetGUID(); - if (Creature* Nazan = me->SummonCreature(ENTRY_NAZAN,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,TEMPSUMMON_CORPSE_TIMED_DESPAWN,6000000)) - NazanGUID = Nazan->GetGUID(); - summoned = true; - me->SetVisibility(VISIBILITY_OFF); - me->addUnitState(UNIT_STAT_ROOT); - } - } - - void EnterCombat(Unit * /*who*/) - { - if (phase == 0) - { - phase = 1; - check = 0; - DoScriptText(SAY_INTRO, me); - } - } - - void JustSummoned(Creature *summoned) - { - if (!summoned) return; - Unit *victim = me->getVictim(); - if (summoned->GetEntry() == ENTRY_NAZAN) - { - CAST_AI(boss_nazanAI, summoned->AI())->VazrudenGUID = VazrudenGUID; - summoned->AddUnitMovementFlag(MOVEMENTFLAG_LEVITATING); - summoned->SetSpeed(MOVE_FLIGHT, 2.5); - if (victim) - AttackStartNoMove(victim); - } - else if (victim) - summoned->AI()->AttackStart(victim); - } - - void SentryDownBy(Unit* killer) - { - if (sentryDown) - { - AttackStartNoMove(killer); - sentryDown = false; - } - else - sentryDown = true; - } - - void UpdateAI(const uint32 diff) - { - switch(phase) - { - case 0: // circle around the platform - return; - break; - case 1: // go to the middle and begin the fight - if (check <= diff) - { - if (!me->IsWithinDist3d(VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],5)) - { - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2]); - check = 1000; - } - else - { - SummonAdds(); - phase = 2; - return; - } - } else check -= diff; - break; - default: // adds do the job now - if (check <= diff) - { - Creature *Nazan = Unit::GetCreature(*me, NazanGUID); - Creature *Vazruden = Unit::GetCreature(*me, VazrudenGUID); - if (Nazan && Nazan->isAlive() || Vazruden && Vazruden->isAlive()) - { - if (Nazan && Nazan->getVictim() || Vazruden && Vazruden->getVictim()) - return; - else - { - UnsummonAdds(); - EnterEvadeMode(); - return; - } - } - else - { - me->SummonGameObject(ENTRY_REINFORCED_FEL_IRON_CHEST,VazrudenMiddle[0],VazrudenMiddle[1],VazrudenMiddle[2],0,0,0,0,0,0); - me->SetLootRecipient(NULL); // don't think this is necessary.. - me->Kill(me); - } - check = 2000; - } else check -= diff; - break; - } - } -}; - -struct mob_hellfire_sentryAI : public ScriptedAI -{ - mob_hellfire_sentryAI(Creature *c) : ScriptedAI(c) {} - - uint32 KidneyShot_Timer; - - void Reset() - { - KidneyShot_Timer = urand(3000,7000); - } - - void EnterCombat(Unit* /*who*/) {} - - void JustDied(Unit* who) - { - if (Creature *herald = me->FindNearestCreature(ENTRY_VAZRUDEN_HERALD,150)) - CAST_AI(boss_vazruden_the_heraldAI, herald->AI())->SentryDownBy(who); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (KidneyShot_Timer <= diff) - { - if (Unit *victim = me->getVictim()) - DoCast(victim, SPELL_KIDNEY_SHOT); - KidneyShot_Timer = 20000; - } else KidneyShot_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_vazruden_the_herald(Creature* pCreature) -{ - return new boss_vazruden_the_heraldAI (pCreature); -} - -CreatureAI* GetAI_boss_vazruden(Creature* pCreature) -{ - return new boss_vazrudenAI (pCreature); -} - -CreatureAI* GetAI_boss_nazan(Creature* pCreature) -{ - return new boss_nazanAI (pCreature); -} - -CreatureAI* GetAI_mob_hellfire_sentry(Creature* pCreature) -{ - return new mob_hellfire_sentryAI (pCreature); -} - -void AddSC_boss_vazruden_the_herald() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_vazruden_the_herald"; - newscript->GetAI = &GetAI_boss_vazruden_the_herald; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_vazruden"; - newscript->GetAI = &GetAI_boss_vazruden; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_nazan"; - newscript->GetAI = &GetAI_boss_nazan; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_hellfire_sentry"; - newscript->GetAI = &GetAI_mob_hellfire_sentry; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp deleted file mode 100644 index f0e813d3890..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp +++ /dev/null @@ -1,156 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Watchkeeper_Gargolmar -SD%Complete: 80 -SDComment: Missing adds to heal him. Surge should be used on pTarget furthest away, not random. -SDCategory: Hellfire Citadel, Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_TAUNT -1543000 -#define SAY_HEAL -1543001 -#define SAY_SURGE -1543002 -#define SAY_AGGRO_1 -1543003 -#define SAY_AGGRO_2 -1543004 -#define SAY_AGGRO_3 -1543005 -#define SAY_KILL_1 -1543006 -#define SAY_KILL_2 -1543007 -#define SAY_DIE -1543008 - -#define SPELL_MORTAL_WOUND 30641 -#define H_SPELL_MORTAL_WOUND 36814 -#define SPELL_SURGE 34645 -#define SPELL_RETALIATION 22857 - -struct boss_watchkeeper_gargolmarAI : public ScriptedAI -{ - boss_watchkeeper_gargolmarAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Surge_Timer; - uint32 MortalWound_Timer; - uint32 Retaliation_Timer; - - bool HasTaunted; - bool YelledForHeal; - - void Reset() - { - Surge_Timer = 5000; - MortalWound_Timer = 4000; - Retaliation_Timer = 0; - - HasTaunted = false; - YelledForHeal = false; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void MoveInLineOfSight(Unit* who) - { - if (!me->getVictim() && who->isTargetableForAttack() && (me->IsHostileTo(who)) && who->isInAccessiblePlaceFor(me)) - { - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - //who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (!HasTaunted && me->IsWithinDistInMap(who, 60.0f)) - { - DoScriptText(SAY_TAUNT, me); - HasTaunted = true; - } - } - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_KILL_1,SAY_KILL_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (MortalWound_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MORTAL_WOUND); - MortalWound_Timer = 5000+rand()%8000; - } else MortalWound_Timer -= diff; - - if (Surge_Timer <= diff) - { - DoScriptText(SAY_SURGE, me); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SURGE); - - Surge_Timer = 5000+rand()%8000; - } else Surge_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() < 20) - { - if (Retaliation_Timer <= diff) - { - DoCast(me, SPELL_RETALIATION); - Retaliation_Timer = 30000; - } else Retaliation_Timer -= diff; - } - - if (!YelledForHeal) - { - if ((me->GetHealth()*100) / me->GetMaxHealth() < 40) - { - DoScriptText(SAY_HEAL, me); - YelledForHeal = true; - } - } - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_watchkeeper_gargolmarAI(Creature* pCreature) -{ - return new boss_watchkeeper_gargolmarAI (pCreature); -} - -void AddSC_boss_watchkeeper_gargolmar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_watchkeeper_gargolmar"; - newscript->GetAI = &GetAI_boss_watchkeeper_gargolmarAI; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h deleted file mode 100644 index 599aa237774..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/hellfire_ramparts.h +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_RAMPARTS_H -#define DEF_RAMPARTS_H - -#define MAX_ENCOUNTER 2 - -enum eTypes -{ - TYPE_VAZRUDEN = 1, - TYPE_NAZAN = 2 -}; - -#endif diff --git a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp b/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp deleted file mode 100644 index 29c58675e9c..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/hellfire_ramparts/instance_hellfire_ramparts.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Hellfire_Ramparts -SD%Complete: 50 -SDComment: -SDCategory: Hellfire Ramparts -EndScriptData */ - -#include "ScriptedPch.h" -#include "hellfire_ramparts.h" - -struct instance_ramparts : public ScriptedInstance -{ - instance_ramparts(Map* pMap) : ScriptedInstance(pMap) {Initialize();} - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint64 m_uiChestNGUID; - uint64 m_uiChestHGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiChestNGUID = 0; - m_uiChestHGUID = 0; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 185168: m_uiChestNGUID = pGo->GetGUID(); break; - case 185169: m_uiChestHGUID = pGo->GetGUID(); break; - } - } - - void SetData(uint32 uiType, uint32 uiData) - { - debug_log("TSCR: Instance Ramparts: SetData received for type %u with data %u",uiType,uiData); - - switch(uiType) - { - case TYPE_VAZRUDEN: - if (uiData == DONE && m_auiEncounter[1] == DONE) - DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); - m_auiEncounter[0] = uiData; - break; - case TYPE_NAZAN: - if (uiData == DONE && m_auiEncounter[0] == DONE) - DoRespawnGameObject(instance->IsHeroic() ? m_uiChestHGUID : m_uiChestNGUID, HOUR*IN_MILISECONDS); - m_auiEncounter[1] = uiData; - break; - } - } -}; - -InstanceData* GetInstanceData_instance_ramparts(Map* pMap) -{ - return new instance_ramparts(pMap); -} - -void AddSC_instance_ramparts() -{ - Script* pNewScript; - pNewScript = new Script; - pNewScript->Name = "instance_ramparts"; - pNewScript->GetInstanceData = &GetInstanceData_instance_ramparts; - pNewScript->RegisterSelf(); -} diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp deleted file mode 100644 index 5fb381f4065..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/boss_magtheridon.cpp +++ /dev/null @@ -1,570 +0,0 @@ -/* Copyright(C) 2006 - 2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -*(at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Magtheridon -SD%Complete: 60 -SDComment: In Development -SDCategory: Hellfire Citadel, Magtheridon's lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "magtheridons_lair.h" - -struct Yell -{ - int32 id; -}; - -static Yell RandomTaunt[]= -{ - {-1544000}, - {-1544001}, - {-1544002}, - {-1544003}, - {-1544004}, - {-1544005}, -}; - -#define SAY_FREED -1544006 -#define SAY_AGGRO -1544007 -#define SAY_BANISH -1544008 -#define SAY_CHAMBER_DESTROY -1544009 -#define SAY_PLAYER_KILLED -1544010 -#define SAY_DEATH -1544011 - -#define EMOTE_BERSERK -1544012 -#define EMOTE_BLASTNOVA -1544013 -#define EMOTE_BEGIN -1544014 - -#define MOB_MAGTHERIDON 17257 -#define MOB_ROOM 17516 -#define MOB_CHANNELLER 17256 -#define MOB_ABYSSAL 17454 - -#define SPELL_BLASTNOVA 30616 -#define SPELL_CLEAVE 30619 -#define SPELL_QUAKE_TRIGGER 30657 // must be cast with 30561 as the proc spell -#define SPELL_QUAKE_KNOCKBACK 30571 -#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 -#define SPELL_BLAZE_TRAP 30542 -#define SPELL_DEBRIS_KNOCKDOWN 36449 -#define SPELL_DEBRIS_VISUAL 30632 -#define SPELL_DEBRIS_DAMAGE 30631 // core bug, does not support target 8 -#define SPELL_CAMERA_SHAKE 36455 -#define SPELL_BERSERK 27680 - -#define SPELL_SHADOW_CAGE 30168 -#define SPELL_SHADOW_GRASP 30410 -#define SPELL_SHADOW_GRASP_VISUAL 30166 -#define SPELL_MIND_EXHAUSTION 44032 //Casted by the cubes when channeling ends - -#define SPELL_SHADOW_CAGE_C 30205 -#define SPELL_SHADOW_GRASP_C 30207 - -#define SPELL_SHADOW_BOLT_VOLLEY 30510 -#define SPELL_DARK_MENDING 30528 -#define SPELL_FEAR 30530 //39176 -#define SPELL_BURNING_ABYSSAL 30511 -#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 - -#define SPELL_FIRE_BLAST 37110 - -// count of clickers needed to interrupt blast nova -#define CLICKERS_COUNT 5 - -typedef std::map CubeMap; - -struct mob_abyssalAI : public ScriptedAI -{ - mob_abyssalAI(Creature *c) : ScriptedAI(c) - { - trigger = 0; - Despawn_Timer = 60000; - } - - uint32 FireBlast_Timer; - uint32 Despawn_Timer; - uint32 trigger; - - void Reset() - { - FireBlast_Timer = 6000; - } - - void SpellHit(Unit*, const SpellEntry *spell) - { - if (trigger == 2 && spell->Id == SPELL_BLAZE_TARGET) - { - DoCast(me, SPELL_BLAZE_TRAP, true); - me->SetVisibility(VISIBILITY_OFF); - Despawn_Timer = 130000; - } - } - - void SetTrigger(uint32 _trigger) - { - trigger = _trigger; - me->SetDisplayId(11686); - if (trigger == 1) //debris - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - DoCast(me, SPELL_DEBRIS_VISUAL, true); - FireBlast_Timer = 5000; - Despawn_Timer = 10000; - } - } - - void EnterCombat(Unit* /*who*/) {DoZoneInCombat();} - void AttackStart(Unit *who) {if (!trigger) ScriptedAI::AttackStart(who);} - void MoveInLineOfSight(Unit *who) {if (!trigger) ScriptedAI::MoveInLineOfSight(who);} - - void UpdateAI(const uint32 diff) - { - if (trigger) - { - if (trigger == 1) - { - if (FireBlast_Timer <= diff) - { - DoCast(me, SPELL_DEBRIS_DAMAGE, true); - trigger = 3; - } else FireBlast_Timer -= diff; - } - return; - } - - if (Despawn_Timer <= diff) - { - me->ForcedDespawn(); - } else Despawn_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (FireBlast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FIRE_BLAST); - FireBlast_Timer = 5000+rand()%10000; - } else FireBlast_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -struct boss_magtheridonAI : public ScriptedAI -{ - boss_magtheridonAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - - // target 7, random target with certain entry spell, need core fix - SpellEntry *TempSpell; - TempSpell = GET_SPELL(SPELL_BLAZE_TARGET); - if (TempSpell && TempSpell->EffectImplicitTargetA[0] != 6) - { - TempSpell->EffectImplicitTargetA[0] = 6; - TempSpell->EffectImplicitTargetB[0] = 0; - } - TempSpell = GET_SPELL(SPELL_QUAKE_TRIGGER); - if (TempSpell && TempSpell->EffectTriggerSpell[0] != SPELL_QUAKE_KNOCKBACK) - { - TempSpell->EffectTriggerSpell[0] = SPELL_QUAKE_KNOCKBACK; - } - } - - CubeMap Cube; - - ScriptedInstance* pInstance; - - uint32 Berserk_Timer; - uint32 Quake_Timer; - uint32 Cleave_Timer; - uint32 BlastNova_Timer; - uint32 Blaze_Timer; - uint32 Debris_Timer; - uint32 RandChat_Timer; - - bool Phase3; - bool NeedCheckCube; - - void Reset() - { - Berserk_Timer = 1320000; - Quake_Timer = 40000; - Debris_Timer = 10000; - Blaze_Timer = 10000+rand()%20000; - BlastNova_Timer = 60000; - Cleave_Timer = 15000; - RandChat_Timer = 90000; - - Phase3 = false; - NeedCheckCube = false; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); - me->addUnitState(UNIT_STAT_STUNNED); - DoCast(me, SPELL_SHADOW_CAGE_C, true); - } - - void JustReachedHome() - { - if (pInstance) - { - pInstance->SetData(DATA_MAGTHERIDON_EVENT, NOT_STARTED); - pInstance->SetData(DATA_COLLAPSE, false); - } - } - - void SetClicker(uint64 cubeGUID, uint64 clickerGUID) - { - // to avoid multiclicks from 1 cube - if (uint64 guid = Cube[cubeGUID]) - DebuffClicker(Unit::GetUnit(*me, guid)); - Cube[cubeGUID] = clickerGUID; - NeedCheckCube = true; - } - - //function to interrupt channeling and debuff clicker with mind exh(used if second person clicks with same cube or after dispeling/ending shadow grasp DoT) - void DebuffClicker(Unit *clicker) - { - if (!clicker || !clicker->isAlive()) - return; - - clicker->RemoveAurasDueToSpell(SPELL_SHADOW_GRASP); // cannot interrupt triggered spells - clicker->InterruptNonMeleeSpells(false); - clicker->CastSpell(clicker, SPELL_MIND_EXHAUSTION, true); - } - - void NeedCheckCubeStatus() - { - uint32 ClickerNum = 0; - // now checking if every clicker has debuff from manticron(it is dispelable atm rev 6110 : S) - // if not - apply mind exhaustion and delete from clicker's list - for (CubeMap::iterator i = Cube.begin(); i != Cube.end(); ++i) - { - Unit *clicker = Unit::GetUnit(*me, (*i).second); - if (!clicker || !clicker->HasAura(SPELL_SHADOW_GRASP)) - { - DebuffClicker(clicker); - (*i).second = 0; - } else ++ClickerNum; - } - - // if 5 clickers from other cubes apply shadow cage - if (ClickerNum >= CLICKERS_COUNT && !me->HasAura(SPELL_SHADOW_CAGE)) - { - DoScriptText(SAY_BANISH, me); - DoCast(me, SPELL_SHADOW_CAGE, true); - } - else if (ClickerNum < CLICKERS_COUNT && me->HasAura(SPELL_SHADOW_CAGE)) - me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE); - - if (!ClickerNum) NeedCheckCube = false; - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(SAY_PLAYER_KILLED, me); - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - pInstance->SetData(DATA_MAGTHERIDON_EVENT, DONE); - - DoScriptText(SAY_DEATH, me); - } - - void MoveInLineOfSight(Unit* /*who*/) {} - - void AttackStart(Unit *who) - { - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - ScriptedAI::AttackStart(who); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_MAGTHERIDON_EVENT, IN_PROGRESS); - DoZoneInCombat(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveAurasDueToSpell(SPELL_SHADOW_CAGE_C); - - DoScriptText(SAY_FREED, me); - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) - { - if (RandChat_Timer <= diff) - { - DoScriptText(RandomTaunt[rand()%6].id, me); - RandChat_Timer = 90000; - } else RandChat_Timer -= diff; - } - - if (!UpdateVictim()) - return; - - if (NeedCheckCube) NeedCheckCubeStatus(); - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - DoScriptText(EMOTE_BERSERK, me); - Berserk_Timer = 60000; - } else Berserk_Timer -= diff; - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CLEAVE); - Cleave_Timer = 10000; - } else Cleave_Timer -= diff; - - if (BlastNova_Timer <= diff) - { - // to avoid earthquake interruption - if (!me->hasUnitState(UNIT_STAT_STUNNED)) - { - DoScriptText(EMOTE_BLASTNOVA, me); - DoCast(me, SPELL_BLASTNOVA); - BlastNova_Timer = 60000; - } - } else BlastNova_Timer -= diff; - - if (Quake_Timer <= diff) - { - // to avoid blastnova interruption - if (!me->IsNonMeleeSpellCasted(false)) - { - DoCast(me, SPELL_QUAKE_TRIGGER, true); - Quake_Timer = 50000; - } - } else Quake_Timer -= diff; - - if (Blaze_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - pTarget->GetPosition(x, y, z); - Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (summon) - { - CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(2); - DoCast(summon, SPELL_BLAZE_TARGET, true); - summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - } - } - Blaze_Timer = 20000 + rand()%20000; - } else Blaze_Timer -= diff; - - if (!Phase3 && me->GetHealth()*10 < me->GetMaxHealth()*3 - && !me->IsNonMeleeSpellCasted(false) // blast nova - && !me->hasUnitState(UNIT_STAT_STUNNED)) // shadow cage and earthquake - { - Phase3 = true; - DoScriptText(SAY_CHAMBER_DESTROY, me); - DoCast(me, SPELL_CAMERA_SHAKE, true); - DoCast(me, SPELL_DEBRIS_KNOCKDOWN, true); - - if (pInstance) - pInstance->SetData(DATA_COLLAPSE, true); - } - - if (Phase3) - { - if (Debris_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - float x, y, z; - pTarget->GetPosition(x, y, z); - Creature *summon = me->SummonCreature(MOB_ABYSSAL, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); - if (summon) CAST_AI(mob_abyssalAI, summon->AI())->SetTrigger(1); - } - Debris_Timer = 10000; - } else Debris_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_hellfire_channelerAI : public ScriptedAI -{ - mob_hellfire_channelerAI(Creature *c) : ScriptedAI(c) - { - pInstance =me->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 ShadowBoltVolley_Timer; - uint32 DarkMending_Timer; - uint32 Fear_Timer; - uint32 Infernal_Timer; - - uint32 Check_Timer; - - void Reset() - { - ShadowBoltVolley_Timer = 8000 + rand()%2000; - DarkMending_Timer = 10000; - Fear_Timer = 15000 + rand()%5000; - Infernal_Timer = 10000 + rand()%40000; - - Check_Timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, IN_PROGRESS); - - me->InterruptNonMeleeSpells(false); - DoZoneInCombat(); - } - - void JustReachedHome() - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, NOT_STARTED); - - DoCast(me, SPELL_SHADOW_GRASP_C, false); - } - - void JustSummoned(Creature *summon) - { - summon->AI()->AttackStart(me->getVictim()); - } - - void DamageTaken(Unit*, uint32 &damage) - { - if (damage >= me->GetHealth()) - DoCast(me, SPELL_SOUL_TRANSFER, true); - } - - void JustDied(Unit* /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_CHANNELER_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ShadowBoltVolley_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_BOLT_VOLLEY); - ShadowBoltVolley_Timer = 10000 + rand()%10000; - } else ShadowBoltVolley_Timer -= diff; - - if (DarkMending_Timer <= diff) - { - if ((me->GetHealth()*100 / me->GetMaxHealth()) < 50) - DoCast(me, SPELL_DARK_MENDING); - DarkMending_Timer = 10000 +(rand() % 10000); - } else DarkMending_Timer -= diff; - - if (Fear_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - DoCast(pTarget, SPELL_FEAR); - Fear_Timer = 25000 + rand()%15000; - } else Fear_Timer -= diff; - - if (Infernal_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_BURNING_ABYSSAL, true); - Infernal_Timer = 30000 + rand()%10000; - } else Infernal_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Manticron Cube -bool GOHello_go_Manticron_Cube(Player* pPlayer, GameObject* pGo) -{ - ScriptedInstance* pInstance = pGo->GetInstanceData(); - if (!pInstance) - return true; - if (pInstance->GetData(DATA_MAGTHERIDON_EVENT) != IN_PROGRESS) return true; - Creature *Magtheridon =Unit::GetCreature(*pGo, pInstance->GetData64(DATA_MAGTHERIDON)); - if (!Magtheridon || !Magtheridon->isAlive()) return true; - - // if exhausted or already channeling return - if (pPlayer->HasAura(SPELL_MIND_EXHAUSTION) || pPlayer->HasAura(SPELL_SHADOW_GRASP)) - return true; - - pPlayer->InterruptNonMeleeSpells(false); - pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP, true); - pPlayer->CastSpell(pPlayer, SPELL_SHADOW_GRASP_VISUAL, false); - CAST_AI(boss_magtheridonAI, Magtheridon->AI())->SetClicker(pGo->GetGUID(), pPlayer->GetGUID()); - return true; -} - -CreatureAI* GetAI_boss_magtheridon(Creature* pCreature) -{ - return new boss_magtheridonAI(pCreature); -} - -CreatureAI* GetAI_mob_hellfire_channeler(Creature* pCreature) -{ - return new mob_hellfire_channelerAI(pCreature); -} - -CreatureAI* GetAI_mob_abyssalAI(Creature* pCreature) -{ - return new mob_abyssalAI(pCreature); -} - -void AddSC_boss_magtheridon() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_magtheridon"; - newscript->GetAI = &GetAI_boss_magtheridon; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_hellfire_channeler"; - newscript->GetAI = &GetAI_mob_hellfire_channeler; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "go_manticron_cube"; - newscript->pGOHello = &GOHello_go_Manticron_Cube; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_abyssal"; - newscript->GetAI = &GetAI_mob_abyssalAI; - newscript->RegisterSelf(); - -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp deleted file mode 100644 index d5b459a1fa1..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/instance_magtheridons_lair.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Magtheridons_Lair -SD%Complete: 100 -SDComment: -SDCategory: Hellfire Citadel, Magtheridon's lair -EndScriptData */ - -#include "ScriptedPch.h" -#include "magtheridons_lair.h" - -#define SPELL_SOUL_TRANSFER 30531 // core bug, does not support target 7 -#define SPELL_BLAZE_TARGET 30541 // core bug, does not support target 7 - -#define CHAMBER_CENTER_X -15.14 -#define CHAMBER_CENTER_Y 1.8 -#define CHAMBER_CENTER_Z -0.4 - -#define MAX_ENCOUNTER 2 - -#define EMOTE_BONDS_WEAKEN "'s bonds begin to weaken!" - -struct instance_magtheridons_lair : public ScriptedInstance -{ - instance_magtheridons_lair(Map* pMap) : ScriptedInstance(pMap) - { - Initialize(); - } - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - uint64 MagtheridonGUID; - std::set ChannelerGUID; - uint64 DoorGUID; - std::set ColumnGUID; - - uint32 CageTimer; - uint32 RespawnTimer; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - MagtheridonGUID = 0; - ChannelerGUID.clear(); - DoorGUID = 0; - ColumnGUID.clear(); - - CageTimer = 0; - RespawnTimer = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 17257: - MagtheridonGUID = pCreature->GetGUID(); - break; - case 17256: - ChannelerGUID.insert(pCreature->GetGUID()); - break; - } - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case 181713: - pGo->SetUInt32Value(GAMEOBJECT_FLAGS, 0); - break; - case 183847: - DoorGUID = pGo->GetGUID(); - break; - case 184653: // hall - case 184634: // six columns - case 184635: - case 184636: - case 184637: - case 184638: - case 184639: - ColumnGUID.insert(pGo->GetGUID()); - break; - } - } - - uint64 GetData64(uint32 type) - { - switch(type) - { - case DATA_MAGTHERIDON: - return MagtheridonGUID; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_MAGTHERIDON_EVENT: - m_auiEncounter[0] = data; - if (data == NOT_STARTED) - RespawnTimer = 10000; - if (data != IN_PROGRESS) - HandleGameObject(DoorGUID, true); - break; - case DATA_CHANNELER_EVENT: - switch(data) - { - case NOT_STARTED: // Reset all channelers once one is reset. - if (m_auiEncounter[1] != NOT_STARTED) - { - m_auiEncounter[1] = NOT_STARTED; - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - if (Creature *Channeler = instance->GetCreature(*i)) - { - if (Channeler->isAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } - } - CageTimer = 0; - HandleGameObject(DoorGUID, true); - } - break; - case IN_PROGRESS: // Event start. - if (m_auiEncounter[1] != IN_PROGRESS) - { - m_auiEncounter[1] = IN_PROGRESS; - // Let all five channelers aggro. - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - Creature *Channeler = instance->GetCreature(*i); - if (Channeler && Channeler->isAlive()) - Channeler->AI()->AttackStart(Channeler->SelectNearestTarget(999)); - } - // Release Magtheridon after two minutes. - Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); - if (Magtheridon && Magtheridon->isAlive()) - { - Magtheridon->MonsterTextEmote(EMOTE_BONDS_WEAKEN, 0); - CageTimer = 120000; - } - HandleGameObject(DoorGUID, false); - } - break; - case DONE: // Add buff and check if all channelers are dead. - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - Creature *Channeler = instance->GetCreature(*i); - if (Channeler && Channeler->isAlive()) - { - //Channeler->CastSpell(Channeler, SPELL_SOUL_TRANSFER, true); - data = IN_PROGRESS; - break; - } - } - break; - } - m_auiEncounter[1] = data; - break; - case DATA_COLLAPSE: - // true - collapse / false - reset - for (std::set::const_iterator i = ColumnGUID.begin(); i != ColumnGUID.end(); ++i) - DoUseDoorOrButton(*i); - break; - default: - break; - } - } - - uint32 GetData(uint32 type) - { - if (type == DATA_MAGTHERIDON_EVENT) - return m_auiEncounter[0]; - return 0; - } - - void Update(uint32 diff) - { - if (CageTimer) - { - if (CageTimer <= diff) - { - Creature *Magtheridon = instance->GetCreature(MagtheridonGUID); - if (Magtheridon && Magtheridon->isAlive()) - { - Magtheridon->clearUnitState(UNIT_STAT_STUNNED); - Magtheridon->AI()->AttackStart(Magtheridon->SelectNearestTarget(999)); - } - CageTimer = 0; - } else CageTimer -= diff; - } - - if (RespawnTimer) - { - if (RespawnTimer <= diff) - { - for (std::set::const_iterator i = ChannelerGUID.begin(); i != ChannelerGUID.end(); ++i) - { - if (Creature *Channeler = instance->GetCreature(*i)) - { - if (Channeler->isAlive()) - Channeler->AI()->EnterEvadeMode(); - else - Channeler->Respawn(); - } - } - RespawnTimer = 0; - } else RespawnTimer -= diff; - } - } -}; - -InstanceData* GetInstanceData_instance_magtheridons_lair(Map* pMap) -{ - return new instance_magtheridons_lair(pMap); -} - -void AddSC_instance_magtheridons_lair() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_magtheridons_lair"; - newscript->GetInstanceData = &GetInstanceData_instance_magtheridons_lair; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h b/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h deleted file mode 100644 index 1b3e525fc54..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/magtheridons_lair/magtheridons_lair.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_MAGTHERIDONS_LAIR_H -#define DEF_MAGTHERIDONS_LAIR_H - -#define DATA_MAGTHERIDON_EVENT 1 -#define DATA_MAGTHERIDON 3 -#define DATA_CHANNELER_EVENT 2 -#define DATA_COLLAPSE 6 -#define DATA_CHANNELER 9 -#endif - diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp deleted file mode 100644 index e3ded52edc9..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_nethekurse.cpp +++ /dev/null @@ -1,396 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Grand_Warlock_Nethekurse -SD%Complete: 75 -SDComment: encounter not fully completed. missing part where boss kill minions. -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -boss_grand_warlock_nethekurse -mob_fel_orc_convert -mob_lesser_shadow_fissure -EndContentData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -struct Say -{ - int32 id; -}; - -static Say PeonAttacked[]= -{ - {-1540001}, - {-1540002}, - {-1540003}, - {-1540004}, -}; -static Say PeonDies[]= -{ - {-1540005}, - {-1540006}, - {-1540007}, - {-1540008}, -}; - -#define SAY_INTRO -1540000 -#define SAY_TAUNT_1 -1540009 -#define SAY_TAUNT_2 -1540010 -#define SAY_TAUNT_3 -1540011 -#define SAY_AGGRO_1 -1540012 -#define SAY_AGGRO_2 -1540013 -#define SAY_AGGRO_3 -1540014 -#define SAY_SLAY_1 -1540015 -#define SAY_SLAY_2 -1540016 -#define SAY_DIE -1540017 - -#define SPELL_DEATH_COIL 30500 -#define SPELL_DARK_SPIN 30502 // core bug spell attack caster :D -#define SPELL_SHADOW_FISSURE 30496 // Summon the ShadowFissure NPC - -#define SPELL_SHADOW_CLEAVE 30495 -#define H_SPELL_SHADOW_SLAM 35953 - -#define SPELL_HEMORRHAGE 30478 - -#define SPELL_CONSUMPTION 30497 -#define SPELL_TEMPORARY_VISUAL 39312 // this is wrong, a temporary solution. spell consumption already has the purple visual, but doesn't display as it should - -struct boss_grand_warlock_nethekurseAI : public ScriptedAI -{ - boss_grand_warlock_nethekurseAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - bool IntroOnce; - bool IsIntroEvent; - bool IsMainEvent; - bool SpinOnce; - //bool HasTaunted; - bool Phase; - - uint32 PeonEngagedCount; - uint32 PeonKilledCount; - - uint32 IntroEvent_Timer; - uint32 DeathCoil_Timer; - uint32 ShadowFissure_Timer; - uint32 Cleave_Timer; - - void Reset() - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - IsIntroEvent = false; - IntroOnce = false; - IsMainEvent = false; - //HasTaunted = false; - SpinOnce = false; - Phase = false; - - PeonEngagedCount = 0; - PeonKilledCount = 0; - - IntroEvent_Timer = 90000; //how long before getting bored and kills his minions? - DeathCoil_Timer = 20000; - ShadowFissure_Timer = 8000; - Cleave_Timer = 5000; - } - - void DoYellForPeonAggro() - { - if (PeonEngagedCount >= 4) - return; - - DoScriptText(PeonAttacked[PeonEngagedCount].id, me); - ++PeonEngagedCount; - } - - void DoYellForPeonDeath() - { - if (PeonKilledCount >= 4) - return; - - DoScriptText(PeonDies[PeonKilledCount].id, me); - ++PeonKilledCount; - - if (PeonKilledCount == 4) - { - IsIntroEvent = false; - IsMainEvent = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - } - - void DoTauntPeons() - { - DoScriptText(RAND(SAY_TAUNT_1,SAY_TAUNT_2,SAY_TAUNT_3), me); - - //TODO: kill the peons first - IsIntroEvent = false; - PeonEngagedCount = 4; - PeonKilledCount = 4; - IsMainEvent = true; - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - void AttackStart(Unit* who) - { - if (IsIntroEvent || !IsMainEvent) - return; - - if (me->Attack(who, true)) - { - if (Phase) - DoStartNoMovement(who); - else - DoStartMovement(who); - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!IntroOnce && me->IsWithinDistInMap(who, 50.0f)) - { - if (who->GetTypeId() != TYPEID_PLAYER) - return; - - DoScriptText(SAY_INTRO, me); - IntroOnce = true; - IsIntroEvent = true; - - if (pInstance) - pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); - } - - if (IsIntroEvent || !IsMainEvent) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO_1,SAY_AGGRO_2,SAY_AGGRO_3), me); - } - - void JustSummoned(Creature *summoned) - { - summoned->setFaction(16); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - //triggered spell of consumption does not properly show it's SpellVisual, wrong spellid? - summoned->CastSpell(summoned,SPELL_TEMPORARY_VISUAL,true); - summoned->CastSpell(summoned,SPELL_CONSUMPTION,false,0,0,me->GetGUID()); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DIE, me); - - if (!pInstance) - return; - - pInstance->SetData(TYPE_NETHEKURSE,DONE); - pInstance->HandleGameObject(pInstance->GetData64(DATA_NETHEKURSE_DOOR), true); - } - - void UpdateAI(const uint32 diff) - { - if (IsIntroEvent) - { - if (!pInstance) - return; - - if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) - { - if (IntroEvent_Timer <= diff) - DoTauntPeons(); - else - IntroEvent_Timer -= diff; - } - } - - if (!UpdateVictim()) - return; - - if (!IsMainEvent) - return; - - if (Phase) - { - if (!SpinOnce) - { - DoCast(me->getVictim(), SPELL_DARK_SPIN); - SpinOnce = true; - } - - if (Cleave_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SHADOW_CLEAVE); - Cleave_Timer = 6000+rand()%2500; - } else Cleave_Timer -= diff; - } - else - { - if (ShadowFissure_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_SHADOW_FISSURE); - ShadowFissure_Timer = urand(7500,15000); - } else ShadowFissure_Timer -= diff; - - if (DeathCoil_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - DoCast(pTarget, SPELL_DEATH_COIL); - DeathCoil_Timer = urand(15000,20000); - } else DeathCoil_Timer -= diff; - - if ((me->GetHealth()*100) / me->GetMaxHealth() <= 20) - Phase = true; - - DoMeleeAttackIfReady(); - } - } -}; - -struct mob_fel_orc_convertAI : public ScriptedAI -{ - mob_fel_orc_convertAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - uint32 Hemorrhage_Timer; - - void Reset() - { - me->SetNoCallAssistance(true); //we don't want any assistance (WE R HEROZ!) - Hemorrhage_Timer = 3000; - } - - void MoveInLineOfSight(Unit * /*who*/) - { - } - - void EnterCombat(Unit* /*who*/) - { - if (pInstance) - { - if (pInstance->GetData64(DATA_NETHEKURSE)) - { - Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE)); - if (pKurse && me->IsWithinDist(pKurse, 45.0f)) - { - CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonAggro(); - - if (pInstance->GetData(TYPE_NETHEKURSE) == IN_PROGRESS) - return; - else - pInstance->SetData(TYPE_NETHEKURSE,IN_PROGRESS); - } - } - } - } - - void JustDied(Unit* /*Killer*/) - { - if (pInstance) - { - if (pInstance->GetData(TYPE_NETHEKURSE) != IN_PROGRESS) - return; - if (pInstance->GetData64(DATA_NETHEKURSE)) - if (Creature *pKurse = Unit::GetCreature(*me,pInstance->GetData64(DATA_NETHEKURSE))) - CAST_AI(boss_grand_warlock_nethekurseAI, pKurse->AI())->DoYellForPeonDeath(); - } - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Hemorrhage_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_HEMORRHAGE); - Hemorrhage_Timer = 15000; - } else Hemorrhage_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//NOTE: this Creature are also summoned by other spells, for different creatures -struct mob_lesser_shadow_fissureAI : public ScriptedAI -{ - mob_lesser_shadow_fissureAI(Creature *c) : ScriptedAI(c) {} - - void Reset() { } - void MoveInLineOfSight(Unit * /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void EnterCombat(Unit* /*who*/) {} -}; - -CreatureAI* GetAI_boss_grand_warlock_nethekurse(Creature* pCreature) -{ - return new boss_grand_warlock_nethekurseAI (pCreature); -} - -CreatureAI* GetAI_mob_fel_orc_convert(Creature* pCreature) -{ - return new mob_fel_orc_convertAI (pCreature); -} - -CreatureAI* GetAI_mob_lesser_shadow_fissure(Creature* pCreature) -{ - return new mob_lesser_shadow_fissureAI (pCreature); -} - -void AddSC_boss_grand_warlock_nethekurse() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_grand_warlock_nethekurse"; - newscript->GetAI = &GetAI_boss_grand_warlock_nethekurse; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_fel_orc_convert"; - newscript->GetAI = &GetAI_mob_fel_orc_convert; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_lesser_shadow_fissure"; - newscript->GetAI = &GetAI_mob_lesser_shadow_fissure; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp deleted file mode 100644 index 6fa1c9efe33..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warbringer_omrogg.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warbringer_Omrogg -SD%Complete: 85 -SDComment: Heroic enabled. Spell timing may need additional tweaks -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -mob_omrogg_heads -boss_warbringer_omrogg -EndContentData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -enum eEnums -{ - YELL_DIE_L = -1540039, - YELL_DIE_R = -1540040, - EMOTE_ENRAGE = -1540041, - - SPELL_BLAST_WAVE = 30600, - SPELL_FEAR = 30584, - SPELL_THUNDERCLAP = 30633, - - SPELL_BURNING_MAUL = 30598, - H_SPELL_BURNING_MAUL = 36056, - - NPC_LEFT_HEAD = 19523, - NPC_RIGHT_HEAD = 19524 -}; - -struct Yell -{ - int32 id; - uint32 creature; -}; - -static Yell GoCombat[]= -{ - {-1540018, NPC_LEFT_HEAD}, - {-1540019, NPC_LEFT_HEAD}, - {-1540020, NPC_LEFT_HEAD}, -}; -static Yell GoCombatDelay[]= -{ - {-1540021, NPC_RIGHT_HEAD}, - {-1540022, NPC_RIGHT_HEAD}, - {-1540023, NPC_RIGHT_HEAD}, -}; - -static Yell Threat[]= -{ - {-1540024, NPC_LEFT_HEAD}, - {-1540025, NPC_RIGHT_HEAD}, - {-1540026, NPC_LEFT_HEAD}, - {-1540027, NPC_LEFT_HEAD}, -}; -static Yell ThreatDelay1[]= -{ - {-1540028, NPC_RIGHT_HEAD}, - {-1540029, NPC_LEFT_HEAD}, - {-1540030, NPC_RIGHT_HEAD}, - {-1540031, NPC_RIGHT_HEAD}, -}; -static Yell ThreatDelay2[]= -{ - {-1540032, NPC_LEFT_HEAD}, - {-1540033, NPC_RIGHT_HEAD}, - {-1540034, NPC_LEFT_HEAD}, - {-1540035, NPC_LEFT_HEAD}, -}; - -static Yell Killing[]= -{ - {-1540036, NPC_LEFT_HEAD}, - {-1540037, NPC_RIGHT_HEAD}, -}; -static Yell KillingDelay[]= -{ - {-1540038, NPC_RIGHT_HEAD}, - {-1000000, NPC_LEFT_HEAD}, -}; - -struct mob_omrogg_headsAI : public ScriptedAI -{ - mob_omrogg_headsAI(Creature *c) : ScriptedAI(c) {} - - bool DeathYell; - uint32 Death_Timer; - - void Reset() - { - Death_Timer = 4000; - DeathYell = false; - } - void EnterCombat(Unit* /*who*/) {} - - void DoDeathYell() - { - DeathYell = true; - } - - void UpdateAI(const uint32 diff) - { - if (!DeathYell) - return; - - if (Death_Timer <= diff) - { - DoScriptText(YELL_DIE_R, me); - Death_Timer = false; - me->setDeathState(JUST_DIED); - } else Death_Timer -= diff; - } -}; - -struct boss_warbringer_omroggAI : public ScriptedAI -{ - boss_warbringer_omroggAI(Creature *c) : ScriptedAI(c) - { - LeftHeadGUID = 0; - RightHeadGUID = 0; - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint64 LeftHeadGUID; - uint64 RightHeadGUID; - int iaggro; - int ithreat; - int ikilling; - - bool AggroYell; - bool ThreatYell; - bool ThreatYell2; - bool KillingYell; - - uint32 Delay_Timer; - uint32 BlastWave_Timer; - uint32 BlastCount; - uint32 Fear_Timer; - uint32 BurningMaul_Timer; - uint32 ThunderClap_Timer; - uint32 ResetThreat_Timer; - - void Reset() - { - if (Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) - { - pLeftHead->setDeathState(JUST_DIED); - LeftHeadGUID = 0; - } - - if (Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID)) - { - pRightHead->setDeathState(JUST_DIED); - RightHeadGUID = 0; - } - - AggroYell = false; - ThreatYell = false; - ThreatYell2 = false; - KillingYell = false; - - Delay_Timer = 4000; - BlastWave_Timer = 0; - BlastCount = 0; - Fear_Timer = 8000; - BurningMaul_Timer = 25000; - ThunderClap_Timer = 15000; - ResetThreat_Timer = 30000; - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, NOT_STARTED); //End boss can use this later. O'mrogg must be defeated(DONE) or he will come to aid. - } - - void DoYellForThreat() - { - Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit *pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - ithreat = rand()%4; - - Unit *source = (pLeftHead->GetEntry() == Threat[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(Threat[ithreat].id, source); - - Delay_Timer = 3500; - ThreatYell = true; - } - - void EnterCombat(Unit * /*who*/) - { - me->SummonCreature(NPC_LEFT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); - me->SummonCreature(NPC_RIGHT_HEAD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0); - - if (Unit *pLeftHead = Unit::GetUnit(*me,LeftHeadGUID)) - { - iaggro = rand()%3; - - DoScriptText(GoCombat[iaggro].id, pLeftHead); - - Delay_Timer = 3500; - AggroYell = true; - } - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, IN_PROGRESS); - } - - void JustSummoned(Creature *summoned) - { - if (summoned->GetEntry() == NPC_LEFT_HEAD) - LeftHeadGUID = summoned->GetGUID(); - - if (summoned->GetEntry() == NPC_RIGHT_HEAD) - RightHeadGUID = summoned->GetGUID(); - - //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - //summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - summoned->SetVisibility(VISIBILITY_OFF); - } - - void KilledUnit(Unit* /*victim*/) - { - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - ikilling = rand()%2; - - Unit *source = (pLeftHead->GetEntry() == Killing[ikilling].creature ? pLeftHead : pRightHead); - - switch(ikilling) - { - case 0: - DoScriptText(Killing[ikilling].id, source); - Delay_Timer = 3500; - KillingYell = true; - break; - case 1: - DoScriptText(Killing[ikilling].id, source); - KillingYell = false; - break; - } - } - - void JustDied(Unit* /*Killer*/) - { - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - DoScriptText(YELL_DIE_L, pLeftHead); - - CAST_AI(mob_omrogg_headsAI, CAST_CRE(pRightHead)->AI())->DoDeathYell(); - - if (pInstance) - pInstance->SetData(TYPE_OMROGG, DONE); - } - - void UpdateAI(const uint32 diff) - { - if (Delay_Timer <= diff) - { - Delay_Timer = 3500; - - Unit* pLeftHead = Unit::GetUnit(*me,LeftHeadGUID); - Unit* pRightHead = Unit::GetUnit(*me,RightHeadGUID); - - if (!pLeftHead || !pRightHead) - return; - - if (AggroYell) - { - DoScriptText(GoCombatDelay[iaggro].id, pRightHead); - AggroYell = false; - } - - if (ThreatYell2) - { - Unit *source = (pLeftHead->GetEntry() == ThreatDelay2[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(ThreatDelay2[ithreat].id, source); - ThreatYell2 = false; - } - - if (ThreatYell) - { - Unit *source = (pLeftHead->GetEntry() == ThreatDelay1[ithreat].creature ? pLeftHead : pRightHead); - - DoScriptText(ThreatDelay1[ithreat].id, source); - ThreatYell = false; - ThreatYell2 = true; - } - - if (KillingYell) - { - Unit *source = (pLeftHead->GetEntry() == KillingDelay[ikilling].creature ? pLeftHead : pRightHead); - - DoScriptText(KillingDelay[ikilling].id, source); - KillingYell = false; - } - } else Delay_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (BlastCount && BlastWave_Timer <= diff) - { - DoCast(me, SPELL_BLAST_WAVE); - BlastWave_Timer = 5000; - ++BlastCount; - - if (BlastCount == 3) - BlastCount = 0; - } else BlastWave_Timer -= diff; - - if (BurningMaul_Timer <= diff) - { - DoScriptText(EMOTE_ENRAGE, me); - DoCast(me, SPELL_BURNING_MAUL); - BurningMaul_Timer = 40000; - BlastWave_Timer = 16000; - BlastCount = 1; - } else BurningMaul_Timer -= diff; - - if (ResetThreat_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - { - DoYellForThreat(); - DoResetThreat(); - me->AddThreat(pTarget, 0.0f); - } - ResetThreat_Timer = 25000+rand()%15000; - } else ResetThreat_Timer -= diff; - - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 15000+rand()%20000; - } else Fear_Timer -= diff; - - if (ThunderClap_Timer <= diff) - { - DoCast(me, SPELL_THUNDERCLAP); - ThunderClap_Timer = 15000+rand()%15000; - } else ThunderClap_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_warbringer_omrogg(Creature* pCreature) -{ - return new boss_warbringer_omroggAI (pCreature); -} - -CreatureAI* GetAI_mob_omrogg_heads(Creature* pCreature) -{ - return new mob_omrogg_headsAI (pCreature); -} - -void AddSC_boss_warbringer_omrogg() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_warbringer_omrogg"; - newscript->GetAI = &GetAI_boss_warbringer_omrogg; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_omrogg_heads"; - newscript->GetAI = &GetAI_mob_omrogg_heads; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp deleted file mode 100644 index b108077518a..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/boss_warchief_kargath_bladefist.cpp +++ /dev/null @@ -1,288 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Warchief_Kargath_Bladefist -SD%Complete: 90 -SDComment: -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -/* ContentData -boss_warchief_kargath_bladefist -EndContentData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO1 -1540042 -#define SAY_AGGRO2 -1540043 -#define SAY_AGGRO3 -1540044 -#define SAY_SLAY1 -1540045 -#define SAY_SLAY2 -1540046 -#define SAY_DEATH -1540047 - -#define SPELL_BLADE_DANCE 30739 -#define H_SPELL_CHARGE 25821 - -#define TARGET_NUM 5 - -#define MOB_SHATTERED_ASSASSIN 17695 -#define MOB_HEARTHEN_GUARD 17621 -#define MOB_SHARPSHOOTER_GUARD 17622 -#define MOB_REAVER_GUARD 17623 - -float AssassEntrance[3] = {275.136,-84.29,2.3}; // y -8 -float AssassExit[3] = {184.233,-84.29,2.3}; // y -8 -float AddsEntrance[3] = {306.036,-84.29,1.93}; - -struct boss_warchief_kargath_bladefistAI : public ScriptedAI -{ - boss_warchief_kargath_bladefistAI(Creature *c) : ScriptedAI(c) - { - } - - std::vector adds; - std::vector assassins; - - uint32 Charge_timer; - uint32 Blade_Dance_Timer; - uint32 Summon_Assistant_Timer; - uint32 resetcheck_timer; - uint32 Wait_Timer; - - uint32 Assassins_Timer; - - uint32 summoned; - bool InBlade; - - uint32 target_num; - - void Reset() - { - removeAdds(); - - me->SetSpeed(MOVE_RUN,2); - me->RemoveUnitMovementFlag(MOVEMENTFLAG_WALK_MODE); - - summoned = 2; - InBlade = false; - Wait_Timer = 0; - - Charge_timer = 0; - Blade_Dance_Timer = 45000; - Summon_Assistant_Timer = 30000; - Assassins_Timer = 5000; - resetcheck_timer = 5000; - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(RAND(SAY_AGGRO1,SAY_AGGRO2,SAY_AGGRO3), me); - } - - void JustSummoned(Creature *summoned) - { - switch(summoned->GetEntry()) - { - case MOB_HEARTHEN_GUARD: - case MOB_SHARPSHOOTER_GUARD: - case MOB_REAVER_GUARD: - summoned->AI()->AttackStart(SelectUnit(SELECT_TARGET_RANDOM,0)); - adds.push_back(summoned->GetGUID()); - break; - case MOB_SHATTERED_ASSASSIN: - assassins.push_back(summoned->GetGUID()); - break; - } - } - - void KilledUnit(Unit* victim) - { - if (victim->GetTypeId() == TYPEID_PLAYER) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - removeAdds(); - } - - void MovementInform(uint32 type, uint32 id) - { - if (InBlade) - { - if (type != POINT_MOTION_TYPE) - return; - - if (id != 1) - return; - - if (target_num > 0) // to prevent loops - { - Wait_Timer = 1; - DoCast(me, SPELL_BLADE_DANCE, true); - target_num--; - } - } - } - - void removeAdds() - { - for (std::vector::const_iterator itr = adds.begin(); itr!= adds.end(); ++itr) - { - Unit* temp = Unit::GetUnit((*me),*itr); - if (temp && temp->isAlive()) - { - (*temp).GetMotionMaster()->Clear(true); - me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - CAST_CRE(temp)->RemoveCorpse(); - } - } - adds.clear(); - - for (std::vector::const_iterator itr = assassins.begin(); itr!= assassins.end(); ++itr) - { - Unit* temp = Unit::GetUnit((*me),*itr); - if (temp && temp->isAlive()) - { - (*temp).GetMotionMaster()->Clear(true); - me->DealDamage(temp,temp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - CAST_CRE(temp)->RemoveCorpse(); - } - } - assassins.clear(); - } - void SpawnAssassin() - { - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]+8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassEntrance[0],AssassEntrance[1]-8, AssassEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]+8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - me->SummonCreature(MOB_SHATTERED_ASSASSIN,AssassExit[0],AssassExit[1]-8, AssassExit[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Assassins_Timer) - if (Assassins_Timer <= diff) - { - SpawnAssassin(); - Assassins_Timer = 0; - } else Assassins_Timer -= diff; - - if (InBlade) - { - if (Wait_Timer) - if (Wait_Timer <= diff) - { - if (target_num <= 0) - { - // stop bladedance - InBlade = false; - me->SetSpeed(MOVE_RUN,2); - me->GetMotionMaster()->MoveChase(me->getVictim()); - Blade_Dance_Timer = 30000; - Wait_Timer = 0; - if (IsHeroic()) - Charge_timer = 5000; - } - else - { - //move in bladedance - float x,y,randx,randy; - randx = (rand()%40); - randy = (rand()%40); - x = 210+ randx ; - y = -60- randy ; - me->GetMotionMaster()->MovePoint(1,x,y,me->GetPositionZ()); - Wait_Timer = 0; - } - } else Wait_Timer -= diff; - } - else - { - if (Blade_Dance_Timer) - if (Blade_Dance_Timer <= diff) - { - target_num = TARGET_NUM; - Wait_Timer = 1; - InBlade = true; - Blade_Dance_Timer = 0; - me->SetSpeed(MOVE_RUN,4); - return; - } else Blade_Dance_Timer -= diff; - - if (Charge_timer) - if (Charge_timer <= diff) - { - DoCast(SelectUnit(SELECT_TARGET_RANDOM, 0), H_SPELL_CHARGE); - Charge_timer = 0; - } else Charge_timer -= diff; - - if (Summon_Assistant_Timer <= diff) - { - for (uint8 i = 0; i < summoned; ++i) - { - switch (urand(0,2)) - { - case 0: me->SummonCreature(MOB_HEARTHEN_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - case 1: me->SummonCreature(MOB_SHARPSHOOTER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - case 2: me->SummonCreature(MOB_REAVER_GUARD,AddsEntrance[0],AddsEntrance[1], AddsEntrance[2], 0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,30000); break; - } - } - if (urand(0,9) < 2) - ++summoned; - Summon_Assistant_Timer = urand(25000,35000); - } else Summon_Assistant_Timer -= diff; - - DoMeleeAttackIfReady(); - } - - if (resetcheck_timer <= diff) - { - uint32 tempx,tempy; - tempx = uint32(me->GetPositionX()); - tempy = uint32(me->GetPositionY()); - if (tempx > 255 || tempx < 205) - { - EnterEvadeMode(); - return; - } - resetcheck_timer = 5000; - } else resetcheck_timer -= diff; - } -}; - -CreatureAI* GetAI_boss_warchief_kargath_bladefist(Creature* pCreature) -{ - return new boss_warchief_kargath_bladefistAI (pCreature); -} - -void AddSC_boss_warchief_kargath_bladefist() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_warchief_kargath_bladefist"; - newscript->GetAI = &GetAI_boss_warchief_kargath_bladefist; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp deleted file mode 100644 index c29df4d6411..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/instance_shattered_halls.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Shattered_Halls -SD%Complete: 50 -SDComment: currently missing info about door. instance not complete -SDCategory: Hellfire Citadel, Shattered Halls -EndScriptData */ - -#include "ScriptedPch.h" -#include "shattered_halls.h" - -#define MAX_ENCOUNTER 2 - -#define DOOR_NETHEKURSE 1 - -struct instance_shattered_halls : public ScriptedInstance -{ - instance_shattered_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - uint64 nethekurseGUID; - uint64 nethekurseDoorGUID; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - nethekurseGUID = 0; - nethekurseDoorGUID = 0; - } - - void OnGameObjectCreate(GameObject* pGo, bool /*add*/) - { - switch(pGo->GetEntry()) - { - case DOOR_NETHEKURSE: nethekurseDoorGUID = pGo->GetGUID(); break; - } - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 16807: nethekurseGUID = pCreature->GetGUID(); break; - } - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case TYPE_NETHEKURSE: - m_auiEncounter[0] = data; - break; - case TYPE_OMROGG: - m_auiEncounter[1] = data; - break; - } - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case TYPE_NETHEKURSE: - return m_auiEncounter[0]; - case TYPE_OMROGG: - return m_auiEncounter[1]; - } - return 0; - } - - uint64 GetData64(uint32 data) - { - switch(data) - { - case DATA_NETHEKURSE: - return nethekurseGUID; - case DATA_NETHEKURSE_DOOR: - return nethekurseDoorGUID; - } - return 0; - } -}; - -InstanceData* GetInstanceData_instance_shattered_halls(Map* pMap) -{ - return new instance_shattered_halls(pMap); -} - -void AddSC_instance_shattered_halls() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_shattered_halls"; - newscript->GetInstanceData = &GetInstanceData_instance_shattered_halls; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h b/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h deleted file mode 100644 index cbfa23ec4e0..00000000000 --- a/src/server/scripts/Outland/HellfireCitadel/shattered_halls/shattered_halls.h +++ /dev/null @@ -1,14 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_SHATTERED_H -#define DEF_SHATTERED_H - -#define TYPE_NETHEKURSE 1 -#define DATA_NETHEKURSE 2 -#define DATA_NETHEKURSE_DOOR 3 - -#define TYPE_OMROGG 4 -#endif - diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp new file mode 100644 index 00000000000..af5f1bd95c1 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -0,0 +1,523 @@ +/* Copyright(C) 2006 - 2008 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +*(at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: boss_alar +SD%Complete: 95 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define SPELL_FLAME_BUFFET 34121 // Flame Buffet - every 1,5 secs in phase 1 if there is no victim in melee range and after Dive Bomb in phase 2 with same conditions +#define SPELL_FLAME_QUILLS 34229 // Randomly after changing position in phase after watching tonns of movies, set probability 20% +#define SPELL_REBIRTH 34342 // Rebirth - beginning of second phase(after loose all health in phase 1) +#define SPELL_REBIRTH_2 35369 // Rebirth(another, without healing to full HP) - after Dive Bomb in phase 2 +#define SPELL_MELT_ARMOR 35410 // Melt Armor - every 60 sec in phase 2 +#define SPELL_CHARGE 35412 // Charge - 30 sec cooldown +#define SPELL_DIVE_BOMB_VISUAL 35367 // Bosskillers says 30 sec cooldown, wowwiki says 30 sec colldown, DBM and BigWigs addons says ~47 sec +#define SPELL_DIVE_BOMB 35181 // after watching tonns of movies, set cooldown to 40+rand()%5. +#define SPELL_BERSERK 45078 // 10 minutes after phase 2 starts(id is wrong, but proper id is unknown) + +#define CREATURE_EMBER_OF_ALAR 19551 // Al'ar summons one Ember of Al'ar every position change in phase 1 and two after Dive Bomb. Also in phase 2 when Ember of Al'ar dies, boss loose 3% health. +#define SPELL_EMBER_BLAST 34133 // When Ember of Al'ar dies, it casts Ember Blast + +#define CREATURE_FLAME_PATCH_ALAR 20602 // Flame Patch - every 30 sec in phase 2 +#define SPELL_FLAME_PATCH 35380 // + +static float waypoint[6][3] = +{ + {340.15, 58.65, 17.71}, + {388.09, 31.54, 20.18}, + {388.18, -32.85, 20.18}, + {340.29, -60.19, 17.72}, + {332, 0.01, 39}, // better not use the same xy coord + {331, 0.01, -2.39} +}; + +enum WaitEventType +{ + WE_NONE = 0, + WE_DUMMY = 1, + WE_PLATFORM = 2, + WE_QUILL = 3, + WE_DIE = 4, + WE_REVIVE = 5, + WE_CHARGE = 6, + WE_METEOR = 7, + WE_DIVE = 8, + WE_LAND = 9, + WE_SUMMON = 10 +}; + +struct boss_alarAI : public ScriptedAI +{ + boss_alarAI(Creature *c) : ScriptedAI(c) + { + pInstance =c->GetInstanceData(); + DefaultMoveSpeedRate = c->GetSpeedRate(MOVE_RUN); + } + + ScriptedInstance *pInstance; + + WaitEventType WaitEvent; + uint32 WaitTimer; + + bool AfterMoving; + + uint32 Platforms_Move_Timer; + uint32 DiveBomb_Timer; + uint32 MeltArmor_Timer; + uint32 Charge_Timer; + uint32 FlamePatch_Timer; + uint32 Berserk_Timer; + + float DefaultMoveSpeedRate; + + bool Phase1; + bool ForceMove; + uint32 ForceTimer; + + int8 cur_wp; + + void Reset() + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, NOT_STARTED); + + Berserk_Timer = 1200000; + Platforms_Move_Timer = 0; + + Phase1 = true; + WaitEvent = WE_NONE; + WaitTimer = 0; + AfterMoving = false; + ForceMove = false; + ForceTimer = 5000; + + cur_wp = 4; + + me->SetDisplayId(me->GetNativeDisplayId()); + me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + //me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + //me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->setActive(false); + } + + void EnterCombat(Unit * /*who*/) + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, IN_PROGRESS); + + me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); // after enterevademode will be set walk movement + DoZoneInCombat(); + me->setActive(true); + } + + void JustDied(Unit * /*victim*/) + { + if (pInstance) + pInstance->SetData(DATA_ALAREVENT, DONE); + } + + void JustSummoned(Creature *summon) + { + if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR) + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + summon->AI()->AttackStart(pTarget); + } + + void MoveInLineOfSight(Unit * /*who*/) {} + + void AttackStart(Unit* who) + { + if (Phase1) + AttackStartNoMove(who); + else + ScriptedAI::AttackStart(who); + } + + void DamageTaken(Unit* /*pKiller*/, uint32 &damage) + { + if (damage >= me->GetHealth() && Phase1) + { + damage = 0; + if (!WaitEvent) + { + WaitEvent = WE_DIE; + WaitTimer = 0; + me->SetHealth(0); + me->InterruptNonMeleeSpells(true); + me->RemoveAllAuras(); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->AttackStop(); + me->SetUInt64Value(UNIT_FIELD_TARGET, 0); + me->SetSpeed(MOVE_RUN, 5.0f); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]); + } + } + } + + void SpellHit(Unit*, const SpellEntry *spell) + { + if (spell->Id == SPELL_DIVE_BOMB_VISUAL) + { + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + me->SetDisplayId(11686); + //me->SendUpdateObjectToAllExcept(NULL); + } + } + + void MovementInform(uint32 type, uint32 /*id*/) + { + if (type == POINT_MOTION_TYPE) + { + WaitTimer = 1; + AfterMoving = true; + ForceMove = false; + } + } + + void UpdateAI(const uint32 diff) + { + if (!me->isInCombat()) // sometimes isincombat but !incombat, faction bug? + return; + + if (Berserk_Timer <= diff) + { + DoCast(me, SPELL_BERSERK, true); + Berserk_Timer = 60000; + } else Berserk_Timer -= diff; + + if (ForceMove) + { + if (ForceTimer <= diff) + { + me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); + ForceTimer = 5000; + } else ForceTimer -= diff; + + } + if (WaitEvent) + { + if (WaitTimer) + { + if (WaitTimer <= diff) + { + if (AfterMoving) + { + me->GetMotionMaster()->MoveIdle(); + AfterMoving = false; + } + + switch(WaitEvent) + { + case WE_PLATFORM: + Platforms_Move_Timer = 30000+rand()%5000; + break; + case WE_QUILL: + DoCast(me, SPELL_FLAME_QUILLS, true); + Platforms_Move_Timer = 1; + WaitTimer = 10000; + WaitEvent = WE_DUMMY; + return; + case WE_DIE: + ForceMove = false; + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); + WaitTimer = 5000; + WaitEvent = WE_REVIVE; + return; + case WE_REVIVE: + me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); + me->SetHealth(me->GetMaxHealth()); + me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoZoneInCombat(); + DoCast(me, SPELL_REBIRTH, true); + MeltArmor_Timer = 60000; + Charge_Timer = 7000; + DiveBomb_Timer = 40000+rand()%5000; + FlamePatch_Timer = 30000; + Phase1 = false; + break; + case WE_METEOR: + me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); + DoCast(me, SPELL_DIVE_BOMB_VISUAL, false); + WaitEvent = WE_DIVE; + WaitTimer = 4000; + return; + case WE_DIVE: + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL); + DoCast(pTarget, SPELL_DIVE_BOMB, true); + float dist = 3.0f; + if (me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f)) + dist = 5.0f; + WaitTimer = 1000 + floor(dist / 80 * 1000.0f); + me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f); + me->StopMoving(); + WaitEvent = WE_LAND; + } + else + { + EnterEvadeMode(); + return; + } + case WE_LAND: + WaitEvent = WE_SUMMON; + WaitTimer = 2000; + return; + case WE_SUMMON: + for (uint8 i = 0; i < 2; ++i) + DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetDisplayId(me->GetNativeDisplayId()); + DoCast(me, SPELL_REBIRTH_2, true); + break; + case WE_DUMMY: + default: + break; + } + + WaitEvent = WE_NONE; + WaitTimer = 0; + } else WaitTimer -= diff; + } + return; + } + + if (Phase1) + { + if (me->getThreatManager().getThreatList().empty()) + { + EnterEvadeMode(); + return; + } + + if (Platforms_Move_Timer <= diff) + { + if (cur_wp == 4) + { + cur_wp = 0; + WaitEvent = WE_PLATFORM; + } + else + { + if (urand(0,4)) // next platform + { + DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (cur_wp == 3) + cur_wp = 0; + else + ++cur_wp; + WaitEvent = WE_PLATFORM; + } + else // flame quill + { + cur_wp = 4; + WaitEvent = WE_QUILL; + } + } + ForceMove = true; + ForceTimer = 5000; + me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); + WaitTimer = 0; + return; + } else Platforms_Move_Timer -= diff; + } + else + { + if (Charge_Timer <= diff) + { + Unit *pTarget= SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); + if (pTarget) + DoCast(pTarget, SPELL_CHARGE); + Charge_Timer = 30000; + } else Charge_Timer -= diff; + + if (MeltArmor_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MELT_ARMOR); + MeltArmor_Timer = 60000; + } else MeltArmor_Timer -= diff; + + if (DiveBomb_Timer <= diff) + { + me->AttackStop(); + me->GetMotionMaster()->MovePoint(6, waypoint[4][0], waypoint[4][1], waypoint[4][2]); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 50); + WaitEvent = WE_METEOR; + WaitTimer = 0; + DiveBomb_Timer = 40000+rand()%5000; + return; + } else DiveBomb_Timer -= diff; + + if (FlamePatch_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + Creature* Summoned = me->SummonCreature(CREATURE_FLAME_PATCH_ALAR, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000); + if (Summoned) + { + Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Summoned->SetFloatValue(OBJECT_FIELD_SCALE_X, Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); + Summoned->SetDisplayId(11686); + Summoned->setFaction(me->getFaction()); + Summoned->SetLevel(me->getLevel()); + Summoned->CastSpell(Summoned, SPELL_FLAME_PATCH, false); + } + } + FlamePatch_Timer = 30000; + } else FlamePatch_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + + void DoMeleeAttackIfReady() + { + if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) + { + if (me->IsWithinMeleeRange(me->getVictim())) + { + me->AttackerStateUpdate(me->getVictim()); + me->resetAttackTimer(); + } + else + { + Unit *pTarget = NULL; + pTarget = me->SelectNearestTargetInAttackDistance(5); + if (pTarget) + me->AI()->AttackStart(pTarget); + else + { + DoCast(me, SPELL_FLAME_BUFFET, true); + me->setAttackTimer(BASE_ATTACK, 1500); + } + } + } + } +}; + +CreatureAI* GetAI_boss_alar(Creature* pCreature) +{ + return new boss_alarAI(pCreature); +} + +struct mob_ember_of_alarAI : public ScriptedAI +{ + mob_ember_of_alarAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + c->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); + c->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); + } + + ScriptedInstance *pInstance; + bool toDie; + + void Reset() {toDie = false;} + void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} + void EnterEvadeMode() {me->setDeathState(JUST_DIED);} + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage >= me->GetHealth() && pKiller != me && !toDie) + { + damage = 0; + DoCast(me, SPELL_EMBER_BLAST, true); + me->SetDisplayId(11686); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (pInstance && pInstance->GetData(DATA_ALAREVENT) == 2) + { + if (Unit* Alar = Unit::GetUnit((*me), pInstance->GetData64(DATA_ALAR))) + { + int AlarHealth = Alar->GetHealth() - Alar->GetMaxHealth()*0.03; + if (AlarHealth > 0) + Alar->SetHealth(AlarHealth); + else + Alar->SetHealth(1); + } + } + toDie = true; + } + } + + void UpdateAI(const uint32 /*diff*/) + { + if (!UpdateVictim()) + return; + + if (toDie) + { + me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + //me->SetVisibility(VISIBILITY_OFF); + } + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_mob_ember_of_alar(Creature* pCreature) +{ + return new mob_ember_of_alarAI(pCreature); +} + +struct mob_flame_patch_alarAI : public ScriptedAI +{ + mob_flame_patch_alarAI(Creature *c) : ScriptedAI(c) {} + void Reset() {} + void EnterCombat(Unit * /*who*/) {} + void AttackStart(Unit* /*who*/) {} + void MoveInLineOfSight(Unit* /*who*/) {} + void UpdateAI(const uint32 /*diff*/) {} +}; + +CreatureAI* GetAI_mob_flame_patch_alar(Creature* pCreature) +{ + return new mob_flame_patch_alarAI(pCreature); +} + +void AddSC_boss_alar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_alar"; + newscript->GetAI = &GetAI_boss_alar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ember_of_alar"; + newscript->GetAI = &GetAI_mob_ember_of_alar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flame_patch_alar"; + newscript->GetAI = &GetAI_mob_flame_patch_alar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp new file mode 100644 index 00000000000..e9e217a5c62 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp @@ -0,0 +1,466 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Astromancer +SD%Complete: 80 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +enum eEnums +{ + SAY_AGGRO = -1550007, + SAY_SUMMON1 = -1550008, + SAY_SUMMON2 = -1550009, + SAY_KILL1 = -1550010, + SAY_KILL2 = -1550011, + SAY_KILL3 = -1550012, + SAY_DEATH = -1550013, + SAY_VOIDA = -1550014, + SAY_VOIDB = -1550015, + + SPELL_ARCANE_MISSILES = 33031, + SPELL_WRATH_OF_THE_ASTROMANCER = 42783, + SPELL_BLINDING_LIGHT = 33009, + SPELL_FEAR = 34322, + SPELL_VOID_BOLT = 39329, + + SPELL_SPOTLIGHT = 25824, + NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT = 18928, + + NPC_SOLARIUM_AGENT = 18925, + NPC_SOLARIUM_PRIEST = 18806, + + MODEL_HUMAN = 18239, + MODEL_VOIDWALKER = 18988, + + SPELL_SOLARIUM_GREAT_HEAL = 33387, + SPELL_SOLARIUM_HOLY_SMITE = 25054, + SPELL_SOLARIUM_ARCANE_TORRENT = 33390, + + WV_ARMOR = 31000 +}; + +const float CENTER_X = 432.909f; +const float CENTER_Y = -373.424f; +const float CENTER_Z = 17.9608f; +const float CENTER_O = 1.06421f; +const float SMALL_PORTAL_RADIUS = 12.6f; +const float LARGE_PORTAL_RADIUS = 26.0f; +const float PORTAL_Z = 17.005f; + + // x, y, z, o +static float SolarianPos[4] = {432.909, -373.424, 17.9608, 1.06421}; + +struct boss_high_astromancer_solarianAI : public ScriptedAI +{ + boss_high_astromancer_solarianAI(Creature *c) : ScriptedAI(c), Summons(me) + { + pInstance = c->GetInstanceData(); + + defaultarmor = c->GetArmor(); + defaultsize = c->GetFloatValue(OBJECT_FIELD_SCALE_X); + } + + ScriptedInstance *pInstance; + SummonList Summons; + + uint8 Phase; + + uint32 ArcaneMissiles_Timer; + uint32 m_uiWrathOfTheAstromancer_Timer; + uint32 BlindingLight_Timer; + uint32 Fear_Timer; + uint32 VoidBolt_Timer; + uint32 Phase1_Timer; + uint32 Phase2_Timer; + uint32 Phase3_Timer; + uint32 AppearDelay_Timer; + uint32 defaultarmor; + uint32 Wrath_Timer; + + float defaultsize; + float Portals[3][3]; + + bool AppearDelay; + bool BlindingLight; + + void Reset() + { + ArcaneMissiles_Timer = 2000; + m_uiWrathOfTheAstromancer_Timer = 15000; + BlindingLight_Timer = 41000; + Fear_Timer = 20000; + VoidBolt_Timer = 10000; + Phase1_Timer = 50000; + Phase2_Timer = 10000; + Phase3_Timer = 15000; + AppearDelay_Timer = 2000; + BlindingLight = false; + AppearDelay = false; + Wrath_Timer = 20000+rand()%5000;//twice in phase one + Phase = 1; + Wrath_Timer = 20000+rand()%5000;//twice in phase one + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); + + me->SetArmor(defaultarmor); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + me->SetDisplayId(MODEL_HUMAN); + + Summons.DespawnAll(); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_KILL1,SAY_KILL2,SAY_KILL3), me); + } + + void JustDied(Unit * /*victim*/) + { + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); + me->SetDisplayId(MODEL_HUMAN); + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); + } + + void SummonMinion(uint32 entry, float x, float y, float z) + { + Creature* Summoned = me->SummonCreature(entry, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + if (Summoned) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + Summoned->AI()->AttackStart(pTarget); + + Summons.Summon(Summoned); + } + } + + float Portal_X(float radius) + { + if (urand(0,1)) + radius = -radius; + + return radius * (float)(rand()%100)/100.0f + CENTER_X; + } + + float Portal_Y(float x, float radius) + { + float z = RAND(1, -1); + + return (z*sqrt(radius*radius - (x - CENTER_X)*(x - CENTER_X)) + CENTER_Y); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (AppearDelay) + { + me->StopMoving(); + me->AttackStop(); + if (AppearDelay_Timer <= diff) + { + AppearDelay = false; + if (Phase == 2) + { + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_OFF); + } + AppearDelay_Timer = 2000; + } else AppearDelay_Timer -= diff; + } + + if (Phase == 1) + { + if (BlindingLight_Timer <= diff) + { + BlindingLight = true; + BlindingLight_Timer = 45000; + } else BlindingLight_Timer -= diff; + + if (Wrath_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) + DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER, true); + Wrath_Timer = 20000+rand()%5000; + } else Wrath_Timer -= diff; + + if (ArcaneMissiles_Timer <= diff) + { + if (BlindingLight) + { + DoCast(me->getVictim(), SPELL_BLINDING_LIGHT); + BlindingLight = false; + }else{ + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (!me->HasInArc(2.5f, pTarget)) + pTarget = me->getVictim(); + + if (pTarget) + DoCast(pTarget, SPELL_ARCANE_MISSILES); + } + ArcaneMissiles_Timer = 3000; + } else ArcaneMissiles_Timer -= diff; + + if (m_uiWrathOfTheAstromancer_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + + //Target the tank ? + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) + if (pTarget->GetTypeId() == TYPEID_PLAYER) + { + DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER); + m_uiWrathOfTheAstromancer_Timer = 25000; + } + else + m_uiWrathOfTheAstromancer_Timer = 1000; + } else m_uiWrathOfTheAstromancer_Timer -= diff; + + //Phase1_Timer + if (Phase1_Timer <= diff) + { + Phase = 2; + Phase1_Timer = 50000; + //After these 50 seconds she portals to the middle of the room and disappears, leaving 3 light portals behind. + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, CENTER_X, CENTER_Y, CENTER_Z, CENTER_O); + for (uint8 i=0; i <= 2; ++i) + { + if (!i) + { + Portals[i][0] = Portal_X(SMALL_PORTAL_RADIUS); + Portals[i][1] = Portal_Y(Portals[i][0], SMALL_PORTAL_RADIUS); + Portals[i][2] = CENTER_Z; + } + else + { + Portals[i][0] = Portal_X(LARGE_PORTAL_RADIUS); + Portals[i][1] = Portal_Y(Portals[i][0], LARGE_PORTAL_RADIUS); + Portals[i][2] = PORTAL_Z; + } + } + if ((abs(Portals[2][0] - Portals[1][0]) < 7) && (abs(Portals[2][1] - Portals[1][1]) < 7)) + { + int i=1; + if (abs(CENTER_X + 26.0f - Portals[2][0]) < 7) + i = -1; + Portals[2][0] = Portals[2][0]+7*i; + Portals[2][1] = Portal_Y(Portals[2][0], LARGE_PORTAL_RADIUS); + } + for (int i=0; i <= 2; ++i) + { + if (Creature* Summoned = me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O, TEMPSUMMON_TIMED_DESPAWN, Phase2_Timer+Phase3_Timer+AppearDelay_Timer+1700)) + { + Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + Summoned->CastSpell(Summoned, SPELL_SPOTLIGHT, false); + } + } + AppearDelay = true; + } else Phase1_Timer-=diff; + } + else if (Phase == 2) + { + //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. + me->AttackStop(); + me->StopMoving(); + if (Phase2_Timer <= diff) + { + Phase = 3; + for (int i=0; i <= 2; ++i) + for (int j=1; j <= 4; j++) + SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); + + DoScriptText(SAY_SUMMON1, me); + Phase2_Timer = 10000; + } else Phase2_Timer -= diff; + } + else if (Phase == 3) + { + me->AttackStop(); + me->StopMoving(); + + //Check Phase3_Timer + if (Phase3_Timer <= diff) + { + Phase = 1; + + //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. + int i = rand()%3; + me->GetMotionMaster()->Clear(); + me->GetMap()->CreatureRelocation(me, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); + + for (int j=0; j <= 2; j++) + if (j != i) + SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + + DoScriptText(SAY_SUMMON2, me); + AppearDelay = true; + Phase3_Timer = 15000; + } else Phase3_Timer -= diff; + } + else if (Phase == 4) + { + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me, SPELL_FEAR); + Fear_Timer = 20000; + } else Fear_Timer -= diff; + + //VoidBolt_Timer + if (VoidBolt_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_VOID_BOLT); + VoidBolt_Timer = 10000; + } else VoidBolt_Timer -= diff; + } + + //When Solarian reaches 20% she will transform into a huge void walker. + if (Phase != 4 && ((me->GetHealth()*100 / me->GetMaxHealth())<20)) + { + Phase = 4; + + //To make sure she wont be invisible or not selecatble + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetVisibility(VISIBILITY_ON); + DoScriptText(SAY_VOIDA, me); + DoScriptText(SAY_VOIDB, me); + me->SetArmor(WV_ARMOR); + me->SetDisplayId(MODEL_VOIDWALKER); + me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize*2.5f); + } + + DoMeleeAttackIfReady(); + } +}; + +struct mob_solarium_priestAI : public ScriptedAI +{ + mob_solarium_priestAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 healTimer; + uint32 holysmiteTimer; + uint32 aoesilenceTimer; + + void Reset() + { + healTimer = 9000; + holysmiteTimer = 1; + aoesilenceTimer = 15000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (healTimer <= diff) + { + Unit *pTarget = NULL; + + switch (urand(0,1)) + { + case 0: + if (pInstance) + pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_ASTROMANCER)); + break; + case 1: + pTarget = me; + break; + } + + if (pTarget) + { + DoCast(pTarget, SPELL_SOLARIUM_GREAT_HEAL); + healTimer = 9000; + } + } else healTimer -= diff; + + if (holysmiteTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARIUM_HOLY_SMITE); + holysmiteTimer = 4000; + } else holysmiteTimer -= diff; + + if (aoesilenceTimer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARIUM_ARCANE_TORRENT); + aoesilenceTimer = 13000; + } else aoesilenceTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_solarium_priest(Creature* pCreature) +{ + return new mob_solarium_priestAI (pCreature); +} + +CreatureAI* GetAI_boss_high_astromancer_solarian(Creature* pCreature) +{ + return new boss_high_astromancer_solarianAI (pCreature); +} + +void AddSC_boss_high_astromancer_solarian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_high_astromancer_solarian"; + newscript->GetAI = &GetAI_boss_high_astromancer_solarian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_solarium_priest"; + newscript->GetAI = &GetAI_mob_solarium_priest; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp new file mode 100644 index 00000000000..05681fb7539 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -0,0 +1,1498 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Kaelthas +SD%Complete: 60 +SDComment: SQL, weapon scripts, mind control, need correct spells(interruptible/uninterruptible), phoenix spawn location & animation, phoenix behaviour & spawn during gravity lapse +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" +#include "WorldPacket.h" + +enum eEnums +{ + //kael'thas Speech + SAY_INTRO = -1550016, + SAY_INTRO_CAPERNIAN = -1550017, + SAY_INTRO_TELONICUS = -1550018, + SAY_INTRO_THALADRED = -1550019, + SAY_INTRO_SANGUINAR = -1550020, + SAY_PHASE2_WEAPON = -1550021, + SAY_PHASE3_ADVANCE = -1550022, + SAY_PHASE4_INTRO2 = -1550023, + SAY_PHASE5_NUTS = -1550024, + SAY_SLAY1 = -1550025, + SAY_SLAY2 = -1550026, + SAY_SLAY3 = -1550027, + SAY_MINDCONTROL1 = -1550028, + SAY_MINDCONTROL2 = -1550029, + SAY_GRAVITYLAPSE1 = -1550030, + SAY_GRAVITYLAPSE2 = -1550031, + SAY_SUMMON_PHOENIX1 = -1550032, + SAY_SUMMON_PHOENIX2 = -1550033, + SAY_DEATH = -1550034, + + //Thaladred the Darkener speech + SAY_THALADRED_AGGRO = -1550035, + SAY_THALADRED_DEATH = -1550036, + EMOTE_THALADRED_GAZE = -1550037, + + //Lord Sanguinar speech + SAY_SANGUINAR_AGGRO = -1550038, + SAY_SANGUINAR_DEATH = -1550039, + + //Grand Astromancer Capernian speech + SAY_CAPERNIAN_AGGRO = -1550040, + SAY_CAPERNIAN_DEATH = -1550041, + + //Master Engineer Telonicus speech + SAY_TELONICUS_AGGRO = -1550042, + SAY_TELONICUS_DEATH = -1550043, + + //Phase 2 spells + SPELL_SUMMON_WEAPONS = 36976, + SPELL_SUMMON_WEAPONA = 36958, + SPELL_SUMMON_WEAPONB = 36959, + SPELL_SUMMON_WEAPONC = 36960, + SPELL_SUMMON_WEAPOND = 36961, + SPELL_SUMMON_WEAPONE = 36962, + SPELL_SUMMON_WEAPONF = 36963, + SPELL_SUMMON_WEAPONG = 36964, + SPELL_RES_VISUAL = 24171, + + //Phase 4 spells + SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell + SPELL_PYROBLAST = 36819, + SPELL_FLAME_STRIKE = 36735, + SPELL_FLAME_STRIKE_VIS = 36730, + SPELL_FLAME_STRIKE_DMG = 36731, + SPELL_ARCANE_DISRUPTION = 36834, + SPELL_SHOCK_BARRIER = 36815, + SPELL_PHOENIX_ANIMATION = 36723, + SPELL_MIND_CONTROL = 32830, + + //Phase 5 spells + SPELL_EXPLODE = 36092, + SPELL_FULLPOWER = 36187, + SPELL_KNOCKBACK = 11027, + SPELL_GRAVITY_LAPSE = 34480, + SPELL_GRAVITY_LAPSE_AURA = 39432, + SPELL_NETHER_BEAM = 35873, + + //Thaladred the Darkener spells + SPELL_PSYCHIC_BLOW = 10689, + SPELL_SILENCE = 30225, + //Lord Sanguinar spells + SPELL_BELLOWING_ROAR = 40636, + //Grand Astromancer Capernian spells + + SPELL_CAPERNIAN_FIREBALL = 36971, + SPELL_CONFLAGRATION = 37018, + SPELL_ARCANE_EXPLOSION = 36970, + //Master Engineer Telonicus spells + SPELL_BOMB = 37036, + SPELL_REMOTE_TOY = 37027, + //Nether Vapor spell + SPELL_NETHER_VAPOR = 35859, + //Phoenix spell + SPELL_BURN = 36720, + SPELL_EMBER_BLAST = 34341, + SPELL_REBIRTH = 41587, + + //Creature IDs + NPC_PHOENIX = 21362, + NPC_PHOENIX_EGG = 21364, + + //Phoenix egg and phoenix model + MODEL_ID_PHOENIX = 19682, + MODEL_ID_PHOENIX_EGG = 20245, + + MAX_ADVISORS = 4 +}; + +uint32 m_auiSpellSummonWeapon[]= +{ + SPELL_SUMMON_WEAPONA, SPELL_SUMMON_WEAPONB, SPELL_SUMMON_WEAPONC, SPELL_SUMMON_WEAPOND, + SPELL_SUMMON_WEAPONE, SPELL_SUMMON_WEAPONF, SPELL_SUMMON_WEAPONG +}; + +const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target +const float KAEL_VISIBLE_RANGE = 50.0f; + +const float afGravityPos[3] = {795.0f, 0.0f, 70.0f}; + +#define TIME_PHASE_2_3 120000 +#define TIME_PHASE_3_4 180000 + +//Base AI for Advisors +struct advisorbase_ai : public ScriptedAI +{ + advisorbase_ai(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = pCreature->GetInstanceData(); + m_bDoubled_Health = false; + } + + ScriptedInstance* m_pInstance; + bool FakeDeath; + bool m_bDoubled_Health; + uint32 DelayRes_Timer; + uint64 DelayRes_Target; + + void Reset() + { + if (m_bDoubled_Health) + { + me->SetMaxHealth(me->GetMaxHealth() / 2); + m_bDoubled_Health = false; + } + + FakeDeath = false; + DelayRes_Timer = 0; + DelayRes_Target = 0; + + me->SetStandState(UNIT_STAND_STATE_STAND); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + //reset encounter + if (m_pInstance && (m_pInstance->GetData(DATA_KAELTHASEVENT) == 1 || m_pInstance->GetData(DATA_KAELTHASEVENT) == 3)) + if (Creature *Kaelthas = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_KAELTHAS))) + Kaelthas->AI()->EnterEvadeMode(); + } + + void MoveInLineOfSight(Unit *who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::MoveInLineOfSight(who); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void Revive(Unit* /*Target*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + // double health for phase 3 + me->SetMaxHealth(me->GetMaxHealth() * 2); + m_bDoubled_Health = true; + me->SetHealth(me->GetMaxHealth()); + me->SetStandState(UNIT_STAND_STATE_STAND); + + DoCast(me, SPELL_RES_VISUAL, false); + DelayRes_Timer = 2000; + } + + void DamageTaken(Unit* pKiller, uint32 &damage) + { + if (damage < me->GetHealth()) + return; + + //Prevent glitch if in fake death + if (FakeDeath && m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) + { + damage = 0; + return; + } + + //Don't really die in phase 1 & 3, only die after that + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) + { + //prevent death + damage = 0; + FakeDeath = true; + + me->InterruptNonMeleeSpells(false); + me->SetHealth(0); + me->StopMoving(); + me->ClearComboPointHolders(); + me->RemoveAllAurasOnDeath(); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->ClearAllReactives(); + me->SetUInt64Value(UNIT_FIELD_TARGET,0); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->SetStandState(UNIT_STAND_STATE_DEAD); + JustDied(pKiller); + } + } + + void UpdateAI(const uint32 diff) + { + if (DelayRes_Timer) + { + if (DelayRes_Timer <= diff) + { + DelayRes_Timer = 0; + FakeDeath = false; + + Unit* Target = Unit::GetUnit((*me), DelayRes_Target); + if (!Target) + Target = me->getVictim(); + + DoResetThreat(); + AttackStart(Target); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveChase(Target); + me->AddThreat(Target, 0.0f); + } else DelayRes_Timer -= diff; + } + } + +}; + +//Kael'thas AI +struct boss_kaelthasAI : public ScriptedAI +{ + boss_kaelthasAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me) + { + m_pInstance = pCreature->GetInstanceData(); + memset(&m_auiAdvisorGuid, 0, sizeof(m_auiAdvisorGuid)); + } + + ScriptedInstance* m_pInstance; + + uint32 Fireball_Timer; + uint32 ArcaneDisruption_Timer; + uint32 Phoenix_Timer; + uint32 ShockBarrier_Timer; + uint32 GravityLapse_Timer; + uint32 GravityLapse_Phase; + uint32 NetherBeam_Timer; + uint32 NetherVapor_Timer; + uint32 FlameStrike_Timer; + uint32 MindControl_Timer; + uint32 Phase; + uint32 PhaseSubphase; //generic + uint32 Phase_Timer; //generic timer + uint32 PyrosCasted; + + bool InGravityLapse; + bool IsCastingFireball; + bool ChainPyros; + + SummonList summons; + + uint64 m_auiAdvisorGuid[MAX_ADVISORS]; + + void Reset() + { + Fireball_Timer = 5000+rand()%10000; + ArcaneDisruption_Timer = 45000; + MindControl_Timer = 40000; + Phoenix_Timer = 50000; + ShockBarrier_Timer = 60000; + FlameStrike_Timer = 30000; + GravityLapse_Timer = 20000; + GravityLapse_Phase = 0; + NetherBeam_Timer = 8000; + NetherVapor_Timer = 10000; + PyrosCasted = 0; + Phase = 0; + InGravityLapse = false; + IsCastingFireball = false; + ChainPyros = false; + + if (me->isInCombat()) + PrepareAdvisors(); + + summons.DespawnAll(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 0); + } + + void PrepareAdvisors() + { + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + if (Creature *pCreature = Unit::GetCreature((*me), m_auiAdvisorGuid[i])) + { + pCreature->Respawn(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->setFaction(me->getFaction()); + pCreature->AI()->EnterEvadeMode(); + } + } + } + + void StartEvent() + { + if (!m_pInstance) + return; + + m_auiAdvisorGuid[0] = m_pInstance->GetData64(DATA_THALADREDTHEDARKENER); + m_auiAdvisorGuid[1] = m_pInstance->GetData64(DATA_LORDSANGUINAR); + m_auiAdvisorGuid[2] = m_pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN); + m_auiAdvisorGuid[3] = m_pInstance->GetData64(DATA_MASTERENGINEERTELONICUS); + + if (!m_auiAdvisorGuid[0] || !m_auiAdvisorGuid[1] || !m_auiAdvisorGuid[2] || !m_auiAdvisorGuid[3]) + { + error_log("TSCR: Kael'Thas One or more advisors missing, Skipping Phases 1-3"); + + DoScriptText(SAY_PHASE4_INTRO2, me); + + Phase = 4; + + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + AttackStart(pTarget); + + } + else + { + PrepareAdvisors(); + + DoScriptText(SAY_INTRO, me); + + m_pInstance->SetData(DATA_KAELTHASEVENT, 1); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + PhaseSubphase = 0; + Phase_Timer = 23000; + Phase = 1; + } + } + + void MoveInLineOfSight(Unit *who) + { + if (!me->hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() && + me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) + { + if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = me->GetAttackDistance(who); + if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) + { + if (!me->getVictim() && Phase >= 4) + { + who->RemoveAurasDueToSpell(SPELL_AURA_MOD_STEALTH); + AttackStart(who); + } + else if (me->GetMap()->IsDungeon()) + { + if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) + StartEvent(); + + who->SetInCombatWith(me); + me->AddThreat(who, 0.0f); + } + } + } + } + + void Aggro(Unit * /*who*/) + { + if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) + StartEvent(); + } + + void KilledUnit() + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustSummoned(Creature* pSummoned) + { + // if not phoenix, then it's one of the 7 weapons + if (pSummoned->GetEntry() != NPC_PHOENIX) + { + if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + + summons.Summon(pSummoned); + } + } + + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + + void JustDied(Unit* /*Killer*/) + { + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + DoScriptText(SAY_DEATH, me); + + summons.DespawnAll(); + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 0); + + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + if (Unit* pAdvisor = Unit::GetUnit((*me), m_auiAdvisorGuid[i])) + pAdvisor->Kill(pAdvisor); + } + } + + void UpdateAI(const uint32 diff) + { + //Phase 1 + switch (Phase) + { + case 1: + { + Unit *pTarget = NULL; + Creature* Advisor = NULL; + + //Subphase switch + switch(PhaseSubphase) + { + //Subphase 1 - Start + case 0: + if (Phase_Timer <= diff) + { + DoScriptText(SAY_INTRO_THALADRED, me); + + //start advisor within 7 seconds + Phase_Timer = 7000; + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 1 - Unlock advisor + case 1: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 2 - Start + case 2: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_SANGUINAR, me); + + //start advisor within 12.5 seconds + Phase_Timer = 12500; + ++PhaseSubphase; + } + break; + + //Subphase 2 - Unlock advisor + case 3: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 3 - Start + case 4: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_CAPERNIAN, me); + + //start advisor within 7 seconds + Phase_Timer = 7000; + ++PhaseSubphase; + } + break; + + //Subphase 3 - Unlock advisor + case 5: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //Subphase 4 - Start + case 6: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + DoScriptText(SAY_INTRO_TELONICUS, me); + + //start advisor within 8.4 seconds + Phase_Timer = 8400; + ++PhaseSubphase; + } + break; + + //Subphase 4 - Unlock advisor + case 7: + if (Phase_Timer <= diff) + { + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); + + if (Advisor) + { + Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Advisor->setFaction(me->getFaction()); + + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + if (pTarget) + Advisor->AI()->AttackStart(pTarget); + } + + Phase_Timer = 3000; + ++PhaseSubphase; + } else Phase_Timer -= diff; + break; + + //End of phase 1 + case 8: + Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); + + if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) + { + Phase = 2; + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 2); + + DoScriptText(SAY_PHASE2_WEAPON, me); + + PhaseSubphase = 0; + Phase_Timer = 3500; + DoCast(me, SPELL_SUMMON_WEAPONS); + } + break; + } + } + break; + + case 2: + { + if (PhaseSubphase == 0) + { + if (Phase_Timer <= diff) + { + PhaseSubphase = 1; + } else Phase_Timer -= diff; + } + + //Spawn weapons + if (PhaseSubphase == 1) + { + DoCast(me, SPELL_SUMMON_WEAPONS, false); + + uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32); + + for (uint32 i = 0; i < uiMaxWeapon; ++i) + DoCast(me, m_auiSpellSummonWeapon[i], true); + + PhaseSubphase = 2; + Phase_Timer = TIME_PHASE_2_3; + } + + if (PhaseSubphase == 2) + { + if (Phase_Timer <= diff) + { + DoScriptText(SAY_PHASE3_ADVANCE, me); + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 3); + Phase = 3; + PhaseSubphase = 0; + } else Phase_Timer -= diff; + } + } + break; + + case 3: + { + if (PhaseSubphase == 0) + { + //Respawn advisors + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + Creature *Advisor; + for (uint8 i = 0; i < MAX_ADVISORS; ++i) + { + Advisor = Unit::GetCreature((*me), m_auiAdvisorGuid[i]); + + if (!Advisor) + error_log("SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); + else + CAST_AI(advisorbase_ai, Advisor->AI())->Revive(pTarget); + } + + PhaseSubphase = 1; + Phase_Timer = TIME_PHASE_3_4; + } + + if (Phase_Timer <= diff) + { + DoScriptText(SAY_PHASE4_INTRO2, me); + Phase = 4; + + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + + // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. + DoResetThreat(); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + AttackStart(pTarget); + + Phase_Timer = 30000; + } else Phase_Timer -= diff; + } + break; + + case 4: + case 5: + case 6: + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Fireball_Timer + if (!InGravityLapse && !ChainPyros && Phase != 5) + { + if (Fireball_Timer <= diff) + { + if (!IsCastingFireball) + { + if (!me->IsNonMeleeSpellCasted(false)) + { + //interruptable + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); + int32 dmg = 20000+rand()%5000; + me->CastCustomSpell(me->getVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); + IsCastingFireball = true; + Fireball_Timer = 2500; + } + } + else + { + //apply resistance + me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); + IsCastingFireball = false; + Fireball_Timer = 5000+rand()%10000; + } + } else Fireball_Timer -= diff; + + //ArcaneDisruption_Timer + if (ArcaneDisruption_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_DISRUPTION, true); + ArcaneDisruption_Timer = 60000; + } else ArcaneDisruption_Timer -= diff; + + if (FlameStrike_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_FLAME_STRIKE); + + FlameStrike_Timer = 30000; + } else FlameStrike_Timer -= diff; + + if (MindControl_Timer <= diff) + { + if (me->getThreatManager().getThreatList().size() >= 2) + for (uint32 i = 0; i < 3; ++i) + { + debug_log("SD2: Kael'Thas mind control not supported."); + //DoCast(pUnit, SPELL_MIND_CONTROL); + } + + MindControl_Timer = 60000; + } else MindControl_Timer -= diff; + } + + //Phoenix_Timer + if (Phoenix_Timer <= diff) + { + DoCast(me, SPELL_PHOENIX_ANIMATION); + DoScriptText(RAND(SAY_SUMMON_PHOENIX1,SAY_SUMMON_PHOENIX2), me); + + Phoenix_Timer = 60000; + } else Phoenix_Timer -= diff; + + //Phase 4 specific spells + if (Phase == 4) + { + if (me->GetHealth()*100 / me->GetMaxHealth() < 50) + { + if (m_pInstance) + m_pInstance->SetData(DATA_KAELTHASEVENT, 4); + Phase = 5; + Phase_Timer = 10000; + + DoScriptText(SAY_PHASE5_NUTS, me); + + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); + me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, 0, 0); + + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_FULLPOWER); + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + //ShockBarrier_Timer + if (ShockBarrier_Timer <= diff) + { + DoCast(me, SPELL_SHOCK_BARRIER); + ChainPyros = true; + PyrosCasted = 0; + ShockBarrier_Timer = 60000; + } else ShockBarrier_Timer -= diff; + + //Chain Pyros (3 of them max) + if (ChainPyros && !me->IsNonMeleeSpellCasted(false)) + { + if (PyrosCasted < 3) + { + DoCast(me->getVictim(), SPELL_PYROBLAST); + ++PyrosCasted; + } + else + { + ChainPyros = false; + Fireball_Timer = 2500; + ArcaneDisruption_Timer = 60000; + } + } + } + + if (Phase == 5) + { + if (Phase_Timer <= diff) + { + me->InterruptNonMeleeSpells(false); + me->RemoveAurasDueToSpell(SPELL_FULLPOWER); + + DoCast(me, SPELL_EXPLODE); + + me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Phase = 6; + AttackStart(me->getVictim()); + } else Phase_Timer -= diff; + } + + //Phase 5 + if (Phase == 6) + { + + //GravityLapse_Timer + if (GravityLapse_Timer <= diff) + { + std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); + switch (GravityLapse_Phase) + { + case 0: + me->StopMoving(); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MoveIdle(); + me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); + me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, MOVEMENTFLAG_NONE, 0); + + // 1) Kael'thas will portal the whole raid right into his body + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) + { + //Use work around packet to prevent player from being dropped from combat + DoTeleportPlayer(pUnit, afGravityPos[0], afGravityPos[1], afGravityPos[2], pUnit->GetOrientation()); + } + } + + GravityLapse_Timer = 500; + ++GravityLapse_Phase; + InGravityLapse = true; + ShockBarrier_Timer = 1000; + NetherBeam_Timer = 5000; + break; + + case 1: + DoScriptText(RAND(SAY_GRAVITYLAPSE1,SAY_GRAVITYLAPSE2), me); + + // 2) At that point he will put a Gravity Lapse debuff on everyone + for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) + { + if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) + { + DoCast(pUnit, SPELL_KNOCKBACK, true); + //Gravity lapse - needs an exception in Spell system to work + + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); + pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); + + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + GravityLapse_Timer = 10000; + ++GravityLapse_Phase; + break; + + case 2: + //Cast nether vapor aura on self + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_NETHER_VAPOR); + + GravityLapse_Timer = 20000; + ++GravityLapse_Phase; + break; + + case 3: + //Remove flight + for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) + { + if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) + { + //Using packet workaround + WorldPacket data(12); + data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); + data.append(pUnit->GetPackGUID()); + data << uint32(0); + pUnit->SendMessageToSet(&data, true); + } + } + + me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); + InGravityLapse = false; + GravityLapse_Timer = 60000; + GravityLapse_Phase = 0; + AttackStart(me->getVictim()); + break; + } + } else GravityLapse_Timer -= diff; + + if (InGravityLapse) + { + //ShockBarrier_Timer + if (ShockBarrier_Timer <= diff) + { + DoCast(me, SPELL_SHOCK_BARRIER); + ShockBarrier_Timer = 20000; + } else ShockBarrier_Timer -= diff; + + //NetherBeam_Timer + if (NetherBeam_Timer <= diff) + { + if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pUnit, SPELL_NETHER_BEAM); + + NetherBeam_Timer = 4000; + } else NetherBeam_Timer -= diff; + } + } + + if (!InGravityLapse) + DoMeleeAttackIfReady(); + } + } + } +}; + +//Thaladred the Darkener AI +struct boss_thaladred_the_darkenerAI : public advisorbase_ai +{ + boss_thaladred_the_darkenerAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Gaze_Timer; + uint32 Silence_Timer; + uint32 PsychicBlow_Timer; + + void Reset() + { + Gaze_Timer = 100; + Silence_Timer = 20000; + PsychicBlow_Timer = 10000; + + advisorbase_ai::Reset(); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_THALADRED_AGGRO, me); + me->AddThreat(who, 5000000.0f); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_THALADRED_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Gaze_Timer + if (Gaze_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + { + DoResetThreat(); + me->AddThreat(pTarget, 5000000.0f); + DoScriptText(EMOTE_THALADRED_GAZE, me, pTarget); + Gaze_Timer = 8500; + } + } else Gaze_Timer -= diff; + + //Silence_Timer + if (Silence_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SILENCE); + Silence_Timer = 20000; + } else Silence_Timer -= diff; + + //PsychicBlow_Timer + if (PsychicBlow_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_PSYCHIC_BLOW); + PsychicBlow_Timer = 20000+rand()%5000; + } else PsychicBlow_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Lord Sanguinar AI +struct boss_lord_sanguinarAI : public advisorbase_ai +{ + boss_lord_sanguinarAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Fear_Timer; + + void Reset() + { + Fear_Timer = 20000; + advisorbase_ai::Reset(); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_SANGUINAR_AGGRO, me); + } + + void JustDied(Unit* /*Killer*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_SANGUINAR_DEATH, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Fear_Timer + if (Fear_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); + Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds + } else Fear_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Grand Astromancer Capernian AI +struct boss_grand_astromancer_capernianAI : public advisorbase_ai +{ + boss_grand_astromancer_capernianAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Fireball_Timer; + uint32 Conflagration_Timer; + uint32 ArcaneExplosion_Timer; + uint32 Yell_Timer; + bool Yell; + + void Reset() + { + Fireball_Timer = 2000; + Conflagration_Timer = 20000; + ArcaneExplosion_Timer = 5000; + Yell_Timer = 2000; + Yell = false; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_CAPERNIAN_DEATH, me); + } + + void AttackStart(Unit* who) + { + if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (me->Attack(who, true)) + { + me->AddThreat(who, 0.0f); + me->SetInCombatWith(who); + who->SetInCombatWith(me); + + me->GetMotionMaster()->MoveChase(who, CAPERNIAN_DISTANCE); + } + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, don't do anything + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Yell_Timer + if (!Yell) + { + if (Yell_Timer <= diff) + { + DoScriptText(SAY_CAPERNIAN_AGGRO, me); + Yell = true; + } else Yell_Timer -= diff; + } + + //Fireball_Timer + if (Fireball_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_CAPERNIAN_FIREBALL); + Fireball_Timer = 4000; + } else Fireball_Timer -= diff; + + //Conflagration_Timer + if (Conflagration_Timer <= diff) + { + Unit *pTarget = NULL; + pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); + + if (pTarget && me->IsWithinDistInMap(pTarget, 30)) + DoCast(pTarget, SPELL_CONFLAGRATION); + else + DoCast(me->getVictim(), SPELL_CONFLAGRATION); + + Conflagration_Timer = 10000+rand()%5000; + } else Conflagration_Timer -= diff; + + //ArcaneExplosion_Timer + if (ArcaneExplosion_Timer <= diff) + { + bool InMeleeRange = false; + Unit *pTarget = NULL; + std::list& m_threatlist = me->getThreatManager().getThreatList(); + for (std::list::const_iterator i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) + { + Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); + //if in melee range + if (pUnit && pUnit->IsWithinDistInMap(me, 5)) + { + InMeleeRange = true; + pTarget = pUnit; + break; + } + } + + if (InMeleeRange) + DoCast(pTarget, SPELL_ARCANE_EXPLOSION); + + ArcaneExplosion_Timer = 4000+rand()%2000; + } else ArcaneExplosion_Timer -= diff; + + //Do NOT deal any melee damage. + } +}; + +//Master Engineer Telonicus AI +struct boss_master_engineer_telonicusAI : public advisorbase_ai +{ + boss_master_engineer_telonicusAI(Creature* pCreature) : advisorbase_ai(pCreature) {} + + uint32 Bomb_Timer; + uint32 RemoteToy_Timer; + + void Reset() + { + Bomb_Timer = 10000; + RemoteToy_Timer = 5000; + + advisorbase_ai::Reset(); + } + + void JustDied(Unit* /*pKiller*/) + { + if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) + DoScriptText(SAY_TELONICUS_DEATH, me); + } + + void Aggro(Unit *who) + { + if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + if (!who || FakeDeath) + return; + + DoScriptText(SAY_TELONICUS_AGGRO, me); + } + + void UpdateAI(const uint32 diff) + { + advisorbase_ai::UpdateAI(diff); + + //Faking Death, do nothing + if (FakeDeath) + return; + + //Return since we have no target + if (!UpdateVictim()) + return; + + //Bomb_Timer + if (Bomb_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_BOMB); + Bomb_Timer = 25000; + } else Bomb_Timer -= diff; + + //RemoteToy_Timer + if (RemoteToy_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_REMOTE_TOY); + + RemoteToy_Timer = 10000+rand()%5000; + } else RemoteToy_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Flame Strike AI +struct mob_kael_flamestrikeAI : public Scripted_NoMovementAI +{ + mob_kael_flamestrikeAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) {} + + uint32 Timer; + bool Casting; + bool KillSelf; + + void Reset() + { + Timer = 5000; + Casting = false; + KillSelf = false; + + me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + me->setFaction(14); + } + + void MoveInLineOfSight(Unit * /*who*/) {} + + void EnterCombat(Unit * /*who*/) {} + + void UpdateAI(const uint32 diff) + { + if (!Casting) + { + DoCast(me, SPELL_FLAME_STRIKE_VIS); + Casting = true; + } + + //Timer + if (Timer <= diff) + { + if (!KillSelf) + { + me->InterruptNonMeleeSpells(false); + DoCast(me, SPELL_FLAME_STRIKE_DMG); + } else me->Kill(me); + + KillSelf = true; + Timer = 1000; + } else Timer -= diff; + } +}; + +//Phoenix AI +struct mob_phoenix_tkAI : public ScriptedAI +{ + mob_phoenix_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 Cycle_Timer; + + void Reset() + { + Cycle_Timer = 2000; + DoCast(me, SPELL_BURN, true); + } + + void JustDied(Unit* /*killer*/) + { + //is this spell in use anylonger? + //DoCast(me, SPELL_EMBER_BLAST, true); + me->SummonCreature(NPC_PHOENIX_EGG,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,16000); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (Cycle_Timer <= diff) + { + //spell Burn should possible do this, but it doesn't, so do this for now. + uint32 dmg = urand(4500,5500); + if (me->GetHealth() > dmg) + me->SetHealth(uint32(me->GetHealth()-dmg)); + Cycle_Timer = 2000; + } else Cycle_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +//Phoenix Egg AI +struct mob_phoenix_egg_tkAI : public ScriptedAI +{ + mob_phoenix_egg_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} + + uint32 Rebirth_Timer; + + void Reset() + { + Rebirth_Timer = 15000; + } + + //ignore any + void MoveInLineOfSight(Unit* /*who*/) {} + + void AttackStart(Unit* who) + { + if (me->Attack(who, false)) + { + me->SetInCombatWith(who); + who->SetInCombatWith(me); + + DoStartNoMovement(who); + } + } + + void JustSummoned(Creature* summoned) + { + summoned->AddThreat(me->getVictim(), 0.0f); + summoned->CastSpell(summoned,SPELL_REBIRTH,false); + } + + void UpdateAI(const uint32 diff) + { + if (!Rebirth_Timer) + return; + + if (Rebirth_Timer <= diff) + { + me->SummonCreature(NPC_PHOENIX,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,5000); + Rebirth_Timer = 0; + } else Rebirth_Timer -= diff; + } +}; + +CreatureAI* GetAI_boss_kaelthas(Creature* pCreature) +{ + return new boss_kaelthasAI(pCreature); +} + +CreatureAI* GetAI_boss_thaladred_the_darkener(Creature* pCreature) +{ + return new boss_thaladred_the_darkenerAI(pCreature); +} + +CreatureAI* GetAI_boss_lord_sanguinar(Creature* pCreature) +{ + return new boss_lord_sanguinarAI(pCreature); +} + +CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature* pCreature) +{ + return new boss_grand_astromancer_capernianAI(pCreature); +} + +CreatureAI* GetAI_boss_master_engineer_telonicus(Creature* pCreature) +{ + return new boss_master_engineer_telonicusAI(pCreature); +} + +CreatureAI* GetAI_mob_kael_flamestrike(Creature* pCreature) +{ + return new mob_kael_flamestrikeAI(pCreature); +} + +CreatureAI* GetAI_mob_phoenix_tk(Creature* pCreature) +{ + return new mob_phoenix_tkAI(pCreature); +} + +CreatureAI* GetAI_mob_phoenix_egg_tk(Creature* pCreature) +{ + return new mob_phoenix_egg_tkAI(pCreature); +} + +void AddSC_boss_kaelthas() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_kaelthas"; + newscript->GetAI = &GetAI_boss_kaelthas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_thaladred_the_darkener"; + newscript->GetAI = &GetAI_boss_thaladred_the_darkener; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lord_sanguinar"; + newscript->GetAI = &GetAI_boss_lord_sanguinar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_grand_astromancer_capernian"; + newscript->GetAI = &GetAI_boss_grand_astromancer_capernian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_master_engineer_telonicus"; + newscript->GetAI = &GetAI_boss_master_engineer_telonicus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_kael_flamestrike"; + newscript->GetAI = &GetAI_mob_kael_flamestrike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phoenix_tk"; + newscript->GetAI = &GetAI_mob_phoenix_tk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_phoenix_egg_tk"; + newscript->GetAI = &GetAI_mob_phoenix_egg_tk; + newscript->RegisterSelf(); +} diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp new file mode 100644 index 00000000000..e1b60b20948 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp @@ -0,0 +1,179 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Void_Reaver +SD%Complete: 90 +SDComment: Should reset if raid are out of room. +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +enum eEnums +{ + SAY_AGGRO = -1550000, + SAY_SLAY1 = -1550001, + SAY_SLAY2 = -1550002, + SAY_SLAY3 = -1550003, + SAY_DEATH = -1550004, + SAY_POUNDING1 = -1550005, + SAY_POUNDING2 = -1550006, + + SPELL_POUNDING = 34162, + SPELL_ARCANE_ORB = 34172, + SPELL_KNOCK_AWAY = 25778, + SPELL_BERSERK = 27680 +}; + +struct boss_void_reaverAI : public ScriptedAI +{ + boss_void_reaverAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance* pInstance; + + uint32 Pounding_Timer; + uint32 ArcaneOrb_Timer; + uint32 KnockAway_Timer; + uint32 Berserk_Timer; + + bool Enraged; + + void Reset() + { + Pounding_Timer = 15000; + ArcaneOrb_Timer = 3000; + KnockAway_Timer = 30000; + Berserk_Timer = 600000; + + Enraged = false; + + if (pInstance && me->isAlive()) + pInstance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); + } + + void KilledUnit(Unit * /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); + } + + void JustDied(Unit * /*victim*/) + { + DoScriptText(SAY_DEATH, me); + DoZoneInCombat(); + + if (pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, DONE); + } + + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + + if (pInstance) + pInstance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + // Pounding + if (Pounding_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_POUNDING); + + DoScriptText(RAND(SAY_POUNDING1,SAY_POUNDING2), me); + Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000) + } else Pounding_Timer -= diff; + + // Arcane Orb + if (ArcaneOrb_Timer <= diff) + { + Unit *pTarget = NULL; + std::list t_list = me->getThreatManager().getThreatList(); + std::vector target_list; + for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + { + pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); + if (!pTarget) + continue; + + // exclude pets & totems + if (pTarget->GetTypeId() != TYPEID_PLAYER) + continue; + + //18 yard radius minimum + if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive() && !pTarget->IsWithinDist(me, 18, false)) + target_list.push_back(pTarget); + pTarget = NULL; + } + + if (target_list.size()) + pTarget = *(target_list.begin()+rand()%target_list.size()); + else + pTarget = me->getVictim(); + + if (pTarget) + me->CastSpell(pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(), SPELL_ARCANE_ORB, false, NULL, NULL, NULL, pTarget); + + ArcaneOrb_Timer = 3000; + } else ArcaneOrb_Timer -= diff; + + // Single Target knock back, reduces aggro + if (KnockAway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCK_AWAY); + + //Drop 25% aggro + if (DoGetThreat(me->getVictim())) + DoModifyThreatPercent(me->getVictim(),-25); + + KnockAway_Timer = 30000; + } else KnockAway_Timer -= diff; + + //Berserk + if (Berserk_Timer < diff && !Enraged) + { + DoCast(me, SPELL_BERSERK); + Enraged = true; + } else Berserk_Timer -= diff; + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(diff); + } +}; + +CreatureAI* GetAI_boss_void_reaver(Creature* pCreature) +{ + return new boss_void_reaverAI (pCreature); +} + +void AddSC_boss_void_reaver() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_void_reaver"; + newscript->GetAI = &GetAI_boss_void_reaver; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp new file mode 100644 index 00000000000..59c72071238 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Eye/instance_the_eye.cpp @@ -0,0 +1,176 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_The_Eye +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define MAX_ENCOUNTER 5 + +/* The Eye encounters: +0 - Kael'thas event +1 - Al' ar event +2 - Solarian Event +3 - Void Reaver event +*/ + +struct instance_the_eye : public ScriptedInstance +{ + instance_the_eye(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint64 ThaladredTheDarkener; + uint64 LordSanguinar; + uint64 GrandAstromancerCapernian; + uint64 MasterEngineerTelonicus; + uint64 Kaelthas; + uint64 Astromancer; + uint64 Alar; + + uint8 KaelthasEventPhase; + uint8 AlarEventPhase; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + + ThaladredTheDarkener = 0; + LordSanguinar = 0; + GrandAstromancerCapernian = 0; + MasterEngineerTelonicus = 0; + Kaelthas = 0; + Astromancer = 0; + Alar = 0; + + KaelthasEventPhase = 0; + AlarEventPhase = 0; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void OnCreatureCreate(Creature* pCreature, bool /*add*/) + { + switch(pCreature->GetEntry()) + { + case 20064: ThaladredTheDarkener = pCreature->GetGUID(); break; + case 20063: MasterEngineerTelonicus = pCreature->GetGUID(); break; + case 20062: GrandAstromancerCapernian = pCreature->GetGUID(); break; + case 20060: LordSanguinar = pCreature->GetGUID(); break; + case 19622: Kaelthas = pCreature->GetGUID(); break; + case 18805: Astromancer = pCreature->GetGUID(); break; + case 19514: Alar = pCreature->GetGUID(); break; + } + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_THALADREDTHEDARKENER: return ThaladredTheDarkener; + case DATA_LORDSANGUINAR: return LordSanguinar; + case DATA_GRANDASTROMANCERCAPERNIAN: return GrandAstromancerCapernian; + case DATA_MASTERENGINEERTELONICUS: return MasterEngineerTelonicus; + case DATA_KAELTHAS: return Kaelthas; + case DATA_ASTROMANCER: return Astromancer; + case DATA_ALAR: return Alar; + } + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_ALAREVENT: AlarEventPhase = data; m_auiEncounter[0] = data; break; + case DATA_HIGHASTROMANCERSOLARIANEVENT: m_auiEncounter[1] = data; break; + case DATA_VOIDREAVEREVENT: m_auiEncounter[2] = data; break; + case DATA_KAELTHASEVENT: KaelthasEventPhase = data; m_auiEncounter[3] = data; break; + } + if (data == DONE) + SaveToDB(); + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_ALAREVENT: return AlarEventPhase; + case DATA_HIGHASTROMANCERSOLARIANEVENT: return m_auiEncounter[1]; + case DATA_VOIDREAVEREVENT: return m_auiEncounter[2]; + case DATA_KAELTHASEVENT: return KaelthasEventPhase; + } + return 0; + } + + std::string GetSaveData() + { + OUT_SAVE_INST_DATA; + std::ostringstream stream; + stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; + char* out = new char[stream.str().length() + 1]; + strcpy(out, stream.str().c_str()); + if (out) + { + OUT_SAVE_INST_DATA_COMPLETE; + return out; + } + return NULL; + } + + void Load(const char* in) + { + if (!in) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + OUT_LOAD_INST_DATA(in); + std::istringstream stream(in); + stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. + m_auiEncounter[i] = NOT_STARTED; + OUT_LOAD_INST_DATA_COMPLETE; + } +}; + +InstanceData* GetInstanceData_instance_the_eye(Map* pMap) +{ + return new instance_the_eye(pMap); +} + +void AddSC_instance_the_eye() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_the_eye"; + newscript->GetInstanceData = &GetInstanceData_instance_the_eye; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp new file mode 100644 index 00000000000..97021fdc031 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp @@ -0,0 +1,98 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: The_Eye +SD%Complete: 100 +SDComment: +SDCategory: Tempest Keep, The Eye +EndScriptData */ + +/* ContentData +mob_crystalcore_devastator +EndContentData */ + +#include "ScriptedPch.h" +#include "the_eye.h" + +#define SPELL_COUNTERCHARGE 35035 +#define SPELL_KNOCKAWAY 22893 + +struct mob_crystalcore_devastatorAI : public ScriptedAI +{ + mob_crystalcore_devastatorAI(Creature *c) : ScriptedAI(c) {} + + uint32 Knockaway_Timer; + uint32 Countercharge_Timer; + + void Reset() + { + Countercharge_Timer = 9000; + Knockaway_Timer = 25000; + } + + void EnterCombat(Unit * /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + //Check if we have a current target + //Knockaway_Timer + if (Knockaway_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); + + // current aggro target is knocked away pick new target + Unit* pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); + + if (!pTarget || pTarget == me->getVictim()) + pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); + + if (pTarget) + me->TauntApply(pTarget); + + Knockaway_Timer = 23000; + } else Knockaway_Timer -= diff; + + //Countercharge_Timer + if (Countercharge_Timer <= diff) + { + DoCast(me, SPELL_COUNTERCHARGE); + Countercharge_Timer = 45000; + } else Countercharge_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_crystalcore_devastator(Creature* pCreature) +{ + return new mob_crystalcore_devastatorAI (pCreature); +} + +void AddSC_the_eye() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "mob_crystalcore_devastator"; + newscript->GetAI = &GetAI_mob_crystalcore_devastator; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h new file mode 100644 index 00000000000..d0d3ea09061 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.h @@ -0,0 +1,20 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_THE_EYE_H +#define DEF_THE_EYE_H + +#define DATA_ALAREVENT 1 +#define DATA_ASTROMANCER 2 +#define DATA_GRANDASTROMANCERCAPERNIAN 3 +#define DATA_HIGHASTROMANCERSOLARIANEVENT 4 +#define DATA_KAELTHAS 5 +#define DATA_KAELTHASEVENT 6 +#define DATA_LORDSANGUINAR 7 +#define DATA_MASTERENGINEERTELONICUS 8 +#define DATA_THALADREDTHEDARKENER 10 +#define DATA_VOIDREAVEREVENT 11 +#define DATA_ALAR 12 +#endif + diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_gyrokill.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_gyrokill.cpp new file mode 100644 index 00000000000..b9c365eda65 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_gyrokill.cpp @@ -0,0 +1,39 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Boss_Gatewatcher_Gyrokill +SD%Complete: 0 +SDComment: Place Holder +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +//not used +#define SAY_AGGRO -1554000 +#define SAY_SAW_ATTACK1 -1554001 +#define SAY_SAW_ATTACK2 -1554002 +#define SAY_SLAY1 -1554003 +#define SAY_SLAY2 -1554004 +#define SAY_DEATH -1554005 + +#define SPELL_STREAM_OF_MACHINE_FLUID 35311 +#define SPELL_SAW_BLADE 35318 +#define H_SPELL_SAW_BLADE 39192 +#define SPELL_SHADOW_POWER 35322 +#define H_SPELL_SHADOW_POWER 39193 + diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp new file mode 100644 index 00000000000..50c3a6171ce --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_gatewatcher_ironhand.cpp @@ -0,0 +1,130 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Gatewatcher_Ironhand +SD%Complete: 75 +SDComment: +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO_1 -1554006 +#define SAY_HAMMER_1 -1554007 +#define SAY_HAMMER_2 -1554008 +#define SAY_SLAY_1 -1554009 +#define SAY_SLAY_2 -1554010 +#define SAY_DEATH_1 -1554011 +#define EMOTE_HAMMER -1554012 + +// Spells to be casted +#define SPELL_SHADOW_POWER 35322 +#define H_SPELL_SHADOW_POWER 39193 +#define SPELL_HAMMER_PUNCH 35326 +#define SPELL_JACKHAMMER 35327 +#define H_SPELL_JACKHAMMER 39194 +#define SPELL_STREAM_OF_MACHINE_FLUID 35311 + +// Gatewatcher Iron-Hand AI +struct boss_gatewatcher_iron_handAI : public ScriptedAI +{ + boss_gatewatcher_iron_handAI(Creature *c) : ScriptedAI(c) + { + } + + uint32 Shadow_Power_Timer; + uint32 Jackhammer_Timer; + uint32 Stream_of_Machine_Fluid_Timer; + + void Reset() + { + Shadow_Power_Timer = 25000; + Jackhammer_Timer = 45000; + Stream_of_Machine_Fluid_Timer = 55000; + + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO_1, me); + } + + void KilledUnit(Unit* /*victim*/) + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH_1, me); + //TODO: Add door check/open code + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Shadow Power + if (Shadow_Power_Timer <= diff) + { + DoCast(me, SPELL_SHADOW_POWER); + Shadow_Power_Timer = 20000 + rand()%8000; + } else Shadow_Power_Timer -= diff; + + //Jack Hammer + if (Jackhammer_Timer <= diff) + { + //TODO: expect cast this about 5 times in a row (?), announce it by emote only once + DoScriptText(EMOTE_HAMMER, me); + DoCast(me->getVictim(), SPELL_JACKHAMMER); + + //chance to yell, but not same time as emote (after spell in fact casted) + if (rand()%2) + return; + + DoScriptText(RAND(SAY_HAMMER_1,SAY_HAMMER_2), me); + Jackhammer_Timer = 30000; + } else Jackhammer_Timer -= diff; + + //Stream of Machine Fluid + if (Stream_of_Machine_Fluid_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_STREAM_OF_MACHINE_FLUID); + Stream_of_Machine_Fluid_Timer = 35000 + rand()%15000; + } else Stream_of_Machine_Fluid_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_gatewatcher_iron_hand(Creature* pCreature) +{ + return new boss_gatewatcher_iron_handAI (pCreature); +} + +void AddSC_boss_gatewatcher_iron_hand() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_gatewatcher_iron_hand"; + newscript->GetAI = &GetAI_boss_gatewatcher_iron_hand; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp new file mode 100644 index 00000000000..ededec0196d --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp @@ -0,0 +1,245 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss_Nethermancer_Sepethrea +SD%Complete: 90 +SDComment: Need adjustments to initial summons +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" +#include "mechanar.h" + +#define SAY_AGGRO -1554013 +#define SAY_SUMMON -1554014 +#define SAY_DRAGONS_BREATH_1 -1554015 +#define SAY_DRAGONS_BREATH_2 -1554016 +#define SAY_SLAY1 -1554017 +#define SAY_SLAY2 -1554018 +#define SAY_DEATH -1554019 + +#define SPELL_SUMMON_RAGIN_FLAMES 35275 +#define H_SPELL_SUMMON_RAGIN_FLAMES 39084 + +#define SPELL_FROST_ATTACK 35263 +#define SPELL_ARCANE_BLAST 35314 +#define SPELL_DRAGONS_BREATH 35250 +#define SPELL_KNOCKBACK 37317 +#define SPELL_SOLARBURN 35267 + +struct boss_nethermancer_sepethreaAI : public ScriptedAI +{ + boss_nethermancer_sepethreaAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 frost_attack_Timer; + uint32 arcane_blast_Timer; + uint32 dragons_breath_Timer; + uint32 knockback_Timer; + uint32 solarburn_Timer; + + void Reset() + { + frost_attack_Timer = 7000 + rand()%3000; + arcane_blast_Timer = 12000 + rand()%6000; + dragons_breath_Timer = 18000 + rand()%4000; + knockback_Timer = 22000 + rand()%6000; + solarburn_Timer = 30000; + + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, NOT_STARTED); + } + + void EnterCombat(Unit* who) + { + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, me); + DoCast(who, SPELL_SUMMON_RAGIN_FLAMES); + DoScriptText(SAY_SUMMON, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + if (pInstance) + pInstance->SetData(DATA_NETHERMANCER_EVENT, DONE); + } + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + //Frost Attack + if (frost_attack_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_FROST_ATTACK); + frost_attack_Timer = 7000 + rand()%3000; + } else frost_attack_Timer -= diff; + + //Arcane Blast + if (arcane_blast_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_BLAST); + arcane_blast_Timer = 15000; + } else arcane_blast_Timer -= diff; + + //Dragons Breath + if (dragons_breath_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_DRAGONS_BREATH); + { + if (rand()%2) + return; + + DoScriptText(RAND(SAY_DRAGONS_BREATH_1,SAY_DRAGONS_BREATH_2), me); + } + dragons_breath_Timer = 12000 + rand()%10000; + } else dragons_breath_Timer -= diff; + + //Knockback + if (knockback_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_KNOCKBACK); + knockback_Timer = 15000 + rand()%10000; + } else knockback_Timer -= diff; + + //Solarburn + if (solarburn_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_SOLARBURN); + solarburn_Timer = 30000; + } else solarburn_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_nethermancer_sepethrea(Creature* pCreature) +{ + return new boss_nethermancer_sepethreaAI (pCreature); +} + +#define SPELL_INFERNO 35268 +#define H_SPELL_INFERNO 39346 +#define SPELL_FIRE_TAIL 35278 + +struct mob_ragin_flamesAI : public ScriptedAI +{ + mob_ragin_flamesAI(Creature *c) : ScriptedAI(c) + { + pInstance = c->GetInstanceData(); + } + + ScriptedInstance *pInstance; + + uint32 inferno_Timer; + uint32 flame_timer; + uint32 Check_Timer; + + bool onlyonce; + + void Reset() + { + inferno_Timer = 10000; + flame_timer = 500; + Check_Timer = 2000; + onlyonce = false; + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); + me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); + me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); + } + + void EnterCombat(Unit* /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + //Check_Timer + if (Check_Timer <= diff) + { + if (pInstance) + { + if (pInstance->GetData(DATA_NETHERMANCER_EVENT) != IN_PROGRESS) + { + //remove + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } + } + Check_Timer = 1000; + } else Check_Timer -= diff; + + if (!UpdateVictim()) + return; + + if (!onlyonce) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) + me->GetMotionMaster()->MoveChase(pTarget); + onlyonce = true; + } + + if (inferno_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_INFERNO); + me->TauntApply(me->getVictim()); + inferno_Timer = 10000; + } else inferno_Timer -= diff; + + if (flame_timer <= diff) + { + DoCast(me, SPELL_FIRE_TAIL); + flame_timer = 500; + } else flame_timer -=diff; + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_mob_ragin_flames(Creature* pCreature) +{ + return new mob_ragin_flamesAI (pCreature); +} +void AddSC_boss_nethermancer_sepethrea() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_nethermancer_sepethrea"; + newscript->GetAI = &GetAI_boss_nethermancer_sepethrea; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ragin_flames"; + newscript->GetAI = &GetAI_mob_ragin_flames; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp new file mode 100644 index 00000000000..c0c06704db7 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_pathaleon_the_calculator.cpp @@ -0,0 +1,246 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* ScriptData +SDName: Boss Pathaleon the Calculator +SD%Complete: 50 +SDComment: Event missing. Script for himself 99% blizzlike. +SDCategory: Tempest Keep, The Mechanar +EndScriptData */ + +#include "ScriptedPch.h" + +#define SAY_AGGRO -1554020 +#define SAY_DOMINATION_1 -1554021 +#define SAY_DOMINATION_2 -1554022 +#define SAY_SUMMON -1554023 +#define SAY_ENRAGE -1554024 +#define SAY_SLAY_1 -1554025 +#define SAY_SLAY_2 -1554026 +#define SAY_DEATH -1554027 + +// Spells to be casted +#define SPELL_MANA_TAP 36021 +#define SPELL_ARCANE_TORRENT 36022 +#define SPELL_DOMINATION 35280 +#define H_SPELL_ARCANE_EXPLOSION 15453 +#define SPELL_FRENZY 36992 + +#define SPELL_SUMMON_NETHER_WRAITH_1 35285 //Spells work, but not implemented +#define SPELL_SUMMON_NETHER_WRAITH_2 35286 +#define SPELL_SUMMON_NETHER_WRAITH_3 35287 +#define SPELL_SUMMON_NETHER_WRAITH_4 35288 + +// Add Spells +#define SPELL_DETONATION 35058 +#define SPELL_ARCANE_MISSILES 35034 + +struct boss_pathaleon_the_calculatorAI : public ScriptedAI +{ + boss_pathaleon_the_calculatorAI(Creature *c) : ScriptedAI(c), summons(me) + { + } + + uint32 Summon_Timer; + SummonList summons; + uint32 ManaTap_Timer; + uint32 ArcaneTorrent_Timer; + uint32 Domination_Timer; + uint32 ArcaneExplosion_Timer; + + bool Enraged; + + uint32 Counter; + + void Reset() + { + Summon_Timer = 30000; + ManaTap_Timer = 12000 + rand()%8000; + ArcaneTorrent_Timer = 16000 + rand()%9000; + Domination_Timer = 25000 + rand()%15000; + ArcaneExplosion_Timer = 8000 + rand()%5000; + + Enraged = false; + + Counter = 0; + summons.DespawnAll(); + } + void EnterCombat(Unit * /*who*/) + { + DoScriptText(SAY_AGGRO, me); + } + + void KilledUnit(Unit* /*victim*/) + { + DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); + } + + void JustDied(Unit* /*Killer*/) + { + DoScriptText(SAY_DEATH, me); + + summons.DespawnAll(); + } + + void JustSummoned(Creature *summon) {summons.Summon(summon);} + void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} + + void UpdateAI(const uint32 diff) + { + //Return since we have no target + if (!UpdateVictim()) + return; + + if (Summon_Timer <= diff) + { + for (uint8 i = 0; i < 3; ++i) + { + Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); + Creature* Wraith = me->SummonCreature(21062,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); + if (pTarget && Wraith) + Wraith->AI()->AttackStart(pTarget); + } + DoScriptText(SAY_SUMMON, me); + Summon_Timer = 30000 + rand()%15000; + } else Summon_Timer -= diff; + + if (ManaTap_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_MANA_TAP); + ManaTap_Timer = 14000 + rand()%8000; + } else ManaTap_Timer -= diff; + + if (ArcaneTorrent_Timer <= diff) + { + DoCast(me->getVictim(), SPELL_ARCANE_TORRENT); + ArcaneTorrent_Timer = 12000 + rand()%6000; + } else ArcaneTorrent_Timer -= diff; + + if (Domination_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + { + DoScriptText(RAND(SAY_DOMINATION_1,SAY_DOMINATION_2), me); + + DoCast(pTarget, SPELL_DOMINATION); + } + Domination_Timer = 25000 + rand()%5000; + } else Domination_Timer -= diff; + + //Only casting if Heroic Mode is used + if (IsHeroic()) + { + if (ArcaneExplosion_Timer <= diff) + { + DoCast(me->getVictim(), H_SPELL_ARCANE_EXPLOSION); + ArcaneExplosion_Timer = 10000 + rand()%4000; + } else ArcaneExplosion_Timer -= diff; + } + + if (!Enraged && me->GetHealth()*100 / me->GetMaxHealth() < 21) + { + DoCast(me, SPELL_FRENZY); + DoScriptText(SAY_ENRAGE, me); + Enraged = true; + + } + + DoMeleeAttackIfReady(); + } +}; +CreatureAI* GetAI_boss_pathaleon_the_calculator(Creature* pCreature) +{ + return new boss_pathaleon_the_calculatorAI (pCreature); +} + +struct mob_nether_wraithAI : public ScriptedAI +{ + mob_nether_wraithAI(Creature *c) : ScriptedAI(c) {} + + uint32 ArcaneMissiles_Timer; + uint32 Detonation_Timer; + uint32 Die_Timer; + bool Detonation; + + void Reset() + { + ArcaneMissiles_Timer = 1000 + rand()%3000; + Detonation_Timer = 20000; + Die_Timer = 2200; + Detonation = false; + + } + + void EnterCombat(Unit* /*who*/) + { + } + + void UpdateAI(const uint32 diff) + { + if (!UpdateVictim()) + return; + + if (ArcaneMissiles_Timer <= diff) + { + if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) + DoCast(pTarget, SPELL_ARCANE_MISSILES); + else + DoCast(me->getVictim(), SPELL_ARCANE_MISSILES); + + ArcaneMissiles_Timer = 5000 + rand()%5000; + } else ArcaneMissiles_Timer -=diff; + + if (!Detonation) + { + if (Detonation_Timer <= diff) + { + DoCast(me, SPELL_DETONATION); + Detonation = true; + } else Detonation_Timer -= diff; + } + + if (Detonation) + { + if (Die_Timer <= diff) + { + me->setDeathState(JUST_DIED); + me->RemoveCorpse(); + } else Die_Timer -= diff; + } + + DoMeleeAttackIfReady(); + } + +}; +CreatureAI* GetAI_mob_nether_wraith(Creature* pCreature) +{ + return new mob_nether_wraithAI (pCreature); +} + +void AddSC_boss_pathaleon_the_calculator() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_pathaleon_the_calculator"; + newscript->GetAI = &GetAI_boss_pathaleon_the_calculator; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nether_wraith"; + newscript->GetAI = &GetAI_mob_nether_wraith; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp new file mode 100644 index 00000000000..c70da24ea3f --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/instance_mechanar.cpp @@ -0,0 +1,86 @@ +/* Copyright (C) 2006 - 2009 ScriptDev2 + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* ScriptData +SDName: Instance_Mechanar +SD%Complete: 100 +SDComment: +SDCategory: Mechanar +EndScriptData */ + +#include "ScriptedPch.h" +#include "mechanar.h" + +#define MAX_ENCOUNTER 1 + +struct instance_mechanar : public ScriptedInstance +{ + instance_mechanar(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case DATA_NETHERMANCER_EVENT: return m_auiEncounter[0]; + } + + return false; + } + + uint64 GetData64 (uint32 /*identifier*/) + { + return 0; + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case DATA_NETHERMANCER_EVENT: m_auiEncounter[0] = data; break; + } + } +}; + +InstanceData* GetInstanceData_instance_mechanar(Map* pMap) +{ + return new instance_mechanar(pMap); +} + +void AddSC_instance_mechanar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_mechanar"; + newscript->GetInstanceData = &GetInstanceData_instance_mechanar; + newscript->RegisterSelf(); +} + diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/mechanar.h b/src/server/scripts/Outland/TempestKeep/Mechanar/mechanar.h new file mode 100644 index 00000000000..d1b53eebf53 --- /dev/null +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/mechanar.h @@ -0,0 +1,6 @@ +#ifndef DEF_MECHANAR_H +#define DEF_MECHANAR_H + +#define DATA_NETHERMANCER_EVENT 1 +#endif + diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp deleted file mode 100644 index af5f1bd95c1..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_eye/boss_alar.cpp +++ /dev/null @@ -1,523 +0,0 @@ -/* Copyright(C) 2006 - 2008 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -*(at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: boss_alar -SD%Complete: 95 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define SPELL_FLAME_BUFFET 34121 // Flame Buffet - every 1,5 secs in phase 1 if there is no victim in melee range and after Dive Bomb in phase 2 with same conditions -#define SPELL_FLAME_QUILLS 34229 // Randomly after changing position in phase after watching tonns of movies, set probability 20% -#define SPELL_REBIRTH 34342 // Rebirth - beginning of second phase(after loose all health in phase 1) -#define SPELL_REBIRTH_2 35369 // Rebirth(another, without healing to full HP) - after Dive Bomb in phase 2 -#define SPELL_MELT_ARMOR 35410 // Melt Armor - every 60 sec in phase 2 -#define SPELL_CHARGE 35412 // Charge - 30 sec cooldown -#define SPELL_DIVE_BOMB_VISUAL 35367 // Bosskillers says 30 sec cooldown, wowwiki says 30 sec colldown, DBM and BigWigs addons says ~47 sec -#define SPELL_DIVE_BOMB 35181 // after watching tonns of movies, set cooldown to 40+rand()%5. -#define SPELL_BERSERK 45078 // 10 minutes after phase 2 starts(id is wrong, but proper id is unknown) - -#define CREATURE_EMBER_OF_ALAR 19551 // Al'ar summons one Ember of Al'ar every position change in phase 1 and two after Dive Bomb. Also in phase 2 when Ember of Al'ar dies, boss loose 3% health. -#define SPELL_EMBER_BLAST 34133 // When Ember of Al'ar dies, it casts Ember Blast - -#define CREATURE_FLAME_PATCH_ALAR 20602 // Flame Patch - every 30 sec in phase 2 -#define SPELL_FLAME_PATCH 35380 // - -static float waypoint[6][3] = -{ - {340.15, 58.65, 17.71}, - {388.09, 31.54, 20.18}, - {388.18, -32.85, 20.18}, - {340.29, -60.19, 17.72}, - {332, 0.01, 39}, // better not use the same xy coord - {331, 0.01, -2.39} -}; - -enum WaitEventType -{ - WE_NONE = 0, - WE_DUMMY = 1, - WE_PLATFORM = 2, - WE_QUILL = 3, - WE_DIE = 4, - WE_REVIVE = 5, - WE_CHARGE = 6, - WE_METEOR = 7, - WE_DIVE = 8, - WE_LAND = 9, - WE_SUMMON = 10 -}; - -struct boss_alarAI : public ScriptedAI -{ - boss_alarAI(Creature *c) : ScriptedAI(c) - { - pInstance =c->GetInstanceData(); - DefaultMoveSpeedRate = c->GetSpeedRate(MOVE_RUN); - } - - ScriptedInstance *pInstance; - - WaitEventType WaitEvent; - uint32 WaitTimer; - - bool AfterMoving; - - uint32 Platforms_Move_Timer; - uint32 DiveBomb_Timer; - uint32 MeltArmor_Timer; - uint32 Charge_Timer; - uint32 FlamePatch_Timer; - uint32 Berserk_Timer; - - float DefaultMoveSpeedRate; - - bool Phase1; - bool ForceMove; - uint32 ForceTimer; - - int8 cur_wp; - - void Reset() - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, NOT_STARTED); - - Berserk_Timer = 1200000; - Platforms_Move_Timer = 0; - - Phase1 = true; - WaitEvent = WE_NONE; - WaitTimer = 0; - AfterMoving = false; - ForceMove = false; - ForceTimer = 5000; - - cur_wp = 4; - - me->SetDisplayId(me->GetNativeDisplayId()); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); - //me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - //me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10); - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->setActive(false); - } - - void EnterCombat(Unit * /*who*/) - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, IN_PROGRESS); - - me->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); // after enterevademode will be set walk movement - DoZoneInCombat(); - me->setActive(true); - } - - void JustDied(Unit * /*victim*/) - { - if (pInstance) - pInstance->SetData(DATA_ALAREVENT, DONE); - } - - void JustSummoned(Creature *summon) - { - if (summon->GetEntry() == CREATURE_EMBER_OF_ALAR) - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - summon->AI()->AttackStart(pTarget); - } - - void MoveInLineOfSight(Unit * /*who*/) {} - - void AttackStart(Unit* who) - { - if (Phase1) - AttackStartNoMove(who); - else - ScriptedAI::AttackStart(who); - } - - void DamageTaken(Unit* /*pKiller*/, uint32 &damage) - { - if (damage >= me->GetHealth() && Phase1) - { - damage = 0; - if (!WaitEvent) - { - WaitEvent = WE_DIE; - WaitTimer = 0; - me->SetHealth(0); - me->InterruptNonMeleeSpells(true); - me->RemoveAllAuras(); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->AttackStop(); - me->SetUInt64Value(UNIT_FIELD_TARGET, 0); - me->SetSpeed(MOVE_RUN, 5.0f); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]); - } - } - } - - void SpellHit(Unit*, const SpellEntry *spell) - { - if (spell->Id == SPELL_DIVE_BOMB_VISUAL) - { - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - me->SetDisplayId(11686); - //me->SendUpdateObjectToAllExcept(NULL); - } - } - - void MovementInform(uint32 type, uint32 /*id*/) - { - if (type == POINT_MOTION_TYPE) - { - WaitTimer = 1; - AfterMoving = true; - ForceMove = false; - } - } - - void UpdateAI(const uint32 diff) - { - if (!me->isInCombat()) // sometimes isincombat but !incombat, faction bug? - return; - - if (Berserk_Timer <= diff) - { - DoCast(me, SPELL_BERSERK, true); - Berserk_Timer = 60000; - } else Berserk_Timer -= diff; - - if (ForceMove) - { - if (ForceTimer <= diff) - { - me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); - ForceTimer = 5000; - } else ForceTimer -= diff; - - } - if (WaitEvent) - { - if (WaitTimer) - { - if (WaitTimer <= diff) - { - if (AfterMoving) - { - me->GetMotionMaster()->MoveIdle(); - AfterMoving = false; - } - - switch(WaitEvent) - { - case WE_PLATFORM: - Platforms_Move_Timer = 30000+rand()%5000; - break; - case WE_QUILL: - DoCast(me, SPELL_FLAME_QUILLS, true); - Platforms_Move_Timer = 1; - WaitTimer = 10000; - WaitEvent = WE_DUMMY; - return; - case WE_DIE: - ForceMove = false; - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_DEAD); - WaitTimer = 5000; - WaitEvent = WE_REVIVE; - return; - case WE_REVIVE: - me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND); - me->SetHealth(me->GetMaxHealth()); - me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - DoZoneInCombat(); - DoCast(me, SPELL_REBIRTH, true); - MeltArmor_Timer = 60000; - Charge_Timer = 7000; - DiveBomb_Timer = 40000+rand()%5000; - FlamePatch_Timer = 30000; - Phase1 = false; - break; - case WE_METEOR: - me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, false); - DoCast(me, SPELL_DIVE_BOMB_VISUAL, false); - WaitEvent = WE_DIVE; - WaitTimer = 4000; - return; - case WE_DIVE: - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - me->RemoveAurasDueToSpell(SPELL_DIVE_BOMB_VISUAL); - DoCast(pTarget, SPELL_DIVE_BOMB, true); - float dist = 3.0f; - if (me->IsWithinDist3d(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 5.0f)) - dist = 5.0f; - WaitTimer = 1000 + floor(dist / 80 * 1000.0f); - me->GetMap()->CreatureRelocation(me, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f); - me->StopMoving(); - WaitEvent = WE_LAND; - } - else - { - EnterEvadeMode(); - return; - } - case WE_LAND: - WaitEvent = WE_SUMMON; - WaitTimer = 2000; - return; - case WE_SUMMON: - for (uint8 i = 0; i < 2; ++i) - DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetDisplayId(me->GetNativeDisplayId()); - DoCast(me, SPELL_REBIRTH_2, true); - break; - case WE_DUMMY: - default: - break; - } - - WaitEvent = WE_NONE; - WaitTimer = 0; - } else WaitTimer -= diff; - } - return; - } - - if (Phase1) - { - if (me->getThreatManager().getThreatList().empty()) - { - EnterEvadeMode(); - return; - } - - if (Platforms_Move_Timer <= diff) - { - if (cur_wp == 4) - { - cur_wp = 0; - WaitEvent = WE_PLATFORM; - } - else - { - if (urand(0,4)) // next platform - { - DoSpawnCreature(CREATURE_EMBER_OF_ALAR, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (cur_wp == 3) - cur_wp = 0; - else - ++cur_wp; - WaitEvent = WE_PLATFORM; - } - else // flame quill - { - cur_wp = 4; - WaitEvent = WE_QUILL; - } - } - ForceMove = true; - ForceTimer = 5000; - me->GetMotionMaster()->MovePoint(0, waypoint[cur_wp][0], waypoint[cur_wp][1], waypoint[cur_wp][2]); - WaitTimer = 0; - return; - } else Platforms_Move_Timer -= diff; - } - else - { - if (Charge_Timer <= diff) - { - Unit *pTarget= SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true); - if (pTarget) - DoCast(pTarget, SPELL_CHARGE); - Charge_Timer = 30000; - } else Charge_Timer -= diff; - - if (MeltArmor_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MELT_ARMOR); - MeltArmor_Timer = 60000; - } else MeltArmor_Timer -= diff; - - if (DiveBomb_Timer <= diff) - { - me->AttackStop(); - me->GetMotionMaster()->MovePoint(6, waypoint[4][0], waypoint[4][1], waypoint[4][2]); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 50); - WaitEvent = WE_METEOR; - WaitTimer = 0; - DiveBomb_Timer = 40000+rand()%5000; - return; - } else DiveBomb_Timer -= diff; - - if (FlamePatch_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - Creature* Summoned = me->SummonCreature(CREATURE_FLAME_PATCH_ALAR, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 120000); - if (Summoned) - { - Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Summoned->SetFloatValue(OBJECT_FIELD_SCALE_X, Summoned->GetFloatValue(OBJECT_FIELD_SCALE_X)*2.5f); - Summoned->SetDisplayId(11686); - Summoned->setFaction(me->getFaction()); - Summoned->SetLevel(me->getLevel()); - Summoned->CastSpell(Summoned, SPELL_FLAME_PATCH, false); - } - } - FlamePatch_Timer = 30000; - } else FlamePatch_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - - void DoMeleeAttackIfReady() - { - if (me->isAttackReady() && !me->IsNonMeleeSpellCasted(false)) - { - if (me->IsWithinMeleeRange(me->getVictim())) - { - me->AttackerStateUpdate(me->getVictim()); - me->resetAttackTimer(); - } - else - { - Unit *pTarget = NULL; - pTarget = me->SelectNearestTargetInAttackDistance(5); - if (pTarget) - me->AI()->AttackStart(pTarget); - else - { - DoCast(me, SPELL_FLAME_BUFFET, true); - me->setAttackTimer(BASE_ATTACK, 1500); - } - } - } - } -}; - -CreatureAI* GetAI_boss_alar(Creature* pCreature) -{ - return new boss_alarAI(pCreature); -} - -struct mob_ember_of_alarAI : public ScriptedAI -{ - mob_ember_of_alarAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - c->SetUnitMovementFlags(MOVEMENTFLAG_LEVITATING); - c->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true); - } - - ScriptedInstance *pInstance; - bool toDie; - - void Reset() {toDie = false;} - void EnterCombat(Unit * /*who*/) {DoZoneInCombat();} - void EnterEvadeMode() {me->setDeathState(JUST_DIED);} - - void DamageTaken(Unit* pKiller, uint32 &damage) - { - if (damage >= me->GetHealth() && pKiller != me && !toDie) - { - damage = 0; - DoCast(me, SPELL_EMBER_BLAST, true); - me->SetDisplayId(11686); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - if (pInstance && pInstance->GetData(DATA_ALAREVENT) == 2) - { - if (Unit* Alar = Unit::GetUnit((*me), pInstance->GetData64(DATA_ALAR))) - { - int AlarHealth = Alar->GetHealth() - Alar->GetMaxHealth()*0.03; - if (AlarHealth > 0) - Alar->SetHealth(AlarHealth); - else - Alar->SetHealth(1); - } - } - toDie = true; - } - } - - void UpdateAI(const uint32 /*diff*/) - { - if (!UpdateVictim()) - return; - - if (toDie) - { - me->DealDamage(me, me->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); - //me->SetVisibility(VISIBILITY_OFF); - } - - DoMeleeAttackIfReady(); - } - -}; - -CreatureAI* GetAI_mob_ember_of_alar(Creature* pCreature) -{ - return new mob_ember_of_alarAI(pCreature); -} - -struct mob_flame_patch_alarAI : public ScriptedAI -{ - mob_flame_patch_alarAI(Creature *c) : ScriptedAI(c) {} - void Reset() {} - void EnterCombat(Unit * /*who*/) {} - void AttackStart(Unit* /*who*/) {} - void MoveInLineOfSight(Unit* /*who*/) {} - void UpdateAI(const uint32 /*diff*/) {} -}; - -CreatureAI* GetAI_mob_flame_patch_alar(Creature* pCreature) -{ - return new mob_flame_patch_alarAI(pCreature); -} - -void AddSC_boss_alar() -{ - Script *newscript; - - newscript = new Script; - newscript->Name = "boss_alar"; - newscript->GetAI = &GetAI_boss_alar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ember_of_alar"; - newscript->GetAI = &GetAI_mob_ember_of_alar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_flame_patch_alar"; - newscript->GetAI = &GetAI_mob_flame_patch_alar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp deleted file mode 100644 index e9e217a5c62..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_eye/boss_astromancer.cpp +++ /dev/null @@ -1,466 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Astromancer -SD%Complete: 80 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -enum eEnums -{ - SAY_AGGRO = -1550007, - SAY_SUMMON1 = -1550008, - SAY_SUMMON2 = -1550009, - SAY_KILL1 = -1550010, - SAY_KILL2 = -1550011, - SAY_KILL3 = -1550012, - SAY_DEATH = -1550013, - SAY_VOIDA = -1550014, - SAY_VOIDB = -1550015, - - SPELL_ARCANE_MISSILES = 33031, - SPELL_WRATH_OF_THE_ASTROMANCER = 42783, - SPELL_BLINDING_LIGHT = 33009, - SPELL_FEAR = 34322, - SPELL_VOID_BOLT = 39329, - - SPELL_SPOTLIGHT = 25824, - NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT = 18928, - - NPC_SOLARIUM_AGENT = 18925, - NPC_SOLARIUM_PRIEST = 18806, - - MODEL_HUMAN = 18239, - MODEL_VOIDWALKER = 18988, - - SPELL_SOLARIUM_GREAT_HEAL = 33387, - SPELL_SOLARIUM_HOLY_SMITE = 25054, - SPELL_SOLARIUM_ARCANE_TORRENT = 33390, - - WV_ARMOR = 31000 -}; - -const float CENTER_X = 432.909f; -const float CENTER_Y = -373.424f; -const float CENTER_Z = 17.9608f; -const float CENTER_O = 1.06421f; -const float SMALL_PORTAL_RADIUS = 12.6f; -const float LARGE_PORTAL_RADIUS = 26.0f; -const float PORTAL_Z = 17.005f; - - // x, y, z, o -static float SolarianPos[4] = {432.909, -373.424, 17.9608, 1.06421}; - -struct boss_high_astromancer_solarianAI : public ScriptedAI -{ - boss_high_astromancer_solarianAI(Creature *c) : ScriptedAI(c), Summons(me) - { - pInstance = c->GetInstanceData(); - - defaultarmor = c->GetArmor(); - defaultsize = c->GetFloatValue(OBJECT_FIELD_SCALE_X); - } - - ScriptedInstance *pInstance; - SummonList Summons; - - uint8 Phase; - - uint32 ArcaneMissiles_Timer; - uint32 m_uiWrathOfTheAstromancer_Timer; - uint32 BlindingLight_Timer; - uint32 Fear_Timer; - uint32 VoidBolt_Timer; - uint32 Phase1_Timer; - uint32 Phase2_Timer; - uint32 Phase3_Timer; - uint32 AppearDelay_Timer; - uint32 defaultarmor; - uint32 Wrath_Timer; - - float defaultsize; - float Portals[3][3]; - - bool AppearDelay; - bool BlindingLight; - - void Reset() - { - ArcaneMissiles_Timer = 2000; - m_uiWrathOfTheAstromancer_Timer = 15000; - BlindingLight_Timer = 41000; - Fear_Timer = 20000; - VoidBolt_Timer = 10000; - Phase1_Timer = 50000; - Phase2_Timer = 10000; - Phase3_Timer = 15000; - AppearDelay_Timer = 2000; - BlindingLight = false; - AppearDelay = false; - Wrath_Timer = 20000+rand()%5000;//twice in phase one - Phase = 1; - Wrath_Timer = 20000+rand()%5000;//twice in phase one - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, NOT_STARTED); - - me->SetArmor(defaultarmor); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); - me->SetDisplayId(MODEL_HUMAN); - - Summons.DespawnAll(); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_KILL1,SAY_KILL2,SAY_KILL3), me); - } - - void JustDied(Unit * /*victim*/) - { - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize); - me->SetDisplayId(MODEL_HUMAN); - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_HIGHASTROMANCERSOLARIANEVENT, IN_PROGRESS); - } - - void SummonMinion(uint32 entry, float x, float y, float z) - { - Creature* Summoned = me->SummonCreature(entry, x, y, z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); - if (Summoned) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - Summoned->AI()->AttackStart(pTarget); - - Summons.Summon(Summoned); - } - } - - float Portal_X(float radius) - { - if (urand(0,1)) - radius = -radius; - - return radius * (float)(rand()%100)/100.0f + CENTER_X; - } - - float Portal_Y(float x, float radius) - { - float z = RAND(1, -1); - - return (z*sqrt(radius*radius - (x - CENTER_X)*(x - CENTER_X)) + CENTER_Y); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (AppearDelay) - { - me->StopMoving(); - me->AttackStop(); - if (AppearDelay_Timer <= diff) - { - AppearDelay = false; - if (Phase == 2) - { - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_OFF); - } - AppearDelay_Timer = 2000; - } else AppearDelay_Timer -= diff; - } - - if (Phase == 1) - { - if (BlindingLight_Timer <= diff) - { - BlindingLight = true; - BlindingLight_Timer = 45000; - } else BlindingLight_Timer -= diff; - - if (Wrath_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - if (Unit *pTarget = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER, true); - Wrath_Timer = 20000+rand()%5000; - } else Wrath_Timer -= diff; - - if (ArcaneMissiles_Timer <= diff) - { - if (BlindingLight) - { - DoCast(me->getVictim(), SPELL_BLINDING_LIGHT); - BlindingLight = false; - }else{ - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (!me->HasInArc(2.5f, pTarget)) - pTarget = me->getVictim(); - - if (pTarget) - DoCast(pTarget, SPELL_ARCANE_MISSILES); - } - ArcaneMissiles_Timer = 3000; - } else ArcaneMissiles_Timer -= diff; - - if (m_uiWrathOfTheAstromancer_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - - //Target the tank ? - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 1)) - if (pTarget->GetTypeId() == TYPEID_PLAYER) - { - DoCast(pTarget, SPELL_WRATH_OF_THE_ASTROMANCER); - m_uiWrathOfTheAstromancer_Timer = 25000; - } - else - m_uiWrathOfTheAstromancer_Timer = 1000; - } else m_uiWrathOfTheAstromancer_Timer -= diff; - - //Phase1_Timer - if (Phase1_Timer <= diff) - { - Phase = 2; - Phase1_Timer = 50000; - //After these 50 seconds she portals to the middle of the room and disappears, leaving 3 light portals behind. - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, CENTER_X, CENTER_Y, CENTER_Z, CENTER_O); - for (uint8 i=0; i <= 2; ++i) - { - if (!i) - { - Portals[i][0] = Portal_X(SMALL_PORTAL_RADIUS); - Portals[i][1] = Portal_Y(Portals[i][0], SMALL_PORTAL_RADIUS); - Portals[i][2] = CENTER_Z; - } - else - { - Portals[i][0] = Portal_X(LARGE_PORTAL_RADIUS); - Portals[i][1] = Portal_Y(Portals[i][0], LARGE_PORTAL_RADIUS); - Portals[i][2] = PORTAL_Z; - } - } - if ((abs(Portals[2][0] - Portals[1][0]) < 7) && (abs(Portals[2][1] - Portals[1][1]) < 7)) - { - int i=1; - if (abs(CENTER_X + 26.0f - Portals[2][0]) < 7) - i = -1; - Portals[2][0] = Portals[2][0]+7*i; - Portals[2][1] = Portal_Y(Portals[2][0], LARGE_PORTAL_RADIUS); - } - for (int i=0; i <= 2; ++i) - { - if (Creature* Summoned = me->SummonCreature(NPC_ASTROMANCER_SOLARIAN_SPOTLIGHT, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O, TEMPSUMMON_TIMED_DESPAWN, Phase2_Timer+Phase3_Timer+AppearDelay_Timer+1700)) - { - Summoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - Summoned->CastSpell(Summoned, SPELL_SPOTLIGHT, false); - } - } - AppearDelay = true; - } else Phase1_Timer-=diff; - } - else if (Phase == 2) - { - //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals. - me->AttackStop(); - me->StopMoving(); - if (Phase2_Timer <= diff) - { - Phase = 3; - for (int i=0; i <= 2; ++i) - for (int j=1; j <= 4; j++) - SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]); - - DoScriptText(SAY_SUMMON1, me); - Phase2_Timer = 10000; - } else Phase2_Timer -= diff; - } - else if (Phase == 3) - { - me->AttackStop(); - me->StopMoving(); - - //Check Phase3_Timer - if (Phase3_Timer <= diff) - { - Phase = 1; - - //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals. - int i = rand()%3; - me->GetMotionMaster()->Clear(); - me->GetMap()->CreatureRelocation(me, Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O); - - for (int j=0; j <= 2; j++) - if (j != i) - SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - - DoScriptText(SAY_SUMMON2, me); - AppearDelay = true; - Phase3_Timer = 15000; - } else Phase3_Timer -= diff; - } - else if (Phase == 4) - { - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me, SPELL_FEAR); - Fear_Timer = 20000; - } else Fear_Timer -= diff; - - //VoidBolt_Timer - if (VoidBolt_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_VOID_BOLT); - VoidBolt_Timer = 10000; - } else VoidBolt_Timer -= diff; - } - - //When Solarian reaches 20% she will transform into a huge void walker. - if (Phase != 4 && ((me->GetHealth()*100 / me->GetMaxHealth())<20)) - { - Phase = 4; - - //To make sure she wont be invisible or not selecatble - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetVisibility(VISIBILITY_ON); - DoScriptText(SAY_VOIDA, me); - DoScriptText(SAY_VOIDB, me); - me->SetArmor(WV_ARMOR); - me->SetDisplayId(MODEL_VOIDWALKER); - me->SetFloatValue(OBJECT_FIELD_SCALE_X, defaultsize*2.5f); - } - - DoMeleeAttackIfReady(); - } -}; - -struct mob_solarium_priestAI : public ScriptedAI -{ - mob_solarium_priestAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 healTimer; - uint32 holysmiteTimer; - uint32 aoesilenceTimer; - - void Reset() - { - healTimer = 9000; - holysmiteTimer = 1; - aoesilenceTimer = 15000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (healTimer <= diff) - { - Unit *pTarget = NULL; - - switch (urand(0,1)) - { - case 0: - if (pInstance) - pTarget = Unit::GetUnit((*me), pInstance->GetData64(DATA_ASTROMANCER)); - break; - case 1: - pTarget = me; - break; - } - - if (pTarget) - { - DoCast(pTarget, SPELL_SOLARIUM_GREAT_HEAL); - healTimer = 9000; - } - } else healTimer -= diff; - - if (holysmiteTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARIUM_HOLY_SMITE); - holysmiteTimer = 4000; - } else holysmiteTimer -= diff; - - if (aoesilenceTimer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARIUM_ARCANE_TORRENT); - aoesilenceTimer = 13000; - } else aoesilenceTimer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_solarium_priest(Creature* pCreature) -{ - return new mob_solarium_priestAI (pCreature); -} - -CreatureAI* GetAI_boss_high_astromancer_solarian(Creature* pCreature) -{ - return new boss_high_astromancer_solarianAI (pCreature); -} - -void AddSC_boss_high_astromancer_solarian() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_high_astromancer_solarian"; - newscript->GetAI = &GetAI_boss_high_astromancer_solarian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_solarium_priest"; - newscript->GetAI = &GetAI_mob_solarium_priest; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp deleted file mode 100644 index 05681fb7539..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_eye/boss_kaelthas.cpp +++ /dev/null @@ -1,1498 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Kaelthas -SD%Complete: 60 -SDComment: SQL, weapon scripts, mind control, need correct spells(interruptible/uninterruptible), phoenix spawn location & animation, phoenix behaviour & spawn during gravity lapse -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" -#include "WorldPacket.h" - -enum eEnums -{ - //kael'thas Speech - SAY_INTRO = -1550016, - SAY_INTRO_CAPERNIAN = -1550017, - SAY_INTRO_TELONICUS = -1550018, - SAY_INTRO_THALADRED = -1550019, - SAY_INTRO_SANGUINAR = -1550020, - SAY_PHASE2_WEAPON = -1550021, - SAY_PHASE3_ADVANCE = -1550022, - SAY_PHASE4_INTRO2 = -1550023, - SAY_PHASE5_NUTS = -1550024, - SAY_SLAY1 = -1550025, - SAY_SLAY2 = -1550026, - SAY_SLAY3 = -1550027, - SAY_MINDCONTROL1 = -1550028, - SAY_MINDCONTROL2 = -1550029, - SAY_GRAVITYLAPSE1 = -1550030, - SAY_GRAVITYLAPSE2 = -1550031, - SAY_SUMMON_PHOENIX1 = -1550032, - SAY_SUMMON_PHOENIX2 = -1550033, - SAY_DEATH = -1550034, - - //Thaladred the Darkener speech - SAY_THALADRED_AGGRO = -1550035, - SAY_THALADRED_DEATH = -1550036, - EMOTE_THALADRED_GAZE = -1550037, - - //Lord Sanguinar speech - SAY_SANGUINAR_AGGRO = -1550038, - SAY_SANGUINAR_DEATH = -1550039, - - //Grand Astromancer Capernian speech - SAY_CAPERNIAN_AGGRO = -1550040, - SAY_CAPERNIAN_DEATH = -1550041, - - //Master Engineer Telonicus speech - SAY_TELONICUS_AGGRO = -1550042, - SAY_TELONICUS_DEATH = -1550043, - - //Phase 2 spells - SPELL_SUMMON_WEAPONS = 36976, - SPELL_SUMMON_WEAPONA = 36958, - SPELL_SUMMON_WEAPONB = 36959, - SPELL_SUMMON_WEAPONC = 36960, - SPELL_SUMMON_WEAPOND = 36961, - SPELL_SUMMON_WEAPONE = 36962, - SPELL_SUMMON_WEAPONF = 36963, - SPELL_SUMMON_WEAPONG = 36964, - SPELL_RES_VISUAL = 24171, - - //Phase 4 spells - SPELL_FIREBALL = 22088, //wrong but works with CastCustomSpell - SPELL_PYROBLAST = 36819, - SPELL_FLAME_STRIKE = 36735, - SPELL_FLAME_STRIKE_VIS = 36730, - SPELL_FLAME_STRIKE_DMG = 36731, - SPELL_ARCANE_DISRUPTION = 36834, - SPELL_SHOCK_BARRIER = 36815, - SPELL_PHOENIX_ANIMATION = 36723, - SPELL_MIND_CONTROL = 32830, - - //Phase 5 spells - SPELL_EXPLODE = 36092, - SPELL_FULLPOWER = 36187, - SPELL_KNOCKBACK = 11027, - SPELL_GRAVITY_LAPSE = 34480, - SPELL_GRAVITY_LAPSE_AURA = 39432, - SPELL_NETHER_BEAM = 35873, - - //Thaladred the Darkener spells - SPELL_PSYCHIC_BLOW = 10689, - SPELL_SILENCE = 30225, - //Lord Sanguinar spells - SPELL_BELLOWING_ROAR = 40636, - //Grand Astromancer Capernian spells - - SPELL_CAPERNIAN_FIREBALL = 36971, - SPELL_CONFLAGRATION = 37018, - SPELL_ARCANE_EXPLOSION = 36970, - //Master Engineer Telonicus spells - SPELL_BOMB = 37036, - SPELL_REMOTE_TOY = 37027, - //Nether Vapor spell - SPELL_NETHER_VAPOR = 35859, - //Phoenix spell - SPELL_BURN = 36720, - SPELL_EMBER_BLAST = 34341, - SPELL_REBIRTH = 41587, - - //Creature IDs - NPC_PHOENIX = 21362, - NPC_PHOENIX_EGG = 21364, - - //Phoenix egg and phoenix model - MODEL_ID_PHOENIX = 19682, - MODEL_ID_PHOENIX_EGG = 20245, - - MAX_ADVISORS = 4 -}; - -uint32 m_auiSpellSummonWeapon[]= -{ - SPELL_SUMMON_WEAPONA, SPELL_SUMMON_WEAPONB, SPELL_SUMMON_WEAPONC, SPELL_SUMMON_WEAPOND, - SPELL_SUMMON_WEAPONE, SPELL_SUMMON_WEAPONF, SPELL_SUMMON_WEAPONG -}; - -const float CAPERNIAN_DISTANCE = 20.0f; //she casts away from the target -const float KAEL_VISIBLE_RANGE = 50.0f; - -const float afGravityPos[3] = {795.0f, 0.0f, 70.0f}; - -#define TIME_PHASE_2_3 120000 -#define TIME_PHASE_3_4 180000 - -//Base AI for Advisors -struct advisorbase_ai : public ScriptedAI -{ - advisorbase_ai(Creature* pCreature) : ScriptedAI(pCreature) - { - m_pInstance = pCreature->GetInstanceData(); - m_bDoubled_Health = false; - } - - ScriptedInstance* m_pInstance; - bool FakeDeath; - bool m_bDoubled_Health; - uint32 DelayRes_Timer; - uint64 DelayRes_Target; - - void Reset() - { - if (m_bDoubled_Health) - { - me->SetMaxHealth(me->GetMaxHealth() / 2); - m_bDoubled_Health = false; - } - - FakeDeath = false; - DelayRes_Timer = 0; - DelayRes_Target = 0; - - me->SetStandState(UNIT_STAND_STATE_STAND); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - - //reset encounter - if (m_pInstance && (m_pInstance->GetData(DATA_KAELTHASEVENT) == 1 || m_pInstance->GetData(DATA_KAELTHASEVENT) == 3)) - if (Creature *Kaelthas = Unit::GetCreature((*me), m_pInstance->GetData64(DATA_KAELTHAS))) - Kaelthas->AI()->EnterEvadeMode(); - } - - void MoveInLineOfSight(Unit *who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::MoveInLineOfSight(who); - } - - void AttackStart(Unit* who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - ScriptedAI::AttackStart(who); - } - - void Revive(Unit* /*Target*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - // double health for phase 3 - me->SetMaxHealth(me->GetMaxHealth() * 2); - m_bDoubled_Health = true; - me->SetHealth(me->GetMaxHealth()); - me->SetStandState(UNIT_STAND_STATE_STAND); - - DoCast(me, SPELL_RES_VISUAL, false); - DelayRes_Timer = 2000; - } - - void DamageTaken(Unit* pKiller, uint32 &damage) - { - if (damage < me->GetHealth()) - return; - - //Prevent glitch if in fake death - if (FakeDeath && m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) - { - damage = 0; - return; - } - - //Don't really die in phase 1 & 3, only die after that - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) != 0) - { - //prevent death - damage = 0; - FakeDeath = true; - - me->InterruptNonMeleeSpells(false); - me->SetHealth(0); - me->StopMoving(); - me->ClearComboPointHolders(); - me->RemoveAllAurasOnDeath(); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); - me->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->ClearAllReactives(); - me->SetUInt64Value(UNIT_FIELD_TARGET,0); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->SetStandState(UNIT_STAND_STATE_DEAD); - JustDied(pKiller); - } - } - - void UpdateAI(const uint32 diff) - { - if (DelayRes_Timer) - { - if (DelayRes_Timer <= diff) - { - DelayRes_Timer = 0; - FakeDeath = false; - - Unit* Target = Unit::GetUnit((*me), DelayRes_Target); - if (!Target) - Target = me->getVictim(); - - DoResetThreat(); - AttackStart(Target); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveChase(Target); - me->AddThreat(Target, 0.0f); - } else DelayRes_Timer -= diff; - } - } - -}; - -//Kael'thas AI -struct boss_kaelthasAI : public ScriptedAI -{ - boss_kaelthasAI(Creature* pCreature) : ScriptedAI(pCreature), summons(me) - { - m_pInstance = pCreature->GetInstanceData(); - memset(&m_auiAdvisorGuid, 0, sizeof(m_auiAdvisorGuid)); - } - - ScriptedInstance* m_pInstance; - - uint32 Fireball_Timer; - uint32 ArcaneDisruption_Timer; - uint32 Phoenix_Timer; - uint32 ShockBarrier_Timer; - uint32 GravityLapse_Timer; - uint32 GravityLapse_Phase; - uint32 NetherBeam_Timer; - uint32 NetherVapor_Timer; - uint32 FlameStrike_Timer; - uint32 MindControl_Timer; - uint32 Phase; - uint32 PhaseSubphase; //generic - uint32 Phase_Timer; //generic timer - uint32 PyrosCasted; - - bool InGravityLapse; - bool IsCastingFireball; - bool ChainPyros; - - SummonList summons; - - uint64 m_auiAdvisorGuid[MAX_ADVISORS]; - - void Reset() - { - Fireball_Timer = 5000+rand()%10000; - ArcaneDisruption_Timer = 45000; - MindControl_Timer = 40000; - Phoenix_Timer = 50000; - ShockBarrier_Timer = 60000; - FlameStrike_Timer = 30000; - GravityLapse_Timer = 20000; - GravityLapse_Phase = 0; - NetherBeam_Timer = 8000; - NetherVapor_Timer = 10000; - PyrosCasted = 0; - Phase = 0; - InGravityLapse = false; - IsCastingFireball = false; - ChainPyros = false; - - if (me->isInCombat()) - PrepareAdvisors(); - - summons.DespawnAll(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 0); - } - - void PrepareAdvisors() - { - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Creature *pCreature = Unit::GetCreature((*me), m_auiAdvisorGuid[i])) - { - pCreature->Respawn(); - pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - pCreature->setFaction(me->getFaction()); - pCreature->AI()->EnterEvadeMode(); - } - } - } - - void StartEvent() - { - if (!m_pInstance) - return; - - m_auiAdvisorGuid[0] = m_pInstance->GetData64(DATA_THALADREDTHEDARKENER); - m_auiAdvisorGuid[1] = m_pInstance->GetData64(DATA_LORDSANGUINAR); - m_auiAdvisorGuid[2] = m_pInstance->GetData64(DATA_GRANDASTROMANCERCAPERNIAN); - m_auiAdvisorGuid[3] = m_pInstance->GetData64(DATA_MASTERENGINEERTELONICUS); - - if (!m_auiAdvisorGuid[0] || !m_auiAdvisorGuid[1] || !m_auiAdvisorGuid[2] || !m_auiAdvisorGuid[3]) - { - error_log("TSCR: Kael'Thas One or more advisors missing, Skipping Phases 1-3"); - - DoScriptText(SAY_PHASE4_INTRO2, me); - - Phase = 4; - - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - AttackStart(pTarget); - - } - else - { - PrepareAdvisors(); - - DoScriptText(SAY_INTRO, me); - - m_pInstance->SetData(DATA_KAELTHASEVENT, 1); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - PhaseSubphase = 0; - Phase_Timer = 23000; - Phase = 1; - } - } - - void MoveInLineOfSight(Unit *who) - { - if (!me->hasUnitState(UNIT_STAT_STUNNED) && who->isTargetableForAttack() && - me->IsHostileTo(who) && who->isInAccessiblePlaceFor(me)) - { - if (!me->canFly() && me->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE) - return; - - float attackRadius = me->GetAttackDistance(who); - if (me->IsWithinDistInMap(who, attackRadius) && me->IsWithinLOSInMap(who)) - { - if (!me->getVictim() && Phase >= 4) - { - who->RemoveAurasDueToSpell(SPELL_AURA_MOD_STEALTH); - AttackStart(who); - } - else if (me->GetMap()->IsDungeon()) - { - if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); - - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } - } - } - } - - void Aggro(Unit * /*who*/) - { - if (m_pInstance && !m_pInstance->GetData(DATA_KAELTHASEVENT) && !Phase) - StartEvent(); - } - - void KilledUnit() - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustSummoned(Creature* pSummoned) - { - // if not phoenix, then it's one of the 7 weapons - if (pSummoned->GetEntry() != NPC_PHOENIX) - { - if (Unit* pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - pSummoned->AI()->AttackStart(pTarget); - - summons.Summon(pSummoned); - } - } - - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - - void JustDied(Unit* /*Killer*/) - { - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - DoScriptText(SAY_DEATH, me); - - summons.DespawnAll(); - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 0); - - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - if (Unit* pAdvisor = Unit::GetUnit((*me), m_auiAdvisorGuid[i])) - pAdvisor->Kill(pAdvisor); - } - } - - void UpdateAI(const uint32 diff) - { - //Phase 1 - switch (Phase) - { - case 1: - { - Unit *pTarget = NULL; - Creature* Advisor = NULL; - - //Subphase switch - switch(PhaseSubphase) - { - //Subphase 1 - Start - case 0: - if (Phase_Timer <= diff) - { - DoScriptText(SAY_INTRO_THALADRED, me); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 1 - Unlock advisor - case 1: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 2 - Start - case 2: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[0])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_SANGUINAR, me); - - //start advisor within 12.5 seconds - Phase_Timer = 12500; - ++PhaseSubphase; - } - break; - - //Subphase 2 - Unlock advisor - case 3: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 3 - Start - case 4: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[1])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_CAPERNIAN, me); - - //start advisor within 7 seconds - Phase_Timer = 7000; - ++PhaseSubphase; - } - break; - - //Subphase 3 - Unlock advisor - case 5: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //Subphase 4 - Start - case 6: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[2])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - DoScriptText(SAY_INTRO_TELONICUS, me); - - //start advisor within 8.4 seconds - Phase_Timer = 8400; - ++PhaseSubphase; - } - break; - - //Subphase 4 - Unlock advisor - case 7: - if (Phase_Timer <= diff) - { - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); - - if (Advisor) - { - Advisor->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Advisor->setFaction(me->getFaction()); - - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - if (pTarget) - Advisor->AI()->AttackStart(pTarget); - } - - Phase_Timer = 3000; - ++PhaseSubphase; - } else Phase_Timer -= diff; - break; - - //End of phase 1 - case 8: - Advisor = (Unit::GetCreature((*me), m_auiAdvisorGuid[3])); - - if (Advisor && (Advisor->getStandState() == UNIT_STAND_STATE_DEAD)) - { - Phase = 2; - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 2); - - DoScriptText(SAY_PHASE2_WEAPON, me); - - PhaseSubphase = 0; - Phase_Timer = 3500; - DoCast(me, SPELL_SUMMON_WEAPONS); - } - break; - } - } - break; - - case 2: - { - if (PhaseSubphase == 0) - { - if (Phase_Timer <= diff) - { - PhaseSubphase = 1; - } else Phase_Timer -= diff; - } - - //Spawn weapons - if (PhaseSubphase == 1) - { - DoCast(me, SPELL_SUMMON_WEAPONS, false); - - uint8 uiMaxWeapon = sizeof(m_auiSpellSummonWeapon)/sizeof(uint32); - - for (uint32 i = 0; i < uiMaxWeapon; ++i) - DoCast(me, m_auiSpellSummonWeapon[i], true); - - PhaseSubphase = 2; - Phase_Timer = TIME_PHASE_2_3; - } - - if (PhaseSubphase == 2) - { - if (Phase_Timer <= diff) - { - DoScriptText(SAY_PHASE3_ADVANCE, me); - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 3); - Phase = 3; - PhaseSubphase = 0; - } else Phase_Timer -= diff; - } - } - break; - - case 3: - { - if (PhaseSubphase == 0) - { - //Respawn advisors - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - Creature *Advisor; - for (uint8 i = 0; i < MAX_ADVISORS; ++i) - { - Advisor = Unit::GetCreature((*me), m_auiAdvisorGuid[i]); - - if (!Advisor) - error_log("SD2: Kael'Thas Advisor %u does not exist. Possibly despawned? Incorrectly Killed?", i); - else - CAST_AI(advisorbase_ai, Advisor->AI())->Revive(pTarget); - } - - PhaseSubphase = 1; - Phase_Timer = TIME_PHASE_3_4; - } - - if (Phase_Timer <= diff) - { - DoScriptText(SAY_PHASE4_INTRO2, me); - Phase = 4; - - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - - // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. - DoResetThreat(); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - AttackStart(pTarget); - - Phase_Timer = 30000; - } else Phase_Timer -= diff; - } - break; - - case 4: - case 5: - case 6: - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fireball_Timer - if (!InGravityLapse && !ChainPyros && Phase != 5) - { - if (Fireball_Timer <= diff) - { - if (!IsCastingFireball) - { - if (!me->IsNonMeleeSpellCasted(false)) - { - //interruptable - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, false); - int32 dmg = 20000+rand()%5000; - me->CastCustomSpell(me->getVictim(), SPELL_FIREBALL, &dmg, 0, 0, false); - IsCastingFireball = true; - Fireball_Timer = 2500; - } - } - else - { - //apply resistance - me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true); - IsCastingFireball = false; - Fireball_Timer = 5000+rand()%10000; - } - } else Fireball_Timer -= diff; - - //ArcaneDisruption_Timer - if (ArcaneDisruption_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_DISRUPTION, true); - ArcaneDisruption_Timer = 60000; - } else ArcaneDisruption_Timer -= diff; - - if (FlameStrike_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_FLAME_STRIKE); - - FlameStrike_Timer = 30000; - } else FlameStrike_Timer -= diff; - - if (MindControl_Timer <= diff) - { - if (me->getThreatManager().getThreatList().size() >= 2) - for (uint32 i = 0; i < 3; ++i) - { - debug_log("SD2: Kael'Thas mind control not supported."); - //DoCast(pUnit, SPELL_MIND_CONTROL); - } - - MindControl_Timer = 60000; - } else MindControl_Timer -= diff; - } - - //Phoenix_Timer - if (Phoenix_Timer <= diff) - { - DoCast(me, SPELL_PHOENIX_ANIMATION); - DoScriptText(RAND(SAY_SUMMON_PHOENIX1,SAY_SUMMON_PHOENIX2), me); - - Phoenix_Timer = 60000; - } else Phoenix_Timer -= diff; - - //Phase 4 specific spells - if (Phase == 4) - { - if (me->GetHealth()*100 / me->GetMaxHealth() < 50) - { - if (m_pInstance) - m_pInstance->SetData(DATA_KAELTHASEVENT, 4); - Phase = 5; - Phase_Timer = 10000; - - DoScriptText(SAY_PHASE5_NUTS, me); - - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, 0, 0); - - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_FULLPOWER); - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - } - - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ChainPyros = true; - PyrosCasted = 0; - ShockBarrier_Timer = 60000; - } else ShockBarrier_Timer -= diff; - - //Chain Pyros (3 of them max) - if (ChainPyros && !me->IsNonMeleeSpellCasted(false)) - { - if (PyrosCasted < 3) - { - DoCast(me->getVictim(), SPELL_PYROBLAST); - ++PyrosCasted; - } - else - { - ChainPyros = false; - Fireball_Timer = 2500; - ArcaneDisruption_Timer = 60000; - } - } - } - - if (Phase == 5) - { - if (Phase_Timer <= diff) - { - me->InterruptNonMeleeSpells(false); - me->RemoveAurasDueToSpell(SPELL_FULLPOWER); - - DoCast(me, SPELL_EXPLODE); - - me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - Phase = 6; - AttackStart(me->getVictim()); - } else Phase_Timer -= diff; - } - - //Phase 5 - if (Phase == 6) - { - - //GravityLapse_Timer - if (GravityLapse_Timer <= diff) - { - std::list::const_iterator i = me->getThreatManager().getThreatList().begin(); - switch (GravityLapse_Phase) - { - case 0: - me->StopMoving(); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveIdle(); - me->GetMap()->CreatureRelocation(me, afGravityPos[0], afGravityPos[1], afGravityPos[2], 0); - me->SendMonsterMove(afGravityPos[0], afGravityPos[1], afGravityPos[2], 0, MOVEMENTFLAG_NONE, 0); - - // 1) Kael'thas will portal the whole raid right into his body - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - if (pUnit && (pUnit->GetTypeId() == TYPEID_PLAYER)) - { - //Use work around packet to prevent player from being dropped from combat - DoTeleportPlayer(pUnit, afGravityPos[0], afGravityPos[1], afGravityPos[2], pUnit->GetOrientation()); - } - } - - GravityLapse_Timer = 500; - ++GravityLapse_Phase; - InGravityLapse = true; - ShockBarrier_Timer = 1000; - NetherBeam_Timer = 5000; - break; - - case 1: - DoScriptText(RAND(SAY_GRAVITYLAPSE1,SAY_GRAVITYLAPSE2), me); - - // 2) At that point he will put a Gravity Lapse debuff on everyone - for (i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) - { - if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) - { - DoCast(pUnit, SPELL_KNOCKBACK, true); - //Gravity lapse - needs an exception in Spell system to work - - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE, true, 0, 0, me->GetGUID()); - pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_AURA, true, 0, 0, me->GetGUID()); - - //Using packet workaround - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_SET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - GravityLapse_Timer = 10000; - ++GravityLapse_Phase; - break; - - case 2: - //Cast nether vapor aura on self - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_NETHER_VAPOR); - - GravityLapse_Timer = 20000; - ++GravityLapse_Phase; - break; - - case 3: - //Remove flight - for (i = me->getThreatManager().getThreatList().begin(); i!= me->getThreatManager().getThreatList().end(); ++i) - { - if (Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid())) - { - //Using packet workaround - WorldPacket data(12); - data.SetOpcode(SMSG_MOVE_UNSET_CAN_FLY); - data.append(pUnit->GetPackGUID()); - data << uint32(0); - pUnit->SendMessageToSet(&data, true); - } - } - - me->RemoveAurasDueToSpell(SPELL_NETHER_VAPOR); - InGravityLapse = false; - GravityLapse_Timer = 60000; - GravityLapse_Phase = 0; - AttackStart(me->getVictim()); - break; - } - } else GravityLapse_Timer -= diff; - - if (InGravityLapse) - { - //ShockBarrier_Timer - if (ShockBarrier_Timer <= diff) - { - DoCast(me, SPELL_SHOCK_BARRIER); - ShockBarrier_Timer = 20000; - } else ShockBarrier_Timer -= diff; - - //NetherBeam_Timer - if (NetherBeam_Timer <= diff) - { - if (Unit* pUnit = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pUnit, SPELL_NETHER_BEAM); - - NetherBeam_Timer = 4000; - } else NetherBeam_Timer -= diff; - } - } - - if (!InGravityLapse) - DoMeleeAttackIfReady(); - } - } - } -}; - -//Thaladred the Darkener AI -struct boss_thaladred_the_darkenerAI : public advisorbase_ai -{ - boss_thaladred_the_darkenerAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Gaze_Timer; - uint32 Silence_Timer; - uint32 PsychicBlow_Timer; - - void Reset() - { - Gaze_Timer = 100; - Silence_Timer = 20000; - PsychicBlow_Timer = 10000; - - advisorbase_ai::Reset(); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_THALADRED_AGGRO, me); - me->AddThreat(who, 5000000.0f); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_THALADRED_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Gaze_Timer - if (Gaze_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - { - DoResetThreat(); - me->AddThreat(pTarget, 5000000.0f); - DoScriptText(EMOTE_THALADRED_GAZE, me, pTarget); - Gaze_Timer = 8500; - } - } else Gaze_Timer -= diff; - - //Silence_Timer - if (Silence_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SILENCE); - Silence_Timer = 20000; - } else Silence_Timer -= diff; - - //PsychicBlow_Timer - if (PsychicBlow_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_PSYCHIC_BLOW); - PsychicBlow_Timer = 20000+rand()%5000; - } else PsychicBlow_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Lord Sanguinar AI -struct boss_lord_sanguinarAI : public advisorbase_ai -{ - boss_lord_sanguinarAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Fear_Timer; - - void Reset() - { - Fear_Timer = 20000; - advisorbase_ai::Reset(); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_SANGUINAR_AGGRO, me); - } - - void JustDied(Unit* /*Killer*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_SANGUINAR_DEATH, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Fear_Timer - if (Fear_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BELLOWING_ROAR); - Fear_Timer = 25000+rand()%10000; //approximately every 30 seconds - } else Fear_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Grand Astromancer Capernian AI -struct boss_grand_astromancer_capernianAI : public advisorbase_ai -{ - boss_grand_astromancer_capernianAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Fireball_Timer; - uint32 Conflagration_Timer; - uint32 ArcaneExplosion_Timer; - uint32 Yell_Timer; - bool Yell; - - void Reset() - { - Fireball_Timer = 2000; - Conflagration_Timer = 20000; - ArcaneExplosion_Timer = 5000; - Yell_Timer = 2000; - Yell = false; - - advisorbase_ai::Reset(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_CAPERNIAN_DEATH, me); - } - - void AttackStart(Unit* who) - { - if (!who || FakeDeath || me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (me->Attack(who, true)) - { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); - - me->GetMotionMaster()->MoveChase(who, CAPERNIAN_DISTANCE); - } - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking Death, don't do anything - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Yell_Timer - if (!Yell) - { - if (Yell_Timer <= diff) - { - DoScriptText(SAY_CAPERNIAN_AGGRO, me); - Yell = true; - } else Yell_Timer -= diff; - } - - //Fireball_Timer - if (Fireball_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_CAPERNIAN_FIREBALL); - Fireball_Timer = 4000; - } else Fireball_Timer -= diff; - - //Conflagration_Timer - if (Conflagration_Timer <= diff) - { - Unit *pTarget = NULL; - pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0); - - if (pTarget && me->IsWithinDistInMap(pTarget, 30)) - DoCast(pTarget, SPELL_CONFLAGRATION); - else - DoCast(me->getVictim(), SPELL_CONFLAGRATION); - - Conflagration_Timer = 10000+rand()%5000; - } else Conflagration_Timer -= diff; - - //ArcaneExplosion_Timer - if (ArcaneExplosion_Timer <= diff) - { - bool InMeleeRange = false; - Unit *pTarget = NULL; - std::list& m_threatlist = me->getThreatManager().getThreatList(); - for (std::list::const_iterator i = m_threatlist.begin(); i!= m_threatlist.end(); ++i) - { - Unit* pUnit = Unit::GetUnit((*me), (*i)->getUnitGuid()); - //if in melee range - if (pUnit && pUnit->IsWithinDistInMap(me, 5)) - { - InMeleeRange = true; - pTarget = pUnit; - break; - } - } - - if (InMeleeRange) - DoCast(pTarget, SPELL_ARCANE_EXPLOSION); - - ArcaneExplosion_Timer = 4000+rand()%2000; - } else ArcaneExplosion_Timer -= diff; - - //Do NOT deal any melee damage. - } -}; - -//Master Engineer Telonicus AI -struct boss_master_engineer_telonicusAI : public advisorbase_ai -{ - boss_master_engineer_telonicusAI(Creature* pCreature) : advisorbase_ai(pCreature) {} - - uint32 Bomb_Timer; - uint32 RemoteToy_Timer; - - void Reset() - { - Bomb_Timer = 10000; - RemoteToy_Timer = 5000; - - advisorbase_ai::Reset(); - } - - void JustDied(Unit* /*pKiller*/) - { - if (m_pInstance && m_pInstance->GetData(DATA_KAELTHASEVENT) == 3) - DoScriptText(SAY_TELONICUS_DEATH, me); - } - - void Aggro(Unit *who) - { - if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - return; - - if (!who || FakeDeath) - return; - - DoScriptText(SAY_TELONICUS_AGGRO, me); - } - - void UpdateAI(const uint32 diff) - { - advisorbase_ai::UpdateAI(diff); - - //Faking Death, do nothing - if (FakeDeath) - return; - - //Return since we have no target - if (!UpdateVictim()) - return; - - //Bomb_Timer - if (Bomb_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_BOMB); - Bomb_Timer = 25000; - } else Bomb_Timer -= diff; - - //RemoteToy_Timer - if (RemoteToy_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM, 0)) - DoCast(pTarget, SPELL_REMOTE_TOY); - - RemoteToy_Timer = 10000+rand()%5000; - } else RemoteToy_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Flame Strike AI -struct mob_kael_flamestrikeAI : public Scripted_NoMovementAI -{ - mob_kael_flamestrikeAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature) {} - - uint32 Timer; - bool Casting; - bool KillSelf; - - void Reset() - { - Timer = 5000; - Casting = false; - KillSelf = false; - - me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - me->setFaction(14); - } - - void MoveInLineOfSight(Unit * /*who*/) {} - - void EnterCombat(Unit * /*who*/) {} - - void UpdateAI(const uint32 diff) - { - if (!Casting) - { - DoCast(me, SPELL_FLAME_STRIKE_VIS); - Casting = true; - } - - //Timer - if (Timer <= diff) - { - if (!KillSelf) - { - me->InterruptNonMeleeSpells(false); - DoCast(me, SPELL_FLAME_STRIKE_DMG); - } else me->Kill(me); - - KillSelf = true; - Timer = 1000; - } else Timer -= diff; - } -}; - -//Phoenix AI -struct mob_phoenix_tkAI : public ScriptedAI -{ - mob_phoenix_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 Cycle_Timer; - - void Reset() - { - Cycle_Timer = 2000; - DoCast(me, SPELL_BURN, true); - } - - void JustDied(Unit* /*killer*/) - { - //is this spell in use anylonger? - //DoCast(me, SPELL_EMBER_BLAST, true); - me->SummonCreature(NPC_PHOENIX_EGG,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,16000); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (Cycle_Timer <= diff) - { - //spell Burn should possible do this, but it doesn't, so do this for now. - uint32 dmg = urand(4500,5500); - if (me->GetHealth() > dmg) - me->SetHealth(uint32(me->GetHealth()-dmg)); - Cycle_Timer = 2000; - } else Cycle_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -//Phoenix Egg AI -struct mob_phoenix_egg_tkAI : public ScriptedAI -{ - mob_phoenix_egg_tkAI(Creature* pCreature) : ScriptedAI(pCreature) {} - - uint32 Rebirth_Timer; - - void Reset() - { - Rebirth_Timer = 15000; - } - - //ignore any - void MoveInLineOfSight(Unit* /*who*/) {} - - void AttackStart(Unit* who) - { - if (me->Attack(who, false)) - { - me->SetInCombatWith(who); - who->SetInCombatWith(me); - - DoStartNoMovement(who); - } - } - - void JustSummoned(Creature* summoned) - { - summoned->AddThreat(me->getVictim(), 0.0f); - summoned->CastSpell(summoned,SPELL_REBIRTH,false); - } - - void UpdateAI(const uint32 diff) - { - if (!Rebirth_Timer) - return; - - if (Rebirth_Timer <= diff) - { - me->SummonCreature(NPC_PHOENIX,me->GetPositionX(),me->GetPositionY(),me->GetPositionZ(),me->GetOrientation(),TEMPSUMMON_CORPSE_DESPAWN,5000); - Rebirth_Timer = 0; - } else Rebirth_Timer -= diff; - } -}; - -CreatureAI* GetAI_boss_kaelthas(Creature* pCreature) -{ - return new boss_kaelthasAI(pCreature); -} - -CreatureAI* GetAI_boss_thaladred_the_darkener(Creature* pCreature) -{ - return new boss_thaladred_the_darkenerAI(pCreature); -} - -CreatureAI* GetAI_boss_lord_sanguinar(Creature* pCreature) -{ - return new boss_lord_sanguinarAI(pCreature); -} - -CreatureAI* GetAI_boss_grand_astromancer_capernian(Creature* pCreature) -{ - return new boss_grand_astromancer_capernianAI(pCreature); -} - -CreatureAI* GetAI_boss_master_engineer_telonicus(Creature* pCreature) -{ - return new boss_master_engineer_telonicusAI(pCreature); -} - -CreatureAI* GetAI_mob_kael_flamestrike(Creature* pCreature) -{ - return new mob_kael_flamestrikeAI(pCreature); -} - -CreatureAI* GetAI_mob_phoenix_tk(Creature* pCreature) -{ - return new mob_phoenix_tkAI(pCreature); -} - -CreatureAI* GetAI_mob_phoenix_egg_tk(Creature* pCreature) -{ - return new mob_phoenix_egg_tkAI(pCreature); -} - -void AddSC_boss_kaelthas() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_kaelthas"; - newscript->GetAI = &GetAI_boss_kaelthas; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_thaladred_the_darkener"; - newscript->GetAI = &GetAI_boss_thaladred_the_darkener; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_lord_sanguinar"; - newscript->GetAI = &GetAI_boss_lord_sanguinar; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_grand_astromancer_capernian"; - newscript->GetAI = &GetAI_boss_grand_astromancer_capernian; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "boss_master_engineer_telonicus"; - newscript->GetAI = &GetAI_boss_master_engineer_telonicus; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_kael_flamestrike"; - newscript->GetAI = &GetAI_mob_kael_flamestrike; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phoenix_tk"; - newscript->GetAI = &GetAI_mob_phoenix_tk; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_phoenix_egg_tk"; - newscript->GetAI = &GetAI_mob_phoenix_egg_tk; - newscript->RegisterSelf(); -} diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp deleted file mode 100644 index e1b60b20948..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_eye/boss_void_reaver.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Void_Reaver -SD%Complete: 90 -SDComment: Should reset if raid are out of room. -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -enum eEnums -{ - SAY_AGGRO = -1550000, - SAY_SLAY1 = -1550001, - SAY_SLAY2 = -1550002, - SAY_SLAY3 = -1550003, - SAY_DEATH = -1550004, - SAY_POUNDING1 = -1550005, - SAY_POUNDING2 = -1550006, - - SPELL_POUNDING = 34162, - SPELL_ARCANE_ORB = 34172, - SPELL_KNOCK_AWAY = 25778, - SPELL_BERSERK = 27680 -}; - -struct boss_void_reaverAI : public ScriptedAI -{ - boss_void_reaverAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance* pInstance; - - uint32 Pounding_Timer; - uint32 ArcaneOrb_Timer; - uint32 KnockAway_Timer; - uint32 Berserk_Timer; - - bool Enraged; - - void Reset() - { - Pounding_Timer = 15000; - ArcaneOrb_Timer = 3000; - KnockAway_Timer = 30000; - Berserk_Timer = 600000; - - Enraged = false; - - if (pInstance && me->isAlive()) - pInstance->SetData(DATA_VOIDREAVEREVENT, NOT_STARTED); - } - - void KilledUnit(Unit * /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2,SAY_SLAY3), me); - } - - void JustDied(Unit * /*victim*/) - { - DoScriptText(SAY_DEATH, me); - DoZoneInCombat(); - - if (pInstance) - pInstance->SetData(DATA_VOIDREAVEREVENT, DONE); - } - - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - - if (pInstance) - pInstance->SetData(DATA_VOIDREAVEREVENT, IN_PROGRESS); - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - // Pounding - if (Pounding_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_POUNDING); - - DoScriptText(RAND(SAY_POUNDING1,SAY_POUNDING2), me); - Pounding_Timer = 15000; //cast time(3000) + cooldown time(12000) - } else Pounding_Timer -= diff; - - // Arcane Orb - if (ArcaneOrb_Timer <= diff) - { - Unit *pTarget = NULL; - std::list t_list = me->getThreatManager().getThreatList(); - std::vector target_list; - for (std::list::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - pTarget = Unit::GetUnit(*me, (*itr)->getUnitGuid()); - if (!pTarget) - continue; - - // exclude pets & totems - if (pTarget->GetTypeId() != TYPEID_PLAYER) - continue; - - //18 yard radius minimum - if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && pTarget->isAlive() && !pTarget->IsWithinDist(me, 18, false)) - target_list.push_back(pTarget); - pTarget = NULL; - } - - if (target_list.size()) - pTarget = *(target_list.begin()+rand()%target_list.size()); - else - pTarget = me->getVictim(); - - if (pTarget) - me->CastSpell(pTarget->GetPositionX(),pTarget->GetPositionY(),pTarget->GetPositionZ(), SPELL_ARCANE_ORB, false, NULL, NULL, NULL, pTarget); - - ArcaneOrb_Timer = 3000; - } else ArcaneOrb_Timer -= diff; - - // Single Target knock back, reduces aggro - if (KnockAway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCK_AWAY); - - //Drop 25% aggro - if (DoGetThreat(me->getVictim())) - DoModifyThreatPercent(me->getVictim(),-25); - - KnockAway_Timer = 30000; - } else KnockAway_Timer -= diff; - - //Berserk - if (Berserk_Timer < diff && !Enraged) - { - DoCast(me, SPELL_BERSERK); - Enraged = true; - } else Berserk_Timer -= diff; - - DoMeleeAttackIfReady(); - - EnterEvadeIfOutOfCombatArea(diff); - } -}; - -CreatureAI* GetAI_boss_void_reaver(Creature* pCreature) -{ - return new boss_void_reaverAI (pCreature); -} - -void AddSC_boss_void_reaver() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_void_reaver"; - newscript->GetAI = &GetAI_boss_void_reaver; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp deleted file mode 100644 index 59c72071238..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_eye/instance_the_eye.cpp +++ /dev/null @@ -1,176 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_The_Eye -SD%Complete: 100 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define MAX_ENCOUNTER 5 - -/* The Eye encounters: -0 - Kael'thas event -1 - Al' ar event -2 - Solarian Event -3 - Void Reaver event -*/ - -struct instance_the_eye : public ScriptedInstance -{ - instance_the_eye(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint64 ThaladredTheDarkener; - uint64 LordSanguinar; - uint64 GrandAstromancerCapernian; - uint64 MasterEngineerTelonicus; - uint64 Kaelthas; - uint64 Astromancer; - uint64 Alar; - - uint8 KaelthasEventPhase; - uint8 AlarEventPhase; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - ThaladredTheDarkener = 0; - LordSanguinar = 0; - GrandAstromancerCapernian = 0; - MasterEngineerTelonicus = 0; - Kaelthas = 0; - Astromancer = 0; - Alar = 0; - - KaelthasEventPhase = 0; - AlarEventPhase = 0; - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) return true; - - return false; - } - - void OnCreatureCreate(Creature* pCreature, bool /*add*/) - { - switch(pCreature->GetEntry()) - { - case 20064: ThaladredTheDarkener = pCreature->GetGUID(); break; - case 20063: MasterEngineerTelonicus = pCreature->GetGUID(); break; - case 20062: GrandAstromancerCapernian = pCreature->GetGUID(); break; - case 20060: LordSanguinar = pCreature->GetGUID(); break; - case 19622: Kaelthas = pCreature->GetGUID(); break; - case 18805: Astromancer = pCreature->GetGUID(); break; - case 19514: Alar = pCreature->GetGUID(); break; - } - } - - uint64 GetData64(uint32 identifier) - { - switch(identifier) - { - case DATA_THALADREDTHEDARKENER: return ThaladredTheDarkener; - case DATA_LORDSANGUINAR: return LordSanguinar; - case DATA_GRANDASTROMANCERCAPERNIAN: return GrandAstromancerCapernian; - case DATA_MASTERENGINEERTELONICUS: return MasterEngineerTelonicus; - case DATA_KAELTHAS: return Kaelthas; - case DATA_ASTROMANCER: return Astromancer; - case DATA_ALAR: return Alar; - } - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_ALAREVENT: AlarEventPhase = data; m_auiEncounter[0] = data; break; - case DATA_HIGHASTROMANCERSOLARIANEVENT: m_auiEncounter[1] = data; break; - case DATA_VOIDREAVEREVENT: m_auiEncounter[2] = data; break; - case DATA_KAELTHASEVENT: KaelthasEventPhase = data; m_auiEncounter[3] = data; break; - } - if (data == DONE) - SaveToDB(); - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_ALAREVENT: return AlarEventPhase; - case DATA_HIGHASTROMANCERSOLARIANEVENT: return m_auiEncounter[1]; - case DATA_VOIDREAVEREVENT: return m_auiEncounter[2]; - case DATA_KAELTHASEVENT: return KaelthasEventPhase; - } - return 0; - } - - std::string GetSaveData() - { - OUT_SAVE_INST_DATA; - std::ostringstream stream; - stream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " << m_auiEncounter[3]; - char* out = new char[stream.str().length() + 1]; - strcpy(out, stream.str().c_str()); - if (out) - { - OUT_SAVE_INST_DATA_COMPLETE; - return out; - } - return NULL; - } - - void Load(const char* in) - { - if (!in) - { - OUT_LOAD_INST_DATA_FAIL; - return; - } - OUT_LOAD_INST_DATA(in); - std::istringstream stream(in); - stream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]; - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead. - m_auiEncounter[i] = NOT_STARTED; - OUT_LOAD_INST_DATA_COMPLETE; - } -}; - -InstanceData* GetInstanceData_instance_the_eye(Map* pMap) -{ - return new instance_the_eye(pMap); -} - -void AddSC_instance_the_eye() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_the_eye"; - newscript->GetInstanceData = &GetInstanceData_instance_the_eye; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp b/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp deleted file mode 100644 index 97021fdc031..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: The_Eye -SD%Complete: 100 -SDComment: -SDCategory: Tempest Keep, The Eye -EndScriptData */ - -/* ContentData -mob_crystalcore_devastator -EndContentData */ - -#include "ScriptedPch.h" -#include "the_eye.h" - -#define SPELL_COUNTERCHARGE 35035 -#define SPELL_KNOCKAWAY 22893 - -struct mob_crystalcore_devastatorAI : public ScriptedAI -{ - mob_crystalcore_devastatorAI(Creature *c) : ScriptedAI(c) {} - - uint32 Knockaway_Timer; - uint32 Countercharge_Timer; - - void Reset() - { - Countercharge_Timer = 9000; - Knockaway_Timer = 25000; - } - - void EnterCombat(Unit * /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - //Check if we have a current target - //Knockaway_Timer - if (Knockaway_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKAWAY, true); - - // current aggro target is knocked away pick new target - Unit* pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 0); - - if (!pTarget || pTarget == me->getVictim()) - pTarget = SelectUnit(SELECT_TARGET_TOPAGGRO, 1); - - if (pTarget) - me->TauntApply(pTarget); - - Knockaway_Timer = 23000; - } else Knockaway_Timer -= diff; - - //Countercharge_Timer - if (Countercharge_Timer <= diff) - { - DoCast(me, SPELL_COUNTERCHARGE); - Countercharge_Timer = 45000; - } else Countercharge_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_mob_crystalcore_devastator(Creature* pCreature) -{ - return new mob_crystalcore_devastatorAI (pCreature); -} - -void AddSC_the_eye() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "mob_crystalcore_devastator"; - newscript->GetAI = &GetAI_mob_crystalcore_devastator; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h b/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h deleted file mode 100644 index d0d3ea09061..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_eye/the_eye.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ - -#ifndef DEF_THE_EYE_H -#define DEF_THE_EYE_H - -#define DATA_ALAREVENT 1 -#define DATA_ASTROMANCER 2 -#define DATA_GRANDASTROMANCERCAPERNIAN 3 -#define DATA_HIGHASTROMANCERSOLARIANEVENT 4 -#define DATA_KAELTHAS 5 -#define DATA_KAELTHASEVENT 6 -#define DATA_LORDSANGUINAR 7 -#define DATA_MASTERENGINEERTELONICUS 8 -#define DATA_THALADREDTHEDARKENER 10 -#define DATA_VOIDREAVEREVENT 11 -#define DATA_ALAR 12 -#endif - diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp deleted file mode 100644 index b9c365eda65..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_gyrokill.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Boss_Gatewatcher_Gyrokill -SD%Complete: 0 -SDComment: Place Holder -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -//not used -#define SAY_AGGRO -1554000 -#define SAY_SAW_ATTACK1 -1554001 -#define SAY_SAW_ATTACK2 -1554002 -#define SAY_SLAY1 -1554003 -#define SAY_SLAY2 -1554004 -#define SAY_DEATH -1554005 - -#define SPELL_STREAM_OF_MACHINE_FLUID 35311 -#define SPELL_SAW_BLADE 35318 -#define H_SPELL_SAW_BLADE 39192 -#define SPELL_SHADOW_POWER 35322 -#define H_SPELL_SHADOW_POWER 39193 - diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp deleted file mode 100644 index 50c3a6171ce..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_gatewatcher_ironhand.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Gatewatcher_Ironhand -SD%Complete: 75 -SDComment: -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO_1 -1554006 -#define SAY_HAMMER_1 -1554007 -#define SAY_HAMMER_2 -1554008 -#define SAY_SLAY_1 -1554009 -#define SAY_SLAY_2 -1554010 -#define SAY_DEATH_1 -1554011 -#define EMOTE_HAMMER -1554012 - -// Spells to be casted -#define SPELL_SHADOW_POWER 35322 -#define H_SPELL_SHADOW_POWER 39193 -#define SPELL_HAMMER_PUNCH 35326 -#define SPELL_JACKHAMMER 35327 -#define H_SPELL_JACKHAMMER 39194 -#define SPELL_STREAM_OF_MACHINE_FLUID 35311 - -// Gatewatcher Iron-Hand AI -struct boss_gatewatcher_iron_handAI : public ScriptedAI -{ - boss_gatewatcher_iron_handAI(Creature *c) : ScriptedAI(c) - { - } - - uint32 Shadow_Power_Timer; - uint32 Jackhammer_Timer; - uint32 Stream_of_Machine_Fluid_Timer; - - void Reset() - { - Shadow_Power_Timer = 25000; - Jackhammer_Timer = 45000; - Stream_of_Machine_Fluid_Timer = 55000; - - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO_1, me); - } - - void KilledUnit(Unit* /*victim*/) - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH_1, me); - //TODO: Add door check/open code - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Shadow Power - if (Shadow_Power_Timer <= diff) - { - DoCast(me, SPELL_SHADOW_POWER); - Shadow_Power_Timer = 20000 + rand()%8000; - } else Shadow_Power_Timer -= diff; - - //Jack Hammer - if (Jackhammer_Timer <= diff) - { - //TODO: expect cast this about 5 times in a row (?), announce it by emote only once - DoScriptText(EMOTE_HAMMER, me); - DoCast(me->getVictim(), SPELL_JACKHAMMER); - - //chance to yell, but not same time as emote (after spell in fact casted) - if (rand()%2) - return; - - DoScriptText(RAND(SAY_HAMMER_1,SAY_HAMMER_2), me); - Jackhammer_Timer = 30000; - } else Jackhammer_Timer -= diff; - - //Stream of Machine Fluid - if (Stream_of_Machine_Fluid_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_STREAM_OF_MACHINE_FLUID); - Stream_of_Machine_Fluid_Timer = 35000 + rand()%15000; - } else Stream_of_Machine_Fluid_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_gatewatcher_iron_hand(Creature* pCreature) -{ - return new boss_gatewatcher_iron_handAI (pCreature); -} - -void AddSC_boss_gatewatcher_iron_hand() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_gatewatcher_iron_hand"; - newscript->GetAI = &GetAI_boss_gatewatcher_iron_hand; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp deleted file mode 100644 index ededec0196d..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_nethermancer_sepethrea.cpp +++ /dev/null @@ -1,245 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss_Nethermancer_Sepethrea -SD%Complete: 90 -SDComment: Need adjustments to initial summons -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" -#include "mechanar.h" - -#define SAY_AGGRO -1554013 -#define SAY_SUMMON -1554014 -#define SAY_DRAGONS_BREATH_1 -1554015 -#define SAY_DRAGONS_BREATH_2 -1554016 -#define SAY_SLAY1 -1554017 -#define SAY_SLAY2 -1554018 -#define SAY_DEATH -1554019 - -#define SPELL_SUMMON_RAGIN_FLAMES 35275 -#define H_SPELL_SUMMON_RAGIN_FLAMES 39084 - -#define SPELL_FROST_ATTACK 35263 -#define SPELL_ARCANE_BLAST 35314 -#define SPELL_DRAGONS_BREATH 35250 -#define SPELL_KNOCKBACK 37317 -#define SPELL_SOLARBURN 35267 - -struct boss_nethermancer_sepethreaAI : public ScriptedAI -{ - boss_nethermancer_sepethreaAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 frost_attack_Timer; - uint32 arcane_blast_Timer; - uint32 dragons_breath_Timer; - uint32 knockback_Timer; - uint32 solarburn_Timer; - - void Reset() - { - frost_attack_Timer = 7000 + rand()%3000; - arcane_blast_Timer = 12000 + rand()%6000; - dragons_breath_Timer = 18000 + rand()%4000; - knockback_Timer = 22000 + rand()%6000; - solarburn_Timer = 30000; - - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, NOT_STARTED); - } - - void EnterCombat(Unit* who) - { - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, IN_PROGRESS); - - DoScriptText(SAY_AGGRO, me); - DoCast(who, SPELL_SUMMON_RAGIN_FLAMES); - DoScriptText(SAY_SUMMON, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY1,SAY_SLAY2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - if (pInstance) - pInstance->SetData(DATA_NETHERMANCER_EVENT, DONE); - } - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - //Frost Attack - if (frost_attack_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_FROST_ATTACK); - frost_attack_Timer = 7000 + rand()%3000; - } else frost_attack_Timer -= diff; - - //Arcane Blast - if (arcane_blast_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_BLAST); - arcane_blast_Timer = 15000; - } else arcane_blast_Timer -= diff; - - //Dragons Breath - if (dragons_breath_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_DRAGONS_BREATH); - { - if (rand()%2) - return; - - DoScriptText(RAND(SAY_DRAGONS_BREATH_1,SAY_DRAGONS_BREATH_2), me); - } - dragons_breath_Timer = 12000 + rand()%10000; - } else dragons_breath_Timer -= diff; - - //Knockback - if (knockback_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_KNOCKBACK); - knockback_Timer = 15000 + rand()%10000; - } else knockback_Timer -= diff; - - //Solarburn - if (solarburn_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_SOLARBURN); - solarburn_Timer = 30000; - } else solarburn_Timer -= diff; - - DoMeleeAttackIfReady(); - } -}; - -CreatureAI* GetAI_boss_nethermancer_sepethrea(Creature* pCreature) -{ - return new boss_nethermancer_sepethreaAI (pCreature); -} - -#define SPELL_INFERNO 35268 -#define H_SPELL_INFERNO 39346 -#define SPELL_FIRE_TAIL 35278 - -struct mob_ragin_flamesAI : public ScriptedAI -{ - mob_ragin_flamesAI(Creature *c) : ScriptedAI(c) - { - pInstance = c->GetInstanceData(); - } - - ScriptedInstance *pInstance; - - uint32 inferno_Timer; - uint32 flame_timer; - uint32 Check_Timer; - - bool onlyonce; - - void Reset() - { - inferno_Timer = 10000; - flame_timer = 500; - Check_Timer = 2000; - onlyonce = false; - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true); - me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true); - me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f)); - } - - void EnterCombat(Unit* /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - //Check_Timer - if (Check_Timer <= diff) - { - if (pInstance) - { - if (pInstance->GetData(DATA_NETHERMANCER_EVENT) != IN_PROGRESS) - { - //remove - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } - } - Check_Timer = 1000; - } else Check_Timer -= diff; - - if (!UpdateVictim()) - return; - - if (!onlyonce) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0)) - me->GetMotionMaster()->MoveChase(pTarget); - onlyonce = true; - } - - if (inferno_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_INFERNO); - me->TauntApply(me->getVictim()); - inferno_Timer = 10000; - } else inferno_Timer -= diff; - - if (flame_timer <= diff) - { - DoCast(me, SPELL_FIRE_TAIL); - flame_timer = 500; - } else flame_timer -=diff; - - DoMeleeAttackIfReady(); - } - -}; -CreatureAI* GetAI_mob_ragin_flames(Creature* pCreature) -{ - return new mob_ragin_flamesAI (pCreature); -} -void AddSC_boss_nethermancer_sepethrea() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_nethermancer_sepethrea"; - newscript->GetAI = &GetAI_boss_nethermancer_sepethrea; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_ragin_flames"; - newscript->GetAI = &GetAI_mob_ragin_flames; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp deleted file mode 100644 index c0c06704db7..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_mechanar/boss_pathaleon_the_calculator.cpp +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 -* This program is free software; you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation; either version 2 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* ScriptData -SDName: Boss Pathaleon the Calculator -SD%Complete: 50 -SDComment: Event missing. Script for himself 99% blizzlike. -SDCategory: Tempest Keep, The Mechanar -EndScriptData */ - -#include "ScriptedPch.h" - -#define SAY_AGGRO -1554020 -#define SAY_DOMINATION_1 -1554021 -#define SAY_DOMINATION_2 -1554022 -#define SAY_SUMMON -1554023 -#define SAY_ENRAGE -1554024 -#define SAY_SLAY_1 -1554025 -#define SAY_SLAY_2 -1554026 -#define SAY_DEATH -1554027 - -// Spells to be casted -#define SPELL_MANA_TAP 36021 -#define SPELL_ARCANE_TORRENT 36022 -#define SPELL_DOMINATION 35280 -#define H_SPELL_ARCANE_EXPLOSION 15453 -#define SPELL_FRENZY 36992 - -#define SPELL_SUMMON_NETHER_WRAITH_1 35285 //Spells work, but not implemented -#define SPELL_SUMMON_NETHER_WRAITH_2 35286 -#define SPELL_SUMMON_NETHER_WRAITH_3 35287 -#define SPELL_SUMMON_NETHER_WRAITH_4 35288 - -// Add Spells -#define SPELL_DETONATION 35058 -#define SPELL_ARCANE_MISSILES 35034 - -struct boss_pathaleon_the_calculatorAI : public ScriptedAI -{ - boss_pathaleon_the_calculatorAI(Creature *c) : ScriptedAI(c), summons(me) - { - } - - uint32 Summon_Timer; - SummonList summons; - uint32 ManaTap_Timer; - uint32 ArcaneTorrent_Timer; - uint32 Domination_Timer; - uint32 ArcaneExplosion_Timer; - - bool Enraged; - - uint32 Counter; - - void Reset() - { - Summon_Timer = 30000; - ManaTap_Timer = 12000 + rand()%8000; - ArcaneTorrent_Timer = 16000 + rand()%9000; - Domination_Timer = 25000 + rand()%15000; - ArcaneExplosion_Timer = 8000 + rand()%5000; - - Enraged = false; - - Counter = 0; - summons.DespawnAll(); - } - void EnterCombat(Unit * /*who*/) - { - DoScriptText(SAY_AGGRO, me); - } - - void KilledUnit(Unit* /*victim*/) - { - DoScriptText(RAND(SAY_SLAY_1,SAY_SLAY_2), me); - } - - void JustDied(Unit* /*Killer*/) - { - DoScriptText(SAY_DEATH, me); - - summons.DespawnAll(); - } - - void JustSummoned(Creature *summon) {summons.Summon(summon);} - void SummonedCreatureDespawn(Creature *summon) {summons.Despawn(summon);} - - void UpdateAI(const uint32 diff) - { - //Return since we have no target - if (!UpdateVictim()) - return; - - if (Summon_Timer <= diff) - { - for (uint8 i = 0; i < 3; ++i) - { - Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,0); - Creature* Wraith = me->SummonCreature(21062,me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000); - if (pTarget && Wraith) - Wraith->AI()->AttackStart(pTarget); - } - DoScriptText(SAY_SUMMON, me); - Summon_Timer = 30000 + rand()%15000; - } else Summon_Timer -= diff; - - if (ManaTap_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_MANA_TAP); - ManaTap_Timer = 14000 + rand()%8000; - } else ManaTap_Timer -= diff; - - if (ArcaneTorrent_Timer <= diff) - { - DoCast(me->getVictim(), SPELL_ARCANE_TORRENT); - ArcaneTorrent_Timer = 12000 + rand()%6000; - } else ArcaneTorrent_Timer -= diff; - - if (Domination_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - { - DoScriptText(RAND(SAY_DOMINATION_1,SAY_DOMINATION_2), me); - - DoCast(pTarget, SPELL_DOMINATION); - } - Domination_Timer = 25000 + rand()%5000; - } else Domination_Timer -= diff; - - //Only casting if Heroic Mode is used - if (IsHeroic()) - { - if (ArcaneExplosion_Timer <= diff) - { - DoCast(me->getVictim(), H_SPELL_ARCANE_EXPLOSION); - ArcaneExplosion_Timer = 10000 + rand()%4000; - } else ArcaneExplosion_Timer -= diff; - } - - if (!Enraged && me->GetHealth()*100 / me->GetMaxHealth() < 21) - { - DoCast(me, SPELL_FRENZY); - DoScriptText(SAY_ENRAGE, me); - Enraged = true; - - } - - DoMeleeAttackIfReady(); - } -}; -CreatureAI* GetAI_boss_pathaleon_the_calculator(Creature* pCreature) -{ - return new boss_pathaleon_the_calculatorAI (pCreature); -} - -struct mob_nether_wraithAI : public ScriptedAI -{ - mob_nether_wraithAI(Creature *c) : ScriptedAI(c) {} - - uint32 ArcaneMissiles_Timer; - uint32 Detonation_Timer; - uint32 Die_Timer; - bool Detonation; - - void Reset() - { - ArcaneMissiles_Timer = 1000 + rand()%3000; - Detonation_Timer = 20000; - Die_Timer = 2200; - Detonation = false; - - } - - void EnterCombat(Unit* /*who*/) - { - } - - void UpdateAI(const uint32 diff) - { - if (!UpdateVictim()) - return; - - if (ArcaneMissiles_Timer <= diff) - { - if (Unit *pTarget = SelectUnit(SELECT_TARGET_RANDOM,1)) - DoCast(pTarget, SPELL_ARCANE_MISSILES); - else - DoCast(me->getVictim(), SPELL_ARCANE_MISSILES); - - ArcaneMissiles_Timer = 5000 + rand()%5000; - } else ArcaneMissiles_Timer -=diff; - - if (!Detonation) - { - if (Detonation_Timer <= diff) - { - DoCast(me, SPELL_DETONATION); - Detonation = true; - } else Detonation_Timer -= diff; - } - - if (Detonation) - { - if (Die_Timer <= diff) - { - me->setDeathState(JUST_DIED); - me->RemoveCorpse(); - } else Die_Timer -= diff; - } - - DoMeleeAttackIfReady(); - } - -}; -CreatureAI* GetAI_mob_nether_wraith(Creature* pCreature) -{ - return new mob_nether_wraithAI (pCreature); -} - -void AddSC_boss_pathaleon_the_calculator() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "boss_pathaleon_the_calculator"; - newscript->GetAI = &GetAI_boss_pathaleon_the_calculator; - newscript->RegisterSelf(); - - newscript = new Script; - newscript->Name = "mob_nether_wraith"; - newscript->GetAI = &GetAI_mob_nether_wraith; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp b/src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp deleted file mode 100644 index c70da24ea3f..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_mechanar/instance_mechanar.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2006 - 2009 ScriptDev2 - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -/* ScriptData -SDName: Instance_Mechanar -SD%Complete: 100 -SDComment: -SDCategory: Mechanar -EndScriptData */ - -#include "ScriptedPch.h" -#include "mechanar.h" - -#define MAX_ENCOUNTER 1 - -struct instance_mechanar : public ScriptedInstance -{ - instance_mechanar(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; - - uint32 m_auiEncounter[MAX_ENCOUNTER]; - - void Initialize() - { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - } - - bool IsEncounterInProgress() const - { - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) - if (m_auiEncounter[i] == IN_PROGRESS) - return true; - - return false; - } - - uint32 GetData(uint32 type) - { - switch(type) - { - case DATA_NETHERMANCER_EVENT: return m_auiEncounter[0]; - } - - return false; - } - - uint64 GetData64 (uint32 /*identifier*/) - { - return 0; - } - - void SetData(uint32 type, uint32 data) - { - switch(type) - { - case DATA_NETHERMANCER_EVENT: m_auiEncounter[0] = data; break; - } - } -}; - -InstanceData* GetInstanceData_instance_mechanar(Map* pMap) -{ - return new instance_mechanar(pMap); -} - -void AddSC_instance_mechanar() -{ - Script *newscript; - newscript = new Script; - newscript->Name = "instance_mechanar"; - newscript->GetInstanceData = &GetInstanceData_instance_mechanar; - newscript->RegisterSelf(); -} - diff --git a/src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h b/src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h deleted file mode 100644 index d1b53eebf53..00000000000 --- a/src/server/scripts/Outland/TempestKeep/the_mechanar/mechanar.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef DEF_MECHANAR_H -#define DEF_MECHANAR_H - -#define DATA_NETHERMANCER_EVENT 1 -#endif - diff --git a/src/tools/vmap3_assembler/VMapAssembler.cpp b/src/tools/vmap3_assembler/VMapAssembler.cpp new file mode 100644 index 00000000000..6666b54356c --- /dev/null +++ b/src/tools/vmap3_assembler/VMapAssembler.cpp @@ -0,0 +1,120 @@ +#include +#include +#include + +#include "TileAssembler.h" + +//======================================================= +// remove last return or LF and tailing SPACE +// remove all char after a # + +void chompAndTrim(std::string& str) +{ + for(unsigned int i=0;i0) { + char lc = str[str.length()-1]; + if(lc == '\r' || lc == '\n' || lc == ' ') { + str = str.substr(0,str.length()-1); + } else { + break; + } + } +} + +//======================================================= +/** +This callback method is called for each model found in the dir file. +return true if it should be included in the vmap +*/ +bool modelNameFilter(char *pName) +{ +#if 0 + bool result; + result = !Wildcard::wildcardfit("*bush[0-9]*", pName); + if(result) result = !Wildcard::wildcardfit("*shrub[0-9]*", pName); + if(result) result = !Wildcard::wildcardfit("*_Bushes_*", pName); + if(result) result = !Wildcard::wildcardfit("*_Bush_*", pName); + if(!result) { + printf("%s",pName); + } +#endif + return true; +} + +//======================================================= +/** +File contains map names that should be split into tiles +A '#' at the beginning of a line defines a comment +*/ + +/* bool readConfigFile(char *pConffile, VMAP::TileAssembler* pTa) +{ + bool result = false; + char buffer[501]; + FILE *cf = fopen(pConffile, "rb"); + if(cf) { + while(fgets(buffer, 500, cf)) { + std::string name = std::string(buffer); + size_t pos = name.find_first_not_of(' '); + name = name.substr(pos); + chompAndTrim(name); // just to be sure + if(name[0] != '#' && name.size() >0) { // comment? + unsigned int mapId = atoi(name.c_str()); + pTa->addWorldAreaMapId(mapId); + } + } + fclose(cf); + result = true; + } + return(result); +} */ +//======================================================= +int main(int argc, char* argv[]) +{ + if(argc != 3 && argc != 4) + { + printf("\nusage: %s [config file name]\n", argv[0]); + return 1; + } + + char *src = argv[1]; + char *dest = argv[2]; + char *conffile = NULL; + if(argc >= 4) + conffile = argv[3]; + + VMAP::TileAssembler* ta = new VMAP::TileAssembler(std::string(src), std::string(dest)); + ta->setModelNameFilterMethod(modelNameFilter); + + /* + All the names in the list are considered to be world maps or huge instances. + These maps will be spilt into tiles in the vmap assemble process + */ + /* if(conffile != NULL) + { + if(!readConfigFile(conffile, ta)) + { + printf("Can not open file config file: %s\n", conffile); + delete ta; + return 1; + } + } */ + + if(!ta->convertWorld2()) + { + printf("exit with errors\n"); + delete ta; + return 1; + } + + delete ta; + printf("Ok, all done\n"); + return 0; +} diff --git a/src/tools/vmap3_assembler/vmap_assembler.cpp b/src/tools/vmap3_assembler/vmap_assembler.cpp deleted file mode 100644 index 6666b54356c..00000000000 --- a/src/tools/vmap3_assembler/vmap_assembler.cpp +++ /dev/null @@ -1,120 +0,0 @@ -#include -#include -#include - -#include "TileAssembler.h" - -//======================================================= -// remove last return or LF and tailing SPACE -// remove all char after a # - -void chompAndTrim(std::string& str) -{ - for(unsigned int i=0;i0) { - char lc = str[str.length()-1]; - if(lc == '\r' || lc == '\n' || lc == ' ') { - str = str.substr(0,str.length()-1); - } else { - break; - } - } -} - -//======================================================= -/** -This callback method is called for each model found in the dir file. -return true if it should be included in the vmap -*/ -bool modelNameFilter(char *pName) -{ -#if 0 - bool result; - result = !Wildcard::wildcardfit("*bush[0-9]*", pName); - if(result) result = !Wildcard::wildcardfit("*shrub[0-9]*", pName); - if(result) result = !Wildcard::wildcardfit("*_Bushes_*", pName); - if(result) result = !Wildcard::wildcardfit("*_Bush_*", pName); - if(!result) { - printf("%s",pName); - } -#endif - return true; -} - -//======================================================= -/** -File contains map names that should be split into tiles -A '#' at the beginning of a line defines a comment -*/ - -/* bool readConfigFile(char *pConffile, VMAP::TileAssembler* pTa) -{ - bool result = false; - char buffer[501]; - FILE *cf = fopen(pConffile, "rb"); - if(cf) { - while(fgets(buffer, 500, cf)) { - std::string name = std::string(buffer); - size_t pos = name.find_first_not_of(' '); - name = name.substr(pos); - chompAndTrim(name); // just to be sure - if(name[0] != '#' && name.size() >0) { // comment? - unsigned int mapId = atoi(name.c_str()); - pTa->addWorldAreaMapId(mapId); - } - } - fclose(cf); - result = true; - } - return(result); -} */ -//======================================================= -int main(int argc, char* argv[]) -{ - if(argc != 3 && argc != 4) - { - printf("\nusage: %s [config file name]\n", argv[0]); - return 1; - } - - char *src = argv[1]; - char *dest = argv[2]; - char *conffile = NULL; - if(argc >= 4) - conffile = argv[3]; - - VMAP::TileAssembler* ta = new VMAP::TileAssembler(std::string(src), std::string(dest)); - ta->setModelNameFilterMethod(modelNameFilter); - - /* - All the names in the list are considered to be world maps or huge instances. - These maps will be spilt into tiles in the vmap assemble process - */ - /* if(conffile != NULL) - { - if(!readConfigFile(conffile, ta)) - { - printf("Can not open file config file: %s\n", conffile); - delete ta; - return 1; - } - } */ - - if(!ta->convertWorld2()) - { - printf("exit with errors\n"); - delete ta; - return 1; - } - - delete ta; - printf("Ok, all done\n"); - return 0; -} -- cgit v1.2.3