diff --git a/Makefile.am b/Makefile.am index 2acab3b..183bead 100644 --- a/Makefile.am +++ b/Makefile.am @@ -36,6 +36,10 @@ base/follower_ai.cpp \ base/follower_ai.h \ base/guard_ai.cpp \ base/guard_ai.h \ +base/BSW_instance.cpp \ +base/BSW_instance.h \ +base/BSW_ai.cpp \ +base/BSW_ai.h \ base/pet_ai.cpp \ base/pet_ai.h \ include/precompiled.cpp \ @@ -49,6 +53,8 @@ include/sc_instance.cpp \ include/sc_instance.h \ scripts/battlegrounds/battleground.cpp \ scripts/custom/custom_cybernetic.cpp \ +scripts/custom/npc_arena_honor.cpp \ +scripts/custom/teleguy.cpp \ scripts/eastern_kingdoms/alterac_mountains.cpp \ scripts/eastern_kingdoms/arathi_highlands.cpp \ scripts/eastern_kingdoms/blasted_lands.cpp \ @@ -79,6 +85,7 @@ scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp \ scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h \ scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp \ scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp \ +scripts/eastern_kingdoms/blackrock_depths/boss_coren_direbrew.cpp \ scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp \ scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp \ scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp \ @@ -101,6 +108,7 @@ scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp \ scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp \ scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp \ scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp \ +scripts/eastern_kingdoms/blackwing_lair/blackwing_lair.h \ scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp \ scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp \ scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp \ @@ -128,6 +136,7 @@ scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp \ scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp \ scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp \ scripts/eastern_kingdoms/karazhan/bosses_opera.cpp \ +scripts/eastern_kingdoms/karazhan/chess_event.cpp \ scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp \ scripts/eastern_kingdoms/karazhan/karazhan.cpp \ scripts/eastern_kingdoms/karazhan/karazhan.h \ @@ -178,6 +187,7 @@ scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp \ scripts/eastern_kingdoms/scholomance/boss_vectus.cpp \ scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp \ scripts/eastern_kingdoms/scholomance/scholomance.h \ +scripts/eastern_kingdoms/shadowfang_keep/boss_hummel.cpp \ scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp \ scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp \ scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h \ @@ -199,7 +209,11 @@ scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp \ scripts/eastern_kingdoms/sunken_temple/sunken_temple.h \ scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp \ scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp \ +scripts/eastern_kingdoms/sunwell_plateau/boss_eredar_twins.cpp \ +scripts/eastern_kingdoms/sunwell_plateau/boss_felmyst.cpp \ scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp \ +scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp \ +scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp \ scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp \ scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h \ scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp \ @@ -258,9 +272,6 @@ scripts/kalimdor/ungoro_crater.cpp \ scripts/kalimdor/winterspring.cpp \ scripts/kalimdor/blackfathom_deeps/blackfathom_deeps.h \ scripts/kalimdor/blackfathom_deeps/instance_blackfathom_deeps.cpp \ -scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h \ -scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp \ -scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp \ scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp \ scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp \ scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp \ @@ -280,6 +291,7 @@ scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp \ scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp \ scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h \ scripts/kalimdor/dire_maul/boss_pusillin.cpp \ +scripts/kalimdor/dire_maul/dire_maul.cpp \ scripts/kalimdor/dire_maul/dire_maul.h \ scripts/kalimdor/dire_maul/instance_dire_maul.cpp \ scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp \ @@ -329,8 +341,8 @@ scripts/northrend/sholazar_basin.cpp \ scripts/northrend/storm_peaks.cpp \ scripts/northrend/howling_fjord.cpp \ scripts/northrend/zuldrak.cpp \ -scripts/northrend/azjol-nerub/ahnkahet/boss_amanitar.cpp \ scripts/northrend/azjol-nerub/ahnkahet/boss_jedoga.cpp \ +scripts/northrend/azjol-nerub/ahnkahet/boss_amanitar.cpp \ scripts/northrend/azjol-nerub/ahnkahet/boss_nadox.cpp \ scripts/northrend/azjol-nerub/ahnkahet/boss_taldaram.cpp \ scripts/northrend/azjol-nerub/ahnkahet/boss_volazj.cpp \ @@ -341,55 +353,56 @@ scripts/northrend/azjol-nerub/azjol-nerub/boss_anubarak.cpp \ scripts/northrend/azjol-nerub/azjol-nerub/boss_hadronox.cpp \ scripts/northrend/azjol-nerub/azjol-nerub/boss_krikthir.cpp \ scripts/northrend/azjol-nerub/azjol-nerub/instance_azjol-nerub.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h \ -scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp \ -scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h \ +scripts/northrend/draktharon_keep/draktharon_keep.h \ +scripts/northrend/draktharon_keep/boss_dred.cpp \ scripts/northrend/draktharon_keep/boss_novos.cpp \ scripts/northrend/draktharon_keep/boss_tharonja.cpp \ scripts/northrend/draktharon_keep/boss_trollgore.cpp \ scripts/northrend/draktharon_keep/draktharon_keep.h \ scripts/northrend/draktharon_keep/instance_draktharon_keep.cpp \ -scripts/northrend/gundrak/boss_eck.cpp \ scripts/northrend/gundrak/boss_colossus.cpp \ +scripts/northrend/gundrak/boss_eck.cpp \ scripts/northrend/gundrak/boss_galdarah.cpp \ scripts/northrend/gundrak/boss_moorabi.cpp \ scripts/northrend/gundrak/boss_sladran.cpp \ scripts/northrend/gundrak/gundrak.h \ scripts/northrend/gundrak/instance_gundrak.cpp \ -scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_falryn.cpp \ -scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_lich_king.cpp \ -scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_marwyn.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/def_forge.h \ +scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/trash_forge_of_souls.cpp \ scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_forgemaster_gafrost.cpp \ scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_krick_and_ick.cpp \ scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp \ scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp \ scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/pit_of_saron.cpp \ scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/pit_of_saron.h \ -scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp \ -scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp \ -scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.h \ -scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp \ -scripts/northrend/icecrown_citadel/icecrown_citadel/blood_prince_council.cpp \ -scripts/northrend/icecrown_citadel/icecrown_citadel/boss_blood_queen_lanathel.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/def_halls.h \ +scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/halls_of_reflection.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_falric.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_lich_king.cpp \ +scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_marwyn.cpp \ +scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_teleport.cpp \ +scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_spire.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/boss_deathbringer_saurfang.cpp \ -scripts/northrend/icecrown_citadel/icecrown_citadel/boss_festergut.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lady_deathwhisper.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lord_marrowgar.cpp \ +scripts/northrend/icecrown_citadel/icecrown_citadel/blood_prince_council.cpp \ +scripts/northrend/icecrown_citadel/icecrown_citadel/boss_blood_queen_lanathel.cpp \ +scripts/northrend/icecrown_citadel/icecrown_citadel/boss_festergut.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/boss_professor_putricide.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/boss_rotface.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/boss_sindragosa.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/boss_the_lich_king.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/boss_valithria_dreamwalker.cpp \ +scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_citadel.h \ +scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_citadel.cpp \ scripts/northrend/icecrown_citadel/icecrown_citadel/gunship_battle.cpp \ +scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_spire.cpp \ +scripts/northrend/icecrown_citadel/icecrown_citadel/def_spire.h \ scripts/northrend/naxxramas/boss_anubrekhan.cpp \ scripts/northrend/naxxramas/boss_faerlina.cpp \ scripts/northrend/naxxramas/boss_four_horsemen.cpp \ @@ -407,19 +420,30 @@ scripts/northrend/naxxramas/boss_sapphiron.cpp \ scripts/northrend/naxxramas/boss_thaddius.cpp \ scripts/northrend/naxxramas/naxxramas.h \ scripts/northrend/naxxramas/instance_naxxramas.cpp \ +scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp \ scripts/northrend/nexus/nexus/boss_anomalus.cpp \ scripts/northrend/nexus/nexus/boss_keristrasza.cpp \ scripts/northrend/nexus/nexus/boss_ormorok.cpp \ scripts/northrend/nexus/nexus/boss_telestra.cpp \ scripts/northrend/nexus/nexus/nexus.h \ scripts/northrend/nexus/nexus/instance_nexus.cpp \ +scripts/northrend/nexus/oculus/oculus.h \ +scripts/northrend/nexus/oculus/oculus.cpp \ +scripts/northrend/nexus/oculus/instance_oculus.cpp \ +scripts/northrend/nexus/oculus/boss_drakos.cpp \ +scripts/northrend/nexus/oculus/boss_varos.cpp \ +scripts/northrend/nexus/oculus/boss_urom.cpp \ +scripts/northrend/nexus/oculus/boss_eregos.cpp \ scripts/northrend/obsidian_sanctum/boss_sartharion.cpp \ scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp \ scripts/northrend/obsidian_sanctum/obsidian_sanctum.h \ +scripts/northrend/ruby_sanctum/ruby_sanctum.h \ +scripts/northrend/ruby_sanctum/ruby_sanctum.cpp \ scripts/northrend/ruby_sanctum/boss_halion.cpp \ +scripts/northrend/ruby_sanctum/boss_zarithrian.cpp \ scripts/northrend/ruby_sanctum/boss_baltharus.cpp \ scripts/northrend/ruby_sanctum/boss_saviana.cpp \ -scripts/northrend/ruby_sanctum/boss_zarithian.cpp \ +scripts/northrend/ruby_sanctum/instance_ruby_sanctum.cpp \ scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp \ scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp \ scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp \ @@ -428,26 +452,28 @@ scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h \ scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp \ scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp \ scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp \ +scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp \ scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp \ -scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h \ +scripts/northrend/ulduar/halls_of_stone/def_halls_of_stone.h \ scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp \ -scripts/northrend/ulduar/ulduar/assembly_of_iron.cpp \ +scripts/northrend/ulduar/ulduar/instance_ulduar.cpp \ +scripts/northrend/ulduar/ulduar/def_ulduar.h \ scripts/northrend/ulduar/ulduar/boss_algalon.cpp \ scripts/northrend/ulduar/ulduar/boss_auriaya.cpp \ -scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp \ scripts/northrend/ulduar/ulduar/boss_freya.cpp \ -scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp \ scripts/northrend/ulduar/ulduar/boss_hodir.cpp \ scripts/northrend/ulduar/ulduar/boss_ignis.cpp \ +scripts/northrend/ulduar/ulduar/boss_iron_council.cpp \ scripts/northrend/ulduar/ulduar/boss_kologarn.cpp \ +scripts/northrend/ulduar/ulduar/boss_leviathan.cpp \ scripts/northrend/ulduar/ulduar/boss_mimiron.cpp \ scripts/northrend/ulduar/ulduar/boss_razorscale.cpp \ scripts/northrend/ulduar/ulduar/boss_thorim.cpp \ -scripts/northrend/ulduar/ulduar/boss_xt_002.cpp \ +scripts/northrend/ulduar/ulduar/boss_vezax.cpp \ +scripts/northrend/ulduar/ulduar/boss_xt002.cpp \ scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp \ -scripts/northrend/ulduar/ulduar/instance_ulduar.cpp \ scripts/northrend/ulduar/ulduar/ulduar.cpp \ -scripts/northrend/ulduar/ulduar/ulduar.h \ +scripts/northrend/ulduar/ulduar/ulduar_teleport.cpp \ scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar.cpp \ scripts/northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp \ scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_and_dalronn.cpp \ @@ -460,16 +486,12 @@ scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp \ scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp \ scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_utgarde_pinnacle.cpp \ scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h \ -scripts/northrend/violet_hold/boss_cyanigosa.cpp \ -scripts/northrend/violet_hold/boss_erekem.cpp \ -scripts/northrend/violet_hold/boss_ichoron.cpp \ -scripts/northrend/violet_hold/boss_lavanthor.cpp \ -scripts/northrend/violet_hold/boss_moragg.cpp \ -scripts/northrend/violet_hold/boss_xevozz.cpp \ -scripts/northrend/violet_hold/boss_zuramat.cpp \ -scripts/northrend/violet_hold/instance_violet_hold.cpp \ -scripts/northrend/violet_hold/violet_hold.cpp \ -scripts/northrend/violet_hold/violet_hold.h \ +scripts/northrend/vault_of_archavon/boss_archavon.cpp \ +scripts/northrend/vault_of_archavon/boss_emalon.cpp \ +scripts/northrend/vault_of_archavon/boss_koralon.cpp \ +scripts/northrend/vault_of_archavon/boss_toravon.cpp \ +scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp \ +scripts/northrend/vault_of_archavon/vault_of_archavon.h \ scripts/outland/blades_edge_mountains.cpp \ scripts/outland/boss_doomlord_kazzak.cpp \ scripts/outland/boss_doomwalker.cpp \ @@ -481,8 +503,10 @@ scripts/outland/shattrath_city.cpp \ scripts/outland/terokkar_forest.cpp \ scripts/outland/zangarmarsh.cpp \ scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp \ +scripts/outland/auchindoun/auchenai_crypts/boss_shirrak.cpp \ scripts/outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp \ scripts/outland/auchindoun/mana_tombs/boss_pandemonius.cpp \ +scripts/outland/auchindoun/sethekk_halls/boss_anzu.cpp \ scripts/outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp \ scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp \ scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp \ @@ -513,6 +537,7 @@ scripts/outland/coilfang_reservoir/serpent_shrine/boss_morogrim_tidewalker.cpp \ scripts/outland/coilfang_reservoir/serpent_shrine/boss_the_lurker_below.cpp \ scripts/outland/coilfang_reservoir/serpent_shrine/instance_serpent_shrine.cpp \ scripts/outland/coilfang_reservoir/serpent_shrine/serpent_shrine.h \ +scripts/outland/coilfang_reservoir/slave_pens/boss_ahune.cpp \ scripts/outland/coilfang_reservoir/steam_vault/boss_hydromancer_thespia.cpp \ scripts/outland/coilfang_reservoir/steam_vault/boss_mekgineer_steamrigger.cpp \ scripts/outland/coilfang_reservoir/steam_vault/boss_warlord_kalithresh.cpp \ @@ -554,12 +579,45 @@ scripts/outland/tempest_keep/the_eye/boss_void_reaver.cpp \ scripts/outland/tempest_keep/the_eye/instance_the_eye.cpp \ scripts/outland/tempest_keep/the_eye/the_eye.cpp \ scripts/outland/tempest_keep/the_eye/the_eye.h \ -scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp \ scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp \ scripts/outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp \ scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp \ scripts/outland/tempest_keep/the_mechanar/instance_mechanar.cpp \ scripts/outland/tempest_keep/the_mechanar/mechanar.h \ +scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h \ +scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp \ +scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h \ +scripts/northrend/violet_hold/def_violet_hold.h \ +scripts/northrend/violet_hold/violet_hold.cpp \ +scripts/northrend/violet_hold/boss_cyanigosa.cpp \ +scripts/northrend/violet_hold/boss_moragg.cpp \ +scripts/northrend/violet_hold/instance_violet_hold.cpp \ +scripts/northrend/violet_hold/boss_erekem.cpp \ +scripts/northrend/violet_hold/boss_xevozz.cpp \ +scripts/northrend/violet_hold/boss_ichoron.cpp \ +scripts/northrend/violet_hold/boss_zuramat.cpp \ +scripts/northrend/violet_hold/boss_lavanthor.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/def_culling_of_stratholme.h \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_lord_epoch.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholmeai.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_malganis.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite_corruptor.cpp \ +scripts/kalimdor/caverns_of_time/culling_of_stratholme/trash_culling_of_stratholme.cpp \ scripts/world/areatrigger_scripts.cpp \ scripts/world/boss_emeriss.cpp \ scripts/world/boss_lethon.cpp \ diff --git a/ScriptMgr.cpp b/ScriptMgr.cpp index 731fae4..564529b 100644 --- a/ScriptMgr.cpp +++ b/ScriptMgr.cpp @@ -17,10 +17,16 @@ Script *m_scripts[MAX_SCRIPTS]; Config SD2Config; +QueryResult* strSD2Pquery(char* str) +{ +return SD2Database.Query(str); +} + void FillSpellSummary(); void LoadDatabase() { + std::string strSD2DBinfo = SD2Config.GetStringDefault("ScriptDev2DatabaseInfo", ""); if (strSD2DBinfo.empty()) @@ -47,8 +53,6 @@ void LoadDatabase() return; } - SD2Database.HaltDelayThread(); - } struct TSpellSummary { @@ -67,6 +71,7 @@ void ScriptsFree() delete m_scripts[i]; num_sc_scripts = 0; + SD2Database.HaltDelayThread(); } MANGOS_DLL_EXPORT @@ -270,7 +275,9 @@ bool GossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 if (!tmpscript || !tmpscript->pGossipSelect) return false; - pPlayer->PlayerTalkClass->ClearMenus(); +// pPlayer->PlayerTalkClass->ClearMenus(); +// this expression is wrong, where 'return false' from script's GossipSelect +// not return menu ID (cleared in this string) and not allow to work with database-based menus return tmpscript->pGossipSelect(pPlayer, pCreature, uiSender, uiAction); } diff --git a/ScriptMgr.h b/ScriptMgr.h index 66d7685..3ed890b 100644 --- a/ScriptMgr.h +++ b/ScriptMgr.h @@ -7,6 +7,7 @@ #include "Common.h" #include "DBCStructure.h" +#include "Database/DatabaseEnv.h" class Player; class Creature; @@ -75,6 +76,9 @@ struct Script //Generic scripting text function void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget = NULL); +//DB query +QueryResult* strSD2Pquery(char*); + #if COMPILER == COMPILER_GNU #define FUNC_PTR(name,callconvention,returntype,parameters) typedef returntype(*name)parameters __attribute__ ((callconvention)); #else diff --git a/VC100/100ScriptDev2.vcxproj b/VC100/100ScriptDev2.vcxproj index a7eabb3..6c7eda5 100644 --- a/VC100/100ScriptDev2.vcxproj +++ b/VC100/100ScriptDev2.vcxproj @@ -210,10 +210,15 @@ + + + + + @@ -243,6 +248,7 @@ + @@ -289,6 +295,7 @@ + @@ -334,6 +341,7 @@ + @@ -352,10 +360,13 @@ + + + + - @@ -389,6 +400,13 @@ + + + + + + + @@ -423,6 +441,8 @@ + + @@ -452,19 +472,9 @@ + + - - - - - - - - - - - - @@ -475,6 +485,12 @@ + + + + + + @@ -482,14 +498,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -506,38 +561,55 @@ + + + + + + + + + + + + + + + + - - - + + - + + + @@ -548,29 +620,20 @@ + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - @@ -582,8 +645,10 @@ + + @@ -608,7 +673,9 @@ + + @@ -673,11 +740,15 @@ + + + + @@ -694,28 +765,41 @@ + + + + + + + + + + + + - - + + + diff --git a/VC100/100ScriptDev2.vcxproj.filters b/VC100/100ScriptDev2.vcxproj.filters index 53595c0..1b15e87 100644 --- a/VC100/100ScriptDev2.vcxproj.filters +++ b/VC100/100ScriptDev2.vcxproj.filters @@ -309,6 +309,9 @@ base + + base + scripts\battlegrounds @@ -399,6 +402,9 @@ scripts\eastern_kingdoms\blackrock_depths + + scripts\eastern_kingdoms\blackrock_depths + scripts\eastern_kingdoms\blackrock_depths @@ -537,6 +543,9 @@ scripts\eastern_kingdoms\karazhan + + scripts\eastern_kingdoms\karazhan + scripts\eastern_kingdoms\karazhan @@ -672,6 +681,9 @@ scripts\eastern_kingdoms\scholomance + + scripts\eastern_kingdoms\shadowfang_keep + scripts\eastern_kingdoms\shadowfang_keep @@ -726,18 +738,27 @@ scripts\eastern_kingdoms\sunwell_plateau + + scripts\eastern_kingdoms\sunwell_plateau + + + scripts\eastern_kingdoms\sunwell_plateau + scripts\eastern_kingdoms\sunwell_plateau + + scripts\eastern_kingdoms\sunwell_plateau + + + scripts\eastern_kingdoms\sunwell_plateau + scripts\eastern_kingdoms\sunwell_plateau scripts\eastern_kingdoms\uldaman - - scripts\eastern_kingdoms\uldaman - scripts\eastern_kingdoms\uldaman @@ -939,6 +960,12 @@ scripts\kalimdor\caverns_of_time\old_hillsbrad + + scripts\kalimdor\dire_maul + + + scripts\kalimdor\dire_maul + scripts\kalimdor\maraudon @@ -1026,185 +1053,504 @@ scripts\kalimdor\wailing_caverns - + scripts\kalimdor\zulfarrak - - scripts\northrend + + scripts\kalimdor\zulfarrak - - scripts\northrend + + scripts\kalimdor\zulfarrak - - scripts\northrend + + scripts\outland - - scripts\northrend + + scripts\outland - - scripts\northrend + + scripts\outland - - scripts\northrend + + scripts\outland - - scripts\northrend + + scripts\outland - - scripts\northrend + + scripts\outland - - scripts\northrend + + scripts\outland - - scripts\northrend\azjol-nerub\ahnkahet + + scripts\outland - - scripts\northrend\azjol-nerub\ahnkahet + + scripts\outland - - scripts\northrend\azjol-nerub\ahnkahet + + scripts\outland - - scripts\northrend\azjol-nerub\ahnkahet + + scripts\outland\auchindoun\auchenai_crypts - - scripts\northrend\azjol-nerub\ahnkahet + + scripts\outland\auchindoun\mana_tombs - - scripts\northrend\azjol-nerub\azjol-nerub + + scripts\outland\auchindoun\mana_tombs - - scripts\northrend\azjol-nerub\azjol-nerub + + scripts\outland\auchindoun\sethekk_halls - - scripts\northrend\azjol-nerub\azjol-nerub + + scripts\outland\auchindoun\sethekk_halls - - scripts\northrend\azjol-nerub\azjol-nerub + + scripts\outland\auchindoun\sethekk_halls - - scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + scripts\outland\auchindoun\shadow_labyrinth - - scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + scripts\outland\auchindoun\shadow_labyrinth - - scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + scripts\outland\auchindoun\shadow_labyrinth - - scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + scripts\outland\auchindoun\shadow_labyrinth - - scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + scripts\outland\auchindoun\shadow_labyrinth - - scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + scripts\outland\black_temple - - scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + scripts\outland\black_temple - - scripts\northrend\draktharon_keep + + scripts\outland\black_temple - - scripts\northrend\draktharon_keep + + scripts\outland\black_temple - - scripts\northrend\draktharon_keep + + scripts\outland\black_temple - - scripts\northrend\gundrak + + scripts\outland\black_temple - - scripts\northrend\gundrak + + scripts\outland\black_temple - - scripts\northrend\gundrak + + scripts\outland\black_temple - - scripts\northrend\gundrak + + scripts\outland\black_temple - - scripts\northrend\gundrak + + scripts\outland\black_temple - - scripts\northrend\naxxramas + + scripts\outland\black_temple - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\serpent_shrine - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\serpent_shrine - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\serpent_shrine - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\serpent_shrine - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\serpent_shrine - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\serpent_shrine - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\steam_vault - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\steam_vault - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\steam_vault - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\steam_vault - - scripts\northrend\naxxramas + + scripts\outland\coilfang_reservoir\underbog - - scripts\northrend\naxxramas + + scripts\outland\gruuls_lair - - scripts\northrend\naxxramas + + scripts\outland\gruuls_lair - - scripts\northrend\naxxramas + + scripts\outland\gruuls_lair - - scripts\northrend\naxxramas + + scripts\outland\hellfire_citadel\blood_furnace - - scripts\northrend\nexus\nexus + + scripts\outland\hellfire_citadel\blood_furnace - - scripts\northrend\nexus\nexus + + scripts\outland\hellfire_citadel\blood_furnace - - scripts\northrend\nexus\nexus + + scripts\outland\hellfire_citadel\blood_furnace - - scripts\northrend\nexus\nexus + + scripts\outland\hellfire_citadel\hellfire_ramparts - - scripts\northrend\nexus\nexus + + scripts\outland\hellfire_citadel\hellfire_ramparts - - scripts\northrend\obsidian_sanctum + + scripts\outland\hellfire_citadel\hellfire_ramparts - - scripts\northrend\obsidian_sanctum + + scripts\outland\hellfire_citadel\hellfire_ramparts - - scripts\northrend\ulduar\halls_of_lightning + + scripts\outland\hellfire_citadel\magtheridons_lair - - scripts\northrend\ulduar\halls_of_lightning + + scripts\outland\hellfire_citadel\magtheridons_lair - - scripts\northrend\ulduar\halls_of_lightning + + scripts\outland\hellfire_citadel\shattered_halls + + + scripts\outland\hellfire_citadel\shattered_halls + + + scripts\outland\hellfire_citadel\shattered_halls + + + scripts\outland\hellfire_citadel\shattered_halls + + + scripts\outland\tempest_keep\arcatraz + + + scripts\outland\tempest_keep\arcatraz + + + scripts\outland\tempest_keep\arcatraz + + + scripts\outland\tempest_keep\botanica + + + scripts\outland\tempest_keep\botanica + + + scripts\outland\tempest_keep\botanica + + + scripts\outland\tempest_keep\the_eye + + + scripts\outland\tempest_keep\the_eye + + + scripts\outland\tempest_keep\the_eye + + + scripts\outland\tempest_keep\the_eye + + + scripts\outland\tempest_keep\the_eye + + + scripts\outland\tempest_keep\the_mechanar + + + scripts\outland\tempest_keep\the_mechanar + + + scripts\outland\tempest_keep\the_mechanar + + + scripts\outland\tempest_keep\the_mechanar + + + scripts\outland\tempest_keep\the_mechanar + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + scripts\world + + + include + + + include + + + include + + + include + + + system + + + system + + + + scripts\northrend + + + scripts\northrend + + + scripts\northrend + + + scripts\northrend + + + scripts\northrend + + + scripts\northrend + + + scripts\northrend + + + scripts\northrend + + + scripts\northrend + + + scripts\northrend\azjol-nerub\ahnkahet + + + scripts\northrend\azjol-nerub\ahnkahet + + + scripts\northrend\azjol-nerub\ahnkahet + + + scripts\northrend\azjol-nerub\ahnkahet + + + scripts\northrend\azjol-nerub\ahnkahet + + + scripts\northrend\azjol-nerub\ahnkahet + + + scripts\northrend\azjol-nerub\azjol-nerub + + + scripts\northrend\azjol-nerub\azjol-nerub + + + scripts\northrend\azjol-nerub\azjol-nerub + + + scripts\northrend\azjol-nerub\azjol-nerub + + + scripts\northrend\crusaders_coliseum\trial_of_the_champion + + + scripts\northrend\crusaders_coliseum\trial_of_the_champion + + + scripts\northrend\crusaders_coliseum\trial_of_the_champion + + + scripts\northrend\crusaders_coliseum\trial_of_the_champion + + + scripts\northrend\crusaders_coliseum\trial_of_the_champion + + + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + + scripts\northrend\draktharon_keep + + + scripts\northrend\draktharon_keep + + + scripts\northrend\draktharon_keep + + + scripts\northrend\draktharon_keep + + + scripts\northrend\draktharon_keep + + + scripts\northrend\gundrak + + + scripts\northrend\gundrak + + + scripts\northrend\gundrak + + + scripts\northrend\gundrak + + + scripts\northrend\gundrak + + + scripts\northrend\gundrak + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\naxxramas + + + scripts\northrend\nexus\eye_of_eternity + + + scripts\northrend\nexus\nexus + + + scripts\northrend\nexus\nexus + + + scripts\northrend\nexus\nexus + + + scripts\northrend\nexus\nexus + + + scripts\northrend\nexus\nexus + + + scripts\northrend\obsidian_sanctum + + + scripts\northrend\obsidian_sanctum + + + scripts\northrend\ulduar\halls_of_lightning + + + scripts\northrend\ulduar\halls_of_lightning + + + scripts\northrend\ulduar\halls_of_lightning scripts\northrend\ulduar\halls_of_lightning @@ -1269,45 +1615,69 @@ scripts\northrend\ulduar\ulduar - - scripts\northrend\ulduar\ulduar + + scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls - - scripts\northrend\utgarde_keep\utgarde_keep + + scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls - - scripts\northrend\utgarde_keep\utgarde_keep + + scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls - - scripts\northrend\utgarde_keep\utgarde_keep + + scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls - - scripts\northrend\utgarde_keep\utgarde_keep + + scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection - - scripts\northrend\utgarde_keep\utgarde_keep + + scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection - - scripts\northrend\utgarde_keep\utgarde_pinnacle + + scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection - - scripts\northrend\utgarde_keep\utgarde_pinnacle + + scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection - - scripts\northrend\utgarde_keep\utgarde_pinnacle + + scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection - - scripts\northrend\utgarde_keep\utgarde_pinnacle + + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron - - scripts\northrend\utgarde_keep\utgarde_pinnacle + + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron - + + scripts\northrend\vault_of_archavon + + + scripts\northrend\vault_of_archavon + + + scripts\northrend\vault_of_archavon + + + scripts\northrend\vault_of_archavon + + + scripts\northrend\vault_of_archavon + + scripts\northrend\violet_hold - + + scripts\northrend\violet_hold + + scripts\northrend\violet_hold + + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron + + + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron + scripts\northrend\icecrown_citadel\icecrown_citadel @@ -1344,6 +1714,9 @@ scripts\northrend\icecrown_citadel\icecrown_citadel + + scripts\northrend\icecrown_citadel\icecrown_citadel + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron @@ -1353,14 +1726,11 @@ scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron - - scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection - - - scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection + + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron - - scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection + + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls @@ -1374,296 +1744,319 @@ scripts\outland - - scripts\outland + + scripts\northrend\icecrown_citadel\icecrown_citadel - - scripts\outland + + scripts\northrend\icecrown_citadel\icecrown_citadel - - scripts\outland + + scripts\northrend\naxxramas - - scripts\outland + + scripts\northrend\naxxramas - - scripts\outland + + scripts\northrend\naxxramas - - scripts\outland + + scripts\northrend\naxxramas - - scripts\outland + + scripts\northrend\naxxramas - - scripts\outland + + scripts\northrend\naxxramas - - scripts\outland + + scripts\northrend\naxxramas - + + scripts\northrend\naxxramas + + scripts\outland\auchindoun\auchenai_crypts scripts\outland\auchindoun\mana_tombs - - scripts\outland\auchindoun\mana_tombs + + scripts\northrend\naxxramas - + scripts\outland\auchindoun\sethekk_halls - + scripts\outland\auchindoun\sethekk_halls - - scripts\outland\auchindoun\sethekk_halls + + scripts\northrend\naxxramas - - scripts\outland\auchindoun\shadow_labyrinth + + scripts\northrend\naxxramas - - scripts\outland\auchindoun\shadow_labyrinth + + scripts\northrend\naxxramas - - scripts\outland\auchindoun\shadow_labyrinth + + scripts\northrend\naxxramas - - scripts\outland\auchindoun\shadow_labyrinth + + scripts\northrend\naxxramas - - scripts\outland\auchindoun\shadow_labyrinth + + scripts\northrend\nexus\eye_of_eternity - - scripts\outland\black_temple + + scripts\northrend\nexus\eye_of_eternity - - scripts\outland\black_temple + + scripts\northrend\nexus\nexus - - scripts\outland\black_temple + + scripts\northrend\nexus\nexus - - scripts\outland\black_temple + + scripts\northrend\nexus\nexus - - scripts\outland\black_temple + + scripts\northrend\nexus\nexus - - scripts\outland\black_temple + + scripts\northrend\nexus\nexus - - scripts\outland\black_temple + + scripts\northrend\nexus\oculus - - scripts\outland\black_temple + + scripts\northrend\nexus\oculus - - scripts\outland\black_temple + + scripts\northrend\nexus\oculus - - scripts\outland\black_temple + + scripts\northrend\nexus\oculus - - scripts\outland\black_temple + + scripts\northrend\nexus\oculus - - scripts\outland\coilfang_reservoir\serpent_shrine + + scripts\northrend\nexus\oculus - - scripts\outland\coilfang_reservoir\serpent_shrine + + scripts\northrend\obsidian_sanctum - - scripts\outland\coilfang_reservoir\serpent_shrine + + scripts\northrend\obsidian_sanctum - - scripts\outland\coilfang_reservoir\serpent_shrine + + scripts\northrend\ruby_sanctum - - scripts\outland\coilfang_reservoir\serpent_shrine + + scripts\northrend\ruby_sanctum - + + scripts\northrend\ruby_sanctum + + + scripts\northrend\ruby_sanctum + + + scripts\northrend\ruby_sanctum + + + scripts\northrend\ruby_sanctum + + + scripts\northrend\ulduar\halls_of_lightning + + + scripts\northrend\ulduar\halls_of_lightning + + scripts\outland\coilfang_reservoir\serpent_shrine + + scripts\outland\coilfang_reservoir\slave_pens + scripts\outland\coilfang_reservoir\steam_vault - - scripts\outland\coilfang_reservoir\steam_vault + + scripts\northrend\ulduar\halls_of_lightning - - scripts\outland\coilfang_reservoir\steam_vault + + scripts\northrend\ulduar\halls_of_stone - - scripts\outland\coilfang_reservoir\steam_vault + + scripts\northrend\ulduar\halls_of_stone - - scripts\outland\coilfang_reservoir\underbog + + scripts\northrend\ulduar\halls_of_stone - - scripts\outland\gruuls_lair + + scripts\northrend\ulduar\halls_of_stone - - scripts\outland\gruuls_lair + + scripts\northrend\ulduar\halls_of_stone - - scripts\outland\gruuls_lair + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\blood_furnace + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\blood_furnace + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\blood_furnace + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\blood_furnace + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\hellfire_ramparts + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\hellfire_ramparts + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\hellfire_ramparts + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\hellfire_ramparts + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\magtheridons_lair + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\magtheridons_lair + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\shattered_halls + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\shattered_halls + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\shattered_halls + + scripts\northrend\ulduar\ulduar - - scripts\outland\hellfire_citadel\shattered_halls + + scripts\northrend\ulduar\ulduar - - scripts\outland\tempest_keep\arcatraz + + scripts\northrend\ulduar\ulduar - - scripts\outland\tempest_keep\arcatraz + + scripts\northrend\ulduar\ulduar - - scripts\outland\tempest_keep\arcatraz + + scripts\northrend\utgarde_keep\utgarde_keep - - scripts\outland\tempest_keep\botanica + + scripts\northrend\utgarde_keep\utgarde_keep - - scripts\outland\tempest_keep\botanica + + scripts\northrend\utgarde_keep\utgarde_keep - - scripts\outland\tempest_keep\botanica + + scripts\northrend\utgarde_keep\utgarde_keep - - scripts\outland\tempest_keep\the_eye + + scripts\northrend\utgarde_keep\utgarde_keep - - scripts\outland\tempest_keep\the_eye + + scripts\northrend\utgarde_keep\utgarde_pinnacle - - scripts\outland\tempest_keep\the_eye + + scripts\northrend\utgarde_keep\utgarde_pinnacle - - scripts\outland\tempest_keep\the_eye + + scripts\northrend\utgarde_keep\utgarde_pinnacle - - scripts\outland\tempest_keep\the_eye + + scripts\northrend\utgarde_keep\utgarde_pinnacle - - scripts\outland\tempest_keep\the_mechanar + + scripts\northrend\utgarde_keep\utgarde_pinnacle - - scripts\outland\tempest_keep\the_mechanar + + scripts\northrend\vault_of_archavon - - scripts\outland\tempest_keep\the_mechanar + + scripts\northrend\vault_of_archavon - - scripts\outland\tempest_keep\the_mechanar + + scripts\northrend\vault_of_archavon - - scripts\outland\tempest_keep\the_mechanar + + scripts\northrend\vault_of_archavon - - scripts\world + + scripts\northrend\vault_of_archavon - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + scripts\northrend\violet_hold - - scripts\world + + base - - scripts\world + + base - - include + + scripts\custom - - include + + scripts\custom - - include + + scripts\kalimdor\caverns_of_time\culling_of_stratholme - - include + + scripts\kalimdor\caverns_of_time\culling_of_stratholme - - system + + scripts\kalimdor\caverns_of_time\culling_of_stratholme - - system + + scripts\kalimdor\caverns_of_time\culling_of_stratholme - - - scripts\northrend\ruby_sanctum + + scripts\kalimdor\caverns_of_time\culling_of_stratholme - - scripts\northrend\ruby_sanctum + + scripts\kalimdor\caverns_of_time\culling_of_stratholme - - scripts\northrend\ruby_sanctum + + scripts\kalimdor\caverns_of_time\culling_of_stratholme - + scripts\northrend\ruby_sanctum @@ -1677,12 +2070,18 @@ base + + base + scripts\eastern_kingdoms\blackrock_depths scripts\eastern_kingdoms\blackrock_depths + + scripts\eastern_kingdoms\blackwing_lair + scripts\eastern_kingdoms\deadmines @@ -1743,6 +2142,9 @@ scripts\kalimdor\caverns_of_time\old_hillsbrad + + scripts\kalimdor\dire_maul + scripts\kalimdor\onyxias_lair @@ -1758,21 +2160,39 @@ scripts\kalimdor\wailing_caverns + + scripts\kalimdor\zulfarrak + scripts\northrend\azjol-nerub\ahnkahet scripts\northrend\azjol-nerub\azjol-nerub + + scripts\northrend\crusaders_coliseum\trial_of_the_champion + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + scripts\northrend\draktharon_keep + scripts\northrend\gundrak + + scripts\northrend\icecrown_citadel\icecrown_citadel + scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls + + scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection + + + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron + scripts\northrend\naxxramas @@ -1782,6 +2202,9 @@ scripts\northrend\obsidian_sanctum + + scripts\northrend\ruby_sanctum + scripts\northrend\ulduar\halls_of_lightning @@ -1797,6 +2220,9 @@ scripts\northrend\utgarde_keep\utgarde_pinnacle + + scripts\northrend\vault_of_archavon + scripts\northrend\violet_hold @@ -1862,6 +2288,84 @@ + + scripts\northrend\azjol-nerub\ahnkahet + + + scripts\northrend\azjol-nerub\azjol-nerub + + + scripts\northrend\crusaders_coliseum\trial_of_the_champion + + + scripts\northrend\crusaders_coliseum\trial_of_the_crusader + + + scripts\northrend\draktharon_keep + + + scripts\northrend\gundrak + + + scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls + + + scripts\northrend\icecrown_citadel\frozen_halls\halls_of_reflection + + + scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron + + + scripts\northrend\icecrown_citadel\icecrown_citadel + + + scripts\northrend\naxxramas + + + scripts\northrend\nexus\eye_of_eternity + + + scripts\northrend\nexus\nexus + + + scripts\northrend\nexus\oculus + + + scripts\northrend\obsidian_sanctum + + + scripts\northrend\ruby_sanctum + + + scripts\northrend\ulduar\halls_of_lightning + + + scripts\northrend\ulduar\halls_of_stone + + + scripts\northrend\ulduar\ulduar + + + scripts\northrend\utgarde_keep\utgarde_keep + + + scripts\northrend\utgarde_keep\utgarde_pinnacle + + + scripts\northrend\vault_of_archavon + + + scripts\northrend\violet_hold + + + base + + + base + + + scripts\kalimdor\caverns_of_time\culling_of_stratholme + diff --git a/VC80/80ScriptDev2.vcproj b/VC80/80ScriptDev2.vcproj index 79f33f6..b8b0eab 100644 --- a/VC80/80ScriptDev2.vcproj +++ b/VC80/80ScriptDev2.vcproj @@ -381,6 +381,14 @@ RelativePath="..\base\guard_ai.h" > + + + + + + + + + + @@ -619,6 +639,10 @@ + + @@ -739,6 +763,10 @@ RelativePath="..\scripts\eastern_kingdoms\karazhan\bosses_opera.cpp" > + + @@ -963,6 +991,10 @@ + + @@ -1063,10 +1095,26 @@ RelativePath="..\scripts\eastern_kingdoms\sunwell_plateau\boss_brutallus.cpp" > + + + + + + + + @@ -1083,10 +1131,6 @@ RelativePath="..\scripts\eastern_kingdoms\uldaman\boss_archaedas.cpp" > - - @@ -1435,6 +1479,18 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1846,6 +1942,14 @@ RelativePath="..\scripts\northrend\icecrown_citadel\icecrown_citadel\boss_valithria_dreamwalker.cpp" > + + + + @@ -1869,6 +1973,18 @@ RelativePath="..\scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron\boss_scourgelord_tyrannus.cpp" > + + + + + + + + + + + + + + + + + + + + @@ -2114,10 +2258,6 @@ - - @@ -2162,6 +2302,10 @@ RelativePath="..\scripts\northrend\ulduar\ulduar\boss_thorim.cpp" > + + @@ -2171,15 +2315,15 @@ > @@ -2247,10 +2391,43 @@ + + + + + + + + + + + + + + + + + @@ -2318,6 +2495,10 @@ RelativePath="..\scripts\outland\auchindoun\auchenai_crypts\boss_exarch_maladaar.cpp" > + + + + @@ -2458,6 +2643,10 @@ RelativePath="..\scripts\outland\coilfang_reservoir\serpent_shrine\boss_morogrim_tidewalker.cpp" > + + @@ -2470,6 +2659,10 @@ + + - - @@ -2837,6 +3026,22 @@ RelativePath="..\include\sc_instance.h" > + + + + + + + + + + + + + + @@ -630,6 +642,10 @@ + + @@ -750,6 +766,10 @@ RelativePath="..\scripts\eastern_kingdoms\karazhan\bosses_opera.cpp" > + + @@ -974,6 +994,10 @@ + + @@ -1074,10 +1098,26 @@ RelativePath="..\scripts\eastern_kingdoms\sunwell_plateau\boss_brutallus.cpp" > + + + + + + + + @@ -1341,18 +1381,46 @@ + + + + + + + + + + + + + + + + + + @@ -1745,6 +1821,30 @@ + + + + + + + + + + + + + + @@ -1802,6 +1906,10 @@ RelativePath="..\scripts\northrend\draktharon_keep\draktharon_keep.h" > + + @@ -1917,6 +2025,10 @@ + + + + + + + + + + + + + + + + + + + + + + + + @@ -2021,6 +2177,10 @@ + + @@ -2045,10 +2205,6 @@ - - @@ -2058,27 +2214,27 @@ > + + + + @@ -2110,7 +2274,7 @@ > @@ -2178,6 +2342,30 @@ + + + + + + + + + + + + + + + + @@ -2215,11 +2411,11 @@ > @@ -2273,10 +2469,34 @@ RelativePath="..\scripts\northrend\icecrown_citadel\icecrown_citadel\boss_valithria_dreamwalker.cpp" > + + + + + + + + + + + + @@ -2313,7 +2533,7 @@ Name="halls_of_reflection" > + + + + + + + + + + @@ -2401,6 +2641,10 @@ RelativePath="..\scripts\outland\auchindoun\auchenai_crypts\boss_exarch_maladaar.cpp" > + + + + @@ -2557,6 +2805,10 @@ + + + + + + + + + + diff --git a/base/BSW_ai.cpp b/base/BSW_ai.cpp new file mode 100644 index 0000000..e65fb8a --- /dev/null +++ b/base/BSW_ai.cpp @@ -0,0 +1,868 @@ +/* Copyright (C) 2009 - 2010 by /dev/rsa for ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ +#include "precompiled.h" +#include "BSW_ai.h" +#ifdef DEF_BOSS_SPELL_WORKER_H +#include "ace/Process_Mutex.h" + +BSWScriptedAI::BSWScriptedAI(Creature* pCreature) : ScriptedAI(pCreature) +{ + doReset(); + debug_log("BSW: Initialized BSWScriptedAI structure for creature %u difficulty %u",m_creature->GetEntry(),currentDifficulty); +}; + +BSWScriptedAI::~BSWScriptedAI() +{ + m_BSWRecords.clear(); + debug_log("BSW: Removing BSWScriptedAI structure for creature %u",m_creature->GetEntry()); +}; + +void BSWScriptedAI::doReset() +{ + Map* pMap = m_creature->GetMap(); + if (pMap) currentDifficulty = pMap->GetDifficulty(); + else currentDifficulty = RAID_DIFFICULTY_10MAN_NORMAL; + m_BSWRecords.clear(); + setStage(0); + _loadFromDB(); + _fillEmptyDataField(); + resetTimers(); +}; + +void BSWScriptedAI::_resetTimer(uint8 m_uiSpellIdx) +{ + if (m_BSWRecords[m_uiSpellIdx].m_uiSpellTimerMin[currentDifficulty] == 0 + && m_BSWRecords[m_uiSpellIdx].m_uiSpellTimerMax[currentDifficulty] >= HOUR*IN_MILLISECONDS) + { + m_BSWRecords[m_uiSpellIdx].m_SpellTimer = 0; + } + else if (m_BSWRecords[m_uiSpellIdx].m_uiSpellTimerMin[currentDifficulty] != m_BSWRecords[m_uiSpellIdx].m_uiSpellTimerMax[currentDifficulty]) + { + m_BSWRecords[m_uiSpellIdx].m_SpellTimer = urand(0,m_BSWRecords[m_uiSpellIdx].m_uiSpellTimerMax[currentDifficulty]); + } + else m_BSWRecords[m_uiSpellIdx].m_SpellTimer = m_BSWRecords[m_uiSpellIdx].m_uiSpellTimerMin[currentDifficulty]; + +}; + +void BSWScriptedAI::_loadFromDB() +{ + // mutex block for process-safe request execute + ACE_Process_Mutex mMutex = ACE_Process_Mutex("BSW_Lock"); + + debug_log("BSW: Loading table of creature %u spell on difficulty %u", m_creature->GetEntry(), currentDifficulty); + + char query[MAX_QUERY_LEN]; + + sprintf(query, "SELECT entry, spellID_N10, spellID_N25, spellID_H10, spellID_H25, timerMin_N10, timerMin_N25, timerMin_H10, timerMin_H25, timerMax_N10, timerMax_N25, timerMax_H10, timerMax_H25, data1, data2, data3, data4, locData_x, locData_y, locData_z, varData, StageMask_N, StageMask_H, CastType, isVisualEffect, isBugged, textEntry FROM `boss_spell_table` WHERE entry = %u;\r\n", m_creature->GetEntry()); + + mMutex.acquire(); + QueryResult* Result = strSD2Pquery(query); + mMutex.release(); + + if (Result) + { + uint32 uiCount = 0; + do + { + BSWRecord m_BSWRecord; + + Field* pFields = Result->Fetch(); + + m_BSWRecord.id = uiCount; + + uint32 m_creatureEntry = pFields[0].GetUInt32(); + + for (uint8 j = 0; j < DIFFICULTY_LEVELS; ++j) + m_BSWRecord.m_uiSpellEntry[j] = pFields[1+j].GetUInt32(); + + for (uint8 j = 0; j < DIFFICULTY_LEVELS; ++j) + m_BSWRecord.m_uiSpellTimerMin[j] = pFields[1+DIFFICULTY_LEVELS+j].GetUInt32(); + + for (uint8 j = 0; j < DIFFICULTY_LEVELS; ++j) + m_BSWRecord.m_uiSpellTimerMax[j] = pFields[1+DIFFICULTY_LEVELS*2+j].GetUInt32(); + + for (uint8 j = 0; j < DIFFICULTY_LEVELS; ++j) + m_BSWRecord.m_uiSpellData[j] = pFields[1+DIFFICULTY_LEVELS*3+j].GetUInt32(); + + m_BSWRecord.LocData.x = pFields[1+DIFFICULTY_LEVELS*4].GetFloat(); + m_BSWRecord.LocData.y = pFields[2+DIFFICULTY_LEVELS*4].GetFloat(); + m_BSWRecord.LocData.z = pFields[3+DIFFICULTY_LEVELS*4].GetFloat(); + + m_BSWRecord.varData = pFields[4+DIFFICULTY_LEVELS*4].GetInt32(); + + m_BSWRecord.StageMaskN = pFields[5+DIFFICULTY_LEVELS*4].GetUInt32(); + m_BSWRecord.StageMaskH = pFields[6+DIFFICULTY_LEVELS*4].GetUInt32(); + + m_BSWRecord.m_CastTarget = _getBSWCastType(pFields[7+DIFFICULTY_LEVELS*4].GetUInt8()); + + m_BSWRecord.m_IsVisualEffect = (pFields[8+DIFFICULTY_LEVELS*4].GetUInt8() == 0) ? false : true ; + + m_BSWRecord.m_IsBugged = (pFields[9+DIFFICULTY_LEVELS*4].GetUInt8() == 0) ? false : true ; + + m_BSWRecord.textEntry = pFields[10+DIFFICULTY_LEVELS*4].GetInt32(); + + m_BSWRecords.push_back(m_BSWRecord); + + if (m_creatureEntry != m_creature->GetEntry()) error_log("BSW: Unknown error while load boss_spell_table"); + else ++uiCount; + } while (Result->NextRow()); + + delete Result; + + debug_log("BSW: Loaded %u spell data records for creature %u", bossSpellCount(), m_creature->GetEntry()); + } + else + { + error_log("BSW: BSW table for creature %u is empty.", m_creature->GetEntry()); + }; +} + +bool BSWScriptedAI::_QuerySpellPeriod(uint8 m_uiSpellIdx, uint32 diff, bool ignorecast) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + if (m_creature->IsNonMeleeSpellCasted(false) && !ignorecast) return false; + + if (pSpell->m_SpellTimer <= diff) + { + if (pSpell->m_uiSpellTimerMax[currentDifficulty] >= HOUR*IN_MILLISECONDS) pSpell->m_SpellTimer=HOUR*IN_MILLISECONDS; + else pSpell->m_SpellTimer = urand(pSpell->m_uiSpellTimerMin[currentDifficulty],pSpell->m_uiSpellTimerMax[currentDifficulty]); + return true; + } + else + { + pSpell->m_SpellTimer -= diff; + return false; + }; +}; + +CanCastResult BSWScriptedAI::_BSWSpellSelector(uint8 m_uiSpellIdx, Unit* pTarget) +{ + + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + Unit* pSummon = NULL; + + CanCastResult result = CAST_FAIL_OTHER; + + debug_log("BSW: Casting spell number %u type %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); + + if (pSpell->m_uiSpellTimerMax[currentDifficulty] >= HOUR*IN_MILLISECONDS) + m_creature->InterruptNonMeleeSpells(true); + + switch (pSpell->m_CastTarget) { + + case DO_NOTHING: + result = CAST_OK; + break; + + case CAST_ON_SELF: + result = _BSWCastOnTarget(m_creature, m_uiSpellIdx); + break; + + case CAST_ON_SUMMONS: + result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); + break; + + case CAST_ON_VICTIM: + pTarget = m_creature->getVictim(); + result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); + break; + + case CAST_ON_RANDOM: + pTarget = _doSelect(0, false, 60.0f); + result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); + break; + + case CAST_ON_BOTTOMAGGRO: + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_BOTTOMAGGRO,0); + result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); + break; + + case CAST_ON_TARGET: + result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); + break; + + case APPLY_AURA_SELF: + if (_doAura(m_uiSpellIdx, m_creature, EFFECT_INDEX_0)) + result = CAST_OK; + else result = CAST_FAIL_OTHER; + break; + + case APPLY_AURA_TARGET: + if (!pTarget || !pTarget->IsInMap(m_creature)) + { + result = CAST_FAIL_OTHER; + break; + } + if (_doAura(m_uiSpellIdx, pTarget, EFFECT_INDEX_0)) + result = CAST_OK; + else result = CAST_FAIL_OTHER; + break; + + case SUMMON_NORMAL: + pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 5000); + if(pSummon) result = CAST_OK; + else result = CAST_FAIL_OTHER; + break; + + case SUMMON_TEMP: + pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, + urand(pSpell->m_uiSpellTimerMin[currentDifficulty],pSpell->m_uiSpellTimerMax[currentDifficulty])); + if(pSummon) result = CAST_OK; + else result = CAST_FAIL_OTHER; + break; + + case SUMMON_INSTANT: + pSummon = _doSummon(m_uiSpellIdx, TEMPSUMMON_MANUAL_DESPAWN,0); + if(pSummon) result = CAST_OK; + else result = CAST_FAIL_OTHER; + break; + + case CAST_ON_ALLPLAYERS: + { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const& pPlayers = pMap->GetPlayers(); + if (!pPlayers.isEmpty()) + { + for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) + { + pTarget = itr->getSource(); + if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, pSpell->LocData.x)) + { + if (!pSpell->m_IsBugged) + { + m_creature->CastSpell(pTarget, pSpell->m_uiSpellEntry[currentDifficulty], false); + } + else + { + _BSWDoCast(m_uiSpellIdx, pTarget); + }; + result = CAST_OK; + }; + } + } else result = CAST_FAIL_OTHER; + } + break; + + case CAST_ON_FRENDLY: + pTarget = DoSelectLowestHpFriendly(pSpell->LocData.x,0); + result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); + break; + + case CAST_ON_FRENDLY_LOWHP: + pTarget = DoSelectLowestHpFriendly(pSpell->LocData.x,1); + result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); + break; + + case CAST_ON_RANDOM_POINT: + if (!pTarget) pTarget = m_creature; + if (pSpell->LocData.z <= 1.0f) + { + float fPosX, fPosY, fPosZ; + if (!pTarget->IsPositionValid() || !pTarget->IsInMap(m_creature)) + { + if (pTarget->GetTypeId() == TYPEID_PLAYER) + error_log("BSW: CAST_ON_RANDOM_POINT FAILED: player has invalid position. SpellID is %u",pSpell->m_uiSpellEntry[currentDifficulty]); + else error_log("BSW: CAST_ON_RANDOM_POINT FAILED: creature has invalid position. SpellID is %u",pSpell->m_uiSpellEntry[currentDifficulty]); + result = CAST_FAIL_OTHER; + break; + } + + pTarget->GetPosition(fPosX, fPosY, fPosZ); + pTarget->GetRandomPoint(fPosX, fPosY, fPosZ, urand((uint32)pSpell->LocData.x, (uint32)pSpell->LocData.y), fPosX, fPosY, fPosZ); + if ((int)fPosZ == 0) + { + error_log("BSW: CAST_ON_RANDOM_POINT FAILED: Positon Z is NULL. Strange bug"); + result = CAST_FAIL_OTHER; + break; + } + + if (SpellEntry const *spell = (SpellEntry *)GetSpellStore()->LookupEntry(pSpell->m_uiSpellEntry[currentDifficulty])) + if (SpellRangeEntry const *pSpellRange = GetSpellRangeStore()->LookupEntry(spell->rangeIndex)) + if (m_creature->GetDistance(fPosX, fPosY, fPosZ) <= pSpellRange->maxRange) + { + m_creature->CastSpell(fPosX, fPosY, fPosZ, pSpell->m_uiSpellEntry[currentDifficulty], false); + result = CAST_OK; + break; + }; + result = CAST_FAIL_TOO_FAR; + } else result = CAST_FAIL_OTHER; + break; + + case CAST_ON_RANDOM_PLAYER: + if ( pSpell->LocData.x < 1 ) pTarget = _doSelect(0, false, 60.0f); + else pTarget = _doSelect(0, false, (float)pSpell->LocData.x); + result = _BSWCastOnTarget(pTarget, m_uiSpellIdx); + break; + + case APPLY_AURA_ALLPLAYERS: + { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const& pPlayers = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) + { + pTarget = itr->getSource(); + if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, pSpell->LocData.x)) + { + _doAura(m_uiSpellIdx, pTarget, EFFECT_INDEX_0); + result = CAST_OK; + } + } + } + break; + + case FORCE_CAST: + result = _BSWDoForceCast(m_uiSpellIdx, pTarget); + break; + + case SPELLTABLEPARM_NUMBER: + default: + error_log("BSW: FAILED casting spell number %u type %u - type not exists",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); + result = CAST_FAIL_OTHER; + break; + }; + + if (pSpell->textEntry && result == CAST_OK) + { + if (pTarget) + DoScriptText(pSpell->textEntry,m_creature,pTarget); + else + DoScriptText(pSpell->textEntry,m_creature); + }; + + debug_log("BSW: Casted spell number %u, result = %u",pSpell->m_uiSpellEntry[currentDifficulty], result); + + return result; +}; + +CanCastResult BSWScriptedAI::_BSWCastOnTarget(Unit* pTarget, uint8 m_uiSpellIdx) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + if (!pTarget || !pTarget->IsInMap(m_creature) || !pTarget->isAlive()) + { + debug_log("BSW: warning - failed casting (on target) spell number %u - no target or target not in map",pSpell->m_uiSpellEntry[currentDifficulty]); + return CAST_FAIL_OTHER; + } + + debug_log("BSW: Casting (on target) spell %u type %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); + + if (!pSpell->m_IsBugged) return _DoCastSpellIfCan(pTarget, pSpell->m_uiSpellEntry[currentDifficulty]); + else if (pSpell->m_IsBugged) return _BSWDoCast(m_uiSpellIdx, pTarget); + else return CAST_FAIL_OTHER; +}; + +bool BSWScriptedAI::_hasAura(uint8 m_uiSpellIdx, Unit* pTarget) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + return _hasAura(pSpell->m_uiSpellEntry[currentDifficulty], pTarget); + +}; + +bool BSWScriptedAI::_hasAura(uint32 SpellID, Unit* pTarget) +{ + if (!pTarget || !pTarget->IsInMap(m_creature)) + { + error_log("BSW: FAILED Query aura for spell %u - no target or target not in map",SpellID); + return false; + } + + return (pTarget->HasAura(SpellID)); + +}; + +uint8 BSWScriptedAI::_auraCount(uint8 m_uiSpellIdx, Unit* pTarget, SpellEffectIndex index) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + return _auraCount(pSpell->m_uiSpellEntry[currentDifficulty], pTarget, index); + +}; + +uint8 BSWScriptedAI::_auraCount(uint32 SpellID, Unit* pTarget, SpellEffectIndex index) +{ + if (!_hasAura(SpellID,pTarget)) return 0; + + if (Aura* aura = pTarget->GetAura(SpellID, index)) + if (aura->GetStackAmount() > 0) + return aura->GetStackAmount(); + return 0; + +}; + +uint8 BSWScriptedAI::_findSpellIDX(uint32 SpellID) +{ + if (bossSpellCount() > 0) + for(uint8 i = 0; i < bossSpellCount(); ++i) + if (m_BSWRecords[i].m_uiSpellEntry[RAID_DIFFICULTY_10MAN_NORMAL] == SpellID) return i; + + error_log("BSW: spell %u not found in m_creature %u spelltable. Memory or database error?", SpellID, m_creature->GetEntry()); + + return SPELL_INDEX_ERROR; +} + +BSWRecord* BSWScriptedAI::_getRecord(uint32 SpellID) +{ + if (!m_BSWRecords.empty()) + { + for(uint8 i = 0; i < m_BSWRecords.size(); ++i) + if (m_BSWRecords[i].m_uiSpellEntry[RAID_DIFFICULTY_10MAN_NORMAL] == SpellID) return &m_BSWRecords[i]; + } + error_log("BSW: spell %u not found in m_creature %u spelltable. Memory or database error?", SpellID, m_creature->GetEntry()); + return NULL; +} + +BossSpellTableParameters BSWScriptedAI::_getBSWCastType(uint32 pTemp) +{ + switch (pTemp) { + case 0: return DO_NOTHING; + case 1: return CAST_ON_SELF; + case 2: return CAST_ON_SUMMONS; + case 3: return CAST_ON_VICTIM; + case 4: return CAST_ON_RANDOM; + case 5: return CAST_ON_BOTTOMAGGRO; + case 6: return CAST_ON_TARGET; + case 7: return APPLY_AURA_SELF; + case 8: return APPLY_AURA_TARGET; + case 9: return SUMMON_NORMAL; + case 10: return SUMMON_INSTANT; + case 11: return SUMMON_TEMP; + case 12: return CAST_ON_ALLPLAYERS; + case 13: return CAST_ON_FRENDLY; + case 14: return CAST_ON_FRENDLY_LOWHP; + case 15: return CAST_ON_RANDOM_POINT; + case 16: return CAST_ON_RANDOM_PLAYER; + case 17: return APPLY_AURA_ALLPLAYERS; + case 18: return FORCE_CAST; + case 19: return SPELLTABLEPARM_NUMBER; + default: return DO_NOTHING; + }; +}; + +CanCastResult BSWScriptedAI::_BSWDoCast(uint8 m_uiSpellIdx, Unit* pTarget) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + if (!pTarget || !pTarget->IsInMap(m_creature) || !pTarget->isAlive()) + { + error_log("BSW: warning - failed casting bugged spell number %u - no target or target not in map",pSpell->m_uiSpellEntry[currentDifficulty]); + return CAST_FAIL_OTHER; + } + + debug_log("BSW: Casting bugged spell number %u type %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); + + pTarget->InterruptNonMeleeSpells(false); + + pTarget->CastSpell(pTarget, pSpell->m_uiSpellEntry[currentDifficulty], false); + + return CAST_OK; +}; + +CanCastResult BSWScriptedAI::_BSWDoForceCast(uint8 m_uiSpellIdx, Unit* pTarget) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + if (!pTarget || !pTarget->IsInMap(m_creature) || !pTarget->isAlive()) + { + error_log("BSW: warning - failed forced casting spell number %u - no target or target not in map",pSpell->m_uiSpellEntry[currentDifficulty]); + return CAST_FAIL_OTHER; + } + + debug_log("BSW: Forced casting spell number %u ",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); + + pTarget->InterruptNonMeleeSpells(false); + + pTarget->CastSpell(m_creature, pSpell->m_uiSpellEntry[currentDifficulty], true); + + return CAST_OK; +}; + +void BSWScriptedAI::_fillEmptyDataField() +{ + for (uint8 i = 0; i < bossSpellCount(); ++i) + for (uint8 j = 1; j < DIFFICULTY_LEVELS; ++j) + { + if (m_BSWRecords[i].m_uiSpellEntry[j] == 0) + { + SpellEntry const* spell = GetSpellEntryByDifficulty(m_BSWRecords[i].m_uiSpellEntry[0],(Difficulty)j); + if (spell) + m_BSWRecords[i].m_uiSpellEntry[j] = spell->Id; + else m_BSWRecords[i].m_uiSpellEntry[j] = m_BSWRecords[i].m_uiSpellEntry[j-1]; + } + + if (m_BSWRecords[i].m_uiSpellTimerMin[j] == 0) + m_BSWRecords[i].m_uiSpellTimerMin[j] = m_BSWRecords[i].m_uiSpellTimerMin[j-1]; + + if (m_BSWRecords[i].m_uiSpellTimerMax[j] == 0) + m_BSWRecords[i].m_uiSpellTimerMax[j] = m_BSWRecords[i].m_uiSpellTimerMax[j-1]; + + if (m_BSWRecords[i].m_uiSpellData[j] == 0) + m_BSWRecords[i].m_uiSpellData[j] = m_BSWRecords[i].m_uiSpellData[j-1]; + }; +}; + +Unit* BSWScriptedAI::_doSummon(uint8 m_uiSpellIdx, TempSummonType summontype, uint32 delay) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + debug_log("BSW: Summoning creature number %u type %u despawn delay %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget, delay); + + if (pSpell->LocData.z <= 1.0f) + { + float fPosX, fPosY, fPosZ; + if (!m_creature->IsPositionValid()) + { + error_log("BSW: FAILED summoning creature, creature %u has invalid position",m_creature->GetEntry()); + return NULL; + } + m_creature->GetPosition(fPosX, fPosY, fPosZ); + m_creature->GetRandomPoint(fPosX, fPosY, fPosZ, urand((uint32)pSpell->LocData.x, (uint32)pSpell->LocData.y), fPosX, fPosY, fPosZ); + return m_creature->SummonCreature(pSpell->m_uiSpellEntry[currentDifficulty], fPosX, fPosY, fPosZ+0.8f, 0, summontype, delay); + } + else return m_creature->SummonCreature(pSpell->m_uiSpellEntry[currentDifficulty], pSpell->LocData.x, pSpell->LocData.y, pSpell->LocData.z, 0, summontype, delay); +}; + +Unit* BSWScriptedAI::_doSummonAtPosition(uint8 m_uiSpellIdx, float fPosX, float fPosY, float fPosZ) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + switch (pSpell->m_CastTarget) + { + case SUMMON_NORMAL: + return _doSummonAtPosition(pSpell->m_uiSpellEntry[m_uiSpellIdx], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 0, fPosX, fPosY, fPosZ); + break; + + case SUMMON_TEMP: + return _doSummonAtPosition(pSpell->m_uiSpellEntry[m_uiSpellIdx], TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, urand(pSpell->m_uiSpellTimerMin[currentDifficulty],pSpell->m_uiSpellTimerMax[currentDifficulty]), fPosX, fPosY, fPosZ); + break; + + case SUMMON_INSTANT: + return _doSummonAtPosition(pSpell->m_uiSpellEntry[m_uiSpellIdx], TEMPSUMMON_MANUAL_DESPAWN, urand(pSpell->m_uiSpellTimerMin[currentDifficulty],pSpell->m_uiSpellTimerMax[currentDifficulty]), fPosX, fPosY, fPosZ); + break; + + default: + break; + } + error_log("BSW: FAILED creature number %u type %u ",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); + return NULL; +}; + +Unit* BSWScriptedAI::_doSummonAtPosition(uint32 guid, TempSummonType summontype, uint32 delay, float fPosX, float fPosY, float fPosZ) +{ + + debug_log("BSW: Summoning creature number %u despawn delay %u at position %f %f %f", guid, delay, fPosX, fPosY, fPosZ); + + return m_creature->SummonCreature(guid, fPosX, fPosY, fPosZ, 0, summontype, delay); +}; + +bool BSWScriptedAI::_doRemove(uint8 m_uiSpellIdx, Unit* pTarget, uint8 index) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + debug_log("BSW: Removing effects of spell %u type %u",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); + + switch (pSpell->m_CastTarget) + { + case DO_NOTHING: + return true; + break; + + case SUMMON_NORMAL: + case SUMMON_TEMP: + case SUMMON_INSTANT: + return false; + break; + + case CAST_ON_SELF: + case APPLY_AURA_SELF: + pTarget = m_creature; + break; + + case CAST_ON_SUMMONS: + case CAST_ON_VICTIM: + case CAST_ON_BOTTOMAGGRO: + case CAST_ON_TARGET: + case FORCE_CAST: + case APPLY_AURA_TARGET: + if (!pTarget) + return false; + break; + + case CAST_ON_RANDOM: + case CAST_ON_RANDOM_PLAYER: + case APPLY_AURA_ALLPLAYERS: + case CAST_ON_ALLPLAYERS: + _doRemoveFromAll(m_uiSpellIdx); + return true; + break; + + default: + debug_log("BSW: FAILED Removing effects of spell %u type %u - unsupported type",pSpell->m_uiSpellEntry[currentDifficulty], pSpell->m_CastTarget); + return false; + break; + } + + return _doRemove(pSpell->m_uiSpellEntry[currentDifficulty], pTarget, index); + +}; + +bool BSWScriptedAI::_doRemove(uint32 SpellID, Unit* pTarget, uint8 index) +{ + + if (!_hasAura(SpellID, pTarget)) return false; + + if (index == EFFECT_INDEX_ALL) + { + pTarget->RemoveAurasDueToSpell(SpellID); + } + else if (_auraCount(SpellID,pTarget,(SpellEffectIndex)index) > 1) + { + if (SpellAuraHolder* holder = pTarget->GetSpellAuraHolder(SpellID, pTarget->GetGUID())) + { + if (holder->ModStackAmount(-1)) + { + pTarget->RemoveSpellAuraHolder(holder, AURA_REMOVE_BY_DISPEL); + } else return false; + } + } + else + pTarget->RemoveAurasDueToSpell(SpellID); + + debug_log("BSW: Removed effects of spell %u index %u",SpellID, index); + return true; +}; + +bool BSWScriptedAI::_doRemoveFromAll(uint8 m_uiSpellIdx) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + return _doRemoveFromAll(pSpell->m_uiSpellEntry[currentDifficulty]); +}; + +bool BSWScriptedAI::_doRemoveFromAll(uint32 SpellID) +{ + Map* pMap = m_creature->GetMap(); + Map::PlayerList const& pPlayers = pMap->GetPlayers(); + if (!pPlayers.isEmpty()) + { + debug_log("BSW: Removing effects of spell %u from all players",SpellID); + + for (Map::PlayerList::const_iterator itr = pPlayers.begin(); itr != pPlayers.end(); ++itr) + { + Unit* pTarget = itr->getSource(); + if (pTarget && pTarget->IsInWorld()) + { + pTarget->RemoveAurasDueToSpell(SpellID); + if (Pet* pPet = pTarget->GetPet()) + pPet->RemoveAurasDueToSpell(SpellID); + } + } + return true; + } + else + { + debug_log("BSW: Removing effects of spell %u from all players FAILED - no players in map",SpellID); + return false; + } +}; + +bool BSWScriptedAI::_doAura(uint8 m_uiSpellIdx, Unit* pTarget) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + if (!pTarget) + pTarget = m_creature; + + bool result = true; + + for(int i = 0; i < MAX_EFFECT_INDEX; ++i) + result = result && _doAura(m_uiSpellIdx, pTarget, SpellEffectIndex(i), !i); + + return result; + +}; + +bool BSWScriptedAI::_doAura(uint32 SpellID, Unit* pTarget) +{ + if (!pTarget) + pTarget = m_creature; + + bool result = true; + + for(int i = 0; i < MAX_EFFECT_INDEX; ++i) + result = result && _doAura(SpellID, pTarget, SpellEffectIndex(i), 0, !i); + + return result; + +}; + + +bool BSWScriptedAI::_doAura(uint8 m_uiSpellIdx, Unit* pTarget, SpellEffectIndex index, bool isStack) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + if (!pTarget) + pTarget = m_creature; + + return _doAura(pSpell->m_uiSpellEntry[currentDifficulty], pTarget, index, pSpell->varData, isStack); + +}; + + +bool BSWScriptedAI::_doAura(uint32 SpellID, Unit* pTarget, SpellEffectIndex index, int32 basepoint, bool isStack) +{ + if (!pTarget || !pTarget->IsInMap(m_creature) || !pTarget->isAlive()) + { + error_log("BSW: FAILED adding aura of spell number %u - no target or target not in map or target is dead",SpellID); + return false; + } + + if (_hasAura(SpellID,pTarget)) + debug_log("BSW: adding aura stack from spell %u index %u",SpellID, index); + else debug_log("BSW: adding new aura from spell %u index %u",SpellID, index); + + SpellEntry const *spell = (SpellEntry *)GetSpellStore()->LookupEntry(SpellID); + + if (spell) + { + if (IsSpellAppliesAura(spell, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) || IsSpellHaveEffect(spell, SPELL_EFFECT_PERSISTENT_AREA_AURA)) + { + int32 _basepoint = basepoint ? basepoint - 1 : spell->EffectBasePoints[index] + 1; + + bool addedToExisting = true; + + SpellAuraHolder* holder = pTarget->GetSpellAuraHolder(SpellID, pTarget->GetGUID()); + + Aura* aura = NULL; + + if (!holder) + { + holder = CreateSpellAuraHolder(spell, pTarget, pTarget); + addedToExisting = false; + } + + + if (aura = holder->GetAuraByEffectIndex(index)) + { + if (isStack) + holder->ModStackAmount(1); + } + else + { + aura = CreateAura(spell, index, &_basepoint, holder, pTarget); + aura->SetAuraDuration(aura->GetAuraMaxDuration()); + holder->AddAura(aura, index); + } + + if (addedToExisting) + { + pTarget->AddAuraToModList(aura); + holder->SetInUse(true); + aura->ApplyModifier(true,true); + holder->SetInUse(false); + } + else + pTarget->AddSpellAuraHolder(holder); + + return true; + } + } + + error_log("BSW: FAILED adding aura from spell %u index %u",SpellID, index); + + return false; +}; + +CanCastResult BSWScriptedAI::_DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, uint64 uiOriginalCasterGUID) +{ + if (!pTarget || !pTarget->IsInWorld() || !pTarget->IsInMap(m_creature)|| !pTarget->isAlive()) return CAST_FAIL_OTHER; + + return DoCastSpellIfCan(pTarget,uiSpell,uiCastFlags,uiOriginalCasterGUID); +} + +// Not threat-based select random player function + +Unit* BSWScriptedAI::_doSelect(uint32 SpellID, bool spellsearchtype, float range) +{ + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &pList = pMap->GetPlayers(); + if (pList.isEmpty()) return NULL; + + std::vector _list; + _list.clear(); + + for(Map::PlayerList::const_iterator i = pList.begin(); i != pList.end(); ++i) + if (Player* player = i->getSource()) + { + if (player->isGameMaster()) continue; + + if (!player->IsInMap(m_creature)) continue; + + if (player->isAlive() + && player->IsWithinDistInMap(m_creature, range) + && (SpellID == 0 || (player->HasAura(SpellID) == spellsearchtype)) + ) + _list.push_back((Unit*)player); + } + + debug_log("BSW: search random player with criteria = %u, found %u players.",SpellID,_list.size()); + + if (_list.empty()) return NULL; + else return _list[urand(0,_list.size() - 1)]; +}; + +Creature* BSWScriptedAI::doSelectNearestCreature(uint32 id, float range) +{ + Creature* pTarget = GetClosestCreatureWithEntry(m_creature, id, range); + + if (pTarget && pTarget->IsInMap(m_creature) && pTarget != m_creature && pTarget->isAlive()) + { + debug_log("BSW: search creature %u in range %f - found it.",id,range); + return pTarget; + } + else + { + debug_log("BSW: search creature %u in range %f - NOT found.",id,range); + return NULL; + } +} + +uint32 BSWScriptedAI::_getSpellData(uint8 m_uiSpellIdx) +{ + BSWRecord* pSpell = &m_BSWRecords[m_uiSpellIdx]; + + return pSpell->m_uiSpellData[currentDifficulty]; +}; + +bool BSWScriptedAI::doCastAll(uint32 diff) +{ + + uint8 succesfulCast = 0; + + if (bossSpellCount() > 0) + { + for(uint8 i = 0; i < bossSpellCount(); ++i) + if (_QuerySpellPeriod(i, diff)) + if (_BSWSpellSelector(i) == CAST_OK) + ++succesfulCast; + + if (succesfulCast) + debug_log("BSW: Casting all spells for creature %u done. Successful casted %u spells from %u.", m_creature->GetEntry(),succesfulCast,bossSpellCount()); + } + else + { + error_log("BSW: Casting all spells for creature %u failed. Database has no spells.", m_creature->GetEntry()); + } + + return (succesfulCast >= 1) ? true : false; + +}; + +bool BSWScriptedAI::_isDifficultyInMask(uint8 mask) +{ + return ((uint8)currentDifficulty & mask); +}; + +#endif \ No newline at end of file diff --git a/base/BSW_ai.h b/base/BSW_ai.h new file mode 100644 index 0000000..158484e --- /dev/null +++ b/base/BSW_ai.h @@ -0,0 +1,296 @@ +/* Copyright (C) 2009 - 2010 by /dev/rsa for ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_BOSS_SPELL_WORKER_H +#define DEF_BOSS_SPELL_WORKER_H +#define BSW_VERSION 0.6.12 + +#include "precompiled.h" +#include "Player.h" +#include "SpellAuras.h" +#include "SpellMgr.h" +#include "Unit.h" +#include "Database/DatabaseEnv.h" +#include "../ScriptMgr.h" + + +enum +{ + DIFFICULTY_LEVELS = 4, + EFFECT_INDEX_ALL = 255, + SPELL_INDEX_ERROR = 255, +}; + +enum BossSpellFlag +{ + CAST_NORMAL, + CAST_REMOVE, + CAST_OVERRIDE, + SPELLFLAG_NUMBER +}; + +enum BossSpellTableParameters +{ + DO_NOTHING = 0, + CAST_ON_SELF = 1, + CAST_ON_SUMMONS = 2, + CAST_ON_VICTIM = 3, + CAST_ON_RANDOM = 4, + CAST_ON_BOTTOMAGGRO = 5, + CAST_ON_TARGET = 6, + APPLY_AURA_SELF = 7, + APPLY_AURA_TARGET = 8, + SUMMON_NORMAL = 9, + SUMMON_INSTANT = 10, + SUMMON_TEMP = 11, + CAST_ON_ALLPLAYERS = 12, + CAST_ON_FRENDLY = 13, + CAST_ON_FRENDLY_LOWHP = 14, + CAST_ON_RANDOM_POINT = 15, + CAST_ON_RANDOM_PLAYER = 16, + APPLY_AURA_ALLPLAYERS = 17, + FORCE_CAST = 18, + SPELLTABLEPARM_NUMBER +}; + +struct Locations +{ + float x, y, z, o; + int32 id; +}; + +struct WayPoints +{ + WayPoints(int32 _id, float _x, float _y, float _z) + { + id = _id; + x = _x; + y = _y; + z = _z; + } + int32 id; + float x, y, z; +}; + +struct BSWRecord +{ + + public: + // External (loaded from database) variables + uint32 id; + uint32 m_uiSpellEntry[DIFFICULTY_LEVELS]; // Stores spell entry for difficulty levels + uint32 m_uiSpellTimerMin[DIFFICULTY_LEVELS]; // The timer (min) before the next spell casting, in milliseconds + uint32 m_uiSpellTimerMax[DIFFICULTY_LEVELS]; // The timer (max) before the next spell casting + uint32 m_uiSpellData[DIFFICULTY_LEVELS]; // Additional data for spell casting or summon + Locations LocData; // Float data structure for locations + int varData; // Additional data for spell + uint32 StageMaskN; // Stage mask for this spell (normal) + uint32 StageMaskH; // Stage mask for this spell (heroic) + BossSpellTableParameters m_CastTarget; // Target on casting spell + bool m_IsVisualEffect; // Spellcasting is visual effect or real effect + bool m_IsBugged; // Need override for this spell + int32 textEntry; // Text entry from script_text for this spell + // Internal variables + uint32 m_SpellTimer; // Current timer for this spell +}; + +struct MANGOS_DLL_DECL BSWScriptedAI : public ScriptedAI +{ + public: + explicit BSWScriptedAI(Creature* pCreature); + + ~BSWScriptedAI(); + + void doReset(); + + void resetTimer(uint32 SpellID) + { + if (queryIndex(_findSpellIDX(SpellID))) _resetTimer(_findSpellIDX(SpellID)); + else return; + }; + + void resetTimers() + { + for (uint8 i = 0; i < bossSpellCount(); ++i) + _resetTimer(i); + }; + + bool timedQuery(uint32 SpellID, uint32 diff, bool ignorecast = false) + { + return queryIndex(_findSpellIDX(SpellID)) ? _QuerySpellPeriod(_findSpellIDX(SpellID), diff, ignorecast) : false; + }; + + CanCastResult timedCast(uint32 SpellID, uint32 diff, Unit* pTarget = NULL) + { + if (!queryIndex(_findSpellIDX(SpellID))) return CAST_FAIL_OTHER; + return _QuerySpellPeriod(_findSpellIDX(SpellID), diff) ? _BSWSpellSelector(_findSpellIDX(SpellID), pTarget) : CAST_FAIL_STATE; + }; + + CanCastResult doCast(uint32 SpellID, Unit* pTarget = NULL) + { + return queryIndex(_findSpellIDX(SpellID)) ? _BSWSpellSelector(_findSpellIDX(SpellID), pTarget) : CAST_FAIL_OTHER; + }; + + CanCastResult doCast(Unit* pTarget, uint32 SpellID) + { + if (!pTarget) return CAST_FAIL_OTHER; + return queryIndex(_findSpellIDX(SpellID)) ? _BSWCastOnTarget(pTarget, _findSpellIDX(SpellID)) : CAST_FAIL_OTHER; + }; + + bool doRemove(uint32 SpellID, Unit* pTarget = NULL, uint8 index = EFFECT_INDEX_ALL) + { + return queryIndex(_findSpellIDX(SpellID)) ? _doRemove(_findSpellIDX(SpellID),pTarget,index) : _doRemove(SpellID,pTarget,index); + }; + + bool doRemoveFromAll(uint32 SpellID) + { + return queryIndex(_findSpellIDX(SpellID)) ? _doRemoveFromAll(_findSpellIDX(SpellID)) : _doRemoveFromAll(SpellID); + }; + + bool doAura(uint32 SpellID, Unit* pTarget, SpellEffectIndex index, int32 basepoint = 0, bool isStack = true) + { + return queryIndex(_findSpellIDX(SpellID)) ? _doAura(_findSpellIDX(SpellID), pTarget, index, isStack) : _doAura(SpellID, pTarget, index, basepoint, isStack); + }; + + bool doAura(uint32 SpellID, Unit* pTarget = NULL) + { + return queryIndex(_findSpellIDX(SpellID)) ? _doAura(_findSpellIDX(SpellID), pTarget) : _doAura(SpellID, pTarget); + }; + + bool hasAura(uint32 SpellID, Unit* pTarget = NULL) + { + if (!pTarget) pTarget = m_creature; + return queryIndex(_findSpellIDX(SpellID)) ? _hasAura(_findSpellIDX(SpellID),pTarget) : _hasAura(SpellID,pTarget); + }; + + uint8 auraCount(uint32 SpellID, Unit* pTarget = NULL, SpellEffectIndex index = EFFECT_INDEX_0) + { + if (!pTarget) pTarget = m_creature; + return queryIndex(_findSpellIDX(SpellID)) ? _auraCount(_findSpellIDX(SpellID),pTarget,index) : _auraCount(SpellID,pTarget,index); + }; + + Unit* doSummon(uint32 SpellID, TempSummonType type = TEMPSUMMON_CORPSE_TIMED_DESPAWN, uint32 delay = 60000) + { + return queryIndex(_findSpellIDX(SpellID)) ? _doSummon(_findSpellIDX(SpellID), type, delay) : NULL; + }; + + Unit* doSelectRandomPlayer(uint32 SpellID = 0, bool spellsearchtype = false, float range = 100.0f) + { + return _doSelect(SpellID, spellsearchtype, range); + }; + + Unit* doSelectRandomPlayerAtRange(float range) + { + return _doSelect(0, false, range); + }; + + Unit* doSummon(uint32 SpellID, float fPosX, float fPosY, float fPosZ, TempSummonType type = TEMPSUMMON_CORPSE_TIMED_DESPAWN, uint32 delay = 60000) + { + return queryIndex(_findSpellIDX(SpellID)) ? _doSummonAtPosition(_findSpellIDX(SpellID), fPosX, fPosY, fPosZ) : _doSummonAtPosition(SpellID, type, delay, fPosX, fPosY, fPosZ); + }; + + uint8 bossSpellCount() + { + return m_BSWRecords.size(); + }; + + bool queryIndex(uint8 m_uiSpellIdx) + { + if (m_uiSpellIdx == SPELL_INDEX_ERROR) return false; + else if (m_uiSpellIdx >= 0 && m_uiSpellIdx < bossSpellCount()) return true; + else return false; + }; + + Creature* doSelectNearestCreature(uint32 guid, float range = 120.0f); + + uint32 getSpellData(uint32 SpellID) + { + return queryIndex(_findSpellIDX(SpellID)) ? _getSpellData(_findSpellIDX(SpellID)) : 0; + }; + + bool doCastAll(uint32 diff); + + uint8 getStage() { return _stage; }; + + void setStage(uint8 stage) { _stage = stage; }; + + bool isHeroic() { Map* pMap = m_creature->GetMap(); return pMap->IsRaid() ? _isDifficultyInMask(12) : _isDifficultyInMask(2); }; + + bool isNormal() { return !isHeroic(); }; + + bool is25() { Map* pMap = m_creature->GetMap(); return pMap->IsRaid() ? _isDifficultyInMask(10) : false; }; + + protected: + + Difficulty currentDifficulty; + + std::vector m_BSWRecords; + + private: + + BossSpellTableParameters _getBSWCastType(uint32 pTemp); + + uint8 _findSpellIDX(uint32 SpellID); + + BSWRecord* _getRecord(uint32 SpellID); + + void _loadFromDB(); + + void _resetTimer(uint8 m_uiSpellIdx); + + Unit* _doSelect(uint32 SpellID, bool spellsearchtype = false, float range = 100.0f); + + Unit* _doSummon(uint8 m_uiSpellIdx, TempSummonType type = TEMPSUMMON_CORPSE_TIMED_DESPAWN, uint32 delay = 60000); + + Unit* _doSummonAtPosition(uint8 m_uiSpellIdx, float fPosX, float fPosY, float fPosZ); + + Unit* _doSummonAtPosition(uint32 guid, TempSummonType type, uint32 delay, float fPosX, float fPosY, float fPosZ); + + CanCastResult _BSWDoCast(uint8 m_uiSpellIdx, Unit* pTarget); + + CanCastResult _BSWDoForceCast(uint8 m_uiSpellIdx, Unit* pTarget); + + CanCastResult _BSWSpellSelector(uint8 m_uiSpellIdx, Unit* pTarget = NULL); + + CanCastResult _BSWCastOnTarget(Unit* pTarget, uint8 m_uiSpellIdx); + + bool _QuerySpellPeriod(uint8 m_uiSpellIdx, uint32 diff, bool ignorecast = false); + + CanCastResult _DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags = 0, uint64 uiOriginalCasterGUID = 0); + + bool _doRemove(uint8 m_uiSpellIdx, Unit* pTarget = NULL, uint8 index = EFFECT_INDEX_ALL); + + bool _doRemove(uint32 SpellID, Unit* pTarget, uint8 index = EFFECT_INDEX_ALL); + + bool _doRemoveFromAll(uint8 m_uiSpellIdx); + + bool _doRemoveFromAll(uint32 SpellID); + + bool _doAura(uint8 m_uiSpellIdx, Unit* pTarget, SpellEffectIndex index, bool isStack = true); + + bool _doAura(uint32 SpellID, Unit* pTarget, SpellEffectIndex index, int32 basepoint = 0, bool isStack = true); + + bool _doAura(uint8 m_uiSpellIdx, Unit* pTarget); + + bool _doAura(uint32 SpellID, Unit* pTarget); + + bool _hasAura(uint8 m_uiSpellIdx, Unit* pTarget); + + bool _hasAura(uint32 SpellID, Unit* pTarget); + + uint8 _auraCount(uint8 m_uiSpellIdx, Unit* pTarget = NULL, SpellEffectIndex index = EFFECT_INDEX_0); + + uint8 _auraCount(uint32 SpellID, Unit* pTarget, SpellEffectIndex index); + + void _fillEmptyDataField(); + + uint32 _getSpellData(uint8 m_uiSpellIdx); + + bool _isDifficultyInMask(uint8 mask); + + uint8 _stage; + +}; + +#endif \ No newline at end of file diff --git a/base/BSW_instance.cpp b/base/BSW_instance.cpp new file mode 100644 index 0000000..5d40240 --- /dev/null +++ b/base/BSW_instance.cpp @@ -0,0 +1,103 @@ +/* Copyright (C) 2009 - 2010 by /dev/rsa for ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#include "precompiled.h" +#include "BSW_instance.h" + +BSWScriptedInstance::BSWScriptedInstance(Map* pMap) : ScriptedInstance(pMap) +{ + debug_log("BSW: Initialized BSWScriptedInstance structure for map %u difficulty %u",pMap->GetId(),pMap->GetDifficulty()); + m_auiEvent = 0; + m_auiEventTimer = 0; + m_auiCreatureID = 0; + m_auiEventLock = false; + m_pMap = pMap; +}; + +BSWScriptedInstance::~BSWScriptedInstance() +{ + debug_log("BSW: Removing BSWScriptedInstance structure for map %u",m_pMap->GetId()); +}; + +void BSWScriptedInstance::DoCompleteAchievement(uint32 uiAchievmentId) +{ + Map::PlayerList const& lPlayers = instance->GetPlayers(); + + if (!lPlayers.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->CompletedAchievement(uiAchievmentId); + } + } + else + debug_log("BSW: DoCompleteAchievement attempt set data, but no players in map."); +} + +void BSWScriptedInstance::DoOpenDoor(uint64 guid) +{ + if (!guid) + return; + + GameObject* pGo = instance->GetGameObject(guid); + + if (pGo) + pGo->SetGoState(GO_STATE_ACTIVE); + else + debug_log("BSW: DoOpenDoor attempt set data to object %u, but no this object", guid); +} + +void BSWScriptedInstance::DoCloseDoor(uint64 guid) +{ + if (!guid) + return; + + GameObject* pGo = instance->GetGameObject(guid); + + if (pGo) + pGo->SetGoState(GO_STATE_READY); + else + debug_log("BSW: DoCloseDoor attempt set data to object %u, but no this object", guid); +} + +uint32 BSWScriptedInstance::GetEvent(uint32 creatureID) +{ + if (m_auiEventLock || m_auiCreatureID != creatureID) + { + return 0; + } + else + { + debug_log("BSW: GetEvent: send event %u to creature %u",m_auiEvent, creatureID); + m_auiEventLock = true; + return m_auiEvent; + } +} + +void BSWScriptedInstance::SetNextEvent(uint32 EventNum, uint32 creatureID, uint32 timer) +{ + m_auiEvent = EventNum; + m_auiCreatureID = creatureID; + m_auiEventTimer = timer; + m_auiEventLock = false; + debug_log("BSW: SetNextEvent: setted event %u to creature %u, timer %u",m_auiEvent, creatureID, timer); +} + +bool BSWScriptedInstance::GetEventTimer(uint32 creatureID, const uint32 diff) +{ + if (m_auiEvent == 0 || m_auiCreatureID != creatureID) + return false; + + if (m_auiEventTimer <= diff) + { + m_auiEventTimer = 0; + return true; + } + else + { + m_auiEventTimer -= diff; + return false; + } +} diff --git a/base/BSW_instance.h b/base/BSW_instance.h new file mode 100644 index 0000000..93758eb --- /dev/null +++ b/base/BSW_instance.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2009 - 2010 by /dev/rsa for ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef BSW_INSTANCE_H +#define BSW_INSTANCE_H +#define BSW_INSTANCE_VERSION 0.6.14 +#include "sc_instance.h" + +class MANGOS_DLL_DECL BSWScriptedInstance : public ScriptedInstance +{ + public: + + BSWScriptedInstance(Map* pMap); + ~BSWScriptedInstance(); + + //sends completed achievments to all players in instance + void DoCompleteAchievement(uint32 uiAchievmentId); + void DoOpenDoor(uint64 guid); + void DoCloseDoor(uint64 guid); + + void SetNextEvent(uint32 EventNum, uint32 creatureID, uint32 timer = 1000); + uint32 GetEvent(uint32 creatureID); + bool GetEventTimer(uint32 creatureID, const uint32 diff); + + private: + uint32 m_auiEvent; + uint32 m_auiCreatureID; + uint32 m_auiEventTimer; + bool m_auiEventLock; + Map* m_pMap; +}; +#endif diff --git a/base/escort_ai.cpp b/base/escort_ai.cpp index ecc4a62..b34f1d6 100644 --- a/base/escort_ai.cpp +++ b/base/escort_ai.cpp @@ -517,3 +517,4 @@ void npc_escortAI::SetEscortPaused(bool bPaused) else RemoveEscortState(STATE_ESCORT_PAUSED); } + diff --git a/include/sc_creature.cpp b/include/sc_creature.cpp index f0526c8..684938b 100644 --- a/include/sc_creature.cpp +++ b/include/sc_creature.cpp @@ -525,7 +525,7 @@ bool ScriptedAI::EnterEvadeIfOutOfCombatArea(const uint32 uiDiff) return false; break; case NPC_SARTHARION: // sartharion (calculate box) - if (fX > 3218.86f && fX < 3275.69f && fY < 572.40f && fY > 484.68f) + if (fX > 3203.97f && fX < 3289.40f && fY < 576.70f && fY > 484.68f) return false; break; default: diff --git a/include/sc_instance.cpp b/include/sc_instance.cpp index f91b8a0..0ad8a52 100644 --- a/include/sc_instance.cpp +++ b/include/sc_instance.cpp @@ -56,3 +56,19 @@ void ScriptedInstance::DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData) else debug_log("SD2: DoUpdateWorldState attempt send data but no players in map."); } + +void ScriptedInstance::DoCompleteAchievement(uint32 uiAchievmentId) +{ + Map::PlayerList const& lPlayers = instance->GetPlayers(); + + if (!lPlayers.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + pPlayer->CompletedAchievement(uiAchievmentId); + } + } + else + debug_log("SD2: DoCompleteAchievement attempt set data but no players in map."); +} diff --git a/include/sc_instance.h b/include/sc_instance.h index 3b44167..4176e51 100644 --- a/include/sc_instance.h +++ b/include/sc_instance.h @@ -38,5 +38,8 @@ class MANGOS_DLL_DECL ScriptedInstance : public InstanceData //sends world state update to all players in instance void DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData); + + //sends completed achievments to all players in instance + void DoCompleteAchievement(uint32 uiAchievmentId); }; #endif diff --git a/patches/MaNGOS-10790-ScriptDev2.patch b/patches/MaNGOS-10790-ScriptDev2.patch new file mode 100644 index 0000000..a394bcc --- /dev/null +++ b/patches/MaNGOS-10790-ScriptDev2.patch @@ -0,0 +1,63 @@ +From df5d403e6d51a9dbc3dcea66faa20aa3d096f13d Mon Sep 17 00:00:00 2001 +From: Reve +Date: Fri, 5 Mar 2010 21:41:55 +0100 +Subject: [PATCH] ScriptDev2 patch. + +--- + configure.ac | 6 +++++- + src/bindings/Makefile.am | 2 +- + src/mangosd/Makefile.am | 4 ++-- + 3 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 4e7d76c..c86e539 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -364,7 +364,11 @@ AC_CONFIG_FILES([ + src/mangosd/Makefile + src/mangosd/mangosd.conf.dist + src/bindings/Makefile +- src/bindings/universal/Makefile ++ src/bindings/ScriptDev2/Makefile ++ src/bindings/ScriptDev2/scriptdev2.conf.dist ++ src/bindings/ScriptDev2/config.h ++ src/bindings/ScriptDev2/sql/Makefile ++ src/bindings/ScriptDev2/sql/Updates/Makefile + ]) + + ## Configure ACE, if needed +diff --git a/src/bindings/Makefile.am b/src/bindings/Makefile.am +index d7dc654..79ea910 100644 +--- a/src/bindings/Makefile.am ++++ b/src/bindings/Makefile.am +@@ -14,4 +14,4 @@ + # along with this program; if not, write to the Free Software + # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +-SUBDIRS = universal ++SUBDIRS = ScriptDev2 +diff --git a/src/mangosd/Makefile.am b/src/mangosd/Makefile.am +index dd1b2a4..b7723f5 100644 +--- a/src/mangosd/Makefile.am ++++ b/src/mangosd/Makefile.am +@@ -40,7 +40,7 @@ mangos_worldd_SOURCES = \ + + ## Link world daemon against the shared library + mangos_worldd_LDADD = \ +- ../bindings/universal/libmangosscript.la \ ++ ../bindings/ScriptDev2/libmangosscript.la \ + ../game/libmangosgame.a \ + ../game/vmap/libmangosvmaps.a \ + ../shared/Database/libmangosdatabase.a \ +@@ -51,7 +51,7 @@ mangos_worldd_LDADD = \ + ../../dep/src/g3dlite/libg3dlite.a \ + ../../dep/src/gsoap/libgsoap.a + +-mangos_worldd_LDFLAGS = -L../../dep/src/g3dlite -L../../dep/src/gsoap -L../bindings/universal/ -L$(libdir) $(MANGOS_LIBS) -export-dynamic ++mangos_worldd_LDFLAGS = -L../../dep/src/g3dlite -L../../dep/src/gsoap -L../bindings/ScriptDev2/ -L$(libdir) $(MANGOS_LIBS) -export-dynamic + + ## Additional files to include when running 'make dist' + # Include world daemon configuration +-- +1.6.5.1.1367.gcd48 + diff --git a/revision.h b/revision.h new file mode 100644 index 0000000..6740dc0 --- /dev/null +++ b/revision.h @@ -0,0 +1,6 @@ +#ifndef __REVISION_H__ +#define __REVISION_H__ + #define REVISION_ID "54" + #define REVISION_DATE "2010-12-04" + #define REVISION_TIME "21:01:31" +#endif // __REVISION_H__ diff --git a/scripts/battlegrounds/battleground.cpp b/scripts/battlegrounds/battleground.cpp index dcb1b21..ec95533 100644 --- a/scripts/battlegrounds/battleground.cpp +++ b/scripts/battlegrounds/battleground.cpp @@ -57,7 +57,10 @@ struct MANGOS_DLL_DECL npc_spirit_guideAI : public ScriptedAI { // auto cast the whole time this spell if (!m_creature->GetCurrentSpell(CURRENT_CHANNELED_SPELL)) + { + m_creature->CastSpell(m_creature, SPELL_SPIRIT_HEAL, true); m_creature->CastSpell(m_creature, SPELL_SPIRIT_HEAL_CHANNEL, false); + } } void CorpseRemoved(uint32 &) diff --git a/scripts/custom/npc_arena_honor.cpp b/scripts/custom/npc_arena_honor.cpp new file mode 100644 index 0000000..daf5247 --- /dev/null +++ b/scripts/custom/npc_arena_honor.cpp @@ -0,0 +1,100 @@ +/* Copyright (C) 2006 - 2010 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: npc_arena_honor +SD%Complete: 100% +SDComment: by tempura, corrected by /dev/rsa +SDCategory: custom +EndScriptData */ +/* проверка руÑÑкого */ +#include "precompiled.h" +#include "sc_creature.h" +#include "sc_gossip.h" + +#define GOSSIP_ITEM_ARENA_TO_HONOR -3000770 +#define GOSSIP_ITEM_ARENA_TO_HONOR1 -3000771 +#define GOSSIP_ITEM_HONOR_TO_ARENA -3000772 +#define GOSSIP_ITEM_HONOR_TO_ARENA1 -3000773 + +#define UNSUCCESSFUL_HONOR -1001007 +#define UNSUCCESSFUL_ARENA -1001008 + +bool GossipHello_npc_arena_honor(Player* pPlayer, Creature *pCreature) +{ + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_HONOR_TO_ARENA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_HONOR_TO_ARENA1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARENA_TO_HONOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARENA_TO_HONOR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4); + pPlayer->SEND_GOSSIP_MENU(3961,pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_arena_honor(Player *pPlayer, Creature *pCreature, uint32 sender, uint32 action) +{ + if (action == GOSSIP_ACTION_INFO_DEF + 1) + { + if (pPlayer->GetHonorPoints() >= 1000) + { + pPlayer->ModifyHonorPoints(-1000); + pPlayer->ModifyArenaPoints(+90); + } + else + DoScriptText(UNSUCCESSFUL_HONOR, pCreature); + } + if (action == GOSSIP_ACTION_INFO_DEF + 2) + { + if (pPlayer->GetHonorPoints() >= 10000) + { + pPlayer->ModifyHonorPoints(-10000); + pPlayer->ModifyArenaPoints(+900); + } + else + DoScriptText(UNSUCCESSFUL_HONOR, pCreature); + } + if (action == GOSSIP_ACTION_INFO_DEF + 3) + { + if (pPlayer->GetArenaPoints() >= 100) + { + pPlayer->ModifyArenaPoints(-100); + pPlayer->ModifyHonorPoints(+900); + } + else + DoScriptText(UNSUCCESSFUL_ARENA, pCreature); + } + if (action == GOSSIP_ACTION_INFO_DEF + 4) + { + if (pPlayer->GetArenaPoints() >= 1000) + { + pPlayer->ModifyArenaPoints(-1000); + pPlayer->ModifyHonorPoints(+9000); + } + else + DoScriptText(UNSUCCESSFUL_ARENA, pCreature); + } + pPlayer->CLOSE_GOSSIP_MENU(); + return true; +} + +void AddSC_npc_arena_honor() +{ + Script *newscript; + newscript = new Script; + newscript->Name="npc_arena_honor"; + newscript->pGossipHello = &GossipHello_npc_arena_honor; + newscript->pGossipSelect = &GossipSelect_npc_arena_honor; + newscript->RegisterSelf(); +} diff --git a/scripts/custom/teleguy.cpp b/scripts/custom/teleguy.cpp new file mode 100644 index 0000000..f2e8f18 --- /dev/null +++ b/scripts/custom/teleguy.cpp @@ -0,0 +1,877 @@ +#include "precompiled.h" +long long int money; +int costo; + +bool GossipHello_mob_teleguy(Player *player, Creature *_Creature) +{ + if ( player->GetTeam() == ALLIANCE ) { + player->ADD_GOSSIP_ITEM( 5, "Darnassus. 5 Silver" , GOSSIP_SENDER_MAIN, 1203); + player->ADD_GOSSIP_ITEM( 5, "Exodar. 5 Silver" , GOSSIP_SENDER_MAIN, 1216); + player->ADD_GOSSIP_ITEM( 5, "Stormwind. 5 Silver" , GOSSIP_SENDER_MAIN, 1206); + player->ADD_GOSSIP_ITEM( 5, "Ironforge. 5 Silver" , GOSSIP_SENDER_MAIN, 1224); + player->ADD_GOSSIP_ITEM( 5, "Gnomeregan. 5 Silver" , GOSSIP_SENDER_MAIN, 1222); + player->ADD_GOSSIP_ITEM( 5, "Shattrath City. 5 Silver" , GOSSIP_SENDER_MAIN, 1287); + player->ADD_GOSSIP_ITEM( 5, "Dalaran. 5 Silver" , GOSSIP_SENDER_MAIN, 1205); + player->ADD_GOSSIP_ITEM( 5, "Isle Of Quel'Danas. 5 Silver" , GOSSIP_SENDER_MAIN, 1288); + player->ADD_GOSSIP_ITEM( 7, "[Instances] ->" , GOSSIP_SENDER_MAIN, 5550); + player->ADD_GOSSIP_ITEM( 7, "[Instances WotLK] ->" , GOSSIP_SENDER_MAIN, 5554); + } else { + player->ADD_GOSSIP_ITEM( 5, "Orgrimmar. 5 Silver" , GOSSIP_SENDER_MAIN, 1215); + player->ADD_GOSSIP_ITEM( 5, "Silvermoon. 5 Silver" , GOSSIP_SENDER_MAIN, 1217); + player->ADD_GOSSIP_ITEM( 5, "Undercity. 5 Silver" , GOSSIP_SENDER_MAIN, 1213); + player->ADD_GOSSIP_ITEM( 5, "Thunder Bluff. 5 Silver" , GOSSIP_SENDER_MAIN, 1225); + player->ADD_GOSSIP_ITEM( 5, "Gnomeregan. 5 Silver" , GOSSIP_SENDER_MAIN, 1222); + player->ADD_GOSSIP_ITEM( 5, "Shattrath City. 5 Silver" , GOSSIP_SENDER_MAIN, 1287); + player->ADD_GOSSIP_ITEM( 5, "Dalaran. 5 Silver" , GOSSIP_SENDER_MAIN, 1205); + player->ADD_GOSSIP_ITEM( 5, "Isle Of Quel'Danas. 5 Silver" , GOSSIP_SENDER_MAIN, 1288); + player->ADD_GOSSIP_ITEM( 7, "[Instances] ->" , GOSSIP_SENDER_MAIN, 5550); + player->ADD_GOSSIP_ITEM( 7, "[Instances WotLK] ->" , GOSSIP_SENDER_MAIN, 5554); + } + player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE,_Creature->GetGUID()); + return true; +} + + +void SendDefaultMenu_mob_teleguy(Player *player, Creature *_Creature, uint32 action ) +{ + if(!player->getAttackers().empty()) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You are in combat!", LANG_UNIVERSAL); + return; + } + + if( player->getLevel() < 8 ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be lvl 8+", LANG_UNIVERSAL); + return; + } + + money = player-> GetMoney(); + costo = 500; + + if (money < costo ) + { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You haven't enough money", LANG_UNIVERSAL); + return; + } + + switch(action) + { + case 5550: //Instances + player->ADD_GOSSIP_ITEM( 5, "Ragefire Chasm. 10 Silver" , GOSSIP_SENDER_MAIN, 1248); + player->ADD_GOSSIP_ITEM( 5, "The Wailing Caverns. 10 Silver" , GOSSIP_SENDER_MAIN, 1249); + player->ADD_GOSSIP_ITEM( 5, "The Stockade. 10 Silver" , GOSSIP_SENDER_MAIN, 1253); + player->ADD_GOSSIP_ITEM( 5, "Deadmines. 10 Silver" , GOSSIP_SENDER_MAIN, 1250); + player->ADD_GOSSIP_ITEM( 5, "Shadowfang Keep. 10 Silver" , GOSSIP_SENDER_MAIN, 1251); + player->ADD_GOSSIP_ITEM( 5, "Blackfathom Deeps. 10 Silver" , GOSSIP_SENDER_MAIN, 1252); + player->ADD_GOSSIP_ITEM( 5, "Razorfen Kraul. 20 Silver" , GOSSIP_SENDER_MAIN, 1254); + player->ADD_GOSSIP_ITEM( 5, "Razorfen Downs. 20 Silver" , GOSSIP_SENDER_MAIN, 1256); + player->ADD_GOSSIP_ITEM( 5, "Scarlet Monastery. 20 Silver" , GOSSIP_SENDER_MAIN, 1257); + player->ADD_GOSSIP_ITEM( 7, "[More] ->" , GOSSIP_SENDER_MAIN, 5551); + player->ADD_GOSSIP_ITEM( 7, "<- [Main Menu]" , GOSSIP_SENDER_MAIN, 5552); + player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE,_Creature->GetGUID()); + break; + case 5551: //More Instances + player->ADD_GOSSIP_ITEM( 5, "Uldaman. 30 Silver" , GOSSIP_SENDER_MAIN, 1258); + player->ADD_GOSSIP_ITEM( 5, "Zul'Farrak. 30 Silver" , GOSSIP_SENDER_MAIN, 1259); + player->ADD_GOSSIP_ITEM( 5, "Maraudon. 40 Silver" , GOSSIP_SENDER_MAIN, 1260); + player->ADD_GOSSIP_ITEM( 5, "Maraudon. 40 Silver" , GOSSIP_SENDER_MAIN, 1260); + player->ADD_GOSSIP_ITEM( 5, "The Sunken Temple. 40 Silver" , GOSSIP_SENDER_MAIN, 1261); + player->ADD_GOSSIP_ITEM( 5, "Blackrock Depths. 40 Silver" , GOSSIP_SENDER_MAIN, 1262); + player->ADD_GOSSIP_ITEM( 5, "Dire Maul. 50 Silver" , GOSSIP_SENDER_MAIN, 1263); + player->ADD_GOSSIP_ITEM( 5, "Blackrock Spire. 50 Silver" , GOSSIP_SENDER_MAIN, 1264); + player->ADD_GOSSIP_ITEM( 5, "Stratholme. 50 Silver" , GOSSIP_SENDER_MAIN, 1265); + player->ADD_GOSSIP_ITEM( 5, "Scholomance. 50 Silver" , GOSSIP_SENDER_MAIN, 1266); + player->ADD_GOSSIP_ITEM( 7, "[More] ->" , GOSSIP_SENDER_MAIN, 5553); + player->ADD_GOSSIP_ITEM( 7, "<- [Back]" , GOSSIP_SENDER_MAIN, 5550); + player->ADD_GOSSIP_ITEM( 7, "<- [Main Menu]" , GOSSIP_SENDER_MAIN, 5552); + player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE,_Creature->GetGUID()); + break; + +case 5553: //Instances 60-70 +player->ADD_GOSSIP_ITEM( 5, "Karazhan. 1 Gold" , GOSSIP_SENDER_MAIN, 4007); +player->ADD_GOSSIP_ITEM( 5, "Gruul's Lair. 1 Gold" , GOSSIP_SENDER_MAIN, 4008); +player->ADD_GOSSIP_ITEM( 5, "Hellfire Citadel. 1 Gold" , GOSSIP_SENDER_MAIN, 4009); +player->ADD_GOSSIP_ITEM( 5, "Coilfang Reservoir. 1 Gold" , GOSSIP_SENDER_MAIN, 4010); +player->ADD_GOSSIP_ITEM( 5, "Tempest Keep. 1 Gold" , GOSSIP_SENDER_MAIN, 4011); +player->ADD_GOSSIP_ITEM( 5, "Caverns of Time. 1 Gold" , GOSSIP_SENDER_MAIN, 4012); +player->ADD_GOSSIP_ITEM( 5, "Zul'Aman. 1 Gold" , GOSSIP_SENDER_MAIN, 4016); +player->ADD_GOSSIP_ITEM( 5, "Black Temple. 1 Gold" , GOSSIP_SENDER_MAIN, 4013); +player->ADD_GOSSIP_ITEM( 5, "Magister's Terrace. 2 Gold" , GOSSIP_SENDER_MAIN, 4017); +player->ADD_GOSSIP_ITEM( 5, "Sunwell Plateau. 2 Gold" , GOSSIP_SENDER_MAIN, 4018); +player->ADD_GOSSIP_ITEM( 7, "<- [Back]" , GOSSIP_SENDER_MAIN, 5550); +player->ADD_GOSSIP_ITEM( 7, "<- [Main Menu]" , GOSSIP_SENDER_MAIN, 5552); + + +player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE,_Creature->GetGUID()); + +break; + +case 5554: //Instances 75-80 NORTHREND +player->ADD_GOSSIP_ITEM( 5, "Utgarde Keep. 20 Gold" , GOSSIP_SENDER_MAIN, 4019); +player->ADD_GOSSIP_ITEM( 5, "The Nexus. 20 Gold" , GOSSIP_SENDER_MAIN, 4020); +player->ADD_GOSSIP_ITEM( 5, "Azjol-Nerub. 20 Gold" , GOSSIP_SENDER_MAIN, 4021); +player->ADD_GOSSIP_ITEM( 5, "Ahn'kahet: The Old Kingdom. 20 Gold" , GOSSIP_SENDER_MAIN, 4022); +player->ADD_GOSSIP_ITEM( 5, "Drak'Tharon Keep. 20 Gold" , GOSSIP_SENDER_MAIN, 4023); +player->ADD_GOSSIP_ITEM( 5, "The Violet Hold. 20 Gold" , GOSSIP_SENDER_MAIN, 4024); +player->ADD_GOSSIP_ITEM( 5, "Gun' Drak. 20 Gold" , GOSSIP_SENDER_MAIN, 4025); +player->ADD_GOSSIP_ITEM( 5, "Utgarde Pinnacle. 20 Gold" , GOSSIP_SENDER_MAIN, 4026); +player->ADD_GOSSIP_ITEM( 5, "Ulduar. 20 Gold" , GOSSIP_SENDER_MAIN, 4027); +player->ADD_GOSSIP_ITEM( 5, "The Obsidian Sanctum. 20 Gold" , GOSSIP_SENDER_MAIN, 4028); +player->ADD_GOSSIP_ITEM( 5, "Naxxramas. 20 Gold" , GOSSIP_SENDER_MAIN, 4029); +player->ADD_GOSSIP_ITEM( 7, "<- [Back]" , GOSSIP_SENDER_MAIN, 5550); +player->ADD_GOSSIP_ITEM( 7, "<- [Main Menu]" , GOSSIP_SENDER_MAIN, 5552); + + +player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE,_Creature->GetGUID()); + +break; + +case 5552: //Back To Main Menu + if ( player->GetTeam() == ALLIANCE ) { +player->ADD_GOSSIP_ITEM( 5, "Darnassus. 5 Silver" , GOSSIP_SENDER_MAIN, 1203); +player->ADD_GOSSIP_ITEM( 5, "Exodar. 5 Silver" , GOSSIP_SENDER_MAIN, 1216); +player->ADD_GOSSIP_ITEM( 5, "Stormwind. 5 Silver" , GOSSIP_SENDER_MAIN, 1206); +player->ADD_GOSSIP_ITEM( 5, "Ironforge. 5 Silver" , GOSSIP_SENDER_MAIN, 1224); +player->ADD_GOSSIP_ITEM( 5, "Gnomeregan. 5 Silver" , GOSSIP_SENDER_MAIN, 1222); +player->ADD_GOSSIP_ITEM( 5, "Shattrath City. 5 Silver" , GOSSIP_SENDER_MAIN, 1287); +player->ADD_GOSSIP_ITEM( 5, "Dalaran. 5 Silver" , GOSSIP_SENDER_MAIN, 1205); +player->ADD_GOSSIP_ITEM( 5, "Isle Of Quel'Danas. 5 Silver" , GOSSIP_SENDER_MAIN, 1288); +player->ADD_GOSSIP_ITEM( 7, "[Instances] ->" , GOSSIP_SENDER_MAIN, 5550); +player->ADD_GOSSIP_ITEM( 7, "[Instances WotLK] ->" , GOSSIP_SENDER_MAIN, 5554); + + } else { + + +player->ADD_GOSSIP_ITEM( 5, "Orgrimmar. 5 Silver" , GOSSIP_SENDER_MAIN, 1215); +player->ADD_GOSSIP_ITEM( 5, "Silvermoon. 5 Silver" , GOSSIP_SENDER_MAIN, 1217); +player->ADD_GOSSIP_ITEM( 5, "Undercity. 5 Silver" , GOSSIP_SENDER_MAIN, 1213); +player->ADD_GOSSIP_ITEM( 5, "Thunder Bluff. 5 Silver" , GOSSIP_SENDER_MAIN, 1225); +player->ADD_GOSSIP_ITEM( 5, "Gnomeregan. 5 Silver" , GOSSIP_SENDER_MAIN, 1222); +player->ADD_GOSSIP_ITEM( 5, "Shattrath City. 5 Silver" , GOSSIP_SENDER_MAIN, 1287); +player->ADD_GOSSIP_ITEM( 5, "Dalaran. 5 Silver" , GOSSIP_SENDER_MAIN, 1205); +player->ADD_GOSSIP_ITEM( 5, "Isle Of Quel'Danas. 5 Silver" , GOSSIP_SENDER_MAIN, 1288); +player->ADD_GOSSIP_ITEM( 7, "[Instances] ->" , GOSSIP_SENDER_MAIN, 5550); +player->ADD_GOSSIP_ITEM( 7, "[Instances WotLK] ->" , GOSSIP_SENDER_MAIN, 5554); + } + +player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE,_Creature->GetGUID()); + +break; + +case 1203: // Teleport to Darnassus +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(1, 9947.52f, 2482.73f, 1316.21f, 0.0f); +player->ModifyMoney(-1*costo); +break; + +// Teleport to Stormwind +case 1206: +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(0, -8960.14f, 516.266f, 96.3568f, 0.0f); +player->ModifyMoney(-1*costo); +break; + +// Teleport to Dalaran +case 1205: +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(571, 5804.14f, 624.770f, 647.7670f, 1.64f); +player->ModifyMoney(-1*costo); +break; + +// Teleport to Undercity +case 1213: +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(0, 1819.71f, 238.79f, 60.5321f, 0.0f); +player->ModifyMoney(-1*costo); + +break; + +// Teleport to Orgrimmar +case 1215: +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(1, 1552.5f, -4420.66f, 8.94802f, 0.0f); +player->ModifyMoney(-1*costo); +break; + +// Teleport to Exodar +case 1216: +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(530, -4073.03f, -12020.4f, -1.47f, 0.0f); +player->ModifyMoney(-1*costo); +break; + +// Teleport to Silvermoon +case 1217: +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(530, 9338.74f, -7277.27f, 13.7895f, 0.0f); +player->ModifyMoney(-1*costo); + +break; + +case 1222://teleport player to Gnomeregan +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(0, -5163.43f,660.40f,348.28f,4.65f); +player->ModifyMoney(-1*costo); + +break; + +// Teleport to Ironforge +case 1224: +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(0, -4924.07f, -951.95f, 501.55f, 5.40f); +player->ModifyMoney(-1*costo); + +break; + +// Teleport to Thunder Bluff +case 1225: +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(1, -1280.19f,127.21f,131.35f,5.16f); +player->ModifyMoney(-1*costo); + +break; + +case 1248://teleport player to Ragefire Chasm + +if( player->getLevel() >= 8) + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, 1800.53f,-4394.68f,-17.93f,5.49f); + player->ModifyMoney(-2*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 8!", LANG_UNIVERSAL); + } + +break; + +case 1249://teleport player to the Wailing Caverns + +if (player->getLevel() >= 10) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, -722.53f,-2226.30f,16.94f,2.71f); + player->ModifyMoney(-2*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 10!", LANG_UNIVERSAL); + } + +break; + +case 1250://teleport player to the Deadmines + +if (player->getLevel() >= 10) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -11212.04f,1658.58f,25.67f,1.45f); + player->ModifyMoney(-2*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 10!", LANG_UNIVERSAL); + } + +break; + +case 1251://teleport player to Shadowfang Keep + + if (player->getLevel() >= 15) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -254.47f,1524.68f,76.89f,1.56f); + player->ModifyMoney(-2*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 15!", LANG_UNIVERSAL); + } + +break; + +case 1252://teleport player to Blackfathom Deeps + + if (player->getLevel() >= 15) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, 4254.58f,664.74f,-29.04f,1.97f); + player->ModifyMoney(-2*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 15!", LANG_UNIVERSAL); + } + +break; + +case 1253://teleport player to the Stockade + + if (player->getLevel() >= 20) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -8769.76f,813.08f,97.63f,2.26f); + player->ModifyMoney(-2*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 20!", LANG_UNIVERSAL); + } + +break; + +case 1254://teleport player to Razorfen Kraul + + if (player->getLevel() >= 24) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, -4484.04f,-1739.40f,86.47f,1.23f); + player->ModifyMoney(-4*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 24!", LANG_UNIVERSAL); + } + +break; + +case 1255://teleport player to Gnomeregan + + if (player->getLevel() >= 20) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -5162.62f,667.81f,248.05f,1.48f); + player->ModifyMoney(-4*costo); + + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 20!", LANG_UNIVERSAL); + } + +break; + +case 1256://teleport player to Razorfen Downs + + if (player->getLevel() >= 25) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, -4645.08f,-2470.85f,85.53f,4.39f); + player->ModifyMoney(-4*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 25!", LANG_UNIVERSAL); + } + +break; + +case 1257://teleport player to the Scarlet Monastery + + if (player->getLevel() >= 25) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, 2843.89f,-693.74f,139.32f,5.11f); + player->ModifyMoney(-4*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 25!", LANG_UNIVERSAL); + } + +break; + +case 1258://teleport player to Uldaman + + if (player->getLevel() >= 35) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -6119.70f,-2957.30f,204.11f,0.03f); + player->ModifyMoney(-6*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 35!", LANG_UNIVERSAL); + } + +break; + +case 1259://teleport player to Zul'Farrak + + if (player->getLevel() >= 35) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, -6839.39f,-2911.03f,8.87f,0.41f); + player->ModifyMoney(-6*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 35!", LANG_UNIVERSAL); + } + +break; + + +case 1260://teleport player to Maraudon + + if (player->getLevel() >= 40) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, -1433.33f,2955.34f,96.21f,4.82f); + player->ModifyMoney(-8*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 40!", LANG_UNIVERSAL); + } + +break; + +case 1261://teleport player to the Sunken Temple + + if (player->getLevel() >= 45) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -10346.92f,-3851.90f,-43.41f,6.09f); + player->ModifyMoney(-8*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 45!", LANG_UNIVERSAL); + } + +break; + +case 1262://teleport player to Blackrock Depths + + if (player->getLevel() >= 45) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -7301.03f,-913.19f,165.37f,0.08f); + player->ModifyMoney(-8*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 45!", LANG_UNIVERSAL); + } + +break; + +case 1263://teleport player to Dire Maul + + if (player->getLevel() >= 50) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, -3982.47f,1127.79f,161.02f,0.05f); + player->ModifyMoney(-10*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 50!", LANG_UNIVERSAL); + } + +break; + +case 1264://teleport player to Blackrock Spire + + if (player->getLevel() >= 50) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -7535.43f,-1212.04f,285.45f,5.29f); + player->ModifyMoney(-10*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 50!", LANG_UNIVERSAL); + } + +break; + +case 1265://teleport player to Stratholme + + if (player->getLevel() >= 50) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, 3263.54f,-3379.46f,143.59f,0.00f); + player->ModifyMoney(-10*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 50!", LANG_UNIVERSAL); + } + +break; + +case 1266://teleport player to Scholomance + + if (player->getLevel() >= 50) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, 1219.01f,-2604.66f,85.61f,0.50f); + player->ModifyMoney(-10*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 50!", LANG_UNIVERSAL); + } + +break; + +case 1287:// Shattrath City + +if( player->getLevel() >= 58) + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(530, -1850.209961f, 5435.821777f, -10.961435f, 3.403913f); + player->ModifyMoney(-1*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 58!", LANG_UNIVERSAL); + } + +break; + +case 1288://teleport player to Isle Of Quel'Danas + + if (player->getLevel() >= 65) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(530, 12947.4f,-6893.31f,5.68398f,3.09154f); + player->ModifyMoney(-1*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 65!", LANG_UNIVERSAL); + } + +break; + +case 4007:// Karazhan + + if (player->getLevel() >= 70) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(0, -11118.8f, -2010.84f, 47.0807f, 0.0f); + player->ModifyMoney(-20*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 70!", LANG_UNIVERSAL); + } + +break; + +case 4008:// Gruul's Lair + + if (player->getLevel() >= 65) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(530, 3539.007568f, 5082.357910f, 1.691071f, 0.0f); + player->ModifyMoney(-20*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 65!", LANG_UNIVERSAL); + } + +break; + +case 4009:// Hellfire Citadel +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(530, -305.816223f, 3056.401611f, -2.473183f, 2.01f); +player->ModifyMoney(-20*costo); +break; + +case 4010:// Coilfang Reservoir +player->CLOSE_GOSSIP_MENU(); +player->TeleportTo(530, 517.288025f, 6976.279785f, 32.007198f, 0.0f); +player->ModifyMoney(-20*costo); +break; + +case 4011:// Tempest Keep + + if (player->getLevel() >= 70) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(530, 3089.579346f, 1399.046509f, 187.653458f, 4.794070f); + player->ModifyMoney(-20*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 70!", LANG_UNIVERSAL); + } + +break; + +case 4012:// Caverns of Time + + if (player->getLevel() >= 66) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(1, -8173.66f, -4746.36f, 33.8423f, 4.93989f); + player->ModifyMoney(-20*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 66!", LANG_UNIVERSAL); + } + +break; + +case 4016:// Zul'Aman + + if (player->getLevel() >= 70) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(530, 6846.95f, -7954.5f, 170.028f, 4.61501f); + player->ModifyMoney(-20*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 70!", LANG_UNIVERSAL); + } + +break; + +case 4013:// Black Temple + + if (player->getLevel() >= 70) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(530, -3610.719482f, 324.987579f, 37.400028f, 3.282981f); + player->ModifyMoney(-20*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 70!", LANG_UNIVERSAL); + } + +break; + +case 4017:// magistrate + + if (player->getLevel() >= 70) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(530, 12884.6f, -7317.69f, 65.5023f, 4.799f); + player->ModifyMoney(-40*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 70!", LANG_UNIVERSAL); + } + +break; + +case 4018:// sunwell + + if (player->getLevel() >= 70) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(530, 12574.1f, -6774.81f, 15.0904f, 3.13788f); + player->ModifyMoney(-40*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 70!", LANG_UNIVERSAL); + } + +break; + +case 4019:// Utgarde Keep + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 1219.720f, -4865.28f, 41.25f, 0.31f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +case 4020:// The Nexus + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 3776.950f, 6953.80f, 105.05f, 0.345f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +case 4021:// Azjol-Nerub + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 3675.430f, 2169.00f, 35.90f, 2.29f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +case 4022:// Ahn'kahet: The Old Kingdom + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 3646.760f, 2045.17f, 1.79f, 4.37f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +case 4023:// Drak'Tharon Keep + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 4450.860f, -2045.25f, 162.83f, 0.00f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +case 4024:// The Violet Hold + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 5679.820f, 486.80f, 652.40f, 4.08f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +case 4025:// Gun' Drak + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 6937.540f, -4455.98f, 450.68f, 1.00f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +case 4026:// Utgarde Pinnacle + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 1245.690f, -4856.59f, 216.86f, 3.45f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +case 4027:// Ulduar + + if (player->getLevel() >= 80) + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 8976.240f, -1281.33f, 1059.01f, 0.58f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } +break; + +case 4028:// The Obsidian Sanctum + + if (player->getLevel() >= 80) + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 3625.780f, 280.40f, -120.14f, 3.25f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } +break; + +case 4029:// Naxxramas + + if (player->getLevel() >= 80) + + { + player->CLOSE_GOSSIP_MENU(); + player->TeleportTo(571, 3668.719f, -1262.460f, 243.63f, 5.03f); + player->ModifyMoney(-400*costo); + } else { + player->CLOSE_GOSSIP_MENU(); + _Creature->MonsterSay("You must be at least level 80!", LANG_UNIVERSAL); + } + +break; + +} + + +} + +bool GossipSelect_mob_teleguy(Player *player, Creature *_Creature, uint32 sender, uint32 action ) +{ + // Main menu + if (sender == GOSSIP_SENDER_MAIN) + { + player->PlayerTalkClass->ClearMenus(); + SendDefaultMenu_mob_teleguy(player, _Creature, action ); + } + return true; +} + +void AddSC_mob_teleguy() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_teleguy"; + newscript->pGossipHello = &GossipHello_mob_teleguy; + newscript->pGossipSelect = &GossipSelect_mob_teleguy; + newscript->pItemHello = NULL; + newscript->pGOHello = NULL; + newscript->pAreaTrigger = NULL; + newscript->pItemQuestAccept = NULL; + newscript->pGOQuestAccept = NULL; + newscript->pGOChooseReward = NULL; + newscript->RegisterSelf(); +} diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_coren_direbrew.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_coren_direbrew.cpp new file mode 100644 index 0000000..9c03843 --- /dev/null +++ b/scripts/eastern_kingdoms/blackrock_depths/boss_coren_direbrew.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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_coren_direbrew +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Blackrock Depths +EndScriptData */ + +#include "precompiled.h" + +void AddSC_boss_coren_direbrew() +{ +} diff --git a/scripts/eastern_kingdoms/blackwing_lair/blackwing_lair.h b/scripts/eastern_kingdoms/blackwing_lair/blackwing_lair.h new file mode 100644 index 0000000..e592de1 --- /dev/null +++ b/scripts/eastern_kingdoms/blackwing_lair/blackwing_lair.h @@ -0,0 +1,3 @@ +/* Copyright (C) 2006 - 2010 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ diff --git a/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp b/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp index 6a0a8bb..89b6a5f 100644 --- a/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp +++ b/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp @@ -22,3 +22,7 @@ SDCategory: Blackwing Lair EndScriptData */ #include "precompiled.h" + +void AddSC_instance_blackwing_lair() +{ +} diff --git a/scripts/eastern_kingdoms/eversong_woods.cpp b/scripts/eastern_kingdoms/eversong_woods.cpp index f552cc0..727062f 100644 --- a/scripts/eastern_kingdoms/eversong_woods.cpp +++ b/scripts/eastern_kingdoms/eversong_woods.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Eversong_Woods SD%Complete: 100 -SDComment: Quest support: 8483, 8488, 9686 +SDComment: Quest support: 8483, 8488, 8490, 9686 SDCategory: Eversong Woods EndScriptData */ @@ -26,6 +26,7 @@ npc_kelerun_bloodmourn go_harbinger_second_trial npc_prospector_anvilward npc_apprentice_mirveda +npc_infused_crystal EndContentData */ #include "precompiled.h" @@ -434,6 +435,106 @@ CreatureAI* GetAI_npc_apprentice_mirvedaAI(Creature* pCreature) return new npc_apprentice_mirvedaAI (pCreature); } +/*###### +## npc_infused_crystal +######*/ + +enum +{ + NPC_ENRAGED_WRATH = 17086, + QUEST_POWERING_OUR_DEFENSES = 8490, + INFUSED_CRYSTAL_EMOTE = -1999811 +}; + +float fEnragedWrathPosition[3][4] = +{ + {8259.375977f, -7202.288574f, 139.287430f, 5.0f}, + {8255.425781f, -7222.026367f, 139.607162f, 5.0f}, + {8267.902344f, -7193.510742f, 139.430374f, 5.0f} +}; + +struct MANGOS_DLL_DECL npc_infused_crystalAI : public ScriptedAI +{ + npc_infused_crystalAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SetCombatMovement(false); + Reset(); + } + + uint32 m_uiQuestTimer; + uint32 m_uiSpawnTimer; + uint64 m_uiPlayerGUID; + + bool bCompleted; + + void Reset() + { + m_uiQuestTimer = 60000; + m_uiSpawnTimer = 1000; + m_uiPlayerGUID = 0; + bCompleted = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + Player* pPlayer = (Player*)pWho; + + if (pPlayer->GetQuestStatus(QUEST_POWERING_OUR_DEFENSES) != QUEST_STATUS_INCOMPLETE) + return; + + m_uiPlayerGUID = pPlayer->GetGUID(); + } + + void Aggro(Unit* pWho){} + + void JustDied(Unit* pWho) + { + if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID)) + if (pPlayer->GetQuestStatus(QUEST_POWERING_OUR_DEFENSES) == QUEST_STATUS_INCOMPLETE) + pPlayer->FailQuest(QUEST_POWERING_OUR_DEFENSES); + } + + void UpdateAI(const uint32 uiDiff) + { + if (bCompleted) + return; + + if (m_uiSpawnTimer < uiDiff) + { + for (uint8 i = 0; i < 3; ++i) + { + if (Creature* pEnragedWrath = m_creature->SummonCreature(NPC_ENRAGED_WRATH, fEnragedWrathPosition[i][0], fEnragedWrathPosition[i][1], fEnragedWrathPosition[i][2], fEnragedWrathPosition[i][3], TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000)) + { + pEnragedWrath->AI()->AttackStart(m_creature); + } + } + m_uiSpawnTimer = 40000; + } + else + m_uiSpawnTimer -= uiDiff; + + if (m_uiQuestTimer < uiDiff) + { + if(Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID)) + { + pPlayer->KilledMonsterCredit(m_creature->GetEntry()); + DoScriptText(INFUSED_CRYSTAL_EMOTE , m_creature); + m_creature->ForcedDespawn(5000); + } + bCompleted = true; + } + else + m_uiQuestTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_infused_crystal(Creature* pCreature) +{ + return new npc_infused_crystalAI (pCreature); +} + void AddSC_eversong_woods() { Script* pNewScript; @@ -461,4 +562,9 @@ void AddSC_eversong_woods() pNewScript->GetAI = GetAI_npc_apprentice_mirvedaAI; pNewScript->pQuestAccept = &QuestAccept_unexpected_results; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name= "npc_infused_crystal"; + pNewScript->GetAI = &GetAI_npc_infused_crystal; + pNewScript->RegisterSelf(); } diff --git a/scripts/eastern_kingdoms/karazhan/chess_event.cpp b/scripts/eastern_kingdoms/karazhan/chess_event.cpp new file mode 100644 index 0000000..f373d69 --- /dev/null +++ b/scripts/eastern_kingdoms/karazhan/chess_event.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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: chess_event +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Karazhan +EndScriptData */ + +#include "precompiled.h" + +void AddSC_chess_event() +{ +} diff --git a/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp b/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp index 1678318..eddd135 100644 --- a/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp +++ b/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp @@ -16,16 +16,23 @@ /* ScriptData SDName: Ebon_Hold -SD%Complete: 95 -SDComment: Quest support: 12641, 12733, 12739(and 12742 to 12750), 12727, 12848, 12754 - , 12801, Hacked: 12680, 12687, 12698 +SD%Complete: 85 +SDComment: Quest support: 12848, 12733, 12739(and 12742 to 12750), 12727, 12698. SDCategory: Ebon Hold EndScriptData */ +/* ContentData +npc_a_special_surprise +npc_death_knight_initiate +npc_unworthy_initiate_anchor +npc_unworthy_initiate +go_acherus_soul_prison +mob_scarlet_ghoul +EndContentData */ + #include "precompiled.h" #include "escort_ai.h" -#include "WorldPacket.h" -#include "follower_ai.h" +#include "ObjectMgr.h" /*###### ## npc_a_special_surprise @@ -477,11 +484,16 @@ struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI } }; +CreatureAI* GetAI_npc_a_special_surprise(Creature* pCreature) +{ + return new npc_a_special_surpriseAI(pCreature); +} + /*###### ## npc_death_knight_initiate ######*/ -enum npc_death_knight_initiate +enum { SAY_DUEL_A = -1609016, SAY_DUEL_B = -1609017, @@ -676,7 +688,6 @@ bool GossipSelect_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature enum eKoltira { - SAY_BREAKOUT0 = -1609089, SAY_BREAKOUT1 = -1609079, SAY_BREAKOUT2 = -1609080, SAY_BREAKOUT3 = -1609081, @@ -697,7 +708,8 @@ enum eKoltira NPC_HIGH_INQUISITOR_VALROTH = 29001, NPC_KOLTIRA_ALT = 28447, - MODEL_KOLTIRA_TRANSFORM = 25446, + //not sure about this id + //NPC_DEATH_KNIGHT_MOUNT = 29201, MODEL_DEATH_KNIGHT_MOUNT = 25278 }; @@ -711,7 +723,6 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI void Reset() { - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); if (!HasEscortState(STATE_ESCORT_ESCORTING)) { m_uiWave = 0; @@ -724,40 +735,26 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI { switch(uiPointId) { - case 0: // Jump off - m_creature->SetStandState(UNIT_STAND_STATE_STAND); + case 0: DoScriptText(SAY_BREAKOUT1, m_creature); break; - case 1: // Go to chest and get equip + case 1: m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); break; - case 2: + case 2: m_creature->SetStandState(UNIT_STAND_STATE_STAND); - DoCast(m_creature, SPELL_KOLTIRA_TRANSFORM, true); - m_creature->UpdateEntry(NPC_KOLTIRA_ALT); //Somehow aura will be reseted + //m_creature->UpdateEntry(NPC_KOLTIRA_ALT); //unclear if we must update or not + DoCastSpellIfCan(m_creature, SPELL_KOLTIRA_TRANSFORM); break; - case 3: // Kneel with Anti Magic Zone + case 3: SetEscortPaused(true); m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); DoScriptText(SAY_BREAKOUT2, m_creature); - DoCast(m_creature, SPELL_ANTI_MAGIC_ZONE, true); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - SetCombatMovement(false); + DoCastSpellIfCan(m_creature, SPELL_ANTI_MAGIC_ZONE); // cast again that makes bubble up break; - case 4: // Valroth dead, he runs away - { - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); - SetCombatMovement(true); - // just makes him stronger and be able to kill out - const CreatureInfo *cinfo = m_creature->GetCreatureInfo(); - m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg * 100); - m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg * 100); - m_creature->UpdateDamagePhysical(BASE_ATTACK); + case 4: SetRun(true); break; - } case 9: m_creature->Mount(MODEL_DEATH_KNIGHT_MOUNT); break; @@ -772,7 +769,7 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI if (Player* pPlayer = GetPlayerForEscort()) { pSummoned->AI()->AttackStart(pPlayer); - pSummoned->AddThreat(pPlayer); + pSummoned->AddThreat(m_creature); } if (pSummoned->GetEntry() == NPC_HIGH_INQUISITOR_VALROTH) @@ -831,7 +828,7 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI } case 5: DoScriptText(SAY_BREAKOUT9, m_creature); - DoCast(m_creature, SPELL_ANTI_MAGIC_ZONE, false); + m_creature->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE); m_uiWave_Timer = 2500; break; case 6: @@ -845,13 +842,11 @@ struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI else m_uiWave_Timer -= uiDiff; } - else - { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; DoMeleeAttackIfReady(); - } } }; @@ -864,8 +859,7 @@ bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, c { if (pQuest->GetQuestId() == QUEST_BREAKOUT) { - pCreature->SetStandState(UNIT_STAND_STATE_SIT); - DoScriptText(SAY_BREAKOUT0, pCreature); + pCreature->SetStandState(UNIT_STAND_STATE_STAND); if (npc_koltira_deathweaverAI* pEscortAI = dynamic_cast(pCreature->AI())) pEscortAI->Start(false, pPlayer->GetGUID(), pQuest); @@ -874,97 +868,10 @@ bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, c } /*###### -## mob_high_inquisitor_valroth +## ######*/ -enum valroth -{ - SAY_VALROTH1 = -1609090, - SAY_VALROTH2 = -1609091, - SAY_VALROTH3 = -1609092, - SAY_VALROTH4 = -1609093, - SAY_VALROTH5 = -1609094, - SAY_VALROTH6 = -1609095, - SAY_VALROTH7 = -1609096, - SPELL_RENEW = 38210, - SPELL_INQUISITOR_PENANCE = 52922, - SPELL_VALROTH_SMITE = 52926, - SPELL_SUMMON_VALROTH_REMAINS = 52929 -}; -struct MANGOS_DLL_DECL mob_high_inquisitor_valrothAI : public ScriptedAI -{ - mob_high_inquisitor_valrothAI(Creature *pCreature) : ScriptedAI(pCreature) - { - Reset(); - } - - uint32 uiRenew_timer; - uint32 uiInquisitor_Penance_timer; - uint32 uiValroth_Smite_timer; - - void Reset() - { - uiRenew_timer = 10000; - uiInquisitor_Penance_timer = 2000; - uiValroth_Smite_timer = 1000; - DoScriptText(SAY_VALROTH1, m_creature); - } - - void Aggro(Unit* who) - { - DoScriptText(SAY_VALROTH2, m_creature); - DoCast(who, SPELL_VALROTH_SMITE); - } - - void UpdateAI(const uint32 diff) - { - if (uiRenew_timer < diff) - { - Shout(); - DoCast(m_creature, SPELL_RENEW); - uiRenew_timer = 15000 + rand()%5000; - }else uiRenew_timer -= diff; - - if (uiInquisitor_Penance_timer < diff) - { - Shout(); - DoCast(m_creature->getVictim(), SPELL_INQUISITOR_PENANCE); - uiInquisitor_Penance_timer = 2000 + rand()%5000; - }else uiInquisitor_Penance_timer -= diff; - - if (uiValroth_Smite_timer < diff) - { - Shout(); - DoCast(m_creature->getVictim(), SPELL_VALROTH_SMITE); - uiValroth_Smite_timer = 1000 + rand()%5000; - }else uiValroth_Smite_timer -= diff; - - DoMeleeAttackIfReady(); - } - - void Shout() - { - switch(rand()%30) - { - case 0: DoScriptText(SAY_VALROTH3, m_creature);break; - case 1: DoScriptText(SAY_VALROTH4, m_creature);break; - case 2: DoScriptText(SAY_VALROTH5, m_creature);break; - case 3: DoScriptText(SAY_VALROTH6, m_creature);break; - } - } - - void JustDied(Unit* killer) - { - DoScriptText(SAY_VALROTH7, m_creature); - killer->CastSpell(m_creature, SPELL_SUMMON_VALROTH_REMAINS, true); - } -}; - -/*###### -## Quest: The Endless Hunger -######*/ - -enum npc_unworthy_initiate +enum { SAY_START = -1609000, // 8 texts in total, GetTextId() generates random with this as base SAY_AGGRO = -1609008, // 8 texts in total, GetTextId() generates random with this as base @@ -975,11 +882,6 @@ enum npc_unworthy_initiate SPELL_CHAINED_PESANT_BREATH = 54613, SPELL_INITIATE_VISUAL = 51519, - //SPELL_BLOOD_STRIKE = 52374, // Already declared in npc_death_knight_initiate - //SPELL_DEATH_COIL = 52375, - //SPELL_ICY_TOUCH = 52372, - //SPELL_PLAGUE_STRIKE = 52373, - NPC_ANCHOR = 29521, FACTION_MONSTER = 16, @@ -1059,6 +961,11 @@ struct MANGOS_DLL_DECL npc_unworthy_initiate_anchorAI : public ScriptedAI } }; +CreatureAI* GetAI_npc_unworthy_initiate_anchor(Creature* pCreature) +{ + return new npc_unworthy_initiate_anchorAI(pCreature); +} + /*###### ## npc_unworthy_initiate ######*/ @@ -1262,11 +1169,6 @@ CreatureAI* GetAI_npc_unworthy_initiate(Creature* pCreature) return new npc_unworthy_initiateAI(pCreature); } -CreatureAI* GetAI_npc_unworthy_initiate_anchor(Creature* pCreature) -{ - return new npc_unworthy_initiate_anchorAI(pCreature); -} - /*###### ## go_acherus_soul_prison ######*/ @@ -1290,41 +1192,37 @@ struct MANGOS_DLL_DECL npc_eye_of_acherusAI : public ScriptedAI { npc_eye_of_acherusAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_creature->SetActiveObjectState(true); - m_creature->SetLevel(55); //else one hack - StartTimer = 2000; - Active = false; + Reset(); } - uint32 StartTimer; + int32 StartTimer; bool Active; + ObjectGuid ownerGuid; + + void Reset() + { + m_creature->SetDisplayId(26320); + StartTimer = 2000; + Active = false; + } - void Reset(){} void AttackStart(Unit *) {} void MoveInLineOfSight(Unit*) {} - void JustDied(Unit*u) + void JustDied(Unit* killer) { if(!m_creature || m_creature->GetTypeId() != TYPEID_UNIT) return; - Unit *target = m_creature->GetCharmer(); + m_creature->RemoveAurasDueToSpell(530); - if(!target || target->GetTypeId() != TYPEID_PLAYER) - return; - - m_creature->SetCharmerGuid(ObjectGuid()); - target->RemoveAurasDueToSpell(51852); - target->SetCharm(NULL); - - ((Player*)target)->GetCamera().ResetView(); - ((Player*)target)->SetClientControl(m_creature,0); - ((Player*)target)->SetMover(NULL); + Player* owner = m_creature->GetMap()->GetPlayer(ownerGuid); - m_creature->CleanupsBeforeDelete(); - m_creature->AddObjectToRemoveList(); - //m_creature->ForcedDespawn(); + if(!owner) return; + + owner->RemoveAurasDueToSpell(51923); + owner->RemoveAurasDueToSpell(51852); } void MovementInform(uint32 uiType, uint32 uiPointId) @@ -1332,8 +1230,10 @@ struct MANGOS_DLL_DECL npc_eye_of_acherusAI : public ScriptedAI if (uiType != POINT_MOTION_TYPE && uiPointId == 0) return; - //char * text = "The Eye of Acherus is in your control"; - //m_creature->MonsterTextEmote(text, m_creature->GetGUID(), true); + DoScriptText(-1666452, m_creature); + m_creature->SetDisplayId(25499); +// m_creature->SetDisplayId(26320); + m_creature->RemoveAurasDueToSpell(51923); m_creature->CastSpell(m_creature, 51890, true); } @@ -1341,22 +1241,33 @@ struct MANGOS_DLL_DECL npc_eye_of_acherusAI : public ScriptedAI { if(m_creature->isCharmed()) { + if (ownerGuid.IsEmpty()) + ownerGuid = m_creature->GetCharmerOrOwner()->GetObjectGuid(); + if (StartTimer < uiDiff && !Active) { m_creature->CastSpell(m_creature, 70889, true); m_creature->CastSpell(m_creature, 51892, true); - //char * text = "The Eye of Acherus launches towards its destination"; - //m_creature->MonsterTextEmote(text, m_creature->GetGUID(), true); - m_creature->SetSpeedRate(MOVE_FLIGHT, 6.4f,true); + m_creature->CastSpell(m_creature, 51923, true); + m_creature->SetSpeedRate(MOVE_FLIGHT, 4.0f,true); + DoScriptText(-1666451, m_creature); m_creature->GetMotionMaster()->MovePoint(0, 1750.8276f, -5873.788f, 147.2266f); Active = true; } - else StartTimer -= uiDiff; + else + StartTimer -= uiDiff; } else { - m_creature->CleanupsBeforeDelete(); - m_creature->AddObjectToRemoveList(); + if (StartTimer < uiDiff) + { + m_creature->ForcedDespawn(); + if (Player* owner = m_creature->GetMap()->GetPlayer(ownerGuid)) + { + owner->RemoveAurasDueToSpell(51852); + owner->RemoveAurasDueToSpell(51923); + } + } } } }; @@ -1366,404 +1277,162 @@ CreatureAI* GetAI_npc_eye_of_acherus(Creature* pCreature) return new npc_eye_of_acherusAI(pCreature); } -enum zone -{ - SPELL_UNDYING_RESOLVE = 51915, - SPELL_UNDYING_RESOLVE_VISUAL = 51916, - SPELL_REVIVE = 51918, - NPC_VALKYR_BATTLE_MAIDEN = 28534 -}; - -void UpdateWorldState(Map *map, uint32 id, uint32 state) -{ - Map::PlayerList const& players = map->GetPlayers(); - - if (!players.isEmpty()) - { - for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->SendUpdateWorldState(id,state); - } - } -} - /*###### -## npc_palomino - Quest: Grand Theft Palomino - Vehicle HACK +## mob_scarlet_ghoul ######*/ -enum npc_palomino -{ - QUEST_GRAND_THEFT_PALOMINO = 12680, - NPC_SALANAR_THE_HORSEMAN = 28653 -}; -struct MANGOS_DLL_DECL npc_palominoAI : public FollowerAI -{ - npc_palominoAI(Creature* pCreature) : FollowerAI(pCreature) { Reset();} - void Reset() - { - m_creature->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PASSIVE); - m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); - } - void MoveInLineOfSight(Unit *pWho) - { - FollowerAI::MoveInLineOfSight(pWho); - if (!m_creature->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_SALANAR_THE_HORSEMAN) - { - if (m_creature->IsWithinDistInMap(pWho, INTERACTION_DISTANCE*2)) - { - if (Player* pPlayer = GetLeaderForFollower()) - { - pPlayer->KilledMonsterCredit(28767); - } - - SetFollowComplete(); - } - } - } -}; -CreatureAI* GetAI_npc_palomino(Creature* pCreature) -{ - return new npc_palominoAI(pCreature); -} -bool GossipHello_npc_palomino(Player* pPlayer, Creature* pCreature) +enum { + SPELL_HARVESTER_PING_DUMMY = 52514, + ENTRY_GOTHIK = 28658, + + SAY_SCARLET_GHOUL_SPAWN1 = -1609286, + SAY_SCARLET_GHOUL_SPAWN2 = -1609285, + SAY_SCARLET_GHOUL_SPAWN3 = -1609284, + SAY_SCARLET_GHOUL_SPAWN4 = -1609283, + SAY_SCARLET_GHOUL_SPAWN5 = -1609282, + SAY_SCARLET_GHOUL_SPAWN6 = -1609281, + + SAY_SCARLET_GOTHIK1 = -1609280, + SAY_SCARLET_GOTHIK2 = -1609279, + SAY_SCARLET_GOTHIK3 = -1609278, + SAY_SCARLET_GOTHIK4 = -1609277, + SAY_SCARLET_GOTHIK5 = -1609276, +}; - if (pPlayer->GetQuestStatus(QUEST_GRAND_THEFT_PALOMINO) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Let´s go for a ride!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); - - return true; -} - -bool GossipSelect_npc_palomino(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +struct MANGOS_DLL_DECL mob_scarlet_ghoulAI : public ScriptedAI { - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + mob_scarlet_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) { - pPlayer->CLOSE_GOSSIP_MENU(); + m_bIsSpawned = false; + fDist = (float)urand(1, 5); + m_uiCreatorGuid = m_creature->GetCreatorGuid(); + if (Player* pOwner = m_creature->GetMap()->GetPlayer(m_uiCreatorGuid) ) + fAngle = m_creature->GetAngle(pOwner); - if (npc_palominoAI* ppalominoAI = dynamic_cast(pCreature->AI())) - ppalominoAI->StartFollow(pPlayer, FACTION_ESCORT_N_FRIEND_PASSIVE); + Reset(); } - return true; -} - -/*###### -## npc_salanar_the_horseman -######*/ -enum salanar -{ - SPELL_REALM_OF_SHADOWS = 52275, - SPELL_HORSEMANS_CALL = 52362, // not working - NPC_ACHERUS_DEATHCHARGER = 28782, - NPC_DARK_RIDER_OF_ACHERUS = 28768 -}; - -bool GossipHello_npc_salanar_the_horseman(Player* pPlayer, Creature* pCreature) -{ - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu( pCreature->GetGUID() ); - if (pPlayer->GetQuestStatus(12687) == QUEST_STATUS_INCOMPLETE) - pPlayer->ADD_GOSSIP_ITEM( 0, "Send me into the Realm of Shadows.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + Unit* pTarget; - return true; -} + ObjectGuid m_uiCreatorGuid; + uint64 m_uiTargetGUID; + uint64 m_uiHarvesterGUID; -bool GossipSelect_npc_salanar_the_horseman(Player* pPlayer, Creature *pCreature, uint32 uiSender, uint32 uiAction) -{ - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->CLOSE_GOSSIP_MENU(); - pPlayer->CastSpell(pPlayer, SPELL_REALM_OF_SHADOWS, true); - pPlayer->SummonCreature(NPC_DARK_RIDER_OF_ACHERUS, pCreature->GetPositionX(), pCreature->GetPositionY(), pCreature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); - break; - } - return true; -} + uint32 m_uiWaitForThrowTimer; -/*###### -## mob_dark_rider_of_acherus -######*/ -enum darkrider -{ - //SPELL_ICY_TOUCH = 52372, - //SPELL_BLOOD_STRIKE = 52374, - SPELL_PLAGUE_STRIKE2 = 50688, - SPELL_THROW = 52356, - SPELL_DEATH_RACE_COMPLETE = 52361, - SPELL_ACHERUS_DEATHCHARGER = 48778 -}; -struct Locations2 -{ - float x, y, z; -}; -static Locations2 DarkriderWP[]= -{ - {2317.0f, -5662.0f, 153.1f}, - {2248.4f, -5630.8f, 139.1f}, - {2211.3f, -5658.9f, 122.7f}, - {2144.7f, -5705.0f, 102.1f}, - {2097.5f, -5737.9f, 100.1f}, - {2037.7f, -5738.9f, 99.0f} -}; + bool m_bWaitForThrow; + bool m_bIsSpawned; -struct MANGOS_DLL_DECL mob_dark_rider_of_acherusAI : public ScriptedAI -{ - mob_dark_rider_of_acherusAI(Creature *pCreature) : ScriptedAI(pCreature) - { - StartRunning(); - } - uint32 id; - uint32 m_uiWalkTimer; - uint32 uiBlood_strike_timer; - uint32 uiIcy_touch_timer; - uint32 uiPlague_strike_timer; - uint32 uiThrow_timer; - - void StartRunning() - { - m_creature->Mount(25279); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); - m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); - m_creature->SetSpeedRate(MOVE_RUN, 1.4f); // you cant get him, but see - id = 0; - Reset(); - } + float fAngle; + float fDist; void Reset() { - m_creature->GetMotionMaster()->MovePoint(id,DarkriderWP[id].x, DarkriderWP[id].y, DarkriderWP[id].z); - uiBlood_strike_timer = 3000; - uiIcy_touch_timer = 4000; - uiPlague_strike_timer = 5000; - uiThrow_timer = 10000; + m_uiWaitForThrowTimer = 3000; + m_bWaitForThrow = false; + pTarget = NULL; + m_uiTargetGUID = 0; + m_uiHarvesterGUID = 0; } - void UpdateAI(const uint32 diff) + void MoveInLineOfSight(Unit *pWho) { - if (m_creature->getVictim()) - { - if (uiBlood_strike_timer < diff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_BLOOD_STRIKE); - uiBlood_strike_timer = 5000 + rand()%1000; - }else uiBlood_strike_timer -= diff; - - if (uiIcy_touch_timer < diff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_ICY_TOUCH); - uiIcy_touch_timer = 6000 + rand()%1000; - }else uiIcy_touch_timer -= diff; - - if (uiPlague_strike_timer < diff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_PLAGUE_STRIKE2); - uiPlague_strike_timer = 12000 + rand()%1000; - }else uiPlague_strike_timer -= diff; - - if (uiThrow_timer < diff) - { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_THROW); - uiThrow_timer = 10000 + rand()%1000; - }else uiThrow_timer -= diff; - } - if (m_uiWalkTimer) + if (!m_bWaitForThrow && pWho->GetEntry() == ENTRY_GOTHIK && m_creature->GetDistance(pWho) < 15.0f) { - if (m_uiWalkTimer <= diff) - { - m_creature->GetMotionMaster()->MovePoint(id,DarkriderWP[id].x, DarkriderWP[id].y, DarkriderWP[id].z); - m_uiWalkTimer = 0; - - }else m_uiWalkTimer -= diff; - } + m_uiHarvesterGUID = pWho->GetGUID(); - DoMeleeAttackIfReady(); - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) - m_creature->CombatStop(); - } - void JustDied(Unit* killer) - { - killer->CastSpell(killer, SPELL_DEATH_RACE_COMPLETE, true); - m_creature->Unmount(); - Creature* pTemp = killer->SummonCreature(NPC_ACHERUS_DEATHCHARGER, m_creature->GetPositionX()+2, m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); - pTemp->setFaction(killer->getFaction()); - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); - pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); - } - - void MovementInform(uint32 type, uint32 tempid) - { - switch (id) - { - case 1: - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - break; - case 5: - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); - return; + if (Player* pOwner = m_creature->GetMap()->GetPlayer(m_uiCreatorGuid) ) + { + pOwner->KilledMonsterCredit(m_creature->GetEntry(), m_creature->GetGUID() ); + // this will execute if m_creature survived Harvester's wrath + float x, y, z, o; + o = float(urand(53, 57))/10.0f; + pWho->GetNearPoint(pWho, x, y, z, pWho->GetObjectBoundingRadius(), 5.0f, o); + m_creature->GetMotionMaster()->MovePoint(0, x, y, z); + m_bWaitForThrow = true; + } } - - ++id; - m_uiWalkTimer = 200; - } -}; -// Hack until Vehicle Support -bool GossipHello_npc_acherus_deathcharger(Player* pPlayer, Creature* pCreature) -{ - if (pPlayer->GetQuestStatus(12687) == QUEST_STATUS_COMPLETE) - { - pPlayer->Mount(25279); - pCreature->ForcedDespawn(); } - return true; -} - -/*###### -## mob_scarlet_miner -######*/ -enum scarlet_miner -{ - NPC_SCARLET_GHOUL = 28845, - SPELL_GIFT_OF_THE_HARVESTER = 52479, // only works, when miner attack you - SPELL_GIFT_OF_THE_HARVESTER_MISSILE = 52481, - SPELL_SCARLET_MINER_GHOUL_TRANSFORM = 52490, // approx 35% - SPELL_SCARLET_GHOUL_COUNTER = 52500, // not working - SPELL_SCARLET_MINER_GHOST_TRANSFORM = 52505, - SPELL_SCARLET_GHOUL_CREDIT = 52517, // not working - SPELL_GHOULPLOSION_GOTHIK = 52519, // no idea how to implement, but spell works - SPELL_GHOULZAP = 52521, // not working - SPELL_DISPEL_SCARLET_GHOUL_CREDIT_COUNTER = 52555 // is propably castet on player after quest complete -}; + void AttackStart(Unit *pWho) { return; } -struct MANGOS_DLL_DECL mob_scarlet_minerAI : public ScriptedAI -{ - mob_scarlet_minerAI(Creature *pCreature) : ScriptedAI(pCreature) + void UpdateAI(uint32 const uiDiff) { - // hack spell 52481 - SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_GIFT_OF_THE_HARVESTER_MISSILE); - if (TempSpell && TempSpell->EffectImplicitTargetB[0] != 16) + if (!m_bIsSpawned) { - TempSpell->EffectImplicitTargetB[0] = 16; - TempSpell->EffectImplicitTargetB[1] = 87; - TempSpell->EffectImplicitTargetB[2] = 16; + DoScriptText(SAY_SCARLET_GHOUL_SPAWN1 + urand(0, 5), m_creature); + m_bIsSpawned = true; } - Reset(); - } - - void Reset() {} - void SpellHit(Unit* pCaster, const SpellEntry* pSpell) - { - if (pCaster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && pSpell->Id == SPELL_GIFT_OF_THE_HARVESTER_MISSILE) + if (m_bWaitForThrow) { - if(((Player*)pCaster)->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE) + if (m_uiWaitForThrowTimer <= uiDiff) { - if (rand()%100 < 35) + if (Creature* pGothik = m_creature->GetMap()->GetCreature(m_uiHarvesterGUID) ) { - pCaster->CastSpell(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), SPELL_SCARLET_MINER_GHOUL_TRANSFORM, true); - //pCaster->CastSpell(pCaster, SPELL_SCARLET_GHOUL_CREDIT, true); - ((Player*)pCaster)->KilledMonsterCredit(NPC_SCARLET_GHOUL); // hack quest credit - } - else - pCaster->CastSpell(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), SPELL_SCARLET_MINER_GHOST_TRANSFORM, true, 0, 0, m_creature->GetGUID()); + if (pGothik->AI()->DoCastSpellIfCan(m_creature, roll_chance_i(50) ? 52519 : 52521) == CAST_OK) + DoScriptText(SAY_SCARLET_GOTHIK1 + urand(0, 4), pGothik); - m_creature->SetDeathState(JUST_DIED); - m_creature->RemoveCorpse(); + m_uiWaitForThrowTimer = 5000; + m_creature->KnockBackFrom(pGothik, 15.0, 5.0); + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + } + else m_bWaitForThrow = false; } + else m_uiWaitForThrowTimer -= uiDiff; + return; + } + + Player* pOwner = m_creature->GetMap()->GetPlayer(m_uiCreatorGuid); + if (!pOwner || !pOwner->IsInWorld()) + { + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false); + return; + } + + if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != FOLLOW_MOTION_TYPE) + { + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveFollow(pOwner, fDist, fAngle); } } }; -/*###### -## mob_scarlet_courier -######*/ -enum scarletcourier +CreatureAI* GetAI_mob_scarlet_ghoul(Creature* pCreature) { - SAY_TREE1 = -1609101, - SAY_TREE2 = -1609102, - SPELL_SHOOT = 52818, //creature will hardly be in right distance to use this - GO_INCONSPICUOUS_TREE = 191144, - NPC_SCARLET_COURIER = 29076 + return new mob_scarlet_ghoulAI(pCreature); }; -struct MANGOS_DLL_DECL mob_scarlet_courierAI : public ScriptedAI -{ - mob_scarlet_courierAI(Creature *pCreature) : ScriptedAI(pCreature) - { - StartRunning(); - } +// quest 12801 from Ckegg +/*###### +## Npc Highlord Darion Mograine +######*/ - uint32 uiWait_timer; - ObjectGuid m_uiPlayer; - bool found; +void UpdateWorldState(Map *map, uint32 id, uint32 state) +{ + Map::PlayerList const& players = map->GetPlayers(); - void StartRunning() + if (!players.isEmpty()) { - Reset(); - - if (GameObject* treeGO = GetClosestGameObjectWithEntry(m_creature, GO_INCONSPICUOUS_TREE, 20.0f)) + for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) { - m_uiPlayer = treeGO->GetOwnerGuid(); - m_creature->Mount(14338); - m_creature->GetMotionMaster()->MovePoint(1, treeGO->GetPositionX()+3, treeGO->GetPositionY(), treeGO->GetPositionZ()); - DoScriptText(SAY_TREE1, m_creature); + if (Player* pPlayer = itr->getSource()) + pPlayer->SendUpdateWorldState(id,state); } } +} - void Reset() - { - uiWait_timer = 3000; - m_uiPlayer = 0; - found = false; - } - void MovementInform(uint32 type, uint32 id) - { - if(type == POINT_MOTION_TYPE && id ==1) - { - if (GameObject* treeGO = GetClosestGameObjectWithEntry(m_creature, GO_INCONSPICUOUS_TREE, ATTACK_DISTANCE)) - { - DoScriptText(SAY_TREE2, m_creature); - m_creature->Unmount(); - m_creature->HandleEmoteCommand(EMOTE_ONESHOT_KICK); - treeGO->Delete(); - found = true; - } - } - } - void UpdateAI(const uint32 diff) - { - if(found) - { - if (uiWait_timer < diff) - { - Unit* pPlayer = m_creature->GetMap()->GetUnit(m_uiPlayer); - pPlayer->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); - AttackStart(pPlayer); - } - else uiWait_timer -= diff; - } - DoMeleeAttackIfReady(); - } -}; -/*###### -## npc_highlord_darion_mograine -######*/ enum mograine { ENCOUNTER_DK_NUMBER = 5, // how many player queue to start the quest , or - ENCOUNTER_DK_TIMER = 10, // *every 5 minutes. These have to be done in instance data - ENCOUNTER_DEFENDER_NUMBER = 15, // how many of defender - ENCOUNTER_EARTHSHATTER_NUMBER = 5, // how many of earthshatter + ENCOUNTER_DEFENDER_NUMBER = 20, // how many of defender + ENCOUNTER_EARTHSHATTER_NUMBER = 20, // how many of earthshatter ENCOUNTER_ABOMINATION_NUMBER = 3, // how many of abomination ENCOUNTER_BEHEMOTH_NUMBER = 2, // how many of behemoth - ENCOUNTER_GHOUL_NUMBER = 15, // how many of ghoul + ENCOUNTER_GHOUL_NUMBER = 10, // how many of ghoul ENCOUNTER_WARRIOR_NUMBER = 2, // how many of warrior ENCOUNTER_TOTAL_DAWN = 300, // Total number ENCOUNTER_TOTAL_SCOURGE = 10000, @@ -1950,7 +1619,7 @@ enum mograine NPC_RIMBLAT_EARTHSHATTER = 29182, SPELL_CHAIN_HEAL = 33642, - //SPELL_THUNDER = 53630 //spell is annoying and kicking units around + SPELL_THUNDER = 53630 }; struct Locations @@ -1961,36 +1630,36 @@ struct Locations static Locations LightofDawnLoc[]= { - {2281.335f, -5300.409f, 85.170f, 0}, // 0 Tirion Fordring loc + {2281.335f, -5300.409f, 85.170f, 0.0f}, // 0 Tirion Fordring loc {2283.896f, -5287.914f, 83.066f, 1.55f}, // 1 Tirion Fordring loc2 - {2281.461f, -5263.014f, 81.164f, 0}, // 2 Tirion charges - {2262.277f, -5293.477f, 82.167f, 0}, // 3 Tirion run - {2270.286f, -5287.73f, 82.262f, 0}, // 4 Tirion relocate - {2269.511f, -5288.289f, 82.225f, 0}, // 5 Tirion forward - {2262.277f, -5293.477f, 82.167f, 0}, // 6 Tirion runs to Darion - {2270.286f, -5287.73f, 82.262f, 0}, - {2269.511f, -5288.289f, 82.225f, 0}, - {2273.205f, -5288.848f, 82.617f, 0}, // 9 Korfax loc1 - {2274.739f, -5287.926f, 82.684f, 0}, // 10 Korfax loc2 - {2253.673f, -5318.004f, 81.724f, 0}, // 11 Korfax kicked - {2287.028f, -5309.644f, 87.253f, 0}, // 12 Maxwell loc1 - {2286.978f, -5308.025f, 86.83f, 0}, // 13 Maxwell loc2 - {2248.877f, -5307.586f, 82.166f, 0}, // 14 maxwell kicked - {2278.58f, -5316.933f, 88.319f, 0}, // 15 Eligor loc1 - {2278.535f, -5315.479f, 88.08f, 0}, // 16 Eligor loc2 - {2259.416f, -5304.505f, 82.149f, 0}, // 17 eligor kicked - {2289.259f, -5280.355f, 82.112f, 0}, // 18 Koltira loc1 - {2289.02f, -5281.985f, 82.207f, 0}, // 19 Koltira loc2 - {2273.289f, -5273.675f, 81.701f, 0}, // 20 Thassarian loc1 - {2273.332f, -5275.544f, 81.849f, 0}, // 21 Thassarian loc2 - {2281.198f, -5257.397f, 80.224f, 4.66f}, // 22 Alexandros loc1 - {2281.156f, -5259.934f, 80.647f, 0}, // 23 Alexandros loc2 - {2281.294f, -5281.895f, 82.445f, 1.35f}, // 24 Darion loc1 - {2281.093f, -5263.013f, 81.125f, 0}, // 25 Darion loc1 - {2281.313f, -5250.282f, 79.322f, 4.69f}, // 26 Lich King spawns - {2281.523f, -5261.058f, 80.877f, 0}, // 27 Lich king move forwards - {2272.709f, -5255.552f, 78.226f, 0}, // 28 Lich king kicked - {2273.972f, -5257.676f, 78.862f, 0} // 29 Lich king moves forward + {2281.461f, -5263.014f, 81.164f, 0.0f}, // 2 Tirion charges + {2262.277f, -5293.477f, 82.167f, 0.0f}, // 3 Tirion run + {2270.286f, -5287.73f, 82.262f, 0.0f}, // 4 Tirion relocate + {2269.511f, -5288.289f, 82.225f, 0.0f}, // 5 Tirion forward + {2262.277f, -5293.477f, 82.167f, 0.0f}, // 6 Tirion runs to Darion + {2270.286f, -5287.73f, 82.262f, 0.0f}, + {2269.511f, -5288.289f, 82.225f, 0.0f}, + {2273.205f, -5288.848f, 82.617f, 0.0f}, // 9 Korfax loc1 + {2274.739f, -5287.926f, 82.684f, 0.0f}, // 10 Korfax loc2 + {2253.673f, -5318.004f, 81.724f, 0.0f}, // 11 Korfax kicked + {2287.028f, -5309.644f, 87.253f, 0.0f}, // 12 Maxwell loc1 + {2286.978f, -5308.025f, 86.83f, 0.0f}, // 13 Maxwell loc2 + {2248.877f, -5307.586f, 82.166f, 0.0f}, // 14 maxwell kicked + {2278.58f, -5316.933f, 88.319f, 0.0f}, // 15 Eligor loc1 + {2278.535f, -5315.479f, 88.08f, 0.0f}, // 16 Eligor loc2 + {2259.416f, -5304.505f, 82.149f, 0.0f}, // 17 eligor kicked + {2289.259f, -5280.355f, 82.112f, 0.0f}, // 18 Koltira loc1 + {2289.02f, -5281.985f, 82.207f, 0.0f}, // 19 Koltira loc2 + {2273.289f, -5273.675f, 81.701f, 0.0f}, // 20 Thassarian loc1 + {2273.332f, -5275.544f, 81.849f, 0.0f}, // 21 Thassarian loc2 + {2281.198f, -5257.397f, 80.224f, 4.66f}, // 22 Alexandros loc1 + {2281.156f, -5259.934f, 80.647f, 0.0f}, // 23 Alexandros loc2 + {2281.294f, -5281.895f, 82.445f, 1.35f}, // 24 Darion loc1 + {2281.093f, -5263.013f, 81.125f, 0.0f}, // 25 Darion loc1 + {2281.313f, -5250.282f, 79.322f, 4.69f}, // 26 Lich King spawns + {2281.523f, -5261.058f, 80.877f, 0.0f}, // 27 Lich king move forwards + {2272.709f, -5255.552f, 78.226f, 0.0f}, // 28 Lich king kicked + {2273.972f, -5257.676f, 78.862f, 0.0f} // 29 Lich king moves forward }; struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI @@ -2090,13 +1759,13 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI uiEligorGUID = NULL; uiRayneGUID = NULL; - for(uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) + for (uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiDefenderGUID[i])) pTemp->SetDeathState(JUST_DIED); uiDefenderGUID[i] = 0; } - for(uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) + for (uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i) { if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEarthshatterGUID[i])) pTemp->SetDeathState(JUST_DIED); @@ -2170,21 +1839,16 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI AttackStart(who); } - void SetHoldState(bool bOnHold) - { - SetEscortPaused(bOnHold); - } - void WaypointReached(uint32 i) { switch(i) { case 0: m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); - SetHoldState(true); + SetEscortPaused(true); break; case 1: - SetHoldState(true); + SetEscortPaused(true); if (GameObject* pGo = GetClosestGameObjectWithEntry(m_creature, GO_LIGHT_OF_DAWN, 100.0f)) // make dawn of light effect off { @@ -2211,7 +1875,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI NPCChangeTarget(uiThassarianGUID); m_creature->Unmount(); - //m_creature->CastSpell(m_creature, SPELL_THE_MIGHT_OF_MOGRAINE, true); // need to fix, on player only + m_creature->CastSpell(m_creature, SPELL_THE_MIGHT_OF_MOGRAINE, true); // need to fix, on player only if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKoltiraGUID)) pTemp->Unmount(); @@ -2226,21 +1890,21 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI break; case 3: { - Unit* pTirion = m_creature->GetMap()->GetUnit(uiTirionGUID); + Creature* pTirion = m_creature->GetMap()->GetCreature(uiTirionGUID); DoScriptText(EMOTE_LIGHT_OF_DAWN05, m_creature); - if (m_creature->HasAura(SPELL_THE_LIGHT_OF_DAWN, EFFECT_INDEX_0)) + if (m_creature->HasAura(SPELL_THE_LIGHT_OF_DAWN)) m_creature->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKoltiraGUID)) { - if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, EFFECT_INDEX_0)) + if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN)) pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[19].x, LightofDawnLoc[19].y, LightofDawnLoc[19].z); } if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiThassarianGUID)) { - if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN, EFFECT_INDEX_0)) + if (pTemp->HasAura(SPELL_THE_LIGHT_OF_DAWN)) pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN); pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[21].x, LightofDawnLoc[21].y, LightofDawnLoc[21].z); @@ -2271,19 +1935,19 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiThassarianGUID)) pTemp->SetStandState(UNIT_STAND_STATE_KNEEL); - SetHoldState(true); + SetEscortPaused(true); break; case 5: DoScriptText(SAY_LIGHT_OF_DAWN33, m_creature); - SetHoldState(true); + SetEscortPaused(true); break; case 6: - SetHoldState(true); + SetEscortPaused(true); m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SPECIALATTACK1H); JumpToNextStep(1000); break; case 7: - SetHoldState(true); + SetEscortPaused(true); JumpToNextStep(2000); break; case 8: @@ -2291,7 +1955,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID)) m_creature->CastSpell(pTemp, SPELL_ASHBRINGER, true); DoScriptText(EMOTE_LIGHT_OF_DAWN14, m_creature); - SetHoldState(true); + SetEscortPaused(true); break; } } @@ -2312,8 +1976,8 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI break; case 1: // just delay - UpdateWorldState(m_creature->GetMap(), WORLD_STATE_REMAINS, 1); - //UpdateWorldState(m_creature->GetMap(), WORLD_STATE_COUNTDOWN, 0); + //UpdateWorldState(m_creature->GetMap(), WORLD_STATE_REMAINS, 1); + UpdateWorldState(m_creature->GetMap(), WORLD_STATE_COUNTDOWN, 0); UpdateWorldState(m_creature->GetMap(), WORLD_STATE_EVENT_BEGIN, 1); m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); JumpToNextStep(3000); @@ -2418,12 +2082,11 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI case 8: // summon announce DoScriptText(SAY_LIGHT_OF_DAWN06, m_creature); - m_creature->CastSpell(m_creature, SPELL_THE_MIGHT_OF_MOGRAINE, true); // need to fix, on player only JumpToNextStep(5000); break; case 9: // charge begins - SetHoldState(false); + SetEscortPaused(false); if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKoltiraGUID)) { pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); @@ -2497,7 +2160,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[23].x, LightofDawnLoc[23].y, LightofDawnLoc[23].z); DoScriptText(SAY_LIGHT_OF_DAWN32, pTemp); } - SetHoldState(false); // makes darion turns back + SetEscortPaused(false); // makes darion turns back JumpToNextStep(5000); break; @@ -2589,7 +2252,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI { DoScriptText(SAY_LIGHT_OF_DAWN43, pTemp); uiLichKingGUID = pTemp->GetGUID(); - if (Unit* pAlex = m_creature->GetMap()->GetUnit(uiAlexandrosGUID)) + if (Creature* pAlex = m_creature->GetMap()->GetCreature(uiAlexandrosGUID)) pTemp->CastSpell(pAlex, SPELL_SOUL_FEAST_ALEX, false); } JumpToNextStep(2000); @@ -2623,12 +2286,12 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI break; case 33: // Darion supports to jump to lich king here -// disable if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID)) +// disable if (Creature* pTemp = ((Creature*)Unit::GetUnit((*m_creature), uiLichKingGUID))) // because mangos DoCast(m_creature, SPELL_MOGRAINE_CHARGE); // jumping charge // doesn't make it looks well, so workarounds, Darion charges, looks better m_creature->SetSpeedRate(MOVE_RUN, 3.0f); m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); - SetHoldState(false); + SetEscortPaused(false); JumpToNextStep(0); break; @@ -2640,7 +2303,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI } m_creature->SetSpeedRate(MOVE_RUN, 6.0f); ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_DEAD); - SetHoldState(false); // Darion got kicked by lich king + SetEscortPaused(false); // Darion got kicked by lich king JumpToNextStep(0); break; @@ -2803,12 +2466,12 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_STAND); DoScriptText(SAY_LIGHT_OF_DAWN53, m_creature); - SetHoldState(false); // Darion throws sword + SetEscortPaused(false); // Darion throws sword JumpToNextStep(7000); break; case 47: // Ashbringer rebirth - ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_DEAD); + ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_KNEEL); DoScriptText(EMOTE_LIGHT_OF_DAWN15, m_creature); if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID)) { @@ -2824,7 +2487,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI pGo->SetPhaseMask(128, true); if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID)) { - if (pTemp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER, EFFECT_INDEX_0)) + if (pTemp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER)) pTemp->RemoveAurasDueToSpell(SPELL_REBIRTH_OF_THE_ASHBRINGER); pTemp->CastSpell(pTemp, 41542, false); // workarounds, light expoded, makes it cool pTemp->HandleEmoteCommand(EMOTE_ONESHOT_ROAR); @@ -2860,9 +2523,9 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); pTemp->SetSpeedRate(MOVE_RUN, 3.0f); // workarounds, make Tirion still running pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); - //pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2].x -1, LightofDawnLoc[2].y, LightofDawnLoc[2].z); - //if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID)) - // pTemp->GetMap()->CreatureRelocation(pTemp, LightofDawnLoc[28].x, LightofDawnLoc[28].y, LightofDawnLoc[28].z, 0.0f); // workarounds, he should kick back by Tirion, but here we relocate him + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2].x, LightofDawnLoc[2].y, LightofDawnLoc[2].z); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID)) + pTemp->GetMap()->CreatureRelocation(pTemp, LightofDawnLoc[28].x, LightofDawnLoc[28].y, LightofDawnLoc[28].z, 0.0f); // workarounds, he should kick back by Tirion, but here we relocate him } JumpToNextStep(1500); break; @@ -2874,13 +2537,13 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI break; case 54: - //if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID)) - //{ - // pTemp->SetSpeedRate(MOVE_RUN, 1.0f); - // m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); - // pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29].x, LightofDawnLoc[29].y, LightofDawnLoc[29].z); // 26 - //} - JumpToNextStep(0); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID)) + { + pTemp->SetSpeedRate(MOVE_RUN, 1.0f); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29].x, LightofDawnLoc[29].y, LightofDawnLoc[29].z); // 26 + } + JumpToNextStep(4000); break; case 55: @@ -2930,11 +2593,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI case 61: if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID)) - { DoScriptText(SAY_LIGHT_OF_DAWN60, pTemp); - pTemp->CastSpell(m_creature, SPELL_LAY_ON_HANDS, false); - } - ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_KNEEL); JumpToNextStep(3000); break; @@ -2993,8 +2652,8 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI break; case 70: - DoScriptText(SAY_LIGHT_OF_DAWN68, m_creature); ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_STAND); + DoScriptText(SAY_LIGHT_OF_DAWN68, m_creature); JumpToNextStep(10000); break; @@ -3018,7 +2677,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI break; case 72: - SetHoldState(false); // Escort ends + SetEscortPaused(false); // Escort ends JumpToNextStep(0); break; } @@ -3193,10 +2852,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI } if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiOrbazGUID)) - { DoScriptText(EMOTE_LIGHT_OF_DAWN04, pTemp); - DespawnNPC(uiOrbazGUID); - } if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiThassarianGUID)) { @@ -3213,7 +2869,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID)) DoScriptText(SAY_LIGHT_OF_DAWN26, pTemp); - SetHoldState(false); + SetEscortPaused(false); }else uiFight_duration -= diff; @@ -3249,7 +2905,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI for(uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i) { if (!(pTemp = m_creature->GetMap()->GetCreature(uiGhoulGUID[i]))) - { + { pTemp = m_creature->SummonCreature(NPC_ACHERUS_GHOUL, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); pTemp->setFaction(2084); uiGhoulGUID[i] = pTemp->GetGUID(); @@ -3290,7 +2946,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI { pTemp = m_creature->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); pTemp->setFaction(2089); - //m_creature->AddThreat(pTemp, 0.0f); + m_creature->AddThreat(pTemp, 0.0f); uiDefenderGUID[i] = pTemp->GetGUID(); } } @@ -3300,7 +2956,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI { pTemp = m_creature->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); pTemp->setFaction(2089); - //m_creature->AddThreat(pTemp, 0.0f); + m_creature->AddThreat(pTemp, 0.0f); uiEarthshatterGUID[i] = pTemp->GetGUID(); } } @@ -3308,28 +2964,28 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI { pTemp = m_creature->SummonCreature(NPC_KORFAX_CHAMPION_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); pTemp->setFaction(2089); - //m_creature->AddThreat(pTemp, 0.0f); + m_creature->AddThreat(pTemp, 0.0f); uiKorfaxGUID = pTemp->GetGUID(); } if (!(pTemp = m_creature->GetMap()->GetCreature(uiMaxwellGUID))) { pTemp = m_creature->SummonCreature(NPC_LORD_MAXWELL_TYROSUS, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); pTemp->setFaction(2089); - //m_creature->AddThreat(pTemp, 0.0f); + m_creature->AddThreat(pTemp, 0.0f); uiMaxwellGUID = pTemp->GetGUID(); } if (!(pTemp = m_creature->GetMap()->GetCreature(uiEligorGUID))) { pTemp = m_creature->SummonCreature(NPC_COMMANDER_ELIGOR_DAWNBRINGER, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); pTemp->setFaction(2089); - //m_creature->AddThreat(pTemp, 0.0f); + m_creature->AddThreat(pTemp, 0.0f); uiEligorGUID = pTemp->GetGUID(); } if (!(pTemp = m_creature->GetMap()->GetCreature(uiRayneGUID))) { pTemp = m_creature->SummonCreature(NPC_RAYNE, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); pTemp->setFaction(2089); - //m_creature->AddThreat(pTemp, 0.0f); + m_creature->AddThreat(pTemp, 0.0f); uiRayneGUID = pTemp->GetGUID(); } } @@ -3344,6 +3000,7 @@ struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI } } }; + bool GossipHello_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature) { if (pCreature->isQuestGiver()) @@ -3364,7 +3021,7 @@ bool GossipSelect_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreat case GOSSIP_ACTION_INFO_DEF+1: pPlayer->CLOSE_GOSSIP_MENU(); ((npc_highlord_darion_mograineAI*)pCreature->AI())->uiStep = 1; - ((npc_highlord_darion_mograineAI*)pCreature->AI())->Start(true, false, false, pPlayer->GetGUID()); + ((npc_highlord_darion_mograineAI*)pCreature->AI())->Start(false, pPlayer->GetGUID()); break; } return true; @@ -3377,61 +3034,261 @@ struct MANGOS_DLL_DECL npc_the_lich_king_tirion_dawnAI : public ScriptedAI { npc_the_lich_king_tirion_dawnAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } void Reset() {} - void AttackStart(Unit *who) { return; } // very simple, just don't make them aggreesive + void AttackStart(Unit *who) { return; } // very sample, just don't make them aggreesive void UpdateAI(const uint32 diff) { return; } void JustDied(Unit* killer) {} }; -CreatureAI* GetAI_mob_dark_rider_of_acherus(Creature* pCreature) -{ - return new mob_dark_rider_of_acherusAI (pCreature); -} - -CreatureAI* GetAI_npc_a_special_surprise(Creature* pCreature) -{ - return new npc_a_special_surpriseAI (pCreature); -} - -CreatureAI* GetAI_mob_scarlet_miner(Creature* pCreature) -{ - return new mob_scarlet_minerAI (pCreature); -} +/*###### +## npc orbaz, koltira, tassarian +######*/ +struct MANGOS_DLL_DECL npc_minibosses_dawn_of_lightAI : public ScriptedAI +{ + npc_minibosses_dawn_of_lightAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + + uint32 uiIcyTouchTimer; + uint32 uiBloodStrikeTimer; + uint32 uiPlagueStrikeTimer; + + void Reset() + { + uiIcyTouchTimer = urand(10000, 20000); + uiBloodStrikeTimer = urand(10000, 20000); + uiPlagueStrikeTimer = urand(10000, 20000); + } + + bool EnterEvadeIfOutOfCombatArea(const uint32 uiDiff) + { + m_creature->GetMotionMaster()->MoveIdle(); + return false; + } + void EnterEvadeMode() + { + m_creature->GetMotionMaster()->MoveIdle(); + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->getVictim() || !m_creature->SelectHostileTarget() ) + return; + + if (uiIcyTouchTimer <= uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_ICY_TOUCH); + uiIcyTouchTimer = urand(10000, 20000); + } + else uiIcyTouchTimer -= uiDiff; + + if (uiBloodStrikeTimer <= uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_BLOOD_STRIKE); + uiBloodStrikeTimer = urand(10000, 20000); + } + else uiBloodStrikeTimer -= uiDiff; + + if (uiPlagueStrikeTimer <= uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_PLAGUE_STRIKE1); + uiPlagueStrikeTimer = urand(10000, 20000); + } + else uiPlagueStrikeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; -CreatureAI* GetAI_mob_scarlet_courier(Creature* pCreature) +/*###### +## Acherus Ghoul (29219) +######*/ +struct MANGOS_DLL_DECL mob_acherus_ghoulAI : public ScriptedAI { - return new mob_scarlet_courierAI (pCreature); -} + mob_acherus_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsReady = false; + m_bIsSpawned = false; + m_bIsInBattle = (m_creature->GetPositionX() < 2300.0f) ? true : false; + + m_pMap = m_creature->GetMap(); + + Reset(); + } + + Map *m_pMap; + + uint32 m_uiReadyTimer; + uint32 m_uiGhoulplosionTimer; + + bool m_bIsReady; + bool m_bIsSpawned; + bool m_bIsInBattle; + + void EnterEvadeIfOutOfCombatArea(const uint32 uiDiff) { return; } + + void Reset() + { + m_uiReadyTimer = 4000; + m_uiGhoulplosionTimer = 30000; + } + + void MoveInLineOfSight(Unit *pWho) + { + if (!m_bIsReady) + return; + + ScriptedAI::MoveInLineOfSight(pWho); + } + + void AttackStart(Unit *pWho) + { + if (!m_bIsReady) + return; + + ScriptedAI::AttackStart(pWho); + } + + void UpdateAI(uint32 const uiDiff) + { + if (!m_bIsReady) + { + if (!m_bIsSpawned) + { + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); + m_bIsSpawned = true; + } + + if (m_uiReadyTimer <= uiDiff) + m_bIsReady = true; + else m_uiReadyTimer -= uiDiff; + + return; + } + + if (!m_creature->getVictim() || !m_creature->SelectHostileTarget() ) + { + if (m_bIsInBattle && m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != CONFUSED_MOTION_TYPE) + m_creature->GetMotionMaster()->MoveConfused(); + + return; + } + + if (m_uiGhoulplosionTimer <= uiDiff) + { + DoCastSpellIfCan(m_creature, SPELL_GHOULPLOSION); + m_uiGhoulplosionTimer = 30000; + } + else m_uiGhoulplosionTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; -CreatureAI* GetAI_mob_high_inquisitor_valroth(Creature* pCreature) +/*###### +## mob_warrior_of_the_frozen_wastes (53631) +######*/ +struct MANGOS_DLL_DECL mob_warrior_of_the_frozen_wastesAI : public ScriptedAI { - return new mob_high_inquisitor_valrothAI (pCreature); -} + mob_warrior_of_the_frozen_wastesAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsReady = false; + m_bIsSpawned = false; + m_bIsInBattle = (m_creature->GetPositionX() < 2300.0f) ? true : false; + + Reset(); + } + + uint32 m_uiReadyTimer; + uint32 m_uiCleaveTimer; + + bool m_bIsReady; + bool m_bIsSpawned; + bool m_bIsInBattle; + + void EnterEvadeIfOutOfCombatArea(const uint32 uiDiff) { return; } + + void Reset() + { + m_uiReadyTimer = 4000; + m_uiCleaveTimer = urand(3000, 5000); + } + + void AttackStart(Unit *pWho) + { + if (!m_bIsReady) + return; + + ScriptedAI::AttackStart(pWho); + } + + void MoveInLineOfSight(Unit *pWho) + { + if (!m_bIsReady) + return; + + CreatureAI::MoveInLineOfSight(pWho); + } + + void UpdateAI(uint32 const uiDiff) + { + if (!m_bIsReady) + { + if (!m_bIsSpawned) + { + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_EMERGE); + m_bIsSpawned = true; + } + + if (m_uiReadyTimer <= uiDiff) + m_bIsReady = true; + else m_uiReadyTimer -= uiDiff; + + return; + } + + if (!m_creature->getVictim() || !m_creature->SelectHostileTarget() ) + { + if (m_bIsInBattle && m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != CONFUSED_MOTION_TYPE) + m_creature->GetMotionMaster()->MoveConfused(); + + return; + } + + if (m_uiCleaveTimer <= uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE); + m_uiCleaveTimer = urand(13000, 15000); + } + else m_uiCleaveTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; CreatureAI* GetAI_npc_highlord_darion_mograine(Creature* pCreature) -{ +{ return new npc_highlord_darion_mograineAI(pCreature); } CreatureAI* GetAI_npc_the_lich_king_tirion_dawn(Creature* pCreature) { - return new npc_the_lich_king_tirion_dawnAI (pCreature); + return new npc_the_lich_king_tirion_dawnAI(pCreature); +}; + +CreatureAI* GetAI_npc_minibosses_dawn_of_light(Creature* pCreature) +{ + return new npc_minibosses_dawn_of_lightAI (pCreature); } -// Hack until Vehicle Support -bool GossipHello_scarlet_cannon(Player* pPlayer, Creature* pCreature) +CreatureAI* GetAI_mob_warrior_of_the_frozen_wastes(Creature* pCreature) { - if (pPlayer->GetQuestStatus(12701) == QUEST_STATUS_INCOMPLETE) - { - if (rand()%100 < 50) - { - Creature* pTemp = GetClosestCreatureWithEntry(pPlayer, 28834, DEFAULT_VISIBILITY_DISTANCE); - pCreature->CastSpell(pTemp,52436,true,0,0,pPlayer->GetGUID()); - } - else pPlayer->CastSpell(pPlayer,13261,true,0,0,pCreature->GetGUID()); // Some fun malfunction :) - } - return true; + return new mob_warrior_of_the_frozen_wastesAI(pCreature); } +CreatureAI* GetAI_mob_acherus_ghoul(Creature* pCreature) +{ + return new mob_acherus_ghoulAI(pCreature); +}; + void AddSC_ebon_hold() { Script* pNewScript; @@ -3475,29 +3332,8 @@ void AddSC_ebon_hold() pNewScript->RegisterSelf(); pNewScript = new Script; - pNewScript->Name = "npc_salanar_the_horseman"; - pNewScript->pGossipHello = &GossipHello_npc_salanar_the_horseman; - pNewScript->pGossipSelect = &GossipSelect_npc_salanar_the_horseman; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_dark_rider_of_acherus"; - pNewScript->GetAI = &GetAI_mob_dark_rider_of_acherus; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_scarlet_miner"; - pNewScript->GetAI = &GetAI_mob_scarlet_miner; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_scarlet_courier"; - pNewScript->GetAI = &GetAI_mob_scarlet_courier; - pNewScript->RegisterSelf(); - - pNewScript = new Script; - pNewScript->Name = "mob_high_inquisitor_valroth"; - pNewScript->GetAI = &GetAI_mob_high_inquisitor_valroth; + pNewScript->Name = "mob_scarlet_ghoul"; + pNewScript->GetAI = &GetAI_mob_scarlet_ghoul; pNewScript->RegisterSelf(); pNewScript = new Script; @@ -3513,19 +3349,18 @@ void AddSC_ebon_hold() pNewScript->RegisterSelf(); pNewScript = new Script; - pNewScript->Name = "scarlet_cannon"; - pNewScript->pGossipHello = &GossipHello_scarlet_cannon; + pNewScript->Name = "npc_minibosses_dawn_of_light"; + pNewScript->GetAI = &GetAI_npc_minibosses_dawn_of_light; pNewScript->RegisterSelf(); pNewScript = new Script; - pNewScript->Name = "npc_acherus_deathcharger"; - pNewScript->pGossipHello = &GossipHello_npc_acherus_deathcharger; + pNewScript->Name = "mob_acherus_ghoul"; + pNewScript->GetAI = &GetAI_mob_acherus_ghoul; pNewScript->RegisterSelf(); pNewScript = new Script; - pNewScript->Name = "npc_palomino"; - pNewScript->GetAI = &GetAI_npc_palomino; - pNewScript->pGossipHello = &GossipHello_npc_palomino; - pNewScript->pGossipSelect = &GossipSelect_npc_palomino; + pNewScript->Name = "mob_warrior_of_the_frozen_wastes"; + pNewScript->GetAI = &GetAI_mob_warrior_of_the_frozen_wastes; pNewScript->RegisterSelf(); + } diff --git a/scripts/eastern_kingdoms/shadowfang_keep/boss_hummel.cpp b/scripts/eastern_kingdoms/shadowfang_keep/boss_hummel.cpp new file mode 100644 index 0000000..c3eddcf --- /dev/null +++ b/scripts/eastern_kingdoms/shadowfang_keep/boss_hummel.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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_hummel +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Shadowfang Keep +EndScriptData */ + +#include "precompiled.h" + +void AddSC_boss_hummel() +{ +} diff --git a/scripts/eastern_kingdoms/stranglethorn_vale.cpp b/scripts/eastern_kingdoms/stranglethorn_vale.cpp index 0623f82..7635685 100644 --- a/scripts/eastern_kingdoms/stranglethorn_vale.cpp +++ b/scripts/eastern_kingdoms/stranglethorn_vale.cpp @@ -17,15 +17,25 @@ /* ScriptData SDName: Stranglethorn_Vale SD%Complete: 100 -SDComment: Quest support: 592 +SDComment: Quest support: 592, 8193 SDCategory: Stranglethorn Vale EndScriptData */ /* ContentData mob_yenniku +npc_riggle_bassbait EndContentData */ #include "precompiled.h" +#include "GameEventMgr.h" + +enum +{ + SAY_START = -1510356, + SAY_WINNER = -1510357, + SAY_END = -1510358, + QUEST_MASTER_ANGLER = 8193, +}; /*###### ## mob_yenniku @@ -93,8 +103,110 @@ CreatureAI* GetAI_mob_yenniku(Creature *_Creature) } /*###### -## +##npc_riggle_bassbait ######*/ +/** + * AI for Riggle Bassbait. + * This is the AI for Riggle Bassbait, see http://www.wowhead.com/?npc=15077 + * @see ScriptedAI + * @author burned, gotisch + */ +struct MANGOS_DLL_DECL npc_riggle_bassbaitAI : public ScriptedAI +{ + /** + * Constructor of the Creature. + * This is called when the creature is spawned. + * @param c The Creature that this AI is for + */ + npc_riggle_bassbaitAI(Creature *c) : ScriptedAI(c) + { + // This will keep the NPC active even if there are no players around! + c->SetActiveObjectState(true); + bEventAnnounced = bEventIsOver = bEventWinnerFound = false; + Reset(); + } + /** + * Flag to check if event was announced. True if event was announced. + */ + bool bEventAnnounced; + /** + * Flag to check if event is over. True if event is over. + */ + bool bEventIsOver; + /** + * Flag to check if someone won the event. True if someone has won. + */ + bool bEventWinnerFound; + + void Reset() { } + + void Aggro(Unit *who) {} + + void UpdateAI(const uint32 diff) + { + // Announce the event max 1 minute after being spawned. But only if Fishing extravaganza is running. + if (!bEventAnnounced && time(NULL) % 60 == 0 && IsHolidayActive(HOLIDAY_FISHING_EXTRAVAGANZA)) + { + debug_log("SD2: npc_riggle_bassbait announce HOLIDAY_FISHING_EXTRAVAGANZA contest"); + DoScriptText(SAY_START, m_creature); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); //Quest&Gossip are now active + bEventAnnounced = true; + } + // The Event was started (announced) & It was not yet ended & One minute passed & the Fish are gone + if ( bEventAnnounced && !bEventIsOver && time(NULL) % 60 == 0 && !IsHolidayActive(HOLIDAY_FISHING_EXTRAVAGANZA)) + { + debug_log("SD2: npc_riggle_bassbait end HOLIDAY_FISHING_EXTRAVAGANZA contest"); + DoScriptText(SAY_END, m_creature); + bEventIsOver = true; + } + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; +/** + * GossipHello for NPC Riggle Bassbait. + * This is called each time a Player tries to talk with the NPC. + */ +bool GossipHello_npc_riggle_bassbait(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) // If the quest is still running. + { + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + pPlayer->SEND_GOSSIP_MENU(7614, pCreature->GetGUID()); + return true; + } + // The Quest is not there anymore + // There is a winner! + pPlayer->SEND_GOSSIP_MENU(7714, pCreature->GetGUID()); + return true; +} + +bool ChooseReward_npc_riggle_bassbait(Player* pPlayer, Creature* pCreature, const Quest* pQuest, uint32 uiItem) +{ + // TODO: check if this can only be called if NPC has QUESTGIVER flag. + if (pQuest->GetQuestId() == QUEST_MASTER_ANGLER && ((npc_riggle_bassbaitAI*)(pCreature->AI()))->bEventWinnerFound == false) + { + DoScriptText(SAY_WINNER, pCreature,pPlayer); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + ((npc_riggle_bassbaitAI*)(pCreature->AI()))->bEventWinnerFound = true; + Creature* creature2 = GetClosestCreatureWithEntry(pCreature,15087,60.0f); + if (creature2) + { + creature2->SetFlag(UNIT_NPC_FLAGS,UNIT_NPC_FLAG_QUESTGIVER); + } else { + debug_log("Could not change flag of Jang"); + } + return true; + } + return true; +} + +CreatureAI* GetAI_npc_riggle_bassbait(Creature* pCreature) +{ + return new npc_riggle_bassbaitAI(pCreature); +} void AddSC_stranglethorn_vale() { @@ -104,4 +216,11 @@ void AddSC_stranglethorn_vale() newscript->Name = "mob_yenniku"; newscript->GetAI = &GetAI_mob_yenniku; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_riggle_bassbait"; + newscript->GetAI = &GetAI_npc_riggle_bassbait; + newscript->pGossipHello = &GossipHello_npc_riggle_bassbait; + newscript->pChooseReward = &ChooseReward_npc_riggle_bassbait; + newscript->RegisterSelf(); } diff --git a/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp b/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp new file mode 100644 index 0000000..feb22ba --- /dev/null +++ b/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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_muru +SD%Complete: +SDComment: +SDCategory: Sunwell Plateau +EndScriptData */ + +#include "precompiled.h" + +void AddSC_boss_muru() +{ +} diff --git a/scripts/examples/boss_general.cpp b/scripts/examples/boss_general.cpp new file mode 100644 index 0000000..659125d --- /dev/null +++ b/scripts/examples/boss_general.cpp @@ -0,0 +1,113 @@ +/* Copyright (C) 2010 /dev/rsa for 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 +SD%Complete: ?% +SDComment: by /dev/rsa +SDCategory: General boss instance script template +EndScriptData */ + +#include "precompiled.h" +#include "def_instance.h" + +enum BossSpells +{ + SPELL_SUPERSPELL = 99999, +}; + +struct MANGOS_DLL_DECL boss_generalAI : public BSWScriptedAI +{ + boss_generalAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 stage; + + void Reset() + { + if(!pInstance) return; + pInstance->SetData(TYPE_GENERAL, NOT_STARTED); + resetTimers(); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) return; + } + + void KilledUnit(Unit* pVictim) + { +/* switch (urand(0,1)) { + case 0: + DoScriptText(-1631006,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631007,m_creature,pVictim); + break; + };*/ + } + + void JustReachedHome() + { + if (!pInstance) return; + pInstance->SetData(TYPE_GENERAL, FAIL); + } + + void JustSummoned(Creature* summoned) + { + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + pInstance->SetData(TYPE_GENERAL, IN_PROGRESS); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return; + pInstance->SetData(TYPE_GENERAL, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_SUPERSPELL, diff); + + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_boss_general(Creature* pCreature) +{ + return new boss_generalAI(pCreature); +} + +void AddSC_boss_general() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_general"; + newscript->GetAI = &GetAI_boss_general; + newscript->RegisterSelf(); +} diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite_corruptor.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite_corruptor.cpp new file mode 100644 index 0000000..1cd08c7 --- /dev/null +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite_corruptor.cpp @@ -0,0 +1,132 @@ +/* Copyright (C) 2006 - 2010 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_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 +SDCategory: Culling of Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_culling_of_stratholme.h" + +enum +{ + SPELL_COURSE = 60588, + SPELL_STRIKE = 60590 +}; + +struct MANGOS_DLL_DECL boss_infinite_corruptorAI : public ScriptedAI +{ + boss_infinite_corruptorAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiStrikeTimer; + uint32 m_uiCourseTimer; + + void Reset() + { + m_uiCourseTimer = 7000; + m_uiStrikeTimer = 5000; + } + + void Aggro(Unit* who) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_BONUS, SPECIAL); + } + + void JustDied(Unit *killer) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_BONUS, DONE); + } + + void KilledUnit(Unit* pVictim) + { + //switch(rand()%3) + // { + // case 0: DoScriptText(SAY_EPOCH_SLAY01, m_creature); break; + // case 1: DoScriptText(SAY_EPOCH_SLAY02, m_creature); break; + // case 2: DoScriptText(SAY_EPOCH_SLAY03, m_creature); break; + // } + } + + void EnterEvadeMode() + { + if(!m_pInstance) return; + + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + if(m_pInstance) + m_pInstance->SetData(TYPE_BONUS, IN_PROGRESS); + + if(m_creature->isAlive()) + m_creature->GetMotionMaster()->MoveTargetedHome(); + + m_creature->SetLootRecipient(NULL); + + Reset(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + + if (m_uiCourseTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_COURSE); + + m_uiCourseTimer = 17000; + }else m_uiCourseTimer -= diff; + + if (m_uiStrikeTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_STRIKE); + + m_uiStrikeTimer = 5000; + }else m_uiStrikeTimer -= diff; + } +}; + +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(); +} \ No newline at end of file diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_lord_epoch.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_lord_epoch.cpp new file mode 100644 index 0000000..5ea369c --- /dev/null +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_lord_epoch.cpp @@ -0,0 +1,148 @@ +/* Copyright (C) 2006 - 2010 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_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 +SDCategory: Culling of Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_culling_of_stratholme.h" + +enum +{ + SPELL_COURSE = 52772, + SPELL_TIME_STOP = 58848, + SPELL_TIME_WARP = 52766, + SPELL_SPIKE_N = 52771, + SPELL_SPIKE_H = 58830, + + SAY_EPOCH_DEATH = -1594119, + SAY_EPOCH_SLAY01 = -1594120, + SAY_EPOCH_SLAY02 = -1594121, + SAY_EPOCH_SLAY03 = -1594122, + SAY_EPOCH_WARP01 = -1594123, + SAY_EPOCH_WARP02 = -1594124, + SAY_EPOCH_WARP03 = -1594125 +}; + +struct MANGOS_DLL_DECL boss_lord_epochAI : public ScriptedAI +{ + boss_lord_epochAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 Spike_Timer; + uint32 Warp_Timer; + uint32 Stop_Timer; + uint32 Course_Timer; + uint64 m_uiArthasGUID; + + void Reset() + { + Course_Timer = 9300; + Stop_Timer = 21300; + Warp_Timer = 25300; + Spike_Timer = 5300; + } + + void JustDied(Unit *killer) + { + DoScriptText(SAY_EPOCH_DEATH, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + switch(rand()%3) + { + case 0: DoScriptText(SAY_EPOCH_SLAY01, m_creature); break; + case 1: DoScriptText(SAY_EPOCH_SLAY02, m_creature); break; + case 2: DoScriptText(SAY_EPOCH_SLAY03, m_creature); break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + + if (Course_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_COURSE); + + Course_Timer = 9300; + }else Course_Timer -= diff; + + if (Spike_Timer < diff) + { + + DoCast(m_creature->getVictim(),m_bIsHeroic ? SPELL_SPIKE_H : SPELL_SPIKE_N); + + Spike_Timer = 5300; + }else Spike_Timer -= diff; + + if (Stop_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_TIME_STOP); + + Stop_Timer = 21300; + }else Stop_Timer -= diff; + + if (Warp_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_TIME_WARP); + switch(rand()%3) + { + case 0: DoScriptText(SAY_EPOCH_WARP01, m_creature); break; + case 1: DoScriptText(SAY_EPOCH_WARP02, m_creature); break; + case 2: DoScriptText(SAY_EPOCH_WARP03, m_creature); break; + } + + Warp_Timer = 25300; + }else Warp_Timer -= diff; + + } +}; + +CreatureAI* GetAI_boss_lord_epoch(Creature* pCreature) +{ + return new boss_lord_epochAI(pCreature); +} + +void AddSC_boss_lord_epoch() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_lord_epoch"; + newscript->GetAI = &GetAI_boss_lord_epoch; + newscript->RegisterSelf(); +} diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_malganis.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_malganis.cpp new file mode 100644 index 0000000..31f668e --- /dev/null +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_malganis.cpp @@ -0,0 +1,243 @@ +/* Copyright (C) 2006 - 2010 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_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 +SDCategory: Culling of Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_culling_of_stratholme.h" + +enum +{ + SAY_MALGANIS_AGGRO = -1594170, + SAY_MALGANIS_SLAY01 = -1594172, + SAY_MALGANIS_SLAY02 = -1594173, + SAY_MALGANIS_SLAY03 = -1594174, + SAY_MALGANIS_SLAY04 = -1594175, + SAY_MALGANIS_SLAY05 = -1594176, + SAY_MALGANIS_SLAY06 = -1594177, + SAY_MALGANIS_SLAY07 = -1594166, + SAY_MALGANIS_SLEEP01 = -1594185, + SAY_MALGANIS_SLEEP02 = -1594186, + SAY_MALGANIS_Sleep = -1594178, + SAY_MALGANIS_15HP = -1594179, + + SPELL_SWAMP_N = 52720, + SPELL_SWAMP_H = 58852, + SPELL_MIND_BLAST_N = 52722, + SPELL_MIND_BLAST_H = 58850, + SPELL_SLEEP_N = 52721, + SPELL_SLEEP_H = 58849, + SPELL_VAMPIRE = 52723 +}; + +struct MANGOS_DLL_DECL boss_malganisAI : public ScriptedAI +{ + boss_malganisAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + Unit* pTarget; + bool Sleep; + bool Vampire; + uint32 Phase; + Creature* Malganis; + Creature* Arthas; + + uint32 Swamp_Timer; + uint32 MindBlast_Timer; + uint32 Sleep_Timer; + uint32 Vampire_Timer; + + void Reset() + { + Sleep = false; + Vampire = false; + Swamp_Timer = 6300; + MindBlast_Timer = 11300; + Sleep_Timer = 17300; + Vampire_Timer = 30000; + } + + void AttackStart(Unit* who) + { + if(m_pInstance->GetData(TYPE_PHASE) > 9) return; + + if(m_pInstance->GetData(TYPE_MALGANIS) != IN_PROGRESS) return; + + if(!who || who == m_creature) + return; + + ScriptedAI::AttackStart(who); + } + + void KillCreditMalganis() + { + Map *map = m_creature->GetMap(); + Map::PlayerList const& players = map->GetPlayers(); + if (!players.isEmpty() && map->IsDungeon()) + { + for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + { + if(Player* pPlayer = itr->getSource()) + pPlayer->KilledMonsterCredit(31006, m_creature->GetGUID()); + } + } + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + + if(m_pInstance->GetData(TYPE_PHASE) > 9) + { + KillCreditMalganis(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (Creature* pArthas = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_ARTHAS))) + m_creature->SetInCombatWith(pArthas); + } + else + m_creature->RemoveFromWorld(); + + m_creature->SetLootRecipient(NULL); + } + + void Aggro(Unit* who) + { + if(m_pInstance->GetData(TYPE_PHASE) > 9) return; + + DoScriptText(SAY_MALGANIS_AGGRO, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + switch(rand()%7) + { + case 0: DoScriptText(SAY_MALGANIS_SLAY01, m_creature); break; + case 1: DoScriptText(SAY_MALGANIS_SLAY02, m_creature); break; + case 2: DoScriptText(SAY_MALGANIS_SLAY03, m_creature); break; + case 3: DoScriptText(SAY_MALGANIS_SLAY04, m_creature); break; + case 4: DoScriptText(SAY_MALGANIS_SLAY05, m_creature); break; + case 5: DoScriptText(SAY_MALGANIS_SLAY06, m_creature); break; + case 6: DoScriptText(SAY_MALGANIS_SLAY07, m_creature); break; + } + } + + void UpdateAI(const uint32 diff) + { + if(m_pInstance->GetData(TYPE_PHASE) > 9) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + + if (Swamp_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsHeroic ? SPELL_SWAMP_H : SPELL_SWAMP_N); + + Swamp_Timer = 7300; + }else Swamp_Timer -= diff; + + if (MindBlast_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsHeroic ? SPELL_MIND_BLAST_H : SPELL_MIND_BLAST_N); + + MindBlast_Timer = 11300; + }else MindBlast_Timer -= diff; + + if(m_creature->GetHealthPercent() < 40.0f) + { + if(Sleep == false) + { + Sleep = true; + DoScriptText(SAY_MALGANIS_Sleep, m_creature); + } + + if (Sleep_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsHeroic ? SPELL_SLEEP_H : SPELL_SLEEP_N); + switch(rand()%2) + { + case 0: DoScriptText(SAY_MALGANIS_SLEEP01, m_creature); break; + case 1: DoScriptText(SAY_MALGANIS_SLEEP02, m_creature); break; + } + + Sleep_Timer = 17300; + }else Sleep_Timer -= diff; + } + + if(m_creature->GetHealthPercent() < 25.0f) + { + if(Vampire == false) + { + Vampire = true; + DoScriptText(SAY_MALGANIS_15HP, m_creature); + DoCast(m_creature, SPELL_VAMPIRE); + } + + if (Vampire_Timer < diff) + { + DoCast(m_creature, SPELL_VAMPIRE); + + Vampire_Timer = 30000; + }else Vampire_Timer -= diff; + + } + + if(m_creature->GetHealthPercent() < 5.0f) + { + m_pInstance->SetData(TYPE_PHASE, 10); + m_pInstance->SetData(TYPE_MALGANIS, DONE); + EnterEvadeMode(); + } + + } +}; + +CreatureAI* GetAI_boss_malganis(Creature* pCreature) +{ + return new boss_malganisAI(pCreature); +} + +void AddSC_boss_malganis() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_malganis"; + newscript->GetAI = &GetAI_boss_malganis; + newscript->RegisterSelf(); + +} \ No newline at end of file diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp new file mode 100644 index 0000000..7ecbfeb --- /dev/null +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp @@ -0,0 +1,137 @@ +/* Copyright (C) 2006 - 2010 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_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 +SDCategory: Culling of Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_culling_of_stratholme.h" + +enum +{ + SPELL_CHAIN_N = 52696, + SPELL_CHAIN_H = 58823, + SPELL_EXPLODED_N = 52666, + SPELL_EXPLODED_H = 58824, + SPELL_FRENZY = 58841, + + SAY_MEATHOOK_AGGRO = -1594111, + SAY_MEATHOOK_DEATH = -1594112, + SAY_MEATHOOK_SLAY01 = -1594113, + SAY_MEATHOOK_SLAY02 = -1594114, + SAY_MEATHOOK_SLAY03 = -1594115 +}; + +struct MANGOS_DLL_DECL boss_meathookAI : public ScriptedAI +{ + boss_meathookAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 Chain_Timer; + uint32 Exploded_Timer; + uint32 Frenzy_Timer; + + void Reset() + { + Chain_Timer = 6300; + Exploded_Timer = 5000; + Frenzy_Timer = 22300; + } + + void Aggro(Unit* who) + { + DoScriptText(SAY_MEATHOOK_AGGRO, m_creature); + } + + void JustDied(Unit *killer) + { + DoScriptText(SAY_MEATHOOK_DEATH, m_creature); + if(m_pInstance) + m_pInstance->SetData(TYPE_PHASE, 3); + } + + void KilledUnit(Unit* pVictim) + { + switch(rand()%3) + { + case 0: DoScriptText(SAY_MEATHOOK_SLAY01, m_creature); break; + case 1: DoScriptText(SAY_MEATHOOK_SLAY02, m_creature); break; + case 2: DoScriptText(SAY_MEATHOOK_SLAY03, m_creature); break; + } + } + + void UpdateAI(const uint32 diff) + { + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + + if (Chain_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsHeroic ? SPELL_CHAIN_H : SPELL_CHAIN_N); + + Chain_Timer = 6300; + }else Chain_Timer -= diff; + + if (Exploded_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsHeroic ? SPELL_EXPLODED_H : SPELL_EXPLODED_N); + + Exploded_Timer = 5000; + }else Exploded_Timer -= diff; + + if (Frenzy_Timer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature,SPELL_FRENZY); + + Frenzy_Timer = 23300; + }else Frenzy_Timer -= diff; + + } +}; + +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/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp new file mode 100644 index 0000000..ec38367 --- /dev/null +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp @@ -0,0 +1,267 @@ +/* Copyright (C) 2006 - 2010 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_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 +SDCategory: Culling of Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_culling_of_stratholme.h" + +enum +{ + SAY_SALRAMM_AGGRO = -1594130, + SAY_SALRAMM_DEATH = -1594131, + SAY_SALRAMM_SLAY01 = -1594132, + SAY_SALRAMM_SLAY02 = -1594133, + SAY_SALRAMM_SLAY03 = -1594134, + SAY_SALRAMM_STEAL01 = -1594135, + SAY_SALRAMM_STEAL02 = -1594136, + SAY_SALRAMM_STEAL03 = -1594137, + SAY_SUMMON01 = -1594138, + SAY_SUMMON02 = -1594139, + SAY_BOOM01 = -1594140, + SAY_BOOM02 = -1594141, + + SPELL_SB_N = 57725, + SPELL_SB_H = 58827, + SPELL_FLESH = 58845, + SPELL_STEAL = 52708, + SPELL_GNOUL_BLOW = 58825, + SPELL_SUMMON_GNOUL = 52451, + + NPC_GNOUL = 27733 +}; + +struct MANGOS_DLL_DECL boss_salrammAI : public ScriptedAI +{ + boss_salrammAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 ShadowBoltTimer; + uint32 FleshTimer; + uint32 StealTimer; + uint32 SummonTimer; + + void Reset() + { + ShadowBoltTimer = 5000; + FleshTimer = (urand(7000, 9000)); + StealTimer = (urand(9000, 17000)); + SummonTimer = (urand(12000, 17000)); + if(m_pInstance) + m_pInstance->SetData64(NPC_SALRAMM, m_creature->GetGUID()); + } + + void Aggro(Unit* who) + { + DoScriptText(SAY_SALRAMM_AGGRO, m_creature); + } + + void JustDied(Unit *killer) + { + DoScriptText(SAY_SALRAMM_DEATH, m_creature); + if(m_pInstance) + m_pInstance->SetData(TYPE_ENCOUNTER, DONE); + } + + void KilledUnit(Unit* pVictim) + { + switch(rand()%3) + { + case 0: DoScriptText(SAY_SALRAMM_SLAY01, m_creature); break; + case 1: DoScriptText(SAY_SALRAMM_SLAY02, m_creature); break; + case 2: DoScriptText(SAY_SALRAMM_SLAY03, m_creature); break; + } + } + + void SpellHitTarget(Unit *target, const SpellEntry *spell) + { + if(spell->Id == SPELL_GNOUL_BLOW) + if(target->GetTypeId() != TYPEID_PLAYER && target->GetEntry() == NPC_GNOUL) + target->SetDisplayId(11686); + } + + void UpdateAI(const uint32 diff) + { + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (ShadowBoltTimer < diff) + { + DoCast(m_creature->getVictim(), m_bIsHeroic ? SPELL_SB_H : SPELL_SB_N); + + ShadowBoltTimer = (urand(5000, 6000)); + }else ShadowBoltTimer -= diff; + + if (FleshTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target,SPELL_FLESH); + + FleshTimer = 7300; + }else FleshTimer -= diff; + + if (StealTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target,SPELL_STEAL); + + switch(rand()%3) + { + case 0: DoScriptText(SAY_SALRAMM_STEAL01, m_creature); break; + case 1: DoScriptText(SAY_SALRAMM_STEAL02, m_creature); break; + case 2: DoScriptText(SAY_SALRAMM_STEAL03, m_creature); break; + } + + StealTimer = (urand(8000, 11000)); + }else StealTimer -= diff; + + if (SummonTimer < diff) + { + switch(rand()%2) + { + case 0: DoScriptText(SAY_SUMMON01, m_creature); break; + case 1: DoScriptText(SAY_SUMMON02, m_creature); break; + } + + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature,SPELL_SUMMON_GNOUL); + + SummonTimer = (urand(12000, 17000)); + }else SummonTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +/*### +## npc_salramm_gnoul +###*/ + +struct MANGOS_DLL_DECL npc_salramm_gnoulAI : public ScriptedAI +{ + npc_salramm_gnoulAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 m_uiBlowTimer; + + void Reset() + { + m_uiBlowTimer = (urand(3000, 15000)); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiBlowTimer < uiDiff) + { + if(Creature* pSalramm = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_SALRAMM))) + { + if(pSalramm->isDead()) return; + + switch(rand()%2) + { + case 0: DoScriptText(SAY_BOOM01, pSalramm); break; + case 1: DoScriptText(SAY_BOOM02, pSalramm); break; + } + pSalramm->InterruptNonMeleeSpells(false); + pSalramm->CastSpell(m_creature, SPELL_GNOUL_BLOW, false); + } + } + else m_uiBlowTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +CreatureAI* GetAI_boss_salramm(Creature* pCreature) +{ + return new boss_salrammAI(pCreature); +} + +CreatureAI* GetAI_npc_salramm_gnoul(Creature* pCreature) +{ + return new npc_salramm_gnoulAI(pCreature); +} + +void AddSC_boss_salramm() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_salramm"; + newscript->GetAI = &GetAI_boss_salramm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_salramm_gnoul"; + newscript->GetAI = &GetAI_npc_salramm_gnoul; + newscript->RegisterSelf(); +} diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp index abf2044..05207e0 100644 --- a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp @@ -14,222 +14,1765 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* ScriptData -SDName: culling_of_stratholme -SD%Complete: 5% -SDComment: Placeholder +SDName: instance_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 SDCategory: Culling of Stratholme EndScriptData */ #include "precompiled.h" -#include "culling_of_stratholme.h" +#include "def_culling_of_stratholme.h" +#include "escort_ai.h" +#include "WorldPacket.h" +#include "Weather.h" -/* ************* -** npc_chromie (gossip, quest-accept) -************* */ +/*### +## npc_arthas +###*/ enum { - QUEST_DISPELLING_ILLUSIONS = 13149, - QUEST_A_ROYAL_ESCORT = 13151, + SAY_INTRO01 = -1594071, //Arthas + SAY_INTRO02 = -1594072, //Uther + SAY_INTRO03 = -1594073, //Arthas + SAY_INTRO04 = -1594074, //Arthas + SAY_INTRO05 = -1594075, //Uther + SAY_INTRO06 = -1594076, //Arthas + SAY_INTRO07 = -1594077, //Uther + SAY_INTRO08 = -1594078, //Arthas + SAY_INTRO09 = -1594079, //Arthas + SAY_INTRO10 = -1594080, //Uther + SAY_INTRO11 = -1594081, //Arthas + SAY_INTRO12 = -1594082, //Uther + SAY_INTRO13 = -1594083, //Jaina + SAY_INTRO14 = -1594084, //Arthas + SAY_INTRO15 = -1594085, //Uther + SAY_INTRO16 = -1594086, //Arthas + SAY_INTRO17 = -1594087, //Jaina + SAY_INTRO18 = -1594088, //Arthas + + SAY_ENTER01 = -1594089, //Arthas + SAY_ENTER02 = -1594090, //Cityman + SAY_ENTER03 = -1594091, //Arthas + SAY_ENTER04 = -1594092, //Crazyman + SAY_ENTER05 = -1594093, //Crazyman2 + SAY_ENTER06 = -1594094, //Arthas + SAY_ENTER07 = -1594095, //Malganis + SAY_ENTER08 = -1594096, //Malganis + SAY_ENTER09 = -1594097, //Arthas + SAY_ENTER10 = -1594098, //Arthas + + SAY_SALRAMM_SPAWN = -1594129, + SAY_MEATHOOK_SPAWN = -1594110, - ITEM_ARCANE_DISRUPTOR = 37888, + SAY_PHASE501 = -1594142, //Arthas + SAY_PHASE502 = -1594143, //Arthas + SAY_PHASE503 = -1594144, //Human + SAY_PHASE504 = -1594145, //Arthas + SAY_PHASE505 = -1594146, //Arthas + SAY_PHASE506 = -1594147, //Human + SAY_PHASE507 = -1594148, //Arthas + SAY_PHASE508 = -1594149, //Arthas + SAY_PHASE509 = -1594150, //Arthas + SAY_PHASE510 = -1594151, //Arthas + SAY_PHASE511 = -1594152, //Arthas + SAY_PHASE512 = -1594153, //Arthas + SAY_PHASE513 = -1594154, //Arthas - GOSSIP_ITEM_ENTRANCE_1 = -3595000, - GOSSIP_ITEM_ENTRANCE_2 = -3595001, - GOSSIP_ITEM_ENTRANCE_3 = -3595002, + SAY_EPOCH_INTRO = -1594155, + SAY_ARTHAS_INTRO = -1594156, + SAY_EPOCH_AGGRO = -1594157, - TEXT_ID_ENTRANCE_1 = 12992, - TEXT_ID_ENTRANCE_2 = 12993, - TEXT_ID_ENTRANCE_3 = 12994, - TEXT_ID_ENTRANCE_4 = 12995, + SAY_PHASE514 = -1594158, //Arthas Shkaf 01 + SAY_PHASE515 = -1594159, //Arthas Shkaf 02 + SAY_PHASE601 = -1594160, //Arthas Fire + SAY_PHASE602 = -1594161, //Arthas Picnic + SAY_PHASE603 = -1594162, //Arthas Picnic End + SAY_PHASE605 = -1594164, //Arthas mall start + SAY_PHASE606 = -1594188, - GOSSIP_ITEM_INN_1 = -3595003, - GOSSIP_ITEM_INN_2 = -3595004, - GOSSIP_ITEM_INN_3 = -3595005, + SAY_MALGANIS_ESCAPE02 = -1594180, + SAY_MALGANIS_ESCAPE01 = -1594187, + SAY_MALGANIS_OUTRO = -1594182, + SAY_ARTHAS_OUTRO01 = -1594181, + SAY_ARTHAS_OUTRO02 = -1594183, + SAY_ARTHAS_OUTRO03 = -1594184, - TEXT_ID_INN_1 = 12939, - TEXT_ID_INN_2 = 12949, - TEXT_ID_INN_3 = 12950, - TEXT_ID_INN_4 = 12952, + /*SPELL*/ + SPELL_EXORCISM_N = 52445, + SPELL_EXORCISM_H = 58822, + SPELL_HOLY_LIGHT = 52444, + SPELL_ARTHAS_AURA = 52442, + + /*NPC*/ + NPC_CITYMAN = 28167, + NPC_CRAZYMAN = 28169, + NPC_MALGANIS_INTRO = 26533, + + /*OTHER*/ + POINT_LAST_POINT = 0xFFFFFF, + FACTION = 2076 }; -bool GossipHello_npc_chromie(Player *pPlayer, Creature *pCreature) +const float SummonScourge[2][4] = { - if (pCreature->isQuestGiver()) - pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + {2340.058f, 1253.570f, 132.733f, 5.09f}, //right wing + {2272.773f, 1331.824f, 124.171f, 3.12f}, //left wing +}; + +struct MANGOS_DLL_DECL npc_arthasAI : public npc_escortAI +{ + npc_arthasAI(Creature* pCreature) : npc_escortAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + m_creature->SetSpeedRate(MOVE_RUN, 1); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint64 m_uiUtherGUID; + uint64 m_uiJainaGUID; + uint64 m_uiPeople01GUID; + uint64 m_uiPeople02GUID; + uint64 m_uiMalganisGUID; + uint64 m_uiMarine01GUID; + uint64 m_uiMarine02GUID; + uint64 m_uiMarine03GUID; + uint64 m_uiMarine04GUID; + uint64 m_uiPriest01GUID; + uint64 m_uiPriest02GUID; + uint64 m_uiHuman01GUID; + uint64 m_uiHuman02GUID; + uint64 m_uiHuman03GUID; + + uint32 culling_faction; + uint32 m_uiStep; + uint32 m_uiStepTimer; + uint32 m_uiMoveTimer; + uint32 m_uiHealTimer; + uint32 m_uiExorcismTimer; + uint32 m_uiSummonTimer; + uint32 m_uiWaveCount; + + Creature* Malganis; + Creature* pEpoch; + bool StartEvent; + bool MoveSoldier; + + float LastX; + float LastY; + float LastZ; + + void Reset() + { + if(!m_pInstance) return; + + m_creature->SetSpeedRate(MOVE_RUN, 1); + + if(m_pInstance->GetData(TYPE_INTRO) == NOT_STARTED) + { + m_creature->setFaction(35); + RemoveGossip(); + } + + if(m_pInstance->GetData(TYPE_PHASE) == 11) + { + m_creature->SetVisibility(VISIBILITY_OFF); + } + } + + void RemoveGossip() + { + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + void MoveSoldiers() + { + if(Unit* Marine01 = m_creature->GetMap()->GetUnit( m_uiMarine01GUID)) + { + Marine01->GetMotionMaster()->MovePoint(0, 2083.483f,1282.313f,141.198f); + Marine01->setFaction(culling_faction); + } + if(Unit* Marine02 = m_creature->GetMap()->GetUnit( m_uiMarine02GUID)) + { + Marine02->GetMotionMaster()->MovePoint(0, 2083.681f,1292.809f,141.141f); + Marine02->setFaction(culling_faction); + } + if(Unit* Marine03 = m_creature->GetMap()->GetUnit( m_uiMarine03GUID)) + { + Marine03->GetMotionMaster()->MovePoint(0, 2082.158f,1290.406f,141.261f); + Marine03->setFaction(culling_faction); + } + if(Unit* Marine04 = m_creature->GetMap()->GetUnit( m_uiMarine04GUID)) + { + Marine04->GetMotionMaster()->MovePoint(0, 2081.899f,1285.122f,141.302f); + Marine04->setFaction(culling_faction); + } + if(Unit* Priest01 = m_creature->GetMap()->GetUnit( m_uiPriest01GUID)) + { + Priest01->GetMotionMaster()->MovePoint(0, 2081.072f,1292.233f,141.329f); + Priest01->setFaction(culling_faction); + } + if(Unit* Priest02 = m_creature->GetMap()->GetUnit( m_uiPriest02GUID)) + { + Priest02->GetMotionMaster()->MovePoint(0, 2080.632f,1283.004f,141.358f); + Priest02->setFaction(culling_faction); + } + } + + void EnableEscort() + { + SetEscortPaused(false); + } + + void SummonPeople() + { + if(Creature* Cityman = m_creature->SummonCreature(NPC_CITYMAN,2091.977f,1275.021f,140.757f,0.558f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,30000)) + m_uiPeople01GUID = Cityman->GetGUID(); + if(Creature* Crazyman = m_creature->SummonCreature(NPC_CRAZYMAN,2093.514f,1275.842f,140.408f,3.801f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,30000)) + m_uiPeople02GUID = Crazyman->GetGUID(); + } + + void StartAI() + { + SummonPeople(); + m_uiStep = 0; + m_uiStepTimer = 100; + StartEvent = true; + } + + void Aggro(Unit* who) + { + DoCast(m_creature, SPELL_ARTHAS_AURA); + } + + void EnterEvadeMode() + { + if(!m_pInstance) return; + + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + m_uiExorcismTimer = 7400; + m_uiHealTimer = 100; + + m_creature->SetLootRecipient(NULL); - if (instance_culling_of_stratholme* m_pInstance = (instance_culling_of_stratholme*)pCreature->GetInstanceData()) + if(m_pInstance->GetData(TYPE_PHASE) > 4) + { + npc_escortAI::EnterEvadeMode(); + } + + if(m_pInstance->GetData(TYPE_PHASE) > 2 && m_pInstance->GetData(TYPE_PHASE) < 5) + { + m_creature->GetMotionMaster()->MovePoint(POINT_LAST_POINT, LastX, LastY, LastZ); + } + } + + void AttackStart(Unit* pWho) + { + if(!pWho || pWho == m_creature) + return; + + if(m_pInstance && m_pInstance->GetData(TYPE_PHASE) == 4) return; + + npc_escortAI::AttackStart(pWho); + } + + void MoveInLineOfSight(Unit* pWho) { - switch (pCreature->GetEntry()) + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) { - case NPC_CHROMIE_INN: - if (m_pInstance->GetData(TYPE_GRAIN_EVENT) != DONE) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) { - if (pPlayer->GetQuestRewardStatus(QUEST_DISPELLING_ILLUSIONS) && !pPlayer->HasItemCount(ITEM_ARCANE_DISRUPTOR, 1)) - pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_INN_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); } - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_INN_1, pCreature->GetGUID()); - break; - case NPC_CHROMIE_ENTRANCE: - if (m_pInstance->GetData(TYPE_GRAIN_EVENT) == DONE && m_pInstance->GetData(TYPE_ARTHAS_INTRO_EVENT) == NOT_STARTED && pPlayer->GetQuestRewardStatus(QUEST_A_ROYAL_ESCORT)) - pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ENTRANCE_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_ENTRANCE_1, pCreature->GetGUID()); - break; + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); + } + } } } - return true; -} -bool GossipSelect_npc_chromie(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 uiAction) -{ - switch (pCreature->GetEntry()) + void WaypointReached(uint32 uiPointId) { - case NPC_CHROMIE_INN: - switch (uiAction) - { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_INN_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_INN_2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_INN_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_INN_3, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_INN_4, pCreature->GetGUID()); - if (!pPlayer->HasItemCount(ITEM_ARCANE_DISRUPTOR, 1)) - { - if (Item* pItem = pPlayer->StoreNewItemInInventorySlot(ITEM_ARCANE_DISRUPTOR, 1)) + switch(uiPointId) + { + case 2: + DoScriptText(SAY_INTRO18, m_creature); + SetRun(true); + break; + case 8: + GetSoldier(); + SetEscortPaused(true); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_pInstance->SetData(TYPE_INTRO, DONE); + SetRun(false); + break; + case 9: + DoScriptText(SAY_ENTER01, m_creature); + MoveSoldier = true; + m_uiMoveTimer = 12000; + break; + case 10: + SetEscortPaused(true); + m_pInstance->SetData(TYPE_PHASE, 2); + ResetStep(2000); + if(Unit* Cityman = m_creature->GetMap()->GetUnit( m_uiPeople01GUID)) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Cityman->GetGUID()); + Cityman->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + Cityman->GetMotionMaster()->MovePoint(0, 2088.625f,1279.191f,140.743f); + } + break; + case 14: + if(Creature* Human01 = m_creature->SummonCreature(NPC_CITY,2397.308f,1207.565f,134.038f,5.593f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,30000)) + m_uiHuman01GUID = Human01->GetGUID(); + if(Creature* Human02 = m_creature->SummonCreature(NPC_CITY,2400.770f,1207.362f,134.038f,3.454f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,30000)) + m_uiHuman02GUID = Human02->GetGUID(); + if(Creature* Human03 = m_creature->SummonCreature(NPC_CITY,2400.547f,1204.892f,134.038f,2.479f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,30000)) + m_uiHuman03GUID = Human03->GetGUID(); + break; + case 20: + SetEscortPaused(true); + m_creature->setFaction(35); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetRun(false); + break; + case 21: + DoScriptText(SAY_PHASE502, m_creature); + break; + case 22: + SetEscortPaused(true); + m_pInstance->SetData(TYPE_PHASE, 6); + ResetStep(1000); + break; + case 25: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H); + m_creature->SummonCreature(NPC_TIME_RIFT,2428.901f, 1192.164f, 148.076f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + DoScriptText(SAY_PHASE508, m_creature); + break; + case 26: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STAND); + DoScriptText(SAY_PHASE509, m_creature); + break; + case 29: + m_creature->SummonCreature(NPC_TIME_RIFT,2413.773f, 1137.820f, 148.076f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_TIME_RIFT,2404.990f, 1175.121f, 148.076f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + DoScriptText(SAY_PHASE510, m_creature); + break; + case 30: + DoScriptText(SAY_PHASE513, m_creature); + break; + case 31: + ResetStep(1000); + m_pInstance->SetData(TYPE_PHASE, 7); + break; + case 32: + SetEscortPaused(true); + m_pInstance->SetData(TYPE_PHASE, 8); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + SetRun(false); + break; + case 36: + DoScriptText(SAY_PHASE514, m_creature); + break; + case 37: + if(GameObject* pGate = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_SHKAF_GATE))) + pGate->SetGoState(GO_STATE_ACTIVE); + SetRun(true); + DoScriptText(SAY_PHASE515, m_creature); + break; + case 45: + DoScriptText(SAY_PHASE601, m_creature); + break; + case 48: + DoScriptText(SAY_PHASE602, m_creature); + break; + case 51: + SetEscortPaused(true); + m_pInstance->SetData(TYPE_PHASE, 9); + DoScriptText(SAY_PHASE606, m_creature); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + break; + case 53: + SetEscortPaused(true); + m_creature->StopMoving(); + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->setFaction(FACTION); + DoScriptText(SAY_PHASE605, m_creature); + if(Creature* Malganis = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_MALGANIS))) + { + m_pInstance->SetData(TYPE_MALGANIS, IN_PROGRESS); + Malganis->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->AI()->AttackStart(Malganis); + Malganis->AI()->AttackStart(m_creature); + } + break; + } + } + + void JumpNextStep(uint32 Timer) + { + m_uiStepTimer = Timer; + m_uiStep++; + } + + void GetSoldier() //huck + { + //Marine Close Left + if(Creature* pEscort01 = GetClosestCreatureWithEntry(m_creature, NPC_MARINE, 50.0f)) + { + m_uiMarine01GUID = pEscort01->GetGUID(); + pEscort01->UpdateEntry(NPC_CITYMAN); + if(Creature* pEscort02 = GetClosestCreatureWithEntry(m_creature, NPC_MARINE, 50.0f)) + { + m_uiMarine02GUID = pEscort02->GetGUID(); + pEscort02->UpdateEntry(NPC_CITYMAN); + // Right marine 2 + if(Creature* pEscort03 = GetClosestCreatureWithEntry(m_creature, NPC_MARINE, 50.0f)) + { + m_uiMarine03GUID = pEscort03->GetGUID(); + pEscort03->UpdateEntry(NPC_CITYMAN); + if(Creature* pEscort04 = GetClosestCreatureWithEntry(m_creature, NPC_MARINE, 50.0f)) + { + m_uiMarine04GUID = pEscort04->GetGUID(); + pEscort01->UpdateEntry(NPC_MARINE); + pEscort02->UpdateEntry(NPC_MARINE); + pEscort03->UpdateEntry(NPC_MARINE); + } + } + } + } + + if(Creature* pEscort05 = GetClosestCreatureWithEntry(m_creature, NPC_PRIEST, 50.0f)) + { + m_uiPriest01GUID = pEscort05->GetGUID(); + pEscort05->UpdateEntry(NPC_CITYMAN); + if(Creature* pEscort06 = GetClosestCreatureWithEntry(m_creature, NPC_PRIEST, 50.0f)) + { + m_uiPriest02GUID = pEscort06->GetGUID(); + pEscort05->UpdateEntry(NPC_PRIEST); + } + } + } + + void ResetStep(uint32 Timer) + { + m_uiStep = 0; + m_uiStepTimer = Timer; + } + + void IntroEvent() + { + switch(m_uiStep) + { + case 0: + DoScriptText(SAY_INTRO01, m_creature); + JumpNextStep(2000); + break; + case 1: + m_uiUtherGUID = m_pInstance->GetData64(NPC_UTHER); + m_uiJainaGUID = m_pInstance->GetData64(NPC_JAINA); + if(Creature* pUther = m_pInstance->instance->GetCreature(m_uiUtherGUID)) + DoScriptText(SAY_INTRO02, pUther); + JumpNextStep(8000); + break; + case 2: + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + DoScriptText(SAY_INTRO03, m_creature); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + m_creature->GetMotionMaster()->MovePoint(0, 1908.334f, 1315.354f, 149.551f); + if(Creature* pUther = m_pInstance->instance->GetCreature(m_uiUtherGUID)) + pUther->GetMotionMaster()->MovePoint(0, 1903.600f, 1296.678f, 143.383f); + JumpNextStep(2000); + break; + case 3: + if(Creature* pJaina = m_pInstance->instance->GetCreature(m_uiJainaGUID)) + pJaina->GetMotionMaster()->MovePoint(0, 1899.641f, 1298.684f, 143.831f); + JumpNextStep(7000); + break; + case 4: + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, 1911.087f, 1314.263f, 150.026f); + JumpNextStep(1000); + break; + case 5: + DoScriptText(SAY_INTRO04, m_creature); + JumpNextStep(10000); + break; + case 6: + if(Creature* pUther = m_pInstance->instance->GetCreature(m_uiUtherGUID)) + DoScriptText(SAY_INTRO05, pUther); + JumpNextStep(1000); + break; + case 7: + if(Creature* pUther = m_pInstance->instance->GetCreature(m_uiUtherGUID)) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pUther->GetGUID()); + DoScriptText(SAY_INTRO06, m_creature); + JumpNextStep(4000); + break; + case 8: + if(Creature* pUther = m_pInstance->instance->GetCreature(m_uiUtherGUID)) + DoScriptText(SAY_INTRO07, pUther); + JumpNextStep(6000); + break; + case 9: + DoScriptText(SAY_INTRO08, m_creature); + JumpNextStep(4000); + break; + case 10: + if(Creature* pUther = m_pInstance->instance->GetCreature(m_uiUtherGUID)) + DoScriptText(SAY_INTRO09, pUther); + JumpNextStep(8000); + break; + case 11: + DoScriptText(SAY_INTRO10, m_creature); + JumpNextStep(4000); + break; + case 12: + if(Creature* pUther = m_pInstance->instance->GetCreature(m_uiUtherGUID)) + DoScriptText(SAY_INTRO11, pUther); + JumpNextStep(4000); + break; + case 13: + DoScriptText(SAY_INTRO12, m_creature); + JumpNextStep(11000); + break; + case 14: + if(Creature* pJaina = m_pInstance->instance->GetCreature(m_uiJainaGUID)) + DoScriptText(SAY_INTRO13, pJaina); + JumpNextStep(3000); + break; + case 15: + DoScriptText(SAY_INTRO14, m_creature); + JumpNextStep(9000); + break; + case 16: + if(Creature* pUther = m_pInstance->instance->GetCreature(m_uiUtherGUID)) + DoScriptText(SAY_INTRO15, pUther); + JumpNextStep(5000); + break; + case 17: + if(Creature* pJaina = m_pInstance->instance->GetCreature(m_uiJainaGUID)) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pJaina->GetGUID()); + pJaina->GetMotionMaster()->MovePoint(0, 1794.357f,1272.183f,140.558f); + } + JumpNextStep(1000); + break; + case 18: + DoScriptText(SAY_INTRO16, m_creature); + JumpNextStep(1000); + break; + case 19: + if(Creature* pJaina = m_pInstance->instance->GetCreature(m_uiJainaGUID)) + DoScriptText(SAY_INTRO17, pJaina); + JumpNextStep(3000); + break; + case 20: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + ((npc_arthasAI*)m_creature->AI())->Start(false); + JumpNextStep(3000); + break; + } + } + + void EnterEvent() + { + switch(m_uiStep) + { + case 0: + if(Unit* Cityman = m_creature->GetMap()->GetUnit( m_uiPeople01GUID)) + DoScriptText(SAY_ENTER02, Cityman); + JumpNextStep(4000); + break; + case 1: + m_creature->GetMotionMaster()->MovePoint(0, 2087.689f,1280.344f,140.73f); + DoScriptText(SAY_ENTER03, m_creature); + JumpNextStep(3000); + break; + case 2: + if(Unit* Cityman = m_creature->GetMap()->GetUnit( m_uiPeople01GUID)) + DoScriptText(SAY_ENTER04, Cityman); + m_creature->HandleEmoteCommand(37); + JumpNextStep(1000); + break; + case 3: + if(Unit* Cityman = m_creature->GetMap()->GetUnit( m_uiPeople01GUID)) + m_creature->DealDamage(Cityman, Cityman->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if(Unit* Crazyman = m_creature->GetMap()->GetUnit( m_uiPeople02GUID)) + { + DoScriptText(SAY_ENTER05, Crazyman); + Crazyman->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Crazyman->GetGUID()); + m_creature->GetMotionMaster()->MovePoint(0, 2092.154f,1276.645f,140.52f); + } + JumpNextStep(3000); + break; + case 4: + m_creature->HandleEmoteCommand(37); + JumpNextStep(1000); + break; + case 5: + if(Unit* Crazyman = m_creature->GetMap()->GetUnit( m_uiPeople02GUID)) + Crazyman->DealDamage(Crazyman, Crazyman->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + JumpNextStep(1000); + break; + case 6: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + m_creature->GetMotionMaster()->MovePoint(0, 2091.179f,1278.065f,140.476f); + DoScriptText(SAY_ENTER06, m_creature); + JumpNextStep(3000); + break; + case 7: + if(Creature* StalkerM = m_creature->SummonCreature(20562,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,60000)) + StalkerM->CastSpell(StalkerM,63793,false); + JumpNextStep(1000); + break; + case 8: + m_pInstance->SetData(TYPE_ENCOUNTER, IN_PROGRESS); + if(Creature* TempMalganis = m_creature->SummonCreature(NPC_MALGANIS_INTRO,2117.349f,1288.624f,136.271f,1.37f,TEMPSUMMON_TIMED_DESPAWN,29000)) + { + m_uiMalganisGUID = TempMalganis->GetGUID(); + DoScriptText(SAY_ENTER07, TempMalganis); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, TempMalganis->GetGUID()); + TempMalganis->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + TempMalganis->setFaction(35); + } + JumpNextStep(11000); + break; + case 9: + if(Unit* TempMalganis = m_creature->GetMap()->GetUnit( m_uiMalganisGUID)) + DoScriptText(SAY_ENTER08, TempMalganis); + JumpNextStep(17000); + break; + case 10: + DoScriptText(SAY_ENTER09, m_creature); + JumpNextStep(7000); + break; + case 11: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + DoScriptText(SAY_ENTER10, m_creature); + JumpNextStep(12000); + break; + case 12: + m_creature->GetMotionMaster()->MovePoint(0, 2084.584f,1278.331f,141.479f); + JumpNextStep(4000); + break; + case 13: + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, 2087.414f,1279.293f,140.933f); + JumpNextStep(2000); + break; + case 14: + LastX = m_creature->GetPositionX(); + LastY = m_creature->GetPositionY(); + LastZ = m_creature->GetPositionZ(); + if(m_bIsHeroic) + m_pInstance->SetData(TYPE_BONUS, IN_PROGRESS); + m_uiWaveCount = 0; + SetRun(true); + m_pInstance->SetData(TYPE_WING, RIGHT); + m_creature->setFaction(FACTION); + m_uiSummonTimer = 100; + m_pInstance->SetData(TYPE_PHASE, 3); + break; + } + } + + void SummonWing() + { + m_uiWaveCount++; + m_pInstance->DoUpdateWorldState(WORLD_STATE_COS_WAVE_COUNT, m_uiWaveCount); + + switch(m_uiWaveCount) + { + case 1: + m_creature->SummonCreature(NPC_GHOUL,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_GHOUL,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + break; + case 2: + m_creature->SummonCreature(NPC_GHOUL,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_GHOUL,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_FIEND,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + break; + case 3: + m_pInstance->SetData(TYPE_WING, LEFT); + m_creature->SummonCreature(NPC_GHOUL,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_FIEND,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + break; + case 4: + m_pInstance->SetData(TYPE_WING, RIGHT); + m_creature->SummonCreature(NPC_ACOLYTE,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_ACOLYTE,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_FIEND,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + break; + case 5: + m_pInstance->SetData(TYPE_PHASE, 4); + if(Creature* pMeathook = m_creature->SummonCreature(NPC_MEATHOOK,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000)) + { + DoScriptText(SAY_MEATHOOK_SPAWN, pMeathook); + pMeathook->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pMeathook->GetMotionMaster()->MovePoint(0, 2196.036f, 1328.818f, 129.997f); + } + break; + case 6: + m_pInstance->SetData(TYPE_WING, LEFT); + m_creature->SummonCreature(NPC_GHOUL,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_FIEND,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_FIEND,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + break; + case 7: + m_pInstance->SetData(TYPE_WING, RIGHT); + m_creature->SummonCreature(NPC_CONSTRUCT,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_GHOUL,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_GHOUL,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_GHOUL,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + break; + case 8: + m_pInstance->SetData(TYPE_WING, LEFT); + m_creature->SummonCreature(NPC_CONSTRUCT,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_GHOUL,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_GHOUL,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2272.773f, 1331.824f, 124.171f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + break; + case 9: + m_pInstance->SetData(TYPE_WING, RIGHT); + m_creature->SummonCreature(NPC_CONSTRUCT,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_FIEND,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_NECROMANCER,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + m_creature->SummonCreature(NPC_GHOUL,2340.058f, 1253.570f, 132.733f, 5.09f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000); + break; + case 10: + m_pInstance->SetData(TYPE_PHASE, 4); + if(Creature* pSalramm = m_creature->SummonCreature(NPC_SALRAMM,2196.036f, 1328.818f, 129.997f, 3.12f,TEMPSUMMON_CORPSE_TIMED_DESPAWN,29000)) + { + DoScriptText(SAY_SALRAMM_SPAWN, pSalramm); + pSalramm->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pSalramm->GetMotionMaster()->MovePoint(0, 2196.036f, 1328.818f, 129.997f); + } + break; + } + } + + void HouseEvent() + { + switch(m_uiStep) + { + case 0: + if(Creature* Human = m_pInstance->instance->GetCreature(m_uiHuman01GUID)) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Human->GetGUID()); + Human->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + DoScriptText(SAY_PHASE503, Human); + } + JumpNextStep(4000); + break; + case 1: + DoScriptText(SAY_PHASE504, m_creature); + m_creature->GetMotionMaster()->MovePoint(0, 2396.035f, 1206.942f, 134.038f); + JumpNextStep(3000); + break; + case 2: + m_creature->HandleEmoteCommand(37); + JumpNextStep(2000); + break; + case 3: + DoScriptText(SAY_PHASE505, m_creature); + JumpNextStep(2000); + break; + case 4: + if(Creature* Human = m_pInstance->instance->GetCreature(m_uiHuman01GUID)) + DoScriptText(SAY_PHASE506, Human); + JumpNextStep(6000); + break; + case 5: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + if(Creature* Human = m_pInstance->instance->GetCreature(m_uiHuman01GUID)) + { + Human->SetUInt64Value(UNIT_FIELD_TARGET, 0); + Human->UpdateEntry(NPC_INFINITE_ADVERSARY); + } + if(Creature* Human2 = m_pInstance->instance->GetCreature(m_uiHuman02GUID)) + Human2->UpdateEntry(NPC_INFINITE_HUNTER); + if(Creature* Human3 = m_pInstance->instance->GetCreature(m_uiHuman03GUID)) + Human3->UpdateEntry(NPC_INFINITE_AGENT); + JumpNextStep(1000); + break; + case 6: + SetRun(true); + m_creature->GetMotionMaster()->MovePoint(0, 2384.320f, 1202.779f, 134.040f); + DoScriptText(SAY_PHASE507, m_creature); + JumpNextStep(5000); + break; + case 7: + SetEscortPaused(false); + m_creature->setFaction(FACTION); + m_pInstance->SetData(TYPE_PHASE, 5); + JumpNextStep(1000); + break; + } + } + + void EpochEvent() + { + switch(m_uiStep) + { + case 0: + m_creature->SummonCreature(NPC_TIME_RIFT_2,2445.629f,1111.500f,148.076f,3.229f,TEMPSUMMON_TIMED_DESPAWN,9000); + JumpNextStep(2000); + break; + case 1: + pEpoch = m_creature->SummonCreature(NPC_EPOCH,2445.629f,1111.500f,148.076f,3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000); + if(pEpoch) + { + pEpoch->setFaction(35); + DoScriptText(SAY_EPOCH_INTRO, pEpoch); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pEpoch->GetGUID()); + } + JumpNextStep(20000); + break; + case 2: + DoScriptText(SAY_ARTHAS_INTRO, m_creature); + JumpNextStep(6000); + break; + case 3: + if(pEpoch) + { + DoScriptText(SAY_EPOCH_AGGRO, pEpoch); + m_creature->AI()->AttackStart(pEpoch); + pEpoch->AI()->AttackStart(m_creature); + pEpoch->setFaction(14); + } + m_pInstance->SetData(TYPE_PHASE, 5); + SetRun(false); + JumpNextStep(6000); + break; + } + } + + void MalganisEvent() + { + Map::PlayerList const &PlayerList = m_pInstance->instance->GetPlayers(); + bool bNeedSpawn = false; + + switch(m_uiStep) + { + case 0: + m_creature->setFaction(35); + m_creature->GetMotionMaster()->MovePoint(0, 2302.326f, 1491.386f, 128.362f); + if(Creature* Malganis = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_MALGANIS))) + { + DoScriptText(SAY_MALGANIS_ESCAPE01, Malganis); + Malganis->InterruptNonMeleeSpells(false); + Malganis->GetMotionMaster()->MovePoint(0, 2296.665f,1502.362f,128.362f); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Malganis->GetGUID()); + Malganis->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + } + JumpNextStep(10000); + break; + case 1: + if(Creature* Malganis = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_MALGANIS))) + DoScriptText(SAY_MALGANIS_ESCAPE02, Malganis); + JumpNextStep(10000); + break; + case 2: + DoScriptText(SAY_ARTHAS_OUTRO01, m_creature); + JumpNextStep(5000); + break; + case 3: + if(Creature* Malganis = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_MALGANIS))) + DoScriptText(SAY_MALGANIS_OUTRO, Malganis); + JumpNextStep(20000); + break; + case 4: + if(Creature* Malganis = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_MALGANIS))) + { + Malganis->SetVisibility(VISIBILITY_OFF); + m_creature->GetMotionMaster()->MovePoint(0, Malganis->GetPositionX(), Malganis->GetPositionY(), Malganis->GetPositionZ()); + } + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + JumpNextStep(3000); + break; + case 5: + DoScriptText(SAY_ARTHAS_OUTRO02, m_creature); + JumpNextStep(6000); + break; + case 6: + m_creature->GetMotionMaster()->MovePoint(0, 2298.298f,1500.362f,128.362f); + DoScriptText(SAY_ARTHAS_OUTRO03, m_creature); + JumpNextStep(11000); + break; + case 7: + m_creature->GetMotionMaster()->MovePoint(0, 2243.311f, 1476.025f, 132.352f); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->GetQuestStatus(QUEST_A_ROYAL_ESCORT) == QUEST_STATUS_INCOMPLETE || + i->getSource()->GetQuestStatus(QUEST_A_ROYAL_ESCORT) == QUEST_STATUS_COMPLETE) { - pPlayer->SendNewItem(pItem, 1, true, false); - if (instance_culling_of_stratholme* pInstance = (instance_culling_of_stratholme*)pCreature->GetInstanceData()) - { - if (pInstance->GetData(TYPE_GRAIN_EVENT) == NOT_STARTED) - pInstance->SetData(TYPE_GRAIN_EVENT, SPECIAL); - } + bNeedSpawn = true; + break; } - } - break; + + if (bNeedSpawn) + m_creature->SummonCreature(30997, 2311.61f, 1497.85f, 128.01f, 4.14f, TEMPSUMMON_TIMED_DESPAWN, 1800000); + JumpNextStep(11000); + break; + case 8: + m_pInstance->SetData(TYPE_PHASE, 12); + m_creature->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if(!m_pInstance) return; + + if(StartEvent == true) + { + if(m_pInstance->GetData(TYPE_INTRO) != DONE) + { + if(m_uiStepTimer < uiDiff) + { + IntroEvent(); } - break; - case NPC_CHROMIE_ENTRANCE: - switch (uiAction) + else m_uiStepTimer -= uiDiff; + } + + if(m_pInstance->GetData(TYPE_PHASE) == 2) + { + if(m_uiStepTimer < uiDiff) { - case GOSSIP_ACTION_INFO_DEF+1: - pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ENTRANCE_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_ENTRANCE_2, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+2: - pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ENTRANCE_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_ENTRANCE_3, pCreature->GetGUID()); - break; - case GOSSIP_ACTION_INFO_DEF+3: - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_ENTRANCE_4, pCreature->GetGUID()); - if (instance_culling_of_stratholme* pInstance = (instance_culling_of_stratholme*)pCreature->GetInstanceData()) - { - if (pInstance->GetData(TYPE_ARTHAS_INTRO_EVENT) == NOT_STARTED) - pInstance->DoSpawnArthasIfNeeded(); - } - break; + EnterEvent(); } - break; - } - return true; -} + else m_uiStepTimer -= uiDiff; + } -bool QuestAccept_npc_chromie(Player* pPlayer, Creature* pCreature, const Quest* pQuest) -{ - switch (pQuest->GetQuestId()) - { - case QUEST_DISPELLING_ILLUSIONS: - if (instance_culling_of_stratholme* pInstance = (instance_culling_of_stratholme*)pCreature->GetInstanceData()) + if(MoveSoldier == true) + { + if(m_uiMoveTimer < uiDiff) + { + MoveSoldiers(); + MoveSoldier = false; + } + else m_uiMoveTimer -= uiDiff; + } + + if(m_pInstance->GetData(TYPE_PHASE) == 3) + { + if(m_uiSummonTimer < uiDiff) + { + SummonWing(); + m_uiSummonTimer = 70000; + } + else m_uiSummonTimer -= uiDiff; + } + + if(m_pInstance->GetData(TYPE_PHASE) == 4 && m_pInstance->GetData(TYPE_ENCOUNTER) == DONE) + { + m_pInstance->SetData(TYPE_PHASE, 5); + SetRun(true); + EnableEscort(); + DoScriptText(SAY_PHASE501, m_creature); + } + + if(m_pInstance->GetData(TYPE_PHASE) == 6) + { + if(m_uiStepTimer < uiDiff) + { + HouseEvent(); + } + else m_uiStepTimer -= uiDiff; + } + + if(m_pInstance->GetData(TYPE_PHASE) == 7) + { + if(m_uiStepTimer < uiDiff) { - if (pInstance->GetData(TYPE_GRAIN_EVENT) == NOT_STARTED) - pInstance->SetData(TYPE_GRAIN_EVENT, SPECIAL); + EpochEvent(); } - break; - case QUEST_A_ROYAL_ESCORT: - if (instance_culling_of_stratholme* pInstance = (instance_culling_of_stratholme*)pCreature->GetInstanceData()) + else m_uiStepTimer -= uiDiff; + } + + } //close event! + + if(m_pInstance->GetData(TYPE_PHASE) == 10) + { + SetEscortPaused(true); + ResetStep(1000); + m_creature->AttackStop(); + m_pInstance->SetData(TYPE_PHASE, 11); + } + + if(m_pInstance->GetData(TYPE_PHASE) == 11) + { + if(m_uiStepTimer < uiDiff) { - if (pInstance->GetData(TYPE_ARTHAS_INTRO_EVENT) == NOT_STARTED) - pInstance->DoSpawnArthasIfNeeded(); + MalganisEvent(); } - break; + else m_uiStepTimer -= uiDiff; + } + + //} //close event! + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_pInstance->GetData(TYPE_PHASE) > 9) return; + + if (m_uiExorcismTimer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsHeroic ? SPELL_EXORCISM_H : SPELL_EXORCISM_N); + + m_uiExorcismTimer = 7300; + }else m_uiExorcismTimer -= uiDiff; + + if (m_uiHealTimer < uiDiff) + { + if(m_creature->GetHealthPercent() < 40.0f) + { + DoCast(m_creature, SPELL_HOLY_LIGHT); + m_uiHealTimer = 20000; + } + } else m_uiHealTimer -= uiDiff; + + return; } +}; + +/*### +## npc_uther +###*/ + +struct MANGOS_DLL_DECL npc_utherAI : public npc_escortAI +{ + npc_utherAI(Creature* pCreature) : npc_escortAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint64 m_uiArthasGUID; + uint32 m_uiStep; + uint32 m_uiStepTimer; + bool StartEvent; + + uint64 m_uiKnightGUID01; + uint64 m_uiKnightGUID02; + uint64 m_uiKnightGUID03; + + void Reset() + { + m_creature->SetVisibility(VISIBILITY_OFF); + m_uiStep = 0; + m_uiStepTimer = 100; + } + + void StartAI() + { + //m_pInstance->SetWeather(WEATHER_STATE_MEDIUM_RAIN, 0.9999f); + StartEvent = true; + m_creature->SetVisibility(VISIBILITY_ON); + ((npc_utherAI*)m_creature->AI())->Start(true); + + if(Creature* Knight01 = m_creature->SummonCreature(NPC_KNIGHT,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),m_creature->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,110000)) + { + m_uiKnightGUID01 = Knight01->GetGUID(); + Knight01->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + Knight01->GetMotionMaster()->MoveFollow(m_creature,PET_FOLLOW_DIST,M_PI_F/2); + } + + if(Creature* Knight02 = m_creature->SummonCreature(NPC_KNIGHT,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),m_creature->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,110000)) + { + m_uiKnightGUID02 = Knight02->GetGUID(); + Knight02->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + Knight02->GetMotionMaster()->MoveFollow(m_creature,PET_FOLLOW_DIST,M_PI_F/4); + } + + if(Creature* Knight03 = m_creature->SummonCreature(NPC_KNIGHT,m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),m_creature->GetOrientation(),TEMPSUMMON_TIMED_DESPAWN,110000)) + { + m_uiKnightGUID03 = Knight03->GetGUID(); + Knight03->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + Knight03->GetMotionMaster()->MoveFollow(m_creature,PET_FOLLOW_DIST,M_PI_F/3); + } + } + + void WaypointReached(uint32 uiPointId) + { + switch(uiPointId) + { + case 3: + m_uiArthasGUID = m_pInstance->GetData64(NPC_ARTHAS); + if(Creature* pArthas = m_pInstance->instance->GetCreature(m_uiArthasGUID)) + { + pArthas->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pArthas->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + pArthas->GetMotionMaster()->MovePoint(0, 1902.974f, 1291.635f, 143.337f); + } + break; + case 4: + SetRun(false); + if(Creature *pArthas = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_ARTHAS))) + ((npc_arthasAI*)pArthas->AI())->StartAI(); + break; + case 6: + m_creature->SetVisibility(VISIBILITY_OFF); + uint64 m_uiJainaGUID = m_pInstance->GetData64(NPC_JAINA); + if(Creature* pJaina = m_pInstance->instance->GetCreature(m_uiJainaGUID)) + pJaina->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + npc_escortAI::UpdateAI(uiDiff); + + if(!m_pInstance) return; + + return; + } +}; + +/*### +## npc_chromi_middle +###*/ + +#define GOSSIP_ITEM_CHROMI1 "What do you think they're up to?" +#define GOSSIP_ITEM_CHROMI2 "What want me to do what?" +#define GOSSIP_ITEM_CHROMI3 "Very well, Chromie." + +enum +{ + QUEST_ROYAL_ESCORT = 13151, + GOSSIP_TEXTID_CHROMI1 = 12953, + GOSSIP_TEXTID_CHROMI2 = 12949, + GOSSIP_TEXTID_CHROMI3 = 12950, + GOSSIP_TEXTID_CHROMI4 = 12952 +}; + +bool GossipHello_npc_chromi_middle(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + //if (pPlayer->GetQuestStatus(QUEST_ROYAL_ESCORT) == QUEST_STATUS_INCOMPLETE) return true; + + ScriptedInstance* pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + if(pInstance && pInstance->GetData(TYPE_INTRO) == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHROMI1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_CHROMI1, pCreature->GetGUID()); + return true; } -/* ************* -** npc_crates_bunny (spell aura effect dummy) -************* */ +bool GossipSelect_npc_chromi_middle(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if(ScriptedInstance* m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData())) + if(m_pInstance->GetData(TYPE_INTRO) != NOT_STARTED) return true; + + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHROMI2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_CHROMI2, pCreature->GetGUID()); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHROMI3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_CHROMI3, pCreature->GetGUID()); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF+3) + { + if(ScriptedInstance* m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData())) + { + m_pInstance->DoUpdateWorldState(WORLD_STATE_COS_CRATE_ON, 0); + m_pInstance->SetData(TYPE_INTRO, IN_PROGRESS); + if (Creature *pUther = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_UTHER))) + ((npc_utherAI*)pUther->AI())->StartAI(); + } + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_CHROMI4, pCreature->GetGUID()); + } + + return true; +} + +struct MANGOS_DLL_DECL npc_chromi_middleAI : public ScriptedAI +{ + npc_chromi_middleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + m_bUtherHere = false; + Reset(); + } + + ScriptedInstance* m_pInstance; + + bool m_bUtherHere; + + void Reset() + { + m_bUtherHere = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_bUtherHere && m_pInstance && pWho && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->GetDistance2d(pWho) <= 15 && ((Player*)pWho)->GetQuestStatus(QUEST_A_ROYAL_ESCORT) == QUEST_STATUS_INCOMPLETE) + { + m_pInstance->DoUpdateWorldState(WORLD_STATE_COS_CRATE_ON, 0); + m_pInstance->SetData(TYPE_INTRO, IN_PROGRESS); + if (Creature *pUther = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_UTHER))) + ((npc_utherAI*)pUther->AI())->StartAI(); + m_bUtherHere = true; + } + } +}; + +/*### +## npc_arthas_dialog +###*/ + +enum +{ + 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 +}; + +#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) +{ + ScriptedInstance* pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + + if(pInstance && pInstance->GetData(TYPE_PHASE) == 0) + { + 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()); + } + + if(pInstance && pInstance->GetData(TYPE_PHASE) == 5) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_2, pCreature->GetGUID()); + } + + if(pInstance && pInstance->GetData(TYPE_PHASE) == 8) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_3, pCreature->GetGUID()); + } + + if(pInstance && pInstance->GetData(TYPE_PHASE) == 9) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ARTHAS_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->SEND_GOSSIP_MENU(GOSSIP_MENU_ARTHAS_4, pCreature->GetGUID()); + } + + return true; +} + +bool GossipSelect_npc_arthas(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance* m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + + if(m_pInstance && m_pInstance->GetData(TYPE_PHASE) == 0) + { + m_pInstance->SetData(TYPE_PHASE, 1); + ((npc_arthasAI*)pCreature->AI())->EnableEscort(); + ((npc_arthasAI*)pCreature->AI())->RemoveGossip(); + ((npc_arthasAI*)pCreature->AI())->culling_faction = pPlayer->getFaction(); + } + + if(m_pInstance && m_pInstance->GetData(TYPE_PHASE) == 5) + { + ((npc_arthasAI*)pCreature->AI())->EnableEscort(); + ((npc_arthasAI*)pCreature->AI())->RemoveGossip(); + } + + if(m_pInstance && m_pInstance->GetData(TYPE_PHASE) == 8) + { + ((npc_arthasAI*)pCreature->AI())->EnableEscort(); + ((npc_arthasAI*)pCreature->AI())->RemoveGossip(); + } + + if(m_pInstance && m_pInstance->GetData(TYPE_PHASE) == 9) + { + ((npc_arthasAI*)pCreature->AI())->EnableEscort(); + ((npc_arthasAI*)pCreature->AI())->RemoveGossip(); + if(Creature* pMalganis = pCreature->SummonCreature(NPC_MALGANIS,2296.665f,1502.362f,128.362f,4.961f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000)) + { + m_pInstance->SetData64(NPC_MALGANIS, pMalganis->GetGUID()); + pMalganis->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + return true; +} + +/*### +## npc_arthas_priest +###*/ enum { - SPELL_ARCANE_DISRUPTION = 49590 + SPELL_SMITE = 61923, + SPELL_HEAL = 62442 }; -bool EffectAuraDummy_spell_aura_dummy_npc_crates_dummy(const Aura* pAura, bool bApply) +struct MANGOS_DLL_DECL npc_arthas_priestAI : public ScriptedAI { - if (pAura->GetId() == SPELL_ARCANE_DISRUPTION && pAura->GetEffIndex() == EFFECT_INDEX_0 && bApply) + npc_arthas_priestAI(Creature *c) : ScriptedAI(c) + { + SetCombatMovement(false); + Reset(); + } + + uint32 m_uiSmiteTimer; + uint32 m_uiHealTimer; + + void Reset() + { + m_uiSmiteTimer = 100; + m_uiHealTimer = 1000; + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + } + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + + m_creature->SetLootRecipient(NULL); + + Reset(); + } + + void MoveInLineOfSight(Unit* pWho) { - if (Creature* pTarget = (Creature*)pAura->GetTarget()) + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) { - std::list lCrateBunnyList; - if (instance_culling_of_stratholme* pInstance = (instance_culling_of_stratholme*)pTarget->GetInstanceData()) + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) { - pInstance->GetCratesBunnyOrderedList(lCrateBunnyList); - uint8 i = 0; - for (std::list::const_iterator itr = lCrateBunnyList.begin(); itr != lCrateBunnyList.end(); ++itr) + if (!m_creature->getVictim()) { - i++; - if (*itr == pTarget) - break; + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); } - - switch (i) + else if (m_creature->GetMap()->IsDungeon()) { - case 1: - // Start NPC_ROGER_OWENS Event - break; - case 2: - // Start NPC_SERGEANT_MORIGAN Event - break; - case 3: - // Start NPC_JENA_ANDERSON Event - break; - case 4: - // Start NPC_MALCOM_MOORE Event - break; - case 5: - // Start NPC_BARTLEBY_BATTSON Event - break; + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { - if (pInstance->GetData(TYPE_GRAIN_EVENT) != DONE) - pInstance->SetData(TYPE_GRAIN_EVENT, IN_PROGRESS); - // pTarget->ForcedDespawn(); // direct despawn has influence on visual effects, - // but despawning makes it impossible to multi-use the spell at the same place - // perhaps some add. GO-Visual + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiSmiteTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_SMITE); + m_uiSmiteTimer = 3000; + } + else m_uiSmiteTimer -= uiDiff; + + if(m_uiHealTimer < uiDiff) + { + if(m_creature->GetHealthPercent() <= 40.0f) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, SPELL_HEAL); + m_uiHealTimer = 3000; + } + } + else m_uiHealTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +/*### +## npc_arthas_marine +###*/ + +struct MANGOS_DLL_DECL npc_arthas_marineAI : public ScriptedAI +{ + npc_arthas_marineAI(Creature *c) : ScriptedAI(c) + { + Reset(); + } + + float LastX; + float LastY; + float LastZ; + + uint32 m_uiHealTimer; + + void Reset() + { + m_uiHealTimer = 3000; + } + + void Aggro(Unit* who) + { + LastX = m_creature->GetPositionX(); + LastY = m_creature->GetPositionY(); + LastZ = m_creature->GetPositionZ(); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + + if (IsCombatMovement()) + m_creature->GetMotionMaster()->MoveChase(pWho); + } + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + + m_creature->SetLootRecipient(NULL); + m_creature->GetMotionMaster()->MovePoint(POINT_LAST_POINT, LastX, LastY, LastZ); + + Reset(); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); + } } } } - return true; + + void UpdateAI(const uint32 uiDiff) + { + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiHealTimer < uiDiff) + { + if(m_creature->GetHealthPercent() <= 40.0f) + { + if(Creature* pHeal = GetClosestCreatureWithEntry(m_creature, NPC_PRIEST, 50.0f)) + { + if(pHeal->GetHealthPercent() > 40.0f) + { + pHeal->InterruptNonMeleeSpells(false); + pHeal->CastSpell(m_creature, SPELL_HEAL, false); + m_uiHealTimer = 3000; + } + } + } + } + else m_uiHealTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +/*### +## npc_dark_conversion +###*/ + +/*enum +{ + SAY_PEOPLE01 = -1594099, + SAY_PEOPLE02 = -1594100, + SAY_PEOPLE03 = -1594101, + SAY_PEOPLE04 = -1594102, + SAY_PEOPLE05 = -1594103, +};*/ + +struct MANGOS_DLL_DECL npc_dark_conversionAI : public ScriptedAI +{ + npc_dark_conversionAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + + if (m_pInstance && m_pInstance->GetData(TYPE_ENCOUNTER) == IN_PROGRESS) + m_creature->UpdateEntry(NPC_ZOMBIE); + + Reset(); + } + +ScriptedInstance* m_pInstance; + +bool Special; +bool Conversion; +uint32 m_uiStep; +uint32 m_uiStepTimer; + + void Reset() + { + m_creature->setFaction(35); + Conversion = false; + Special = false; + m_uiStep = 1; + m_uiStepTimer = 5000; + + if (m_pInstance && m_pInstance->GetData(TYPE_ENCOUNTER) == IN_PROGRESS) + m_creature->UpdateEntry(NPC_ZOMBIE); + } + + void MalganisScared(Creature* target, float horizontalSpeed, float verticalSpeed) + { + float angle = target->GetAngle(m_creature); + float vsin = sin(angle); + float vcos = cos(angle); + + float ox, oy, oz; + m_creature->GetPosition(ox, oy, oz); + + float g = 19.23f;// seems that physic constant g(earth's gravity) in world of warcraft is about 2 times larger than real + float dh = verticalSpeed*verticalSpeed / (2*g); // maximum parabola height + float time = sqrtf(dh/(0.124976 * verticalSpeed)); //full move time in seconds // should be time = 2*Vert_speed/g, but.. + + float dis = time * horizontalSpeed; + float fx = ox + dis * vcos; + float fy = oy + dis * vsin; + float fz = oz; + + m_creature->UpdateGroundPositionZ(fx, fy, fz); + + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MovePoint(0, fx, fy, fz); + } + + void DarkConversion(bool Move) + { + m_creature->UpdateEntry(NPC_ZOMBIE); + if(Move == true) + { + uint64 m_uiArthasGUID = m_pInstance->GetData64(NPC_ARTHAS); + if(Creature* pArthas = m_pInstance->instance->GetCreature(m_uiArthasGUID)) + m_creature->GetMotionMaster()->MovePoint(0, pArthas->GetPositionX(), pArthas->GetPositionY(), pArthas->GetPositionZ()); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if(!m_pInstance) return; + + if(m_pInstance->GetData(TYPE_ENCOUNTER) == IN_PROGRESS) + { + if(Creature* pMalganis = GetClosestCreatureWithEntry(m_creature, NPC_MALGANIS_INTRO, 20.0f)) + { + if(Special == false) + { + float Dist = m_creature->GetDistance2d(pMalganis->GetPositionX(), pMalganis->GetPositionY()); + Dist = Dist + 2.0f; + MalganisScared(pMalganis, Dist, 1.0f); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_COWER); + m_uiStepTimer = 5000; + Special = true; + } + } + + if(m_uiStepTimer < uiDiff && Conversion != true) + { + Conversion = true; + if(Special != false) + DarkConversion(true); + else + DarkConversion(false); + } + else m_uiStepTimer -= uiDiff; + + } + + DoMeleeAttackIfReady(); + + return; + } +}; + +CreatureAI* GetAI_npc_chromi_middle(Creature* pCreature) +{ + return new npc_chromi_middleAI(pCreature); +} + +CreatureAI* GetAI_npc_uther(Creature* pCreature) +{ + return new npc_utherAI(pCreature); +} + +CreatureAI* GetAI_npc_arthas(Creature* pCreature) +{ + return new npc_arthasAI(pCreature); +} + +CreatureAI* GetAI_npc_arthas_priest(Creature* pCreature) +{ + return new npc_arthas_priestAI(pCreature); +} + +CreatureAI* GetAI_npc_arthas_marine(Creature* pCreature) +{ + return new npc_arthas_marineAI(pCreature); +} + +CreatureAI* GetAI_npc_dark_conversion(Creature* pCreature) +{ + return new npc_dark_conversionAI(pCreature); } void AddSC_culling_of_stratholme() { - Script* pNewScript; + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_chromi_middle"; + newscript->pGossipHello = &GossipHello_npc_chromi_middle; + newscript->pGossipSelect = &GossipSelect_npc_chromi_middle; + newscript->GetAI = &GetAI_npc_chromi_middle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_uther"; + newscript->GetAI = &GetAI_npc_uther; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_arthas"; + newscript->GetAI = &GetAI_npc_arthas; + newscript->pGossipHello = &GossipHello_npc_arthas; + newscript->pGossipSelect = &GossipSelect_npc_arthas; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_arthas_priest"; + newscript->GetAI = &GetAI_npc_arthas_priest; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "npc_chromie"; - pNewScript->pGossipHello = &GossipHello_npc_chromie; - pNewScript->pGossipSelect = &GossipSelect_npc_chromie; - pNewScript->pQuestAccept = &QuestAccept_npc_chromie; - pNewScript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_arthas_marine"; + newscript->GetAI = &GetAI_npc_arthas_marine; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "spell_dummy_npc_crates_bunny"; - pNewScript->pEffectAuraDummy = &EffectAuraDummy_spell_aura_dummy_npc_crates_dummy; - pNewScript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_dark_conversion"; + newscript->GetAI = &GetAI_npc_dark_conversion; + newscript->RegisterSelf(); } diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholmeai.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholmeai.cpp new file mode 100644 index 0000000..3778873 --- /dev/null +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholmeai.cpp @@ -0,0 +1,1293 @@ +/* Copyright (C) 2006 - 2010 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_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 +SDCategory: Culling of Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_culling_of_stratholme.h" +#include "escort_ai.h" +#include "WorldPacket.h" + +/*### +## npc_chromi_start +###*/ + +#define GOSSIP_ITEM_CHROMI1 "Why have I been sent back to this particular place and time?" +#define GOSSIP_ITEM_CHROMI2 "What was this decision?" +#define GOSSIP_ITEM_CHROMI3 "So how does the infinite Dragonflight plan to Interfere?" + +enum +{ + GOSSIP_TEXTID_CHROMI1 = 12939, + GOSSIP_TEXTID_CHROMI2 = 12949, + GOSSIP_TEXTID_CHROMI3 = 12950, + GOSSIP_TEXTID_CHROMI4 = 12952 +}; + +bool GossipHello_npc_chromi_start(Player* pPlayer, Creature* pCreature) +{ + if(pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + if (pPlayer && pPlayer->GetQuestStatus(QUEST_DISPELLING_ILLUSIONS) == QUEST_STATUS_COMPLETE && pInstance && pInstance->GetData(TYPE_QUEST) == NOT_STARTED) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHROMI1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_CHROMI1, pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_chromi_start(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHROMI2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_CHROMI2, pCreature->GetGUID()); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHROMI3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_CHROMI3, pCreature->GetGUID()); + } + + if (uiAction == GOSSIP_ACTION_INFO_DEF+3) + { + // START COUNTER HERE + if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData()) + { + pInstance->DoUpdateWorldState(WORLD_STATE_COS_CRATE_ON, 1); + pInstance->SetData(TYPE_QUEST, IN_PROGRESS); + } + + if (pPlayer) + if (Item* pItem = pPlayer->StoreNewItemInInventorySlot(ITEM_ARCANE_DISRUPTOR, 1)) + pPlayer->SendNewItem(pItem, 1, true, false); + + pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_CHROMI4, pCreature->GetGUID()); + } + + return true; +} + +struct MANGOS_DLL_DECL npc_chromi_startAI : public ScriptedAI +{ + npc_chromi_startAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + m_bCounterHere = false; + Reset(); + } + + ScriptedInstance* m_pInstance; + + bool m_bCounterHere; + + void Reset() + { + m_bCounterHere = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_bCounterHere && m_pInstance && pWho && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->GetDistance2d(pWho) <= 15 && ((Player*)pWho)->GetQuestStatus(QUEST_DISPELLING_ILLUSIONS) == QUEST_STATUS_INCOMPLETE) + { + m_pInstance->DoUpdateWorldState(WORLD_STATE_COS_CRATE_ON, 1); + m_pInstance->SetData(TYPE_QUEST, IN_PROGRESS); + m_bCounterHere = true; + } + } +}; + +/*### +## npc_mike +###*/ + +enum +{ + SAY_MIKE01 = -1557270, + SAY_FORRESTER02 = -1557271, + SAY_JAMES03 = -1557272, + SAY_SIABI04 = -1557273, + SAY_MIKE05 = -1557274, + SAY_CORICKS06 = -1557275, + SAY_GRIAN07 = -1557276, + SAY_CORICKS08 = -1557277, + SAY_JAMES09 = -1557278, + SAY_FORRESTER10 = -1557279, + + EMOTE_SHOT = 5, + EMOTE_TALK = 1, + EMOTE_POINT = 25, + EMOTE_NO = 274, + EMOTE_LAUGH = 11 +}; + +struct MANGOS_DLL_DECL npc_mikeAI : public ScriptedAI +{ + npc_mikeAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiStep; + uint32 m_uiStepTimer; + uint32 m_uiPhase; + + uint64 m_uiForesterGUID; + uint64 m_uiJamesGUID; + uint64 m_uiSiabiGUID; + uint64 m_uiCorricksGUID; + uint64 m_uiGryanGUID; + + void Reset() + { + if(m_uiPhase != 2) + { + m_uiStep = 0; + m_uiStepTimer = 100; + m_uiPhase = 0; + } + } + + void MoveInLineOfSight(Unit* who) + { + if (!who) + return; + + if(!m_pInstance) return; + + if (who->GetTypeId() == TYPEID_PLAYER && m_creature->GetDistance2d(who) <= 15 && who->GetPositionZ() > 99.50f && m_uiPhase == 0) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, who->GetGUID()); + m_uiPhase = 1; + } + } + + void TavernEvent() + { + switch(m_uiStep) + { + case 0: + DoScriptText(SAY_MIKE01, m_creature); + m_uiStepTimer = 4000; + break; + case 1: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + m_uiStepTimer = 5000; + break; + case 2: + m_uiForesterGUID = m_pInstance->GetData64(NPC_FORRESTER); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiForesterGUID)) + DoScriptText(SAY_FORRESTER02, pTemp); + m_uiStepTimer = 6000; + break; + case 3: + m_uiJamesGUID = m_pInstance->GetData64(NPC_JAMES); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiJamesGUID)) + DoScriptText(SAY_JAMES03, pTemp); + m_uiStepTimer = 5000; + break; + case 4: + m_uiSiabiGUID = m_pInstance->GetData64(NPC_FRAS_FRASIABI); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiSiabiGUID)) + DoScriptText(SAY_SIABI04, pTemp); + m_uiStepTimer = 2000; + break; + case 5: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiSiabiGUID)) + pTemp->HandleEmoteCommand(EMOTE_SHOT); + m_uiStepTimer = 5000; + break; + case 6: + m_creature->GetMotionMaster()->MovePoint(0, 1554.849f, 588.465f, 99.775f); + m_uiStepTimer = 3000; + break; + case 7: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiSiabiGUID)) + pTemp->HandleEmoteCommand(EMOTE_LAUGH); + m_uiStepTimer = 3000; + break; + case 8: + DoScriptText(SAY_MIKE05, m_creature); + m_uiStepTimer = 2000; + break; + case 9: + m_creature->HandleEmoteCommand(EMOTE_SHOT); + m_uiStepTimer = 1000; + break; + case 10: + m_uiCorricksGUID = m_pInstance->GetData64(NPC_MAL_CORICS); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiCorricksGUID)) + DoScriptText(SAY_CORICKS06, pTemp); + m_uiStepTimer = 4000; + break; + case 11: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiCorricksGUID)) + pTemp->HandleEmoteCommand(EMOTE_TALK); + m_uiGryanGUID = m_pInstance->GetData64(NPC_GRIAN_STONE); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiGryanGUID)) + DoScriptText(SAY_GRIAN07, pTemp); + m_uiStepTimer = 11000; + break; + case 12: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiCorricksGUID)) + DoScriptText(SAY_CORICKS08, pTemp); + m_creature->GetMotionMaster()->MovePoint(0, 1549.609f, 575.544f, 100.052f); + m_uiStepTimer = 2000; + break; + case 13: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiJamesGUID)) + DoScriptText(SAY_JAMES09, pTemp); + m_uiStepTimer = 2000; + break; + case 14: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiJamesGUID)) + pTemp->HandleEmoteCommand(EMOTE_TALK); + m_uiStepTimer = 5000; + break; + case 15: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiForesterGUID)) + DoScriptText(SAY_FORRESTER10, pTemp); + m_uiPhase = 2; + break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiPhase == 1) + { + if(m_uiStepTimer < uiDiff) + { + TavernEvent(); + m_uiStep++; + } + else m_uiStepTimer -= uiDiff; + } + + return; + } +}; + +/*### +## npc_roger +###*/ + +enum +{ + SAY_ROGER01 = -1557280, + SAY_ROGER02 = -1557281, + SAY_ROGER03 = -1557282, + SAY_ROGER04 = -1557283, +}; + +struct MANGOS_DLL_DECL npc_rogerAI : public ScriptedAI +{ + npc_rogerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiStep; + uint32 m_uiStepTimer; + uint32 m_uiPhase; + + void Reset() + { + if(m_uiPhase != 2) + { + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + m_uiStep = 0; + m_uiStepTimer = 100; + m_uiPhase = 0; + } + } + + void StartRoger() + { + m_uiPhase = 1; + } + + void FirstCrateEvent() + { + switch(m_uiStep) + { + case 0: + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_uiStepTimer = 7000; + break; + case 1: + MoveToPoint(m_creature, 1590.055f, 615.727f, 99.795f, 7000); + m_uiStepTimer = 6900; + break; + case 2: + MoveToPoint(m_creature, 1584.039f, 622.049f, 99.907f, 4000); + m_uiStepTimer = 3900; + break; + case 3: + MoveToPoint(m_creature, 1578.787f, 623.924f, 99.855f, 2000); + m_uiStepTimer = 2500; + break; + case 4: + DoScriptText(SAY_ROGER01, m_creature); + m_uiStepTimer = 6000; + break; + case 5: + MoveToPoint(m_creature, 1579.393f, 624.018f, 99.886f, 900); + m_uiStepTimer = 2000; + break; + case 6: + DoScriptText(SAY_ROGER02, m_creature); + m_uiStepTimer = 6000; + break; + case 7: + MoveToPoint(m_creature, 1579.387f, 623.198f, 99.837f, 300); + m_uiStepTimer = 1000; + break; + case 8: + DoScriptText(SAY_ROGER03, m_creature); + m_uiStepTimer = 4000; + break; + case 9: + MoveToPoint(m_creature, 1575.576f, 619.935f, 99.422f, 1500); + m_uiStepTimer = 2000; + break; + case 10: + MoveToPoint(m_creature, 1575.833f, 620.471f, 99.466f, 300); + m_uiStepTimer = 1000; + break; + case 11: + DoScriptText(SAY_ROGER04, m_creature); + m_uiStepTimer = 6000; + break; + case 12: + MoveToPoint(m_creature, 1580.215f, 624.368f, 99.924f, 2000); + m_uiStepTimer = 1900; + break; + case 13: + MoveToPoint(m_creature, 1587.471f, 618.181f, 99.850f, 4000); + m_uiStepTimer = 3900; + break; + case 14: + MoveToPoint(m_creature, 1592.646f, 590.888f, 99.151f, 11000); + m_uiStepTimer = 13000; + break; + case 15: + m_uiPhase = 2; + m_creature->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void MoveToPoint(Creature* unit, float X, float Y, float Z, uint32 Timer) + { + unit->GetMotionMaster()->MovementExpired(false); + unit->GetMap()->CreatureRelocation(unit, X, Y, Z, unit->GetOrientation()); + unit->SendMonsterMove(X, Y, Z, SPLINETYPE_NORMAL , unit->GetSplineFlags(), Timer); + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiPhase == 1) + { + if(m_uiStepTimer < uiDiff) + { + FirstCrateEvent(); + m_uiStep++; + } + else m_uiStepTimer -= uiDiff; + } + + return; + } +}; + +/*### +## npc_morigan +###*/ + +enum +{ + SAY_MORIGAN01 = -1557284, + SAY_PERELLI02 = -1557285, + SAY_MORIGAN03 = -1557286, + SAY_PERELLI04 = -1557287, + SAY_MORIGAN05 = -1557288, + SAY_PERELLI06 = -1557289, + SAY_MORIGAN07 = -1557290, +}; + +struct MANGOS_DLL_DECL npc_moriganAI : public ScriptedAI +{ + npc_moriganAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint64 m_uiPerelliGUID; + uint32 m_uiStep; + uint32 m_uiStepTimer; + uint32 m_uiPhase; + + void Reset() + { + if(m_uiPhase != 2) + { + m_uiStep = 0; + m_uiStepTimer = 100; + m_uiPhase = 0; + } + } + + void StartMorigan() + { + m_uiPhase = 1; + } + + void SecondCrateEvent() + { + switch(m_uiStep) + { + case 0: + DoScriptText(SAY_MORIGAN01, m_creature); + m_uiStepTimer = 6000; + break; + case 1: + m_uiPerelliGUID = m_pInstance->GetData64(NPC_PERELLI); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiPerelliGUID)) + DoScriptText(SAY_PERELLI02, pTemp); + m_uiStepTimer = 2000; + break; + case 2: + m_creature->GetMotionMaster()->MovePoint(0, 1564.138f, 668.343f, 102.058f); + m_uiStepTimer = 2000; + break; + case 3: + m_creature->GetMotionMaster()->MovePoint(0, 1567.956f, 667.776f, 102.094f); + m_uiStepTimer = 1500; + break; + case 4: + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, 1569.615f, 668.859f, 102.180f); + m_uiStepTimer = 2000; + break; + case 5: + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + m_uiStepTimer = 1000; + break; + case 6: + DoScriptText(SAY_MORIGAN03, m_creature); + m_uiStepTimer = 3000; + break; + case 7: + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiPerelliGUID)) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pTemp->GetGUID()); + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + } + m_uiStepTimer = 3000; + break; + case 8: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiPerelliGUID)) + DoScriptText(SAY_PERELLI04, pTemp); + m_uiStepTimer = 3000; + break; + case 9: + DoScriptText(SAY_MORIGAN05, m_creature); + m_uiStepTimer = 9000; + break; + case 10: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiPerelliGUID)) + DoScriptText(SAY_PERELLI06, pTemp); + m_uiStepTimer = 6000; + break; + case 11: + DoScriptText(SAY_MORIGAN07, m_creature); + m_uiStepTimer = 4000; + break; + case 12: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiPerelliGUID)) + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, 0); + MoveToPoint(m_creature, 1576.119f, 657.675f, 102.09f, 5000); + m_uiStepTimer = 4900; + break; + case 13: + MoveToPoint(m_creature, 1586.040f, 646.113f, 100.910f, 6000); + m_uiStepTimer = 5900; + break; + case 14: + MoveToPoint(m_creature, 1609.189f, 697.134f, 106.902f, 23000); + m_uiStepTimer = 24900; + break; + case 15: + m_uiPhase = 2; + m_creature->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void MoveToPoint(Creature* unit, float X, float Y, float Z, uint32 Timer) + { + unit->GetMap()->CreatureRelocation(unit, X, Y, Z, unit->GetOrientation()); + unit->SendMonsterMove(X, Y, Z, SPLINETYPE_NORMAL , unit->GetSplineFlags(), Timer); + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiPhase == 1) + { + if(m_uiStepTimer < uiDiff) + { + SecondCrateEvent(); + m_uiStep++; + } + else m_uiStepTimer -= uiDiff; + } + + return; + } +}; + +/*### +## npc_jena +###*/ + +enum +{ + SAY_JENA01 = -1557291, + SAY_MARTHA02 = -1557292, + SAY_JENA03 = -1557293, + SAY_JENA04 = -1557294, + SAY_MARTHA05 = -1557295, + +}; + +struct MANGOS_DLL_DECL npc_jenaAI : public ScriptedAI +{ + npc_jenaAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint64 m_uiMarthaGUID; + uint32 m_uiStep; + uint32 m_uiStepTimer; + uint32 m_uiPhase; + + void Reset() + { + if(m_uiPhase != 2) + { + m_uiStep = 0; + m_uiStepTimer = 100; + m_uiPhase = 0; + } + } + + void StartJena() + { + m_uiPhase = 1; + } + + void ThirdCrateEvent() + { + switch(m_uiStep) + { + case 0: + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, 1605.546f, 744.869f, 114.731f); + m_uiStepTimer = 1900; + break; + case 1: + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, 1614.967f, 743.673f, 114.063f); + m_uiStepTimer = 4900; + break; + case 2: + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, 1623.848f, 729.251f, 112.410f); + m_uiStepTimer = 6900; + break; + case 3: + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, 1633.460f, 726.261f, 113.518f); + m_uiStepTimer = 4000; + break; + case 4: + m_uiMarthaGUID = m_pInstance->GetData64(NPC_MARTHA); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pTemp->GetGUID()); + DoScriptText(SAY_JENA01, m_creature); + m_uiStepTimer = 3000; + break; + case 5: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + { + pTemp->RemoveAurasDueToSpell(58925); + pTemp->GetMotionMaster()->MovePoint(0, 1635.918f, 724.357f, 113.561f); + } + m_uiStepTimer = 1000; + break; + case 6: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + { + pTemp->GetMotionMaster()->MovementExpired(false); + pTemp->GetMotionMaster()->MovePoint(0, 1636.721f, 725.88f, 113.561f); + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + } + m_uiStepTimer = 1000; + break; + case 7: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + DoScriptText(SAY_MARTHA02, pTemp); + m_uiStepTimer = 4000; + break; + case 8: + DoScriptText(SAY_JENA03, m_creature); + m_uiStepTimer = 3000; + break; + case 9: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + m_creature->GetMotionMaster()->MovePoint(0, 1629.278f, 727.894f, 112.636f); + m_uiStepTimer = 1500; + break; + case 10: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + { + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, 0); + pTemp->GetMap()->CreatureRelocation(pTemp, 1640.089f, 725.766f, 113.561f, 4.77f); + pTemp->SendMonsterMove(1640.089f, 725.766f, 113.561f, SPLINETYPE_NORMAL , pTemp->GetSplineFlags(), 1500); + } + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, 1629.452f, 729.416f, 112.712f); + m_uiStepTimer = 1000; + break; + case 11: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + pTemp->GetMotionMaster()->MovePoint(0, 1640.103f, 725.522f, 113.561f); + m_uiStepTimer = 500; + break; + case 12: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + pTemp->CastSpell(pTemp, 58925, false); + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + m_uiStepTimer = 1500; + break; + case 13: + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_uiStepTimer = 1000; + break; + case 14: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pTemp->GetGUID()); + DoScriptText(SAY_JENA04, m_creature); + m_uiStepTimer = 3000; + break; + case 15: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiMarthaGUID)) + { + pTemp->RemoveAurasDueToSpell(58925); + DoScriptText(SAY_MARTHA05, pTemp); + MoveToPoint(pTemp, 1638.196f, 726.171f, 113.561f, 1000); + } + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + MoveToPoint(m_creature, 1615.590f, 719.509f, 110.311f, 2000); + m_uiStepTimer = 2000; + break; + case 16: + MoveToPoint(m_creature, 1596.436f, 670.809f, 103.747f, 7000); + m_uiStepTimer = 6900; + break; + case 17: + MoveToPoint(m_creature, 1571.549f, 609.837f, 99.767f, 9000); + m_uiStepTimer = 11000; + break; + case 18: + m_uiPhase = 2; + m_creature->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void MoveToPoint(Creature* unit, float X, float Y, float Z, uint32 Timer) + { + unit->GetMap()->CreatureRelocation(unit, X, Y, Z, unit->GetOrientation()); + unit->SendMonsterMove(X, Y, Z, SPLINETYPE_NORMAL , unit->GetSplineFlags(), Timer); + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiPhase == 1) + { + if(m_uiStepTimer < uiDiff) + { + ThirdCrateEvent(); + m_uiStep++; + } + else m_uiStepTimer -= uiDiff; + } + + return; + } +}; + +/*### +## npc_malcolm +###*/ + +enum +{ + SOUND_ID_DOG_GROWL = 1108, + SOUND_ID_DOG_HOWL = 1018, + EMOTE_DOG_HOWL = 393, + + SAY_MALCOLM01 = -1557296, + SAY_MALCOLM02 = -1557297, + SAY_MALCOLM03 = -1557298, + SAY_MALCOLM04 = -1557299, +}; + +struct MANGOS_DLL_DECL npc_malcolmAI : public ScriptedAI +{ + npc_malcolmAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint64 m_uiDogGUID; + uint32 m_uiStep; + uint32 m_uiStepTimer; + uint32 m_uiPhase; + + void Reset() + { + if(m_uiPhase != 2) + { + m_uiStep = 0; + m_uiStepTimer = 100; + m_uiPhase = 0; + } + } + + void StartMalcolm() + { + m_uiPhase = 1; + } + + void FourCrateEvent() + { + switch(m_uiStep) + { + case 0: + MoveToPoint(m_creature, 1614.066f, 796.722f, 121.739f, 5500); + m_uiDogGUID = m_pInstance->GetData64(NPC_DOG); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + MoveToPoint(pTemp, 1611.459f, 793.274f, 121.928f, 5500); + m_uiStepTimer = 5400; + break; + case 1: + DoScriptText(SAY_MALCOLM01, m_creature); + MoveToPoint(m_creature, 1622.820f, 798.816f, 120.570f, 3500); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + MoveToPoint(pTemp, 1621.467f, 794.323f, 120.323f, 3500); + m_uiStepTimer = 3400; + break; + case 2: + MoveToPoint(m_creature, 1626.574f, 806.781f, 120.270f, 3500); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + MoveToPoint(pTemp, 1629.232f, 803.629f, 120.011f, 3500); + m_uiStepTimer = 3400; + break; + case 3: + MoveToPoint(m_creature, 1622.782f, 808.533f, 121.249f, 1500); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + MoveToPoint(pTemp, 1629.265f, 805.245f, 120.070f, 300); + m_uiStepTimer = 300; + break; + case 4: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + pTemp->PlayDirectSound(SOUND_ID_DOG_GROWL); + m_uiStepTimer = 500; + break; + case 5: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pTemp->GetGUID()); + DoScriptText(SAY_MALCOLM02, m_creature); + m_uiStepTimer = 2000; + break; + case 6: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + MoveToPoint(pTemp, 1629.163f, 809.738f, 120.369f, 1500); + m_uiStepTimer = 2000; + break; + case 7: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + { + pTemp->HandleEmoteCommand(EMOTE_DOG_HOWL); + pTemp->PlayDirectSound(SOUND_ID_DOG_HOWL); + } + m_uiStepTimer = 4000; + break; + case 8: + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + MoveToPoint(m_creature, 1629.922f, 807.799f, 120.122f, 3000); + m_uiStepTimer = 2900; + break; + case 9: + MoveToPoint(m_creature, 1632.169f, 809.851f, 120.047f, 1000); + m_uiStepTimer = 900; + break; + case 10: + MoveToPoint(m_creature, 1630.651f, 811.149f, 120.307f, 800); + m_uiStepTimer = 800; + break; + case 11: + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + DoScriptText(SAY_MALCOLM03, m_creature); + m_uiStepTimer = 4000; + break; + case 12: + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pTemp->GetGUID()); + DoScriptText(SAY_MALCOLM04, m_creature); + m_uiStepTimer = 7000; + break; + case 13: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + MoveToPoint(pTemp, 1630.692f, 808.011f, 120.083f, 400); + m_uiStepTimer = 600; + break; + case 14: + if(Creature* pTemp = m_pInstance->instance->GetCreature(m_uiDogGUID)) + pTemp->SetStandState(UNIT_STAND_STATE_SIT); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + MoveToPoint(m_creature, 1641.452f, 812.600f, 119.948f, 4000); + m_uiStepTimer = 3900; + break; + case 15: + MoveToPoint(m_creature, 1657.975f, 857.352f, 119.097f, 18000); + m_uiStepTimer = 17900; + break; + case 16: + MoveToPoint(m_creature, 1679.852f, 912.245f, 120.533f, 23000); + m_uiStepTimer = 22900; + break; + case 17: + MoveToPoint(m_creature, 1699.915f, 967.110f, 121.643f, 23000); + m_uiStepTimer = 22900; + break; + case 18: + MoveToPoint(m_creature, 1678.393f, 1026.890f, 125.431f, 25000); + m_uiStepTimer = 24900; + break; + case 19: + MoveToPoint(m_creature, 1678.943f, 1093.130f, 126.899f, 26000); + m_uiStepTimer = 25900; + break; + case 20: + MoveToPoint(m_creature, 1700.042f, 1103.880f, 130.872f, 9000); + m_uiStepTimer = 10900; + break; + case 21: + m_uiPhase = 2; + m_creature->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void MoveToPoint(Creature* unit, float X, float Y, float Z, uint32 Timer) + { + unit->GetMap()->CreatureRelocation(unit, X, Y, Z, unit->GetOrientation()); + unit->SendMonsterMove(X, Y, Z, SPLINETYPE_NORMAL , unit->GetSplineFlags(), Timer); + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiPhase == 1) + { + if(m_uiStepTimer < uiDiff) + { + FourCrateEvent(); + m_uiStep++; + } + else m_uiStepTimer -= uiDiff; + } + + return; + } +}; + +/*### +## npc_bartleby +###*/ + +enum +{ + SAY_BARTLEBY01 = -1557300, + SAY_BARTLEBY02 = -1557301, + SAY_BARTLEBY03 = -1557302, + SAY_BARTLEBY04 = -1557303, + SAY_BARTLEBY05 = -1557304, +}; + +struct MANGOS_DLL_DECL npc_bartleby_csAI : public ScriptedAI +{ + npc_bartleby_csAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiStep; + uint32 m_uiStepTimer; + uint32 m_uiPhase; + + void Reset() + { + if(m_uiPhase != 4) + { + m_uiStep = 0; + m_uiStepTimer = 100; + m_uiPhase = 0; + } + } + + void MoveInLineOfSight(Unit* who) + { + if (!who) + return; + + if(!m_pInstance) return; + + if (who->GetTypeId() == TYPEID_PLAYER && m_creature->GetDistance2d(who) <= 20 && m_uiPhase == 0) + { + m_uiPhase = 1; + } + } + + void StartBartleby() + { + m_uiPhase = 3; + } + + void FifthCrateEvent() + { + switch(m_uiStep) + { + case 0: + DoScriptText(SAY_BARTLEBY03, m_creature); + MoveToPoint(m_creature, 1672.539f, 872.277f, 120.113f, 1000); + m_uiStepTimer = 1000; + break; + case 1: + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + m_uiStepTimer = 3000; + break; + case 2: + DoScriptText(SAY_BARTLEBY04, m_creature); + m_uiStepTimer = 7000; + break; + case 3: + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_uiStepTimer = 1000; + break; + case 4: + DoScriptText(SAY_BARTLEBY05, m_creature); + MoveToPoint(m_creature, 1663.054f, 869.959f, 119.734f, 3000); + m_uiStepTimer = 2900; + break; + case 5: + MoveToPoint(m_creature, 1640.732f, 812.422f, 119.933f, 24000); + m_uiStepTimer = 23900; + break; + case 6: + MoveToPoint(m_creature, 1623.704f, 755.741f, 115.710f, 23000); + m_uiStepTimer = 22900; + break; + case 7: + MoveToPoint(m_creature, 1607.108f, 699.637f, 106.971f, 23000); + m_uiStepTimer = 22900; + break; + case 8: + MoveToPoint(m_creature, 1587.750f, 646.929f, 100.990f, 21000); + m_uiStepTimer = 20900; + break; + case 9: + MoveToPoint(m_creature, 1571.103f, 660.949f, 102.084f, 8000); + m_uiStepTimer = 10900; + break; + case 10: + m_uiPhase = 4; + m_creature->SetVisibility(VISIBILITY_OFF); + break; + } + } + + void SpeechEvent() + { + switch(m_uiStep) + { + case 0: + DoScriptText(SAY_BARTLEBY01, m_creature); + m_uiStepTimer = 5000; + break; + case 1: + DoScriptText(SAY_BARTLEBY02, m_creature); + if(m_uiPhase == 1) + m_uiPhase = 2; + break; + } + } + + void MoveToPoint(Creature* unit, float X, float Y, float Z, uint32 Timer) + { + unit->GetMap()->CreatureRelocation(unit, X, Y, Z, unit->GetOrientation()); + unit->SendMonsterMove(X, Y, Z, SPLINETYPE_NORMAL , unit->GetSplineFlags(), Timer); + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiPhase == 3) + { + if(m_uiStepTimer < uiDiff) + { + FifthCrateEvent(); + m_uiStep++; + } + else m_uiStepTimer -= uiDiff; + } + + if(m_uiPhase == 1) + { + if(m_uiStepTimer < uiDiff) + { + SpeechEvent(); + m_uiStep++; + } + else m_uiStepTimer -= uiDiff; + } + + return; + } +}; + +/*### +## npc_crates +###*/ + +enum +{ + SPELL_LIGHT = 49590 +}; + +struct MANGOS_DLL_DECL npc_stratholme_cratesAI : public ScriptedAI +{ + npc_stratholme_cratesAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + + bool Active; + + void Reset() + { + Active = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if(!m_pInstance) return; + + if(m_creature->HasAura(SPELL_LIGHT) && Active != true) + { + if(Creature* pRoger = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_ROGER))) + { + if(m_creature->GetDistance2d(pRoger->GetPositionX(), pRoger->GetPositionY()) < 50.0f) + { + ((npc_rogerAI*)pRoger->AI())->StartRoger(); + } + } + + if(Creature* pMorigan = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_MORIGAN))) + { + if(m_creature->GetDistance2d(pMorigan->GetPositionX(), pMorigan->GetPositionY()) < 50.0f) + { + ((npc_moriganAI*)pMorigan->AI())->StartMorigan(); + } + } + + if(Creature* pJena = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_JENA))) + { + if(m_creature->GetDistance2d(pJena->GetPositionX(), pJena->GetPositionY()) < 50.0f) + { + ((npc_jenaAI*)pJena->AI())->StartJena(); + } + } + + if(Creature* pMalcolm = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_MALCOLM))) + { + if(m_creature->GetDistance2d(pMalcolm->GetPositionX(), pMalcolm->GetPositionY()) < 50.0f) + { + ((npc_malcolmAI*)pMalcolm->AI())->StartMalcolm(); + } + } + + if(Creature* pBartleby = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_BARTLEBY))) + { + if(m_creature->GetDistance2d(pBartleby->GetPositionX(), pBartleby->GetPositionY()) < 50.0f) + { + ((npc_bartleby_csAI*)pBartleby->AI())->StartBartleby(); + } + } + + m_pInstance->SetData(TYPE_CRATES_COUNT, 1); + if(GameObject* pLight = GetClosestGameObjectWithEntry(m_creature, GO_CRATE_LIGHT, 5.0f)) + pLight->SetPhaseMask(0, true); + //m_creature->SetPhaseMask(0, true); + Active = true; + } + + return; + } +}; + +CreatureAI* GetAI_npc_chromi_start(Creature* pCreature) +{ + return new npc_chromi_startAI(pCreature); +} + +CreatureAI* GetAI_npc_mike(Creature* pCreature) +{ + return new npc_mikeAI(pCreature); +} + +CreatureAI* GetAI_npc_roger(Creature* pCreature) +{ + return new npc_rogerAI(pCreature); +} + +CreatureAI* GetAI_npc_morigan(Creature* pCreature) +{ + return new npc_moriganAI(pCreature); +} + +CreatureAI* GetAI_npc_jena(Creature* pCreature) +{ + return new npc_jenaAI(pCreature); +} + +CreatureAI* GetAI_npc_malcolm(Creature* pCreature) +{ + return new npc_malcolmAI(pCreature); +} + +CreatureAI* GetAI_npc_bartleby_cs(Creature* pCreature) +{ + return new npc_bartleby_csAI(pCreature); +} + +CreatureAI* GetAI_npc_stratholme_crates(Creature* pCreature) +{ + return new npc_stratholme_cratesAI(pCreature); +} + +void AddSC_culling_of_stratholmeAI() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_chromi_start"; + newscript->pGossipHello = &GossipHello_npc_chromi_start; + newscript->pGossipSelect = &GossipSelect_npc_chromi_start; + newscript->GetAI = &GetAI_npc_chromi_start; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_mike"; + newscript->GetAI = &GetAI_npc_mike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_roger"; + newscript->GetAI = &GetAI_npc_roger; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_morigan"; + newscript->GetAI = &GetAI_npc_morigan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jena"; + newscript->GetAI = &GetAI_npc_jena; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_malcolm"; + newscript->GetAI = &GetAI_npc_malcolm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_bartleby_cs"; + newscript->GetAI = &GetAI_npc_bartleby_cs; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_stratholme_crates"; + newscript->GetAI = &GetAI_npc_stratholme_crates; + newscript->RegisterSelf(); +} diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/def_culling_of_stratholme.h b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/def_culling_of_stratholme.h new file mode 100644 index 0000000..ab16d2d --- /dev/null +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/def_culling_of_stratholme.h @@ -0,0 +1,110 @@ +/* Copyright (C) 2006 - 2010 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_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 +SDCategory: Culling of Stratholme +EndScriptData */ + +#ifndef DEF_CULLING_OF_STRATHOLME_H +#define DEF_CULLING_OF_STRATHOLME_H + +enum Data +{ + TYPE_QUEST = 1, + TYPE_INTRO = 2, + TYPE_CRATES_COUNT = 3, + TYPE_PHASE = 4, + TYPE_ENCOUNTER = 5, + TYPE_WAVE_COUNT = 6, + TYPE_WING = 7, + TYPE_BONUS = 8, + TYPE_MALGANIS = 9, + + DATA_TEMPSUMMON = 10, + + QUEST_DISPELLING_ILLUSIONS = 13149, + QUEST_A_ROYAL_ESCORT = 13151, + ITEM_ARCANE_DISRUPTOR = 37888, + + NPC_CHROMI01 = 26527, + NPC_CHROMI02 = 27915, + NPC_ARTHAS = 26499, + NPC_JAINA = 26497, + NPC_UTHER = 26528, + NPC_KNIGHT = 28612, + NPC_MIKE = 30571, + NPC_MAL_CORICS = 31017, + NPC_GRIAN_STONE = 30561, + NPC_JAMES = 30553, + NPC_FRAS_FRASIABI = 30552, + NPC_FORRESTER = 30551, + NPC_ROGER = 27903, + NPC_CRATE = 30996, + NPC_MORIGAN = 27877, + NPC_PERELLI = 27876, + NPC_JENA = 27885, + NPC_MARTHA = 27884, + NPC_MALCOLM = 27891, + NPC_DOG = 27892, + NPC_BARTLEBY = 27907, + NPC_MARINE = 27745, + NPC_PRIEST = 27747, + + NPC_INFINITE_ADVERSARY = 27742, + NPC_INFINITE_HUNTER = 27743, + NPC_INFINITE_AGENT = 27744, + NPC_TIME_RIFT = 28409, + NPC_TIME_RIFT_2 = 28439, + 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_ACOLYTE = 27731, + NPC_MEATHOOK = 26529, + NPC_SALRAMM = 26530, + NPC_EPOCH = 26532, + NPC_MALGANIS = 26533, + NPC_CITY = 28167, + NPC_INFINITE_CORRUPTOR = 32273, + + GO_CRATE_LIGHT = 190117, + GO_SHKAF_GATE = 188686, + GO_MALGANIS_GATE1 = 187711, + GO_MALGANIS_GATE2 = 187723, + GO_MALGANIS_CHEST = 190663, + GO_MALGANIS_CHEST_H = 193597, + GO_EXIT = 191788, + + + WORLD_STATE_COS_TIME_ON = 3932, + WORLD_STATE_COS_TIME_COUNT = 3931, + WORLD_STATE_COS_WAVE_COUNT = 3504, + WORLD_STATE_COS_CRATE_ON = 3479, + WORLD_STATE_COS_CRATE_COUNT = 3480, + + RIGHT = 1, + LEFT = 2 +}; + +#endif diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp index 9bc162c..73e8ff4 100644 --- a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp @@ -14,560 +14,376 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + /* ScriptData -SDName: Instance_culling_of_stratholme -SD%Complete: 80% -SDComment: +SDName: instance_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 SDCategory: Culling of Stratholme EndScriptData */ #include "precompiled.h" -#include "culling_of_stratholme.h" - -enum -{ - MAX_ARTHAS_SPAWN_POS = 5, - SAY_CHROMIE_HURRY = -1000000 // TODO -}; - -struct sSpawnLocation -{ - float m_fX, m_fY, m_fZ, m_fO; -}; - -static sSpawnLocation m_aArthasSpawnLocs[] = // need tuning -{ - {1969.73f, 1287.12f, 145.48f, 3.14f}, - {2049.43f, 1287.43f, 142.75f, 0.06f}, - {2365.54f, 1194.85f, 131.98f, 0.47f}, - {2534.46f, 1125.99f, 130.75f, 0.27f}, - {2363.77f, 1406.31f, 128.64f, 3.23f} -}; +#include "def_culling_of_stratholme.h" -static sSpawnLocation m_aChromieSpawnLocs[] = // need tuning, escpecially EndPositions! +struct MANGOS_DLL_DECL instance_culling_of_stratholme : public ScriptedInstance { - {1814.46f, 1283.97f, 142.30f, 4.32f}, // near bridge - {2311.0f, 1502.4f, 127.9f, 0.0f}, // End - {1811.52f, 1285.92f, 142.37f, 4.47f}, // Hourglass, near bridge - {2186.42f, 1323.77f, 129.91f, 0.0f}, // Hourglass, End -}; - -instance_culling_of_stratholme::instance_culling_of_stratholme(Map* pMap) : ScriptedInstance(pMap), - m_uiGrainCrateCount(0), - m_uiRemoveCrateStateTimer(0), - m_uiArthasRespawnTimer(0), - - m_uiChromieInnGUID(0), - m_uiChromieEntranceGUID(0), - m_uiChromieEndGUID(0), - m_uiHourglassGUID(0), - m_uiArthasGUID(0), - m_uiMeathookGUID(0), - m_uiSalrammGUID(0), - m_uiEpochGUID(0), - m_uiCorrupterGUID(0), - m_uiLordaeronCrierGUID(0), - - m_uiBelfastGUID(0), - m_uiForrestenGUID(0), - m_uiSiabiGUID(0), - m_uiJamesGUID(0), - m_uiCorricksGUID(0), - m_uiStoutmantleGUID(0), - - m_uiOwensGUID(0), - m_uiMoriganGUID(0), - m_uiAndersonGUID(0), - m_uiMooreGUID(0), - m_uiBattsonGUID(0), - - m_uiOReillyGUID(0), - - m_uiDoorBookcaseGUID(0), - m_uiDarkRunedChestGUID(0) -{ - Initialize(); -} - -void instance_culling_of_stratholme::Initialize() -{ - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); -} - -void instance_culling_of_stratholme::OnCreatureCreate(Creature* pCreature) -{ - switch(pCreature->GetEntry()) - { - case NPC_CHROMIE_INN: m_uiChromieInnGUID = pCreature->GetGUID(); break; - case NPC_CHROMIE_ENTRANCE: m_uiChromieEntranceGUID = pCreature->GetGUID(); break; - case NPC_CHROMIE_END: m_uiChromieEndGUID = pCreature->GetGUID(); break; - case NPC_HOURGLASS: m_uiHourglassGUID = pCreature->GetGUID(); break; - case NPC_ARTHAS: m_uiArthasGUID = pCreature->GetGUID(); break; - case NPC_MEATHOOK: m_uiMeathookGUID = pCreature->GetGUID(); break; - case NPC_SALRAMM_THE_FLESHCRAFTER: m_uiSalrammGUID = pCreature->GetGUID(); break; - case NPC_CHRONO_LORD_EPOCH: m_uiEpochGUID = pCreature->GetGUID(); break; - case NPC_MALGANIS: m_uiMalganisGUID = pCreature->GetGUID(); break; - case NPC_MICHAEL_BELFAST: m_uiBelfastGUID = pCreature->GetGUID(); break; - case NPC_HEARTHSINGER_FORRESTEN: m_uiForrestenGUID = pCreature->GetGUID(); break; - case NPC_FRAS_SIABI: m_uiSiabiGUID = pCreature->GetGUID(); break; - case NPC_FOOTMAN_JAMES: m_uiJamesGUID = pCreature->GetGUID(); break; - case NPC_MAL_CORRICKS: m_uiCorricksGUID = pCreature->GetGUID(); break; - case NPC_GRYAN_STOUTMANTLE: m_uiStoutmantleGUID = pCreature->GetGUID(); break; - case NPC_ROGER_OWENS: m_uiOwensGUID = pCreature->GetGUID(); break; - case NPC_SERGEANT_MORIGAN: m_uiMoriganGUID = pCreature->GetGUID(); break; - case NPC_JENA_ANDERSON: m_uiAndersonGUID = pCreature->GetGUID(); break; - case NPC_MALCOM_MOORE: m_uiMooreGUID = pCreature->GetGUID(); break; - case NPC_BARTLEBY_BATTSON: m_uiBattsonGUID = pCreature->GetGUID(); break; - case NPC_PATRICIA_O_REILLY: m_uiOReillyGUID = pCreature->GetGUID(); break; - case NPC_LORDAERON_CRIER: m_uiLordaeronCrierGUID = pCreature->GetGUID(); break; - case NPC_INFINITE_CORRUPTER: m_uiCorrupterGUID = pCreature->GetGUID(); break; - - case NPC_CRATES_BUNNY: m_luiCratesBunnyGUIDs.push_back(pCreature->GetGUID()); break; - case NPC_LORDAERON_FOOTMAN: m_luiFootmanGUIDs.push_back(pCreature->GetGUID()); break; - - case NPC_STRATHOLME_CITIZEN: - case NPC_STRATHOLME_RESIDENT: - if (m_auiEncounter[TYPE_ARTHAS_INTRO_EVENT] == DONE) - pCreature->UpdateEntry(NPC_ZOMBIE); - else - m_luiResidentGUIDs.push_back(pCreature->GetGUID()); - break; - case NPC_AGIATED_STRATHOLME_CITIZEN: m_lAgiatedCitizenGUIDList.push_back(pCreature->GetGUID()); break; - case NPC_AGIATED_STRATHOLME_RESIDENT: m_lAgiatedResidentGUIDList.push_back(pCreature->GetGUID()); break; - } -} - -void instance_culling_of_stratholme::OnObjectCreate(GameObject* pGo) -{ - switch(pGo->GetEntry()) + instance_culling_of_stratholme(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint8 m_uiCratesCount; + uint32 m_auiEncounter[7]; + uint32 m_uiHeroicTimer; + uint32 m_uiLastTimer; + + uint64 m_uiChromi01GUID; + uint64 m_uiChromi02GUID; + uint64 m_uiMikeGUID; + uint64 m_uiMalCoricsGUID; + uint64 m_uiGrianStoneGUID; + uint64 m_uiJamesGUID; + uint64 m_uiFrasCiabiGUID; + uint64 m_uiForrestenGUID; + uint64 m_uiRogerGUID; + uint64 m_uiMoriganGUID; + uint64 m_uiPerelliGUID; + uint64 m_uiJenaGUID; + uint64 m_uiMarthaGUID; + uint64 m_uiMalcolmGUID; + uint64 m_uiDogGUID; + uint64 m_uiBartlebyGUID; + uint64 m_uiArthasGUID; + uint64 m_uiUtherGUID; + uint64 m_uiJainaGUID; + uint64 m_uiSalrammGUID; + uint64 m_uiMalganisGUID; + uint64 m_uiCorruptorGUID; + + uint64 m_uiShkafGateGUID; + uint64 m_uiMalGate1GUID; + uint64 m_uiMalGate2GUID; + uint64 m_uiMalChestGUID; + uint64 m_uiExitGUID; + + void Initialize() { - case GO_DOOR_BOOKCASE: - m_uiDoorBookcaseGUID = pGo->GetGUID(); - if (m_auiEncounter[TYPE_EPOCH_EVENT] == DONE) - pGo->SetGoState(GO_STATE_ACTIVE); - break; - case GO_DARK_RUNED_CHEST: - case GO_DARK_RUNED_CHEST_H: - m_uiDarkRunedChestGUID = pGo->GetGUID(); - break; + m_uiHeroicTimer = 1500000; + m_uiLastTimer = 1500000; + m_auiEncounter[0] = NOT_STARTED; + m_auiEncounter[1] = NOT_STARTED; + m_auiEncounter[2] = 0; + m_auiEncounter[3] = NOT_STARTED; + m_auiEncounter[4] = 0; + m_auiEncounter[5] = NOT_STARTED; + m_auiEncounter[6] = NOT_STARTED; + + DoUpdateWorldState(WORLD_STATE_COS_CRATE_COUNT, 0); + DoUpdateWorldState(WORLD_STATE_COS_CRATE_ON, 0); + DoUpdateWorldState(WORLD_STATE_COS_WAVE_COUNT, 0); + DoUpdateWorldState(WORLD_STATE_COS_TIME_COUNT, 0); + DoUpdateWorldState(WORLD_STATE_COS_TIME_ON, 0); + + m_uiCratesCount = 0; + m_uiMikeGUID = 0; + m_uiChromi01GUID = 0; + m_uiChromi02GUID = 0; + m_uiMalCoricsGUID = 0; + m_uiGrianStoneGUID = 0; + m_uiJamesGUID = 0; + m_uiFrasCiabiGUID = 0; + m_uiForrestenGUID = 0; + m_uiRogerGUID = 0; + m_uiMoriganGUID = 0; + m_uiPerelliGUID = 0; + m_uiJenaGUID = 0; + m_uiMarthaGUID = 0; + m_uiMalcolmGUID = 0; + m_uiDogGUID = 0; + m_uiBartlebyGUID = 0; + m_uiArthasGUID = 0; + m_uiUtherGUID = 0; + m_uiJainaGUID = 0; + m_uiShkafGateGUID = 0; + m_uiSalrammGUID = 0; + m_uiCorruptorGUID = 0; + m_uiMalganisGUID = 0; + m_uiMalGate1GUID = 0; + m_uiMalGate2GUID = 0; + m_uiMalChestGUID = 0; + m_uiExitGUID = 0; } -} -Player* instance_culling_of_stratholme::GetPlayerInMap() -{ - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) + void OnCreatureCreate(Creature* pCreature) { - for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + switch(pCreature->GetEntry()) { - if (Player* plr = itr->getSource()) - return plr; + case NPC_CHROMI01: + pCreature->SetActiveObjectState(true); + m_uiChromi01GUID = pCreature->GetGUID(); + break; + case NPC_CHROMI02: + pCreature->SetActiveObjectState(true); + m_uiChromi02GUID = pCreature->GetGUID(); + if (m_auiEncounter[0] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + else + pCreature->SetVisibility(VISIBILITY_OFF); + break; + case NPC_MIKE: + m_uiMikeGUID = pCreature->GetGUID(); + break; + case NPC_MAL_CORICS: + pCreature->SetActiveObjectState(true); + m_uiMalCoricsGUID = pCreature->GetGUID(); + break; + case NPC_GRIAN_STONE: + pCreature->SetActiveObjectState(true); + pCreature->SetStandState(UNIT_STAND_STATE_SIT_MEDIUM_CHAIR); + m_uiGrianStoneGUID = pCreature->GetGUID(); + break; + case NPC_JAMES: + pCreature->SetActiveObjectState(true); + pCreature->SetStandState(UNIT_STAND_STATE_SIT_MEDIUM_CHAIR); + m_uiJamesGUID = pCreature->GetGUID(); + break; + case NPC_FRAS_FRASIABI: + pCreature->SetActiveObjectState(true); + pCreature->SetStandState(UNIT_STAND_STATE_SIT_MEDIUM_CHAIR); + m_uiFrasCiabiGUID = pCreature->GetGUID(); + break; + case NPC_FORRESTER: + pCreature->SetActiveObjectState(true); + pCreature->SetStandState(UNIT_STAND_STATE_SIT_MEDIUM_CHAIR); + m_uiForrestenGUID = pCreature->GetGUID(); + break; + case NPC_ROGER: + m_uiRogerGUID = pCreature->GetGUID(); + break; + case NPC_MORIGAN: + m_uiMoriganGUID = pCreature->GetGUID(); + break; + case NPC_PERELLI: + pCreature->SetActiveObjectState(true); + m_uiPerelliGUID = pCreature->GetGUID(); + break; + case NPC_JENA: + m_uiJenaGUID = pCreature->GetGUID(); + break; + case NPC_MARTHA: + pCreature->CastSpell(pCreature, 58925, false); + pCreature->SetActiveObjectState(true); + m_uiMarthaGUID = pCreature->GetGUID(); + break; + case NPC_MALCOLM: + m_uiMalcolmGUID = pCreature->GetGUID(); + break; + case NPC_DOG: + pCreature->SetActiveObjectState(true); + m_uiDogGUID = pCreature->GetGUID(); + break; + case NPC_BARTLEBY: + m_uiBartlebyGUID = pCreature->GetGUID(); + break; + case NPC_UTHER: + m_uiUtherGUID = pCreature->GetGUID(); + break; + case NPC_ARTHAS: + m_uiArthasGUID = pCreature->GetGUID(); + break; + case NPC_JAINA: + pCreature->SetActiveObjectState(true); + m_uiJainaGUID = pCreature->GetGUID(); + break; + case NPC_INFINITE_CORRUPTOR: + pCreature->SetPhaseMask(0, true); + m_uiCorruptorGUID = pCreature->GetGUID(); + break; } } - return NULL; -} -void instance_culling_of_stratholme::UpdateQuestCredit() -{ - Map::PlayerList const& players = instance->GetPlayers(); - if (!players.isEmpty()) + void OnObjectCreate(GameObject* pGo) { - for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* pPlayer = itr->getSource()) - pPlayer->KilledMonsterCredit(NPC_CRATES_BUNNY); - } - } -} + if (pGo->GetEntry() == GO_SHKAF_GATE) + m_uiShkafGateGUID = pGo->GetGUID(); -void instance_culling_of_stratholme::DoChromieHurrySpeech() -{ - if (Creature* pChromie = instance->GetCreature(m_uiChromieEntranceGUID)) - { - 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()) - DoScriptText(SAY_CHROMIE_HURRY, pChromie, pPlayer); - } - } - } -} + if (pGo->GetEntry() == GO_MALGANIS_GATE1) + m_uiMalGate1GUID = pGo->GetGUID(); -void instance_culling_of_stratholme::SetData(uint32 uiType, uint32 uiData) -{ - switch(uiType) - { - case TYPE_GRAIN_EVENT: - m_auiEncounter[TYPE_GRAIN_EVENT] = uiData; - if (uiData == SPECIAL) - DoUpdateWorldState(WORLD_STATE_CRATES, 1); - else if (uiData == IN_PROGRESS) - { - if (m_uiGrainCrateCount >= 5) - return; + if (pGo->GetEntry() == GO_MALGANIS_GATE2) + m_uiMalGate2GUID = pGo->GetGUID(); - ++m_uiGrainCrateCount; - DoUpdateWorldState(WORLD_STATE_CRATES_COUNT, m_uiGrainCrateCount); + if (pGo->GetEntry() == GO_MALGANIS_CHEST || pGo->GetEntry() == GO_MALGANIS_CHEST_H) + m_uiMalChestGUID = pGo->GetGUID(); - if (m_uiGrainCrateCount == 5) - { - UpdateQuestCredit(); - m_uiRemoveCrateStateTimer = 20000; - SetData(TYPE_GRAIN_EVENT, DONE); - } - } - break; - case TYPE_ARTHAS_INTRO_EVENT: - m_auiEncounter[TYPE_ARTHAS_INTRO_EVENT] = uiData; - break; - case TYPE_ARTHAS_ESCORT_EVENT: - m_auiEncounter[TYPE_ARTHAS_ESCORT_EVENT] = uiData; - break; - case TYPE_MEATHOOK_EVENT: - m_auiEncounter[TYPE_MEATHOOK_EVENT] = uiData; - if (uiData == DONE) - SetData(TYPE_SALRAMM_EVENT, IN_PROGRESS); - break; - case TYPE_SALRAMM_EVENT: - m_auiEncounter[TYPE_SALRAMM_EVENT] = uiData; - if (uiData == DONE) - DoUpdateWorldState(WORLD_STATE_WAVE, 0); // Remove WaveCounter - break; - case TYPE_EPOCH_EVENT: - m_auiEncounter[TYPE_EPOCH_EVENT] = uiData; - break; - case TYPE_MALGANIS_EVENT: - m_auiEncounter[TYPE_MALGANIS_EVENT] = uiData; - if (uiData == DONE) - { - DoRespawnGameObject(m_uiDarkRunedChestGUID, 30*MINUTE); - DoSpawnChromieIfNeeded(); - } - break; - case TYPE_INFINITE_CORRUPTER_TIME: - m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME] = uiData; - if (!uiData) - { - DoUpdateWorldState(WORLD_STATE_TIME, 0); // Remove Timer - DoUpdateWorldState(WORLD_STATE_TIME_COUNTER, 0); - } - else - DoUpdateWorldState(WORLD_STATE_TIME_COUNTER, uiData/(MINUTE*IN_MILLISECONDS)); - break; - case TYPE_INFINITE_CORRUPTER: - m_auiEncounter[TYPE_INFINITE_CORRUPTER] = uiData; - switch(uiData) - { - case IN_PROGRESS: - if (!m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME]) - SetData(TYPE_INFINITE_CORRUPTER_TIME, MINUTE*25*IN_MILLISECONDS); - DoUpdateWorldState(WORLD_STATE_TIME, 1);// Show Timer - break; - case DONE: - SetData(TYPE_INFINITE_CORRUPTER_TIME, 0); - break; - case SPECIAL: - DoChromieHurrySpeech(); - break; - case FAIL: - SetData(TYPE_INFINITE_CORRUPTER_TIME, 0); - if (Creature* pCorrupter = instance->GetCreature(m_uiCorrupterGUID)) - if (pCorrupter->isAlive()) - pCorrupter->ForcedDespawn(); - break; - } - break; + if (pGo->GetEntry() == GO_EXIT) + m_uiExitGUID = pGo->GetGUID(); } - if (uiData == DONE || (uiType == TYPE_INFINITE_CORRUPTER && uiData == FAIL)) + void ChromiWhispers() { - OUT_SAVE_INST_DATA; - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " - << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8]; + Map::PlayerList const &PlayerList = instance->GetPlayers(); - strInstData = saveStream.str(); + if (PlayerList.isEmpty()) + return; - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; - } -} - -void instance_culling_of_stratholme::Load(const char* chrIn) -{ - if (!chrIn) - { - OUT_LOAD_INST_DATA_FAIL; - return; + if (Creature* pChromi = instance->GetCreature(m_uiChromi01GUID)) + { + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + pChromi->MonsterWhisper("Good work with crates! Come to me in front of Stratholme for your next assignment!", i->getSource(), false); + i->getSource()->KilledMonsterCredit(30996, pChromi->GetGUID()); + i->getSource()->DestroyItemCount(ITEM_ARCANE_DISRUPTOR, 1, true); + } + pChromi->SetVisibility(VISIBILITY_OFF); + } + if (Creature* pChromi2 = instance->GetCreature(m_uiChromi02GUID)) + pChromi2->SetVisibility(VISIBILITY_ON); } - OUT_LOAD_INST_DATA(chrIn); - - std::istringstream loadStream(chrIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] >> m_auiEncounter[8]; - - for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + void SetData(uint32 uiType, uint32 uiData) { - if (i != TYPE_INFINITE_CORRUPTER_TIME) + switch(uiType) { - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + case TYPE_QUEST: + m_auiEncounter[0] = uiData; + break; + case TYPE_CRATES_COUNT: + m_uiCratesCount = m_uiCratesCount + uiData; + if(m_uiCratesCount == 5) + { + m_auiEncounter[0] = DONE; + ChromiWhispers(); + } + DoUpdateWorldState(WORLD_STATE_COS_CRATE_COUNT, m_uiCratesCount); + break; + case TYPE_INTRO: + m_auiEncounter[1] = uiData; + break; + case TYPE_PHASE: + m_auiEncounter[2] = uiData; + break; + case TYPE_ENCOUNTER: + m_auiEncounter[3] = uiData; + break; + case TYPE_WING: + m_auiEncounter[4] = uiData; + break; + case TYPE_BONUS: + m_auiEncounter[5] = uiData; + if(uiData == IN_PROGRESS) + { + if(Creature* Corruptor = instance->GetCreature(m_uiCorruptorGUID)) + Corruptor->SetPhaseMask(1, true); + DoUpdateWorldState(WORLD_STATE_COS_TIME_ON, 1); + DoUpdateWorldState(WORLD_STATE_COS_TIME_COUNT, 25); + } + break; + case TYPE_MALGANIS: + m_auiEncounter[6] = uiData; + if (uiData == DONE) + { + DoRespawnGameObject(m_uiMalChestGUID, 30*MINUTE); + if (GameObject* pGo = instance->GetGameObject(m_uiMalChestGUID)) + pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); + if (Creature* pChromi2 = instance->GetCreature(m_uiChromi02GUID)) + pChromi2->SetVisibility(VISIBILITY_OFF); + if (GameObject* pGo = instance->GetGameObject(m_uiExitGUID)) + pGo->SetGoState(GO_STATE_ACTIVE); + } + break; } } - // If already started counting down time, the event is "in progress" - if (m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME]) - m_auiEncounter[TYPE_INFINITE_CORRUPTER] = IN_PROGRESS; - - OUT_LOAD_INST_DATA_COMPLETE; -} - -void instance_culling_of_stratholme::OnPlayerEnter(Player* pPlayer) -{ - if (instance->GetPlayersCountExceptGMs() == 0) - { - DoSpawnArthasIfNeeded(); - DoSpawnChromieIfNeeded(); - - // Show World States if needed, TODO verify if needed and if this is the right way - if (m_auiEncounter[TYPE_GRAIN_EVENT] == IN_PROGRESS || m_auiEncounter[TYPE_GRAIN_EVENT] == SPECIAL) - DoUpdateWorldState(WORLD_STATE_CRATES, 1); // Show Crates Counter - else - DoUpdateWorldState(WORLD_STATE_CRATES, 0); // Remove Crates Counter - - if (m_auiEncounter[TYPE_MEATHOOK_EVENT] == IN_PROGRESS) - DoUpdateWorldState(WORLD_STATE_WAVE, 1); // Add WaveCounter - else if (m_auiEncounter[TYPE_SALRAMM_EVENT] == IN_PROGRESS) - DoUpdateWorldState(WORLD_STATE_WAVE, 6); // Add WaveCounter - else - DoUpdateWorldState(WORLD_STATE_WAVE, 0); // Remove WaveCounter - - if (m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME]) - DoUpdateWorldState(WORLD_STATE_TIME, 1); // Show Timer - else - DoUpdateWorldState(WORLD_STATE_TIME, 0); // Remove Timer - } -} - -uint32 instance_culling_of_stratholme::GetData(uint32 uiType) -{ - switch(uiType) - { - case TYPE_GRAIN_EVENT: return m_auiEncounter[0]; - case TYPE_ARTHAS_INTRO_EVENT: return m_auiEncounter[1]; - case TYPE_MEATHOOK_EVENT: return m_auiEncounter[2]; - case TYPE_SALRAMM_EVENT: return m_auiEncounter[3]; - case TYPE_EPOCH_EVENT: return m_auiEncounter[4]; - case TYPE_ARTHAS_ESCORT_EVENT: return m_auiEncounter[5]; - case TYPE_MALGANIS_EVENT: return m_auiEncounter[6]; - case TYPE_INFINITE_CORRUPTER_TIME: return m_auiEncounter[7]; - case TYPE_INFINITE_CORRUPTER: return m_auiEncounter[8]; - default: return 0; - } -} - -uint64 instance_culling_of_stratholme::GetData64(uint32 uiData) -{ - switch(uiData) - { - case NPC_CHROMIE_INN: return m_uiChromieInnGUID; - case NPC_CHROMIE_ENTRANCE: return m_uiChromieEntranceGUID; - case NPC_CHROMIE_END: return m_uiChromieEndGUID; - case NPC_HOURGLASS: return m_uiHourglassGUID; - case NPC_ARTHAS: return m_uiArthasGUID; - case NPC_MEATHOOK: return m_uiMeathookGUID; - case NPC_SALRAMM_THE_FLESHCRAFTER: return m_uiSalrammGUID; - case NPC_CHRONO_LORD_EPOCH: return m_uiEpochGUID; - case NPC_MALGANIS: return m_uiMalganisGUID; - case NPC_INFINITE_CORRUPTER: return m_uiCorrupterGUID; - case NPC_MICHAEL_BELFAST: return m_uiBelfastGUID; - case NPC_HEARTHSINGER_FORRESTEN: return m_uiForrestenGUID; - case NPC_FRAS_SIABI: return m_uiSiabiGUID; - case NPC_FOOTMAN_JAMES: return m_uiJamesGUID; - case NPC_MAL_CORRICKS: return m_uiCorricksGUID; - case NPC_GRYAN_STOUTMANTLE: return m_uiStoutmantleGUID; - case NPC_ROGER_OWENS: return m_uiOwensGUID; - case NPC_SERGEANT_MORIGAN: return m_uiMoriganGUID; - case NPC_JENA_ANDERSON: return m_uiAndersonGUID; - case NPC_MALCOM_MOORE: return m_uiMooreGUID; - case NPC_BARTLEBY_BATTSON: return m_uiBattsonGUID; - case NPC_PATRICIA_O_REILLY: return m_uiOReillyGUID; - case GO_DOOR_BOOKCASE: return m_uiDoorBookcaseGUID; - default: return 0; - } -} - -uint8 instance_culling_of_stratholme::GetInstancePosition() -{ - if (m_auiEncounter[TYPE_MALGANIS_EVENT] == DONE) - return POS_INSTANCE_FINISHED; - else if (m_auiEncounter[TYPE_ARTHAS_ESCORT_EVENT] == DONE) - return POS_ARTHAS_MALGANIS; - else if (m_auiEncounter[TYPE_EPOCH_EVENT] == DONE) - return POS_ARTHAS_ESCORTING; - else if (m_auiEncounter[TYPE_SALRAMM_EVENT] == DONE) - return POS_ARTHAS_TOWNHALL; - else if (m_auiEncounter[TYPE_MEATHOOK_EVENT] == DONE) - return POS_ARTHAS_WAVES; - else if (m_auiEncounter[TYPE_ARTHAS_INTRO_EVENT] == DONE) - return POS_ARTHAS_WAVES; - else if (m_auiEncounter[TYPE_GRAIN_EVENT] == DONE) - return POS_ARTHAS_INTRO; - else - return 0; -} - -static bool sortFromEastToWest(Creature* pFirst, Creature* pSecond) -{ - return pFirst && pSecond && pFirst->GetPositionY() < pSecond->GetPositionY(); -} - -static bool sortFromSouthToNorth(Creature* pFirst, Creature* pSecond) -{ - return pFirst && pSecond && pFirst->GetPositionX() < pSecond->GetPositionX(); -} - -void instance_culling_of_stratholme::GetCratesBunnyOrderedList(std::list &lList) -{ - std::list lCratesBunnyList; - for (std::list::const_iterator itr = m_luiCratesBunnyGUIDs.begin(); itr != m_luiCratesBunnyGUIDs.end(); itr++) - { - if (Creature* pBunny = instance->GetCreature(*itr)) - lCratesBunnyList.push_back(pBunny); - } - if (lCratesBunnyList.empty()) - return; - - lCratesBunnyList.sort(sortFromEastToWest); - lList = lCratesBunnyList; -} - -Creature* instance_culling_of_stratholme::GetStratIntroFootman() -{ - std::list lFootmanList; - for (std::list::const_iterator itr = m_luiFootmanGUIDs.begin(); itr != m_luiFootmanGUIDs.end(); itr++) - { - if (Creature* pFootman = instance->GetCreature(*itr)) - lFootmanList.push_back(pFootman); - } - - if (lFootmanList.empty()) - return NULL; - else + void SetData64(uint32 uiData, uint64 uiGuid) { - lFootmanList.sort(sortFromSouthToNorth); - return *lFootmanList.begin(); - } -} - -void instance_culling_of_stratholme::GetResidentOrderedList(std::list &lList) -{ - std::list lResidentList; - for (std::list::const_iterator itr = m_luiResidentGUIDs.begin(); itr != m_luiResidentGUIDs.end(); itr++) - { - if (Creature* pResident = instance->GetCreature(*itr)) - lResidentList.push_back(pResident); - } - if (lResidentList.empty()) - return; - - lResidentList.sort(sortFromSouthToNorth); - lList = lResidentList; -} - -void instance_culling_of_stratholme::ArthasJustDied() -{ - m_uiArthasRespawnTimer = 10000; // TODO, could be instant -} - -void instance_culling_of_stratholme::DoSpawnArthasIfNeeded() -{ - Creature* pArthas = instance->GetCreature(m_uiArthasGUID); - if (pArthas && pArthas->isAlive()) - return; - - uint8 uiPosition = GetInstancePosition(); - if (uiPosition && uiPosition <= MAX_ARTHAS_SPAWN_POS) - { - if (Player* pPlayer = GetPlayerInMap()) - pPlayer->SummonCreature(NPC_ARTHAS, m_aArthasSpawnLocs[uiPosition-1].m_fX, m_aArthasSpawnLocs[uiPosition-1].m_fY, m_aArthasSpawnLocs[uiPosition-1].m_fZ, m_aArthasSpawnLocs[uiPosition-1].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - } -} - -// Atm here only new Chromies are spawned - despawning depends on Mangos featuring such a thing -// The hourglass also is not yet spawned/ relocated. -void instance_culling_of_stratholme::DoSpawnChromieIfNeeded() -{ - Player* pPlayer = GetPlayerInMap(); - if (!pPlayer) - return; - - if (GetInstancePosition() == POS_INSTANCE_FINISHED) - { - Creature* pChromie = instance->GetCreature(m_uiChromieEndGUID); - if (!pChromie) - pPlayer->SummonCreature(NPC_CHROMIE_END, m_aChromieSpawnLocs[1].m_fX, m_aChromieSpawnLocs[1].m_fY, m_aChromieSpawnLocs[1].m_fZ, m_aChromieSpawnLocs[1].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); - } - else if (GetInstancePosition() >= POS_ARTHAS_INTRO) - { - Creature* pChromie = instance->GetCreature(m_uiChromieEntranceGUID); - if (!pChromie) - pPlayer->SummonCreature(NPC_CHROMIE_ENTRANCE, m_aChromieSpawnLocs[0].m_fX, m_aChromieSpawnLocs[0].m_fY, m_aChromieSpawnLocs[0].m_fZ, m_aChromieSpawnLocs[0].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + switch(uiData) + { + case NPC_SALRAMM: + m_uiSalrammGUID = uiGuid; + break; + case NPC_MALGANIS: + m_uiMalganisGUID = uiGuid; + break; + } } -} -void instance_culling_of_stratholme::Update(uint32 uiDiff) -{ - // 25min Run - decrease time, update worldstate every ~20s - // as the time is always saved by m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME], there is no need for an extra timer - if (m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME]) + uint32 GetData(uint32 uiType) { - if (m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME] <= uiDiff) - SetData(TYPE_INFINITE_CORRUPTER, FAIL); - else + switch(uiType) { - m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME] -= uiDiff; - if (m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME]/IN_MILLISECONDS % 20 == 0) - SetData(TYPE_INFINITE_CORRUPTER_TIME, m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME]); + case TYPE_QUEST: + return m_auiEncounter[0]; + case TYPE_INTRO: + return m_auiEncounter[1]; + case TYPE_PHASE: + return m_auiEncounter[2]; + case TYPE_ENCOUNTER: + return m_auiEncounter[3]; + case TYPE_WING: + return m_auiEncounter[4]; + case TYPE_BONUS: + return m_auiEncounter[5]; + case TYPE_MALGANIS: + return m_auiEncounter[6]; } - - // This part is needed for a small "hurry up guys" note, TODO, verify 20min - if (m_auiEncounter[TYPE_INFINITE_CORRUPTER] == IN_PROGRESS && m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME] <= 24*MINUTE*IN_MILLISECONDS) - SetData(TYPE_INFINITE_CORRUPTER, SPECIAL); + return 0; } - // Small Timer, to remove Grain-Crate WorldState and Spawn Second Chromie - if (m_uiRemoveCrateStateTimer) + uint64 GetData64(uint32 uiData) { - if (m_uiRemoveCrateStateTimer <= uiDiff) + switch(uiData) { - DoUpdateWorldState(WORLD_STATE_CRATES, 0); - DoSpawnChromieIfNeeded(); - m_uiRemoveCrateStateTimer = 0; + case NPC_FORRESTER: return m_uiForrestenGUID; + case NPC_JAMES: return m_uiJamesGUID; + case NPC_FRAS_FRASIABI: return m_uiFrasCiabiGUID; + case NPC_MAL_CORICS: return m_uiMalCoricsGUID; + case NPC_GRIAN_STONE: return m_uiGrianStoneGUID; + case NPC_ROGER: return m_uiRogerGUID; + case NPC_MORIGAN: return m_uiMoriganGUID; + case NPC_PERELLI: return m_uiPerelliGUID; + case NPC_JENA: return m_uiJenaGUID; + case NPC_MARTHA: return m_uiMarthaGUID; + case NPC_MALCOLM: return m_uiMalcolmGUID; + case NPC_DOG: return m_uiDogGUID; + case NPC_BARTLEBY: return m_uiBartlebyGUID; + case NPC_UTHER: return m_uiUtherGUID; + case NPC_ARTHAS: return m_uiArthasGUID; + case NPC_JAINA: return m_uiJainaGUID; + case NPC_SALRAMM: return m_uiSalrammGUID; + case NPC_MALGANIS: return m_uiMalganisGUID; + case GO_SHKAF_GATE: return m_uiShkafGateGUID; + case GO_MALGANIS_GATE1: return m_uiMalGate1GUID; + case GO_MALGANIS_GATE2: return m_uiMalGate2GUID; + case GO_MALGANIS_CHEST: return m_uiMalChestGUID; + case GO_EXIT: return m_uiExitGUID; } - else - m_uiRemoveCrateStateTimer -= uiDiff; + + return 0; } - // Respawn Arthas after some time - if (m_uiArthasRespawnTimer) + void Update(uint32 uiDiff) { - if (m_uiArthasRespawnTimer <= uiDiff) - { - DoSpawnArthasIfNeeded(); - m_uiArthasRespawnTimer = 0; - } - else - m_uiArthasRespawnTimer -= uiDiff; + if(m_auiEncounter[5] == IN_PROGRESS) + { + if(m_uiHeroicTimer < uiDiff) + { + m_auiEncounter[5] = FAIL; + DoUpdateWorldState(WORLD_STATE_COS_TIME_ON, 0); + if(Creature* Corruptor = instance->GetCreature(m_uiCorruptorGUID)) + Corruptor->SetPhaseMask(0, true); + + }else m_uiHeroicTimer -= uiDiff; + + if(m_uiHeroicTimer < m_uiLastTimer - 60000) + { + m_uiLastTimer = m_uiHeroicTimer; + uint32 tMinutes = m_uiHeroicTimer / 60000; + DoUpdateWorldState(WORLD_STATE_COS_TIME_COUNT, tMinutes); + } + } + + return; } -} +}; InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap) { @@ -576,10 +392,9 @@ InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap) void AddSC_instance_culling_of_stratholme() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "instance_culling_of_stratholme"; - pNewScript->GetInstanceData = &GetInstanceData_instance_culling_of_stratholme; - pNewScript->RegisterSelf(); + Script *newscript; + newscript = new Script; + newscript->Name = "instance_culling_of_stratholme"; + newscript->GetInstanceData = &GetInstanceData_instance_culling_of_stratholme; + newscript->RegisterSelf(); } diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/trash_culling_of_stratholme.cpp b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/trash_culling_of_stratholme.cpp new file mode 100644 index 0000000..60b8a88 --- /dev/null +++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/trash_culling_of_stratholme.cpp @@ -0,0 +1,1094 @@ +/* Copyright (C) 2006 - 2010 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_culling_of_stratholme +SD%Complete: ?% +SDComment: by MaxXx2021 +SDCategory: Culling of Stratholme +EndScriptData */ + +#include "precompiled.h" +#include "def_culling_of_stratholme.h" + +/*### +## npc_cs_gnoul +###*/ + +enum +{ + SPELL_FLESH = 52352 +}; + +struct MANGOS_DLL_DECL npc_cs_gnoulAI : public ScriptedAI +{ + npc_cs_gnoulAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 m_uiFleshTimer; + + uint32 WaypointId; + uint32 MoveTimer; + + void Reset() + { + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + MoveTimer = (urand(100, 5000)); + m_uiFleshTimer = (urand(3000, 10000)); + WaypointId = 1; + } + + void MoveToPoint(float X, float Y, float Z) + { + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, X, Y, Z); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + + if (IsCombatMovement()) + m_creature->GetMotionMaster()->MoveChase(pWho); + } + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + m_uiFleshTimer = (urand(3000, 10000)); + + m_creature->SetLootRecipient(NULL); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); + } + } + } + } + + void JumpNextStep(uint32 Time) + { + MoveTimer = Time; + WaypointId++; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() && m_creature->IsTemporarySummon()) + { + if(MoveTimer < uiDiff) + { + if(m_pInstance->GetData(TYPE_WING) == RIGHT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2356.659f, 1185.501f, 130.636f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2301.735f, 1179.265f, 136.944f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2234.787f, 1180.638f, 136.344f); + JumpNextStep(9000); + break; + case 4: + MoveToPoint(2178.313f, 1244.350f, 136.107f); + JumpNextStep(12000); + break; + case 5: + MoveToPoint(2163.553f, 1277.814f, 133.444f); + JumpNextStep(5000); + break; + case 6: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(5000); + break; + } + } + + if(m_pInstance->GetData(TYPE_WING) == LEFT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2188.318f, 1331.410f, 130.003f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2165.351f, 1279.156f, 133.388f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(9000); + break; + } + } + + } else MoveTimer -= uiDiff; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiFleshTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_FLESH); + m_uiFleshTimer = (urand(3000, 10000)); + } + else m_uiFleshTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +/*### +## npc_cs_necromancer +###*/ + +enum +{ + SPELL_SHADOW_BOLT = 15472, + SPELL_COURSE = 20812, + SPELL_DRAIN_MANA = 58770 +}; + +struct MANGOS_DLL_DECL npc_cs_necromancerAI : public ScriptedAI +{ + npc_cs_necromancerAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 m_uiShadowBoltTimer; + uint32 m_uiCourseTimer; + + uint32 WaypointId; + uint32 MoveTimer; + + void Reset() + { + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + MoveTimer = (urand(100, 5000)); + m_uiCourseTimer = (urand(7000, 17000)); + m_uiShadowBoltTimer = (urand(3000, 10000)); + WaypointId = 1; + } + + void Aggro(Unit* pWho) + { + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->StopMoving(); + } + + void MoveToPoint(float X, float Y, float Z) + { + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, X, Y, Z); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + } + m_creature->GetMotionMaster()->MovementExpired(false); + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + m_uiShadowBoltTimer = (urand(3000, 10000)); + m_uiCourseTimer = (urand(7000, 17000)); + + m_creature->SetLootRecipient(NULL); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); + } + } + } + } + + void JumpNextStep(uint32 Time) + { + MoveTimer = Time; + WaypointId++; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() && m_creature->IsTemporarySummon()) + { + if(MoveTimer < uiDiff) + { + if(m_pInstance->GetData(TYPE_WING) == RIGHT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2356.659f, 1185.501f, 130.636f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2301.735f, 1179.265f, 136.944f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2234.787f, 1180.638f, 136.344f); + JumpNextStep(9000); + break; + case 4: + MoveToPoint(2178.313f, 1244.350f, 136.107f); + JumpNextStep(12000); + break; + case 5: + MoveToPoint(2163.553f, 1277.814f, 133.444f); + JumpNextStep(5000); + break; + case 6: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(5000); + break; + } + } + + if(m_pInstance->GetData(TYPE_WING) == LEFT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2188.318f, 1331.410f, 130.003f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2165.351f, 1279.156f, 133.388f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(9000); + break; + } + } + + } else MoveTimer -= uiDiff; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiShadowBoltTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_SHADOW_BOLT); + m_uiShadowBoltTimer = (urand(3000, 5000)); + } + else m_uiShadowBoltTimer -= uiDiff; + + if(m_uiCourseTimer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(false); + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_COURSE); + m_uiCourseTimer = (urand(7000, 17000)); + } + else m_uiCourseTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +/*### +## npc_cs_field +###*/ + +enum +{ + SPELL_BLOW = 52491, + SPELL_SCARAB = 52496 +}; + +struct MANGOS_DLL_DECL npc_cs_fieldAI : public ScriptedAI +{ + npc_cs_fieldAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 m_uiScarabTimer; + uint32 m_uiBlowTimer; + + uint32 WaypointId; + uint32 MoveTimer; + + void Reset() + { + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + MoveTimer = (urand(100, 5000)); + m_uiBlowTimer = (urand(7000, 17000)); + m_uiScarabTimer = (urand(3000, 10000)); + WaypointId = 1; + } + + void MoveToPoint(float X, float Y, float Z) + { + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, X, Y, Z); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + + if (IsCombatMovement()) + m_creature->GetMotionMaster()->MoveChase(pWho); + } + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + m_uiScarabTimer = (urand(3000, 10000)); + m_uiBlowTimer = (urand(7000, 17000)); + + m_creature->SetLootRecipient(NULL); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); + } + } + } + } + + void JumpNextStep(uint32 Time) + { + MoveTimer = Time; + WaypointId++; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() && m_creature->IsTemporarySummon()) + { + if(MoveTimer < uiDiff) + { + if(m_pInstance->GetData(TYPE_WING) == RIGHT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2356.659f, 1185.501f, 130.636f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2301.735f, 1179.265f, 136.944f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2234.787f, 1180.638f, 136.344f); + JumpNextStep(9000); + break; + case 4: + MoveToPoint(2178.313f, 1244.350f, 136.107f); + JumpNextStep(12000); + break; + case 5: + MoveToPoint(2163.553f, 1277.814f, 133.444f); + JumpNextStep(5000); + break; + case 6: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(5000); + break; + } + } + + if(m_pInstance->GetData(TYPE_WING) == LEFT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2188.318f, 1331.410f, 130.003f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2165.351f, 1279.156f, 133.388f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(9000); + break; + } + } + + } else MoveTimer -= uiDiff; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiScarabTimer < uiDiff) + { + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_SCARAB); + m_uiScarabTimer = (urand(3000, 5000)); + } + else m_uiScarabTimer -= uiDiff; + + if(m_uiBlowTimer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(false); + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_BLOW); + m_uiBlowTimer = (urand(7000, 17000)); + } + else m_uiBlowTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +/*### +## npc_cs_alocyte +###*/ + +enum +{ + SPELL_SHADOW = 17234, + SPELL_COLD = 15244, + SPELL_FIRE = 14145, + SPELL_COURSEA = 39621 +}; + +struct MANGOS_DLL_DECL npc_cs_acolyteAI : public ScriptedAI +{ + npc_cs_acolyteAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 m_uiColdTimer; + uint32 m_uiFireTimer; + uint32 m_uiCourseTimer; + uint32 m_uiShadowTimer; + + uint32 WaypointId; + uint32 MoveTimer; + + void Reset() + { + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + MoveTimer = (urand(100, 5000)); + m_uiColdTimer = (urand(7000, 17000)); + m_uiFireTimer = (urand(3000, 10000)); + m_uiCourseTimer = (urand(5000, 12000)); + m_uiShadowTimer = (urand(1000, 3000)); + WaypointId = 1; + } + + void MoveToPoint(float X, float Y, float Z) + { + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, X, Y, Z); + } + + void Aggro(Unit* pWho) + { + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->StopMoving(); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + } + m_creature->GetMotionMaster()->MovementExpired(false); + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + m_uiColdTimer = (urand(7000, 17000)); + m_uiFireTimer = (urand(3000, 10000)); + m_uiCourseTimer = (urand(5000, 12000)); + m_uiShadowTimer = (urand(1000, 3000)); + + m_creature->SetLootRecipient(NULL); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); + } + } + } + } + + void JumpNextStep(uint32 Time) + { + MoveTimer = Time; + WaypointId++; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() && m_creature->IsTemporarySummon()) + { + if(MoveTimer < uiDiff) + { + if(m_pInstance->GetData(TYPE_WING) == RIGHT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2356.659f, 1185.501f, 130.636f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2301.735f, 1179.265f, 136.944f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2234.787f, 1180.638f, 136.344f); + JumpNextStep(9000); + break; + case 4: + MoveToPoint(2178.313f, 1244.350f, 136.107f); + JumpNextStep(12000); + break; + case 5: + MoveToPoint(2163.553f, 1277.814f, 133.444f); + JumpNextStep(5000); + break; + case 6: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(5000); + break; + } + } + + if(m_pInstance->GetData(TYPE_WING) == LEFT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2188.318f, 1331.410f, 130.003f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2165.351f, 1279.156f, 133.388f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(9000); + break; + } + } + + } else MoveTimer -= uiDiff; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiShadowTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_SHADOW); + m_uiShadowTimer = (urand(3000, 8000)); + } + else m_uiShadowTimer -= uiDiff; + + if(m_uiCourseTimer < uiDiff) + { + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_COURSEA); + m_uiCourseTimer = (urand(7000, 13000)); + } + else m_uiCourseTimer -= uiDiff; + + if(m_uiColdTimer < uiDiff) + { + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_COLD); + m_uiColdTimer = (urand(13000, 17000)); + } + else m_uiColdTimer -= uiDiff; + + if(m_uiFireTimer < uiDiff) + { + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, SPELL_FIRE); + m_uiFireTimer = (urand(6000, 11000)); + } + else m_uiFireTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +/*### +## npc_cs_butcher +###*/ + +enum +{ + SPELL_CLOUD = 52525 +}; + +struct MANGOS_DLL_DECL npc_cs_butcherAI : public ScriptedAI +{ + npc_cs_butcherAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 WaypointId; + uint32 MoveTimer; + + void Reset() + { + DoCast(m_creature, SPELL_CLOUD); + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + MoveTimer = (urand(100, 5000)); + WaypointId = 1; + } + + void MoveToPoint(float X, float Y, float Z) + { + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MovePoint(0, X, Y, Z); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + + if (IsCombatMovement()) + m_creature->GetMotionMaster()->MoveChase(pWho); + } + } + + void EnterEvadeMode() + { + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + + m_creature->SetLootRecipient(NULL); + DoCast(m_creature, SPELL_CLOUD); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (!m_creature->hasUnitState(UNIT_STAT_STUNNED) && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE) + return; + + float attackRadius = m_creature->GetAttackDistance(pWho); + if (m_creature->IsWithinDistInMap(pWho, attackRadius) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + AttackStart(pWho); + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + } + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 0.0f); + } + } + } + } + + void JumpNextStep(uint32 Time) + { + MoveTimer = Time; + WaypointId++; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() && m_creature->IsTemporarySummon()) + { + if(MoveTimer < uiDiff) + { + if(m_pInstance->GetData(TYPE_WING) == RIGHT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2356.659f, 1185.501f, 130.636f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2301.735f, 1179.265f, 136.944f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2234.787f, 1180.638f, 136.344f); + JumpNextStep(9000); + break; + case 4: + MoveToPoint(2178.313f, 1244.350f, 136.107f); + JumpNextStep(12000); + break; + case 5: + MoveToPoint(2163.553f, 1277.814f, 133.444f); + JumpNextStep(5000); + break; + case 6: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(5000); + break; + } + } + + if(m_pInstance->GetData(TYPE_WING) == LEFT) + { + switch(WaypointId) + { + case 1: + MoveToPoint(2188.318f, 1331.410f, 130.003f); + JumpNextStep(10000); + break; + case 2: + MoveToPoint(2165.351f, 1279.156f, 133.388f); + JumpNextStep(8000); + break; + case 3: + MoveToPoint(2083.952f, 1287.716f, 141.146f); + JumpNextStep(9000); + break; + } + } + + } else MoveTimer -= uiDiff; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + + return; + } +}; + +struct MANGOS_DLL_DECL npc_time_riftCSAI : public ScriptedAI +{ + npc_time_riftCSAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsHeroic = pCreature->GetMap()->IsRaidOrHeroicDungeon(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsHeroic; + + uint32 Step; + uint32 m_uiStepTimer; + Creature* Drakonian01; + Creature* Drakonian02; + Creature* Drakonian03; + + void Reset() + { + m_uiStepTimer = 1000; + Step = 1; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiStepTimer < uiDiff) + { + switch(Step) + { + case 1: + if (Creature* pArthas = m_pInstance->instance->GetCreature(m_pInstance->GetData64(NPC_ARTHAS))) + { + Drakonian01 = m_creature->SummonCreature(NPC_INFINITE_ADVERSARY,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000); + Drakonian01->GetMotionMaster()->MovePoint(0, pArthas->GetPositionX(), pArthas->GetPositionY(), pArthas->GetPositionZ()); + Drakonian02 = m_creature->SummonCreature(NPC_INFINITE_HUNTER,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000); + Drakonian02->GetMotionMaster()->MovePoint(0, pArthas->GetPositionX(), pArthas->GetPositionY(), pArthas->GetPositionZ()); + Drakonian03 = m_creature->SummonCreature(NPC_INFINITE_AGENT,(m_creature->GetPositionX()-2)+rand()%4, (m_creature->GetPositionY()-2)+rand()%4, m_creature->GetPositionZ(),3.229f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,900000); + Drakonian03->GetMotionMaster()->MovePoint(0, pArthas->GetPositionX(), pArthas->GetPositionY(), pArthas->GetPositionZ()); + } + m_uiStepTimer = 3000; + Step++; + break; + case 2: + m_creature->RemoveFromWorld(); + Step++; + break; + } + } else m_uiStepTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_cs_gnoul(Creature* pCreature) +{ + return new npc_cs_gnoulAI(pCreature); +} + +CreatureAI* GetAI_npc_cs_necromancer(Creature* pCreature) +{ + return new npc_cs_necromancerAI(pCreature); +} + +CreatureAI* GetAI_npc_cs_field(Creature* pCreature) +{ + return new npc_cs_fieldAI(pCreature); +} + +CreatureAI* GetAI_npc_cs_acolyte(Creature* pCreature) +{ + return new npc_cs_acolyteAI(pCreature); +} + +CreatureAI* GetAI_npc_cs_butcher(Creature* pCreature) +{ + return new npc_cs_butcherAI(pCreature); +} + +CreatureAI* GetAI_npc_time_riftCS(Creature* pCreature) +{ + return new npc_time_riftCSAI(pCreature); +} + +void AddSC_trash_culling_of_stratholme() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_cs_gnoul"; + newscript->GetAI = &GetAI_npc_cs_gnoul; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_cs_necromancer"; + newscript->GetAI = &GetAI_npc_cs_necromancer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_cs_field"; + newscript->GetAI = &GetAI_npc_cs_field; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_cs_acolyte"; + newscript->GetAI = &GetAI_npc_cs_acolyte; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_cs_butcher"; + newscript->GetAI = &GetAI_npc_cs_butcher; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_time_riftCS"; + newscript->GetAI = &GetAI_npc_time_riftCS; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/kalimdor/dire_maul/dire_maul.cpp b/scripts/kalimdor/dire_maul/dire_maul.cpp new file mode 100644 index 0000000..8ca88e1 --- /dev/null +++ b/scripts/kalimdor/dire_maul/dire_maul.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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: dire_maul +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Dire Maul +EndScriptData */ + +#include "precompiled.h" + +void AddSC_dire_maul() +{ +} diff --git a/scripts/kalimdor/dire_maul/dire_maul.h b/scripts/kalimdor/dire_maul/dire_maul.h index e69de29..e592de1 100644 --- a/scripts/kalimdor/dire_maul/dire_maul.h +++ b/scripts/kalimdor/dire_maul/dire_maul.h @@ -0,0 +1,3 @@ +/* Copyright (C) 2006 - 2010 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ diff --git a/scripts/kalimdor/moonglade.cpp b/scripts/kalimdor/moonglade.cpp index 4f08965..56f0ec3 100644 --- a/scripts/kalimdor/moonglade.cpp +++ b/scripts/kalimdor/moonglade.cpp @@ -72,6 +72,7 @@ bool GossipHello_npc_bunthen_plainswind(Player* pPlayer, Creature* pCreature) bool GossipSelect_npc_bunthen_plainswind(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { + pPlayer->PlayerTalkClass->ClearMenus(); switch(uiAction) { case GOSSIP_ACTION_INFO_DEF + 1: @@ -253,6 +254,7 @@ bool GossipHello_npc_great_bear_spirit(Player* pPlayer, Creature* pCreature) bool GossipSelect_npc_great_bear_spirit(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { + pPlayer->PlayerTalkClass->ClearMenus(); switch(uiAction) { case GOSSIP_ACTION_INFO_DEF: @@ -310,6 +312,7 @@ bool GossipHello_npc_silva_filnaveth(Player* pPlayer, Creature* pCreature) bool GossipSelect_npc_silva_filnaveth(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { + pPlayer->PlayerTalkClass->ClearMenus(); switch(uiAction) { case GOSSIP_ACTION_INFO_DEF + 1: diff --git a/scripts/kalimdor/the_barrens.cpp b/scripts/kalimdor/the_barrens.cpp index 163e43b..3f08e6f 100644 --- a/scripts/kalimdor/the_barrens.cpp +++ b/scripts/kalimdor/the_barrens.cpp @@ -467,15 +467,14 @@ CreatureAI* GetAI_npc_twiggy_flathead(Creature* pCreature) bool AreaTrigger_at_twiggy_flathead(Player* pPlayer, AreaTriggerEntry const* pAt) { - if (!pPlayer->isDead() && pPlayer->GetQuestStatus(QUEST_AFFRAY) == QUEST_STATUS_INCOMPLETE) - { - if (uint16 slot = pPlayer->FindQuestSlot(QUEST_AFFRAY)) - { - //we don't want player to start event if failed already. - if (pPlayer->GetQuestSlotState(slot) == QUEST_STATE_FAIL) - return true; - } + if (pPlayer->GetQuestStatus(QUEST_AFFRAY) == QUEST_STATUS_FAILED) + { + //we don't want player to start event if failed already. + return true; + } + else if (!pPlayer->isDead() && pPlayer->GetQuestStatus(QUEST_AFFRAY) == QUEST_STATUS_INCOMPLETE) + { Creature* pCreature = GetClosestCreatureWithEntry(pPlayer, NPC_TWIGGY, 30.0f); if (!pCreature) diff --git a/scripts/northrend/borean_tundra.cpp b/scripts/northrend/borean_tundra.cpp index 3ce5b28..aa44b97 100644 --- a/scripts/northrend/borean_tundra.cpp +++ b/scripts/northrend/borean_tundra.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: Borean_Tundra SD%Complete: 100 -SDComment: Quest support: 11708, 11692, 11961, 11865. Taxi vendors. 11570 +SDComment: Quest support: 11570, 11590, 11692, 11676, 11708, 11919, 11940, 11961. Taxi vendors. SDCategory: Borean Tundra EndScriptData */ @@ -30,10 +30,15 @@ go_caribou_trap npc_surristrasz npc_tiare npc_lurgglbr +npc_nexus_drake +go_scourge_cage +npc_beryl_sorcerer EndContentData */ #include "precompiled.h" #include "escort_ai.h" +#include "ObjectMgr.h" +#include "follower_ai.h" /*###### ## npc_fizzcrank_fullthrottle @@ -527,6 +532,215 @@ CreatureAI* GetAI_npc_lurgglbr(Creature* pCreature) return new npc_lurgglbrAI(pCreature); } +/*###### +## npc_nexus_drake_hatchling +######*/ + +enum +{ + SPELL_DRAKE_HARPOON = 46607, + SPELL_RED_DRAGONBLOOD = 46620, + SPELL_DRAKE_HATCHLING_SUBDUED = 46691, + SPELL_SUBDUED = 46675, + + NPC_RAELORASZ = 26117, + DRAKE_HUNT_KILL_CREDIT = 26175, + + QUEST_DRAKE_HUNT = 11919, + QUEST_DRAKE_HUNT_D = 11940 + +}; + +struct MANGOS_DLL_DECL npc_nexus_drakeAI : public FollowerAI +{ + npc_nexus_drakeAI(Creature* pCreature) : FollowerAI(pCreature) { Reset(); } + + uint64 uiHarpoonerGUID; + bool bWithRedDragonBlood; + bool bIsFollowing; + + void Reset() + { + bWithRedDragonBlood = false; + bIsFollowing = false; + } + + void EnterCombat(Unit* pWho) + { + AttackStart(pWho); + } + + void SpellHit(Unit* pCaster, SpellEntry const* pSpell) + { + if (pSpell->Id == SPELL_DRAKE_HARPOON && pCaster->GetTypeId() == TYPEID_PLAYER) + { + uiHarpoonerGUID = pCaster->GetGUID(); + DoCast(m_creature, SPELL_RED_DRAGONBLOOD, true); + } + m_creature->Attack(pCaster,true); + bWithRedDragonBlood = true; + } + + void MoveInLineOfSight(Unit *pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + + if (pWho->GetEntry() == NPC_RAELORASZ && m_creature->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) + { + if (Player *pHarpooner = m_creature->GetMap()->GetPlayer(uiHarpoonerGUID)) + { + + pHarpooner->KilledMonsterCredit(DRAKE_HUNT_KILL_CREDIT,m_creature->GetGUID()); + pHarpooner->RemoveAurasByCasterSpell(SPELL_DRAKE_HATCHLING_SUBDUED,uiHarpoonerGUID); + SetFollowComplete(); + uiHarpoonerGUID = 0; + m_creature->ForcedDespawn(1000); + } + + } + } + + void UpdateAI(const uint32 uidiff) + { + if (bWithRedDragonBlood && uiHarpoonerGUID && !m_creature->HasAura(SPELL_RED_DRAGONBLOOD)) + { + if (Player *pHarpooner = m_creature->GetMap()->GetPlayer(uiHarpoonerGUID)) + { + EnterEvadeMode(); + StartFollow(pHarpooner, 35, NULL); + + DoCast(m_creature, SPELL_SUBDUED, true); + pHarpooner->CastSpell(pHarpooner, SPELL_DRAKE_HATCHLING_SUBDUED, true); + + m_creature->AttackStop(); + bIsFollowing = true; + bWithRedDragonBlood = false; + } + } + if(bIsFollowing && !m_creature->HasAura(SPELL_SUBDUED)) + { + m_creature->ForcedDespawn(1000); + } + + if (!m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_nexus_drake(Creature* pCreature) +{ + return new npc_nexus_drakeAI(pCreature); +} + +/*##### +## go_scourge_cage +#####*/ + +enum +{ + QUEST_MERCIFUL_FREEDOM = 11676, + NPC_SCOURGE_PRISONER = 25610, +}; + +bool GOHello_go_scourge_cage(Player* pPlayer, GameObject* pGo) +{ + if (pPlayer->GetQuestStatus(QUEST_MERCIFUL_FREEDOM) == QUEST_STATUS_INCOMPLETE) + { + Creature *pCreature = GetClosestCreatureWithEntry(pGo, NPC_SCOURGE_PRISONER, INTERACTION_DISTANCE); + if(pCreature) + { + pPlayer->KilledMonsterCredit(NPC_SCOURGE_PRISONER, pCreature->GetGUID()); + pCreature->CastSpell(pCreature, 43014, false); + } + } + return false; +}; + +/*###### +## npc_beryl_sorcerer +######*/ + +enum eBerylSorcerer +{ + NPC_CAPTURED_BERLY_SORCERER = 25474, + NPC_LIBRARIAN_DONATHAN = 25262, + + SPELL_ARCANE_CHAINS = 45611, + SPELL_COSMETIC_CHAINS = 54324, + SPELL_COSMETIC_ENSLAVE_CHAINS_SELF = 45631 +}; + +struct MANGOS_DLL_DECL npc_beryl_sorcererAI : public FollowerAI +{ + npc_beryl_sorcererAI(Creature* pCreature) : FollowerAI(pCreature) { + Reset(); + m_uiNormalFaction = pCreature->getFaction(); + } + + bool bEnslaved; + uint64 uiChainerGUID; + uint32 m_uiNormalFaction; + + void Reset() + { + m_creature->setFaction(m_uiNormalFaction); + bEnslaved = false; + } + void EnterCombat(Unit* pWho) + { + AttackStart(pWho); + } + + void SpellHit(Unit* pCaster, SpellEntry const* pSpell) + { + if (pSpell->Id == SPELL_ARCANE_CHAINS && pCaster->GetTypeId() == TYPEID_PLAYER && !bEnslaved) + { + EnterEvadeMode(); //We make sure that the npc is not attacking the player! + m_creature->setFaction(35); + uiChainerGUID = pCaster->GetGUID(); + if(Player *pChainer = m_creature->GetMap()->GetPlayer(uiChainerGUID)) + { + StartFollow(pChainer, 35, NULL); + m_creature->UpdateEntry(NPC_CAPTURED_BERLY_SORCERER); + DoCast(m_creature, SPELL_COSMETIC_ENSLAVE_CHAINS_SELF, true); + + bEnslaved = true; + } + } + } + + void MoveInLineOfSight(Unit* pWho) + { + FollowerAI::MoveInLineOfSight(pWho); + + if (pWho->GetEntry() == NPC_LIBRARIAN_DONATHAN && m_creature->IsWithinDistInMap(pWho, INTERACTION_DISTANCE)) + { + if(Player *pChainer = m_creature->GetMap()->GetPlayer(uiChainerGUID)) + { + pChainer->KilledMonsterCredit(NPC_CAPTURED_BERLY_SORCERER,m_creature->GetGUID()); + SetFollowComplete(); + m_creature->ForcedDespawn(1000); + } + } + } + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_npc_beryl_sorcerer(Creature* pCreature) +{ + return new npc_beryl_sorcererAI(pCreature); +} + void AddSC_borean_tundra() { Script *newscript; @@ -576,4 +790,19 @@ void AddSC_borean_tundra() newscript->GetAI = &GetAI_npc_lurgglbr; newscript->pQuestAccept = &QuestAccept_npc_lurgglbr; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_nexus_drake"; + newscript->GetAI = &GetAI_npc_nexus_drake; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_scourge_cage"; + newscript->pGOHello = &GOHello_go_scourge_cage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_beryl_sorcerer"; + newscript->GetAI = &GetAI_npc_beryl_sorcerer; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp new file mode 100644 index 0000000..85c0a4c --- /dev/null +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp @@ -0,0 +1,434 @@ +/* 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_argent_challenge +SD%Complete: 50% +SDComment: missing yells. radiance is "wrong". modified by /dev/rsa +SDCategory: Trial Of the Champion +EndScriptData */ + +#include "precompiled.h" +#include "trial_of_the_champion.h" + +enum +{ + SPELL_BERSERK = 47008, + //yells + + //eadric + SPELL_VENGEANCE = 66889, + SPELL_RADIANCE = 66862, + SPELL_RADIANCE_H = 67681, + SPELL_HAMMER_OF_JUSTICE = 66940, + SPELL_HAMMER = 67680, + //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 = 66547, + //memory + SPELL_FEAR = 66552, + SPELL_FEAR_H = 67677, + SPELL_SHADOWS = 66619, + SPELL_SHADOWS_H = 67678, + SPELL_OLD_WOUNDS = 66620, + SPELL_OLD_WOUNDS_H = 67679, +}; + +// Eadric The Pure +struct MANGOS_DLL_DECL boss_eadricAI : public ScriptedAI +{ + boss_eadricAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Vengeance_Timer; + uint32 Radiance_Timer; + uint32 Hammer_Timer; + uint32 Hammer_Dmg_Timer; + uint32 m_uiBerserk_Timer; + uint64 HammerTarget; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + Vengeance_Timer = 1000; + Radiance_Timer = m_bIsRegularMode ? 15000 : 8000; + Hammer_Timer = m_bIsRegularMode ? 40000 : 10000; + Hammer_Dmg_Timer = m_bIsRegularMode ? 45000 : 20000; + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + HammerTarget = 0; + m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) + return; + if (m_pInstance->GetData(TYPE_ARGENT_CHALLENGE) != DONE) + m_pInstance->SetData(TYPE_ARGENT_CHALLENGE, IN_PROGRESS); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + m_pInstance->SetData(TYPE_ARGENT_CHALLENGE, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Vengeance_Timer < diff) + { + DoCast(m_creature, SPELL_VENGEANCE); + Vengeance_Timer = m_bIsRegularMode ? 12000 : 8000; + }else Vengeance_Timer -= diff; + + if (Radiance_Timer < diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_RADIANCE : SPELL_RADIANCE_H); + Radiance_Timer = m_bIsRegularMode ? 20000 : 12000; + }else Radiance_Timer -= diff; + + if (Hammer_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + { + DoCast(target, SPELL_HAMMER_OF_JUSTICE); + HammerTarget = target->GetGUID(); + } + Hammer_Timer = m_bIsRegularMode ? 40000 : 15000; + }else Hammer_Timer -= diff; + + if (Hammer_Dmg_Timer < diff) + { + if (Unit* pHammerTarget = m_creature->GetMap()->GetUnit(HammerTarget)) + DoCast(pHammerTarget, SPELL_HAMMER); + Hammer_Dmg_Timer = m_bIsRegularMode ? 50000 : 15000; + } + else Hammer_Dmg_Timer -= diff; + + if (m_uiBerserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + } + else m_uiBerserk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_eadric(Creature* pCreature) +{ + return new boss_eadricAI(pCreature); +} + +// Argent Confessor Paletress +struct MANGOS_DLL_DECL boss_paletressAI : public ScriptedAI +{ + boss_paletressAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Smite_Timer; + uint32 Holy_Fire_Timer; + uint32 Renew_Timer; + uint32 Shield_Delay; + uint32 Shield_Check; + uint32 m_uiBerserk_Timer; + bool summoned; + bool shielded; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + m_creature->RemoveAurasDueToSpell(SPELL_SHIELD); + Smite_Timer = 5000; + Holy_Fire_Timer = m_bIsRegularMode ? 10000 : 8000; + Renew_Timer = m_bIsRegularMode ? 7000 : 5000; + Shield_Delay = 0; + Shield_Check = 1000; + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + summoned = false; + shielded = false; + m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + + void JustSummoned(Creature* _summoned) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + _summoned->AddThreat(target); + summoned = true; + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) + return; + if (m_pInstance->GetData(TYPE_ARGENT_CHALLENGE) != DONE) + m_pInstance->SetData(TYPE_ARGENT_CHALLENGE, IN_PROGRESS); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + m_pInstance->SetData(TYPE_ARGENT_CHALLENGE, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Smite_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); + Smite_Timer = 2000; + }else Smite_Timer -= diff; + + if (Holy_Fire_Timer < diff) + { + m_creature->CastStop(m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsRegularMode ? SPELL_HOLY_FIRE : SPELL_HOLY_FIRE_H); + Holy_Fire_Timer = m_bIsRegularMode ? 10000 : 7000; + }else Holy_Fire_Timer -= diff; + + if (Renew_Timer < diff) + { + m_creature->CastStop(m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); + m_creature->CastStop(m_bIsRegularMode ? SPELL_HOLY_FIRE : SPELL_HOLY_FIRE_H); + switch(urand(0, 1)) + { + case 0: + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_MEMORY)))) + if (pTemp->isAlive()) + DoCast(pTemp, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H); + else + DoCast(m_creature, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H); + break; + case 1: + DoCast(m_creature, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H); + break; + } + Renew_Timer = 25000; + }else Renew_Timer -= diff; + + if (((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 35 ) && !summoned ) + { + m_creature->CastStop(m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); + m_creature->CastStop(m_bIsRegularMode ? SPELL_HOLY_FIRE : SPELL_HOLY_FIRE_H); + DoCast(m_creature, SPELL_HOLY_NOVA); + switch(urand(0, 24)) + { + case 0: m_creature->SummonCreature(MEMORY_ALGALON, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 1: m_creature->SummonCreature(MEMORY_CHROMAGGUS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 2: m_creature->SummonCreature(MEMORY_CYANIGOSA, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 3: m_creature->SummonCreature(MEMORY_DELRISSA, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 4: m_creature->SummonCreature(MEMORY_ECK, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 5: m_creature->SummonCreature(MEMORY_ENTROPIUS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 6: m_creature->SummonCreature(MEMORY_GRUUL, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 7: m_creature->SummonCreature(MEMORY_HAKKAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 8: m_creature->SummonCreature(MEMORY_HEIGAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 9: m_creature->SummonCreature(MEMORY_HEROD, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 10: m_creature->SummonCreature(MEMORY_HOGGER, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 11: m_creature->SummonCreature(MEMORY_IGNIS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 12: m_creature->SummonCreature(MEMORY_ILLIDAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 13: m_creature->SummonCreature(MEMORY_INGVAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 14: m_creature->SummonCreature(MEMORY_KALITHRESH, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 15: m_creature->SummonCreature(MEMORY_LUCIFRON, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 16: m_creature->SummonCreature(MEMORY_MALCHEZAAR, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 17: m_creature->SummonCreature(MEMORY_MUTANUS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 18: m_creature->SummonCreature(MEMORY_ONYXIA, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 19: m_creature->SummonCreature(MEMORY_THUNDERAAN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 20: m_creature->SummonCreature(MEMORY_VANCLEEF, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 21: m_creature->SummonCreature(MEMORY_VASHJ, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 22: m_creature->SummonCreature(MEMORY_VEKNILASH, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 23: m_creature->SummonCreature(MEMORY_VEZAX, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + case 24: m_creature->SummonCreature(MEMORY_ARCHIMONDE, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + break; + + } + Shield_Delay = 1000; + }; + if (Shield_Delay < diff && !shielded && summoned) + { + m_creature->CastStop(m_bIsRegularMode ? SPELL_SMITE : SPELL_SMITE_H); + m_creature->CastStop(m_bIsRegularMode ? SPELL_HOLY_FIRE : SPELL_HOLY_FIRE_H); + DoCast(m_creature, SPELL_SHIELD); + shielded = true; + Shield_Check = m_bIsRegularMode ? 3000 : 5000; + }else Shield_Delay -= diff; + + if (Shield_Check < diff && shielded) + { + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_MEMORY)))) + if (!pTemp->isAlive()) + { + m_creature->RemoveAurasDueToSpell(SPELL_SHIELD); + shielded = false; + } else Shield_Check = 1000; + }else Shield_Check -= diff; + + if (m_uiBerserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + } + else m_uiBerserk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_paletress(Creature* pCreature) +{ + return new boss_paletressAI(pCreature); +} + +// Summoned Memory +struct MANGOS_DLL_DECL mob_toc5_memoryAI : public ScriptedAI +{ + mob_toc5_memoryAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Old_Wounds_Timer; + uint32 Shadows_Timer; + uint32 Fear_Timer; + + void Reset() + { + Old_Wounds_Timer = 5000; + Shadows_Timer = 8000; + Fear_Timer = 13000; + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Old_Wounds_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsRegularMode ? SPELL_OLD_WOUNDS : SPELL_OLD_WOUNDS_H); + Old_Wounds_Timer = 10000; + }else Old_Wounds_Timer -= diff; + + if (Fear_Timer < diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_FEAR : SPELL_FEAR_H); + Fear_Timer = 40000; + }else Fear_Timer -= diff; + + if (Shadows_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) + DoCast(target, m_bIsRegularMode ? SPELL_SHADOWS : SPELL_SHADOWS_H); + Shadows_Timer = 10000; + }else Shadows_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_toc5_memory(Creature* pCreature) +{ + return new mob_toc5_memoryAI(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 = "mob_toc5_memory"; + NewScript->GetAI = &GetAI_mob_toc5_memory; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp new file mode 100644 index 0000000..ef1b990 --- /dev/null +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp @@ -0,0 +1,311 @@ +/* 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_black_knight +SD%Complete: 70% +SDComment: missing yells. not sure about timers. modified by /dev/rsa +SDCategory: Trial Of the Champion +EndScriptData */ + +#include "precompiled.h" +#include "trial_of_the_champion.h" + +enum +{ + SPELL_BERSERK = 47008, + //yells + + //undead + SPELL_PLAGUE_STRIKE = 67724, + SPELL_PLAGUE_STRIKE_H = 67884, + SPELL_ICY_TOUCH = 67718, + SPELL_ICY_TOUCH_H = 67881, + SPELL_OBLITERATE = 67725, + SPELL_OBLITERATE_H = 67883, + SPELL_CHOKE = 68306, + //skeleton + SPELL_ARMY = 42650, //replacing original one, since that one spawns millions of ghouls!! + //ghost + SPELL_DEATH = 67808, + SPELL_DEATH_H = 67875, + SPELL_MARK = 67823, + + //risen ghoul + SPELL_CLAW = 67879, + SPELL_EXPLODE = 67729, + SPELL_EXPLODE_H = 67886, + SPELL_LEAP = 67749, + SPELL_LEAP_H = 67880, + + //sword ID + EQUIP_SWORD = 40343 +}; + +// Risen Ghoul +struct MANGOS_DLL_DECL mob_toc5_risen_ghoulAI : public ScriptedAI +{ + mob_toc5_risen_ghoulAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Attack; + + void Reset() + { + Attack = 2500; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Attack < diff) + { + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_BLACK_KNIGHT)))) + if (pTemp->isAlive()) + if ((pTemp->GetHealth()*100 / pTemp->GetMaxHealth()) < 25) + DoCast(m_creature, m_bIsRegularMode ? SPELL_EXPLODE : SPELL_EXPLODE_H); + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 4)) + { + DoCast(m_creature->getVictim(), SPELL_CLAW); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) + m_creature->AI()->AttackStart(target); + Attack = 2500; + }else + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 30)) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_LEAP : SPELL_LEAP_H); + Attack = 2500; + } + }else Attack -= diff; + + if ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 25) + DoCast(m_creature, m_bIsRegularMode ? SPELL_EXPLODE : SPELL_EXPLODE_H); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_toc5_risen_ghoul(Creature* pCreature) +{ + return new mob_toc5_risen_ghoulAI(pCreature); +} + +// The Black Knight +struct MANGOS_DLL_DECL boss_black_knightAI : public ScriptedAI +{ + boss_black_knightAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Plague_Strike_Timer; + uint32 Icy_Touch_Timer; + uint32 Obliterate_Timer; + uint32 Choke_Timer; + uint32 Death_Timer; + uint32 Mark_Timer; + uint32 Phase_Delay; + uint32 Summon_Ghoul; + uint32 m_uiBerserk_Timer; + bool phase1; + bool phase2; + bool phase3; + bool ghoul; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + m_creature->SetDisplayId(29837); + SetEquipmentSlots(false, EQUIP_SWORD, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + Plague_Strike_Timer = m_bIsRegularMode ? 5000 : 4000; + Icy_Touch_Timer = m_bIsRegularMode ? 10000 : 7000; + Obliterate_Timer = m_bIsRegularMode ? 16000 : 10000; + Choke_Timer = 15000; + Summon_Ghoul = 4000; + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + phase1 = true; + phase2 = false; + phase3 = false; + ghoul = false; + m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + + + void Aggro(Unit* pWho) + { + if (!m_pInstance) + return; + if (m_pInstance->GetData(TYPE_BLACK_KNIGHT) != DONE) + m_pInstance->SetData(TYPE_BLACK_KNIGHT, IN_PROGRESS); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if ((uiDamage > m_creature->GetHealth() || + m_creature->GetHealth()/m_creature->GetHealth() <= 0.1 ) && !phase3){ + uiDamage = 0; + if (phase2) + StartPhase3(); + if (phase1) + StartPhase2(); + } + } + + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + if (phase3 && !phase1 && !phase2) + { + m_pInstance->SetData(TYPE_BLACK_KNIGHT, DONE); + } +/* if (phase2 && !phase1 && !phase3) + if (!m_creature->isAlive()) + { + m_creature->Respawn(); + StartPhase3(); + } + if (phase1 && !phase2 && !phase3) + if (!m_creature->isAlive()) + { + m_creature->Respawn(); + StartPhase2(); + }*/ + } + + void StartPhase2() + { + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetDisplayId(27550); + phase1 = false; + phase2 = true; + phase3 = false; + DoCast(m_creature, SPELL_ARMY); + Plague_Strike_Timer = m_bIsRegularMode ? 14000 : 8000; + Icy_Touch_Timer = m_bIsRegularMode ? 12000 : 7000; + Obliterate_Timer = m_bIsRegularMode ? 18000 : 10000; + } + + void StartPhase3() + { + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetDisplayId(14560); + SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + phase1 = false; + phase2 = false; + phase3 = true; + Death_Timer = m_bIsRegularMode ? 5000 : 3000; + Mark_Timer = m_bIsRegularMode ? 9000 : 7000; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Plague_Strike_Timer < diff && !phase3) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_PLAGUE_STRIKE : SPELL_PLAGUE_STRIKE_H); + Plague_Strike_Timer = m_bIsRegularMode ? 10500 : 7000; + }else Plague_Strike_Timer -= diff; + + if (Icy_Touch_Timer < diff && !phase3) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ICY_TOUCH : SPELL_ICY_TOUCH_H); + Icy_Touch_Timer = m_bIsRegularMode ? 10000 : 8000; + }else Icy_Touch_Timer -= diff; + + if (Obliterate_Timer < diff && !phase3) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_OBLITERATE : SPELL_OBLITERATE_H); + Obliterate_Timer = m_bIsRegularMode ? 11000 : 8000; + }else Obliterate_Timer -= diff; + + if (Choke_Timer < diff && phase1) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) + DoCast(m_creature->getVictim(), SPELL_CHOKE); + Choke_Timer = m_bIsRegularMode ? 15000 : 10000; + }else Choke_Timer -= diff; + + if (Summon_Ghoul < diff && phase1 && !ghoul) + { + if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == m_pInstance->GetData(DATA_JAEREN)) + m_creature->SummonCreature(NPC_RISEN_JAEREN, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + else + m_creature->SummonCreature(NPC_RISEN_ARELAS, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000); + ghoul = true; + }else Summon_Ghoul -= diff; + + if (Mark_Timer < diff && phase3) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) + DoCast(target, SPELL_MARK); + Mark_Timer = m_bIsRegularMode ? 15000 : 10000; + }else Mark_Timer -= diff; + + if (Death_Timer < diff && phase3) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_DEATH : SPELL_DEATH_H); + Death_Timer = 3500; + }else Death_Timer -= diff; + + if (m_uiBerserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + } + else m_uiBerserk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_black_knight(Creature* pCreature) +{ + return new boss_black_knightAI(pCreature); +} + +void AddSC_boss_black_knight() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "mob_toc5_risen_ghoul"; + NewScript->GetAI = &GetAI_mob_toc5_risen_ghoul; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_black_knight"; + NewScript->GetAI = &GetAI_boss_black_knight; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp index f54a2a9..f986fc4 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp @@ -1,5 +1,5 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 - * This program is free software; you can redistribute it and/or modify +/* 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. @@ -15,11 +15,734 @@ */ /* ScriptData -SDName: grand_champions -SD%Complete: 0 -SDComment: -SDCategory: Crusader Coliseum, Trial of the Champion +SDName: boss_grand_champions +SD%Complete: 70% +SDComment: missing yells. hunter AI sucks. no pvp diminuishing returns(is it DB related?). modified by /dev/rsa +SDCategory: Trial Of the Champion EndScriptData */ #include "precompiled.h" #include "trial_of_the_champion.h" + +enum +{ + //common + SPELL_BERSERK = 47008, + //yells + //warrior + SPELL_MORTAL_STRIKE = 68783, + SPELL_MORTAL_STRIKE_H = 68784, + SPELL_BLADESTORM = 63784, + SPELL_INTERCEPT = 67540, + SPELL_ROLLING_THROW = 47115, //need core support for spell 67546, using 47115 instead + //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, + //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, + //hunter + SPELL_DISENGAGE = 68340, + SPELL_LIGHTNING_ARROWS = 66083, + SPELL_MULTI_SHOT = 66081, + SPELL_SHOOT = 66079, + //rogue + SPELL_EVISCERATE = 67709, + SPELL_EVISCERATE_H = 68317, + SPELL_FAN_OF_KNIVES = 67706, + SPELL_POISON_BOTTLE = 67701 +}; + +// Warrior +struct MANGOS_DLL_DECL mob_toc5_warriorAI : public ScriptedAI +{ + mob_toc5_warriorAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Mortal_Strike_Timer; + uint32 Bladestorm_Timer; + uint32 Rolling_Throw_Timer; + uint32 Intercept_Cooldown; + uint32 intercept_check; + uint32 m_uiBerserk_Timer; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + Mortal_Strike_Timer = m_bIsRegularMode ? 9000 : 6000; + Bladestorm_Timer = m_bIsRegularMode ? 30000 : 20000; + Rolling_Throw_Timer = m_bIsRegularMode ? 45000 : 30000; + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + Intercept_Cooldown = 0; + intercept_check = 1000; + m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + + } + + + void Aggro(Unit* pWho) + { + if (!m_pInstance) + return; + else + { + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); +// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + } + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + + m_pInstance->SetData(DATA_CHAMPIONS_COUNT, m_pInstance->GetData(DATA_CHAMPIONS_COUNT) - 1); + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Mortal_Strike_Timer < diff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_MORTAL_STRIKE : SPELL_MORTAL_STRIKE_H); + Mortal_Strike_Timer = m_bIsRegularMode ? 6000 : 4000; + }else Mortal_Strike_Timer -= diff; + + if (Rolling_Throw_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_ROLLING_THROW); + Rolling_Throw_Timer = m_bIsRegularMode ? 30000 : 15000; + }else Rolling_Throw_Timer -= diff; + + if (Bladestorm_Timer < diff) + { + DoCast(m_creature, SPELL_BLADESTORM); + Bladestorm_Timer = m_bIsRegularMode ? 60000 : 20000; + }else Bladestorm_Timer -= diff; + + if (intercept_check < diff) + { + if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 8) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 25) && Intercept_Cooldown < diff) + { + DoCast(m_creature->getVictim(), SPELL_INTERCEPT); + Intercept_Cooldown = m_bIsRegularMode ? 15000 : 10000; + } + intercept_check = 1000; + } + else + { + intercept_check -= diff; + Intercept_Cooldown -= diff; + } + if (m_uiBerserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + } + else m_uiBerserk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_toc5_warrior(Creature* pCreature) +{ + return new mob_toc5_warriorAI(pCreature); +} + +// Mage +struct MANGOS_DLL_DECL mob_toc5_mageAI : public ScriptedAI +{ + mob_toc5_mageAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Fireball_Timer; + uint32 Blast_Wave_Timer; + uint32 Haste_Timer; + uint32 Polymorph_Timer; + uint32 m_uiBerserk_Timer; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + Fireball_Timer = 0; + Blast_Wave_Timer = m_bIsRegularMode ? 20000 : 12000; + Haste_Timer = m_bIsRegularMode ? 12000 : 9000; + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + Polymorph_Timer = m_bIsRegularMode ? 12000 : 10000; + m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) + return; + else + { + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); +// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + } + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + + m_pInstance->SetData(DATA_CHAMPIONS_COUNT, m_pInstance->GetData(DATA_CHAMPIONS_COUNT) - 1); + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Fireball_Timer < diff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FIREBALL : SPELL_FIREBALL_H); + Fireball_Timer = m_bIsRegularMode ? 5000 : 3000; + }else Fireball_Timer -= diff; + + if (Blast_Wave_Timer < diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_BLAST_WAVE : SPELL_BLAST_WAVE_H); + Blast_Wave_Timer = m_bIsRegularMode ? 20000 : 12000; + }else Blast_Wave_Timer -= diff; + + if (Haste_Timer < diff) + { + DoCast(m_creature, SPELL_HASTE); + Haste_Timer = m_bIsRegularMode ? 10000 : 8000; + }else Haste_Timer -= diff; + + if (Polymorph_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(target, m_bIsRegularMode ? SPELL_POLYMORPH : SPELL_POLYMORPH_H); + Polymorph_Timer = m_bIsRegularMode ? 20000 : 15000; + }else Polymorph_Timer -= diff; + + if (m_uiBerserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + } + else m_uiBerserk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_toc5_mage(Creature* pCreature) +{ + return new mob_toc5_mageAI(pCreature); +} + +// Shaman +struct MANGOS_DLL_DECL mob_toc5_shamanAI : public ScriptedAI +{ + mob_toc5_shamanAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Chain_Lightning_Timer; + uint32 Earth_Shield_Timer; + uint32 Healing_Wave_Timer; + uint32 Hex_Timer; + + float mob1_health; + float mob2_health; + float mob3_health; + uint32 m_uiBerserk_Timer; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + Chain_Lightning_Timer = m_bIsRegularMode ? 2000 : 1000; + Earth_Shield_Timer = m_bIsRegularMode ? 10000 : 5000; + Healing_Wave_Timer = m_bIsRegularMode ? 20000 : 12000; + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + Hex_Timer = m_bIsRegularMode ? 15000 : 10000; + m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) + return; + else + { + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); +// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + } + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + + m_pInstance->SetData(DATA_CHAMPIONS_COUNT, m_pInstance->GetData(DATA_CHAMPIONS_COUNT) - 1); + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Chain_Lightning_Timer < diff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H); + Chain_Lightning_Timer = m_bIsRegularMode ? 12000 : 8000; + }else Chain_Lightning_Timer -= diff; + + if (Hex_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_HEX_OF_MENDING); + Hex_Timer = m_bIsRegularMode ? 30000 : 20000; + }else Hex_Timer -= diff; + + if (Healing_Wave_Timer < diff) + { + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + if (pTemp->isAlive()) + mob1_health = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); + else + mob1_health = 100; + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + if (pTemp->isAlive()) + mob2_health = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); + else + mob2_health = 100; + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + if (pTemp->isAlive()) + mob3_health = pTemp->GetHealth()*100 / pTemp->GetMaxHealth(); + else + mob3_health = 100; + if (mob1_health < mob2_health && mob1_health < mob3_health && mob1_health < 70) + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + DoCast(pTemp, m_bIsRegularMode ? SPELL_HEALING_WAVE : SPELL_HEALING_WAVE_H); + if (mob1_health > mob2_health && mob2_health < mob3_health && mob2_health < 70) + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + DoCast(pTemp, m_bIsRegularMode ? SPELL_HEALING_WAVE : SPELL_HEALING_WAVE_H); + if (mob3_health < mob2_health && mob1_health > mob3_health && mob3_health < 70) + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + DoCast(pTemp, m_bIsRegularMode ? SPELL_HEALING_WAVE : SPELL_HEALING_WAVE_H); + Healing_Wave_Timer = m_bIsRegularMode ? 8000 : 6000; + }else Healing_Wave_Timer -= diff; + + if (Earth_Shield_Timer < diff) + { + switch(urand(0, 2)) + { + case 0: + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + if (pTemp->isAlive()) + DoCast(pTemp, SPELL_EARTH_SHIELD); + else + DoCast(m_creature, SPELL_EARTH_SHIELD); + break; + case 1: + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + if (pTemp->isAlive()) + DoCast(pTemp, SPELL_EARTH_SHIELD); + else + DoCast(m_creature, SPELL_EARTH_SHIELD); + break; + case 2: + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + if (pTemp->isAlive()) + DoCast(pTemp, SPELL_EARTH_SHIELD); + else + DoCast(m_creature, SPELL_EARTH_SHIELD); + break; + } + Earth_Shield_Timer = m_bIsRegularMode ? 35000 : 25000; + }else Earth_Shield_Timer -= diff; + + if (m_uiBerserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + } + else m_uiBerserk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_toc5_shaman(Creature* pCreature) +{ + return new mob_toc5_shamanAI(pCreature); +} + +// Hunter +struct MANGOS_DLL_DECL mob_toc5_hunterAI : public ScriptedAI +{ + mob_toc5_hunterAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Shoot_Timer; + uint32 Lightning_Arrows_Timer; + uint32 Multi_Shot_Timer; + uint32 Disengage_Cooldown; + uint32 enemy_check; + uint32 disengage_check; + uint32 m_uiBerserk_Timer; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + Shoot_Timer = 0; + Lightning_Arrows_Timer = m_bIsRegularMode ? 18000 : 10000; + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + Multi_Shot_Timer = m_bIsRegularMode ? 15000 : 8000; + Disengage_Cooldown = 0; + enemy_check = 1000; + disengage_check; + m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) + return; + else + { + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); +// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + } + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + + m_pInstance->SetData(DATA_CHAMPIONS_COUNT, m_pInstance->GetData(DATA_CHAMPIONS_COUNT) - 1); + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (enemy_check < diff) + { + if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 8) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 30)) + { + m_creature->SetSpeedRate(MOVE_RUN, 0.0001); + } + else + { + m_creature->SetSpeedRate(MOVE_RUN, 1.2); + } + enemy_check = 100; + }else enemy_check -= diff; + + if (Disengage_Cooldown>0) + Disengage_Cooldown -= diff; + + if (Shoot_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SHOOT); + Shoot_Timer = m_bIsRegularMode ? 5000 : 3000; + }else Shoot_Timer -= diff; + + if (Multi_Shot_Timer < diff) + { + m_creature->CastStop(SPELL_SHOOT); + DoCast(m_creature->getVictim(), SPELL_MULTI_SHOT); + Multi_Shot_Timer = m_bIsRegularMode ? 10000 : 5000; + }else Multi_Shot_Timer -= diff; + + if (Lightning_Arrows_Timer < diff) + { + m_creature->CastStop(SPELL_SHOOT); + DoCast(m_creature, SPELL_LIGHTNING_ARROWS); + Lightning_Arrows_Timer = m_bIsRegularMode ? 15000 : 8000; + }else Lightning_Arrows_Timer -= diff; + + if (disengage_check < diff) + { + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 5) && Disengage_Cooldown == 0) + { + DoCast(m_creature, SPELL_DISENGAGE); + Disengage_Cooldown = m_bIsRegularMode ? 15000 : 10000; + } + disengage_check = 1000; + }else disengage_check -= diff; + + if (m_uiBerserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + } + else m_uiBerserk_Timer -= diff; + + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_toc5_hunter(Creature* pCreature) +{ + return new mob_toc5_hunterAI(pCreature); +} + +// Rogue +struct MANGOS_DLL_DECL mob_toc5_rogueAI : public ScriptedAI +{ + mob_toc5_rogueAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Eviscerate_Timer; + uint32 FoK_Timer; + uint32 Poison_Timer; + uint32 m_uiBerserk_Timer; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + Eviscerate_Timer = m_bIsRegularMode ? 20000 : 10000; + FoK_Timer = m_bIsRegularMode ? 15000 : 10000; + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + Poison_Timer = m_bIsRegularMode ? 12000 : 5000; + m_creature->GetMotionMaster()->MovePoint(0, 746, 614, m_creature->GetPositionZ()); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) + return; + else + { + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); +// m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + } + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + + m_pInstance->SetData(DATA_CHAMPIONS_COUNT, m_pInstance->GetData(DATA_CHAMPIONS_COUNT) - 1); + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + if (m_pInstance->GetData(DATA_CHAMPIONS_COUNT) < 1) { + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, DONE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_1)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_2)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (Creature* pTemp = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_CHAMPION_3)))) + pTemp->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Eviscerate_Timer < diff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_EVISCERATE : SPELL_EVISCERATE_H); + Eviscerate_Timer = m_bIsRegularMode ? 15000 : 10000; + }else Eviscerate_Timer -= diff; + + if (FoK_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_FAN_OF_KNIVES); + FoK_Timer = m_bIsRegularMode ? 12000 : 7000; + }else FoK_Timer -= diff; + + if (Poison_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) + DoCast(m_creature, SPELL_POISON_BOTTLE); + Poison_Timer = m_bIsRegularMode ? 10000 : 5000; + }else Poison_Timer -= diff; + + if (m_uiBerserk_Timer < diff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = m_bIsRegularMode ? 300000 : 180000; + } + else m_uiBerserk_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_toc5_rogue(Creature* pCreature) +{ + return new mob_toc5_rogueAI(pCreature); +} + +void AddSC_boss_grand_champions() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "mob_toc5_warrior"; + NewScript->GetAI = &GetAI_mob_toc5_warrior; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_toc5_mage"; + NewScript->GetAI = &GetAI_mob_toc5_mage; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_toc5_shaman"; + NewScript->GetAI = &GetAI_mob_toc5_shaman; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_toc5_hunter"; + NewScript->GetAI = &GetAI_mob_toc5_hunter; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_toc5_rogue"; + NewScript->GetAI = &GetAI_mob_toc5_rogue; + NewScript->RegisterSelf(); +} diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp index 6fc6932..f6c756f 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp @@ -1,31 +1,555 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_trial_of_the_champion -SD%Complete: 0 -SDComment: -SDCategory: Crusader Coliseum, Trial of the Champion +SDName: Instance_Trial_Of_the_Champion +SD%Complete: 70 +SDComment: modified by /dev/rsa +SDCategory: Trial Of the Champion EndScriptData */ #include "precompiled.h" #include "trial_of_the_champion.h" +#include "World.h" -/* Trial of the Champion encounters: -0 - Grand Champions -1 - Argent Champion -2 - Black Knight -*/ +enum PhaseControl +{ + HORDE_CONTROL_PHASE_SHIFT_1 = 55773, + HORDE_CONTROL_PHASE_SHIFT_2 = 60028, + ALLIANCE_CONTROL_PHASE_SHIFT_1 = 55774, + ALLIANCE_CONTROL_PHASE_SHIFT_2 = 60027, +}; +struct MANGOS_DLL_DECL instance_trial_of_the_champion : public ScriptedInstance +{ + instance_trial_of_the_champion(Map* pMap) : ScriptedInstance(pMap) { Initialize(); } + + uint32 m_auiEncounter[MAX_ENCOUNTER+1]; + + std::string m_strInstData; + + uint64 m_uiJacobGUID; + uint64 m_uiAmbroseGUID; + uint64 m_uiColososGUID; + uint64 m_uiJaelyneGUID; + uint64 m_uiLanaGUID; + uint64 m_uiMokraGUID; + uint64 m_uiEresseaGUID; + uint64 m_uiRunokGUID; + uint64 m_uiZultoreGUID; + uint64 m_uiVisceriGUID; + uint64 m_uiChampionsLootGUID; + uint64 m_uiEadricGUID; + uint64 m_uiEadricLootGUID; + uint64 m_uiPaletressGUID; + uint64 m_uiPaletressLootGUID; + uint64 m_uiBlackKnightGUID; + uint64 m_uiJaerenGUID; + uint64 m_uiArelasGUID; + uint64 m_uiAnnouncerGUID; + uint32 m_uiChampionId1; + uint32 m_uiChampionId2; + uint32 m_uiChampionId3; + uint32 m_uiChampionsCount; + uint64 m_uiChampion1; + uint64 m_uiChampion2; + uint64 m_uiChampion3; + uint64 m_uiBlackKnightMinionGUID; + uint64 m_uiArgentChallenger; + uint64 m_uiArgentChallengerID; + uint64 m_uiMemoryGUID; + + void Initialize() + { + m_uiJacobGUID = 0; + m_uiAmbroseGUID = 0; + m_uiColososGUID = 0; + m_uiJaelyneGUID = 0; + m_uiLanaGUID = 0; + m_uiMokraGUID = 0; + m_uiEresseaGUID = 0; + m_uiRunokGUID = 0; + m_uiZultoreGUID = 0; + m_uiVisceriGUID = 0; + m_uiChampionsLootGUID = 0; + m_uiEadricGUID = 0; + m_uiEadricLootGUID = 0; + m_uiPaletressGUID = 0; + m_uiPaletressLootGUID = 0; + m_uiBlackKnightGUID = 0; + m_uiJaerenGUID = 0; + m_uiArelasGUID = 0; + m_uiAnnouncerGUID = 0; + m_uiBlackKnightMinionGUID = 0; + m_uiChampionId1 = 0; + m_uiChampionId2 = 0; + m_uiChampionId3 = 0; + m_uiChampion1 = 0; + m_uiChampion2 = 0; + m_uiChampion3 = 0; + m_uiChampionsCount = 3; + m_uiArgentChallenger = 0; + m_uiMemoryGUID = 0; + m_uiArgentChallengerID = 0; + + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + m_auiEncounter[i] = NOT_STARTED; + } + + + void OnPlayerEnter(Player *pPlayer) + { + //if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP)) return; + + switch (pPlayer->GetTeam()) + { + case ALLIANCE: + if (pPlayer && pPlayer->IsInWorld() && pPlayer->HasAura(HORDE_CONTROL_PHASE_SHIFT_1)) + pPlayer->RemoveAurasDueToSpell(HORDE_CONTROL_PHASE_SHIFT_1); + pPlayer->CastSpell(pPlayer, HORDE_CONTROL_PHASE_SHIFT_2, false); + break; + case HORDE: + if (pPlayer && pPlayer->IsInWorld() && pPlayer->HasAura(ALLIANCE_CONTROL_PHASE_SHIFT_1)) + pPlayer->RemoveAurasDueToSpell(ALLIANCE_CONTROL_PHASE_SHIFT_1); + pPlayer->CastSpell(pPlayer, ALLIANCE_CONTROL_PHASE_SHIFT_2, false); + break; + } + } + + void OnCreatureCreate(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + // Champions of the Alliance + case NPC_JACOB: + m_uiJacobGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + case NPC_AMBROSE: + m_uiAmbroseGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + case NPC_COLOSOS: + m_uiColososGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + case NPC_JAELYNE: + m_uiJaelyneGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + case NPC_LANA: + m_uiLanaGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + + // Champions of the Horde + case NPC_MOKRA: + m_uiMokraGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + case NPC_ERESSEA: + m_uiEresseaGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + case NPC_RUNOK: + m_uiRunokGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + case NPC_ZULTORE: + m_uiZultoreGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + case NPC_VISCERI: + m_uiVisceriGUID = pCreature->GetGUID(); + if (m_uiChampion1 == 0) + m_uiChampion1 = pCreature->GetGUID(); + else + if (m_uiChampion2 == 0) + m_uiChampion2 = pCreature->GetGUID(); + else + if (m_uiChampion3 == 0) + m_uiChampion3 = pCreature->GetGUID(); + break; + + // Argent Challenge + case NPC_EADRIC: + m_uiEadricGUID = pCreature->GetGUID(); + m_uiArgentChallenger = pCreature->GetGUID(); + break; + case NPC_PALETRESS: + m_uiPaletressGUID = pCreature->GetGUID(); + m_uiArgentChallenger = pCreature->GetGUID(); + break; + + // Black Knight + case NPC_BLACK_KNIGHT: + m_uiBlackKnightGUID = pCreature->GetGUID(); + break; + case NPC_RISEN_JAEREN: + m_uiBlackKnightMinionGUID = pCreature->GetGUID(); + break; + case NPC_RISEN_ARELAS: + m_uiBlackKnightMinionGUID = pCreature->GetGUID(); + break; + + // Coliseum Announcers + case NPC_JAEREN: + m_uiJaerenGUID = pCreature->GetGUID(); + break; + case NPC_ARELAS: + m_uiArelasGUID = pCreature->GetGUID(); + break; + + // memories + case MEMORY_ALGALON: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_ARCHIMONDE: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_CHROMAGGUS: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_CYANIGOSA: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_DELRISSA: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_ECK: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_ENTROPIUS: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_GRUUL: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_HAKKAR: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_HEIGAN: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_HEROD: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_HOGGER: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_IGNIS: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_ILLIDAN: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_INGVAR: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_KALITHRESH: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_LUCIFRON: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_MALCHEZAAR: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_MUTANUS: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_ONYXIA: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_THUNDERAAN: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_VANCLEEF: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_VASHJ: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_VEKNILASH: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + case MEMORY_VEZAX: + m_uiMemoryGUID = pCreature->GetGUID(); + break; + } + } + + void OnObjectCreate(GameObject *pGo) + { + switch(pGo->GetEntry()) + { + case GO_CHAMPIONS_LOOT: + m_uiChampionsLootGUID = pGo->GetGUID(); + break; + case GO_EADRIC_LOOT: + m_uiEadricLootGUID = pGo->GetGUID(); + break; + case GO_PALETRESS_LOOT: + m_uiPaletressLootGUID = pGo->GetGUID(); + break; + case GO_CHAMPIONS_LOOT_H: + m_uiChampionsLootGUID = pGo->GetGUID(); + break; + case GO_EADRIC_LOOT_H: + m_uiEadricLootGUID = pGo->GetGUID(); + break; + case GO_PALETRESS_LOOT_H: + m_uiPaletressLootGUID = pGo->GetGUID(); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case DATA_TOC5_ANNOUNCER: + m_uiAnnouncerGUID = uiData; + break; + case DATA_CHAMPIONID_1: + m_uiChampionId1 = uiData; + break; + case DATA_CHAMPIONID_2: + m_uiChampionId2 = uiData; + break; + case DATA_CHAMPIONID_3: + m_uiChampionId3 = uiData; + break; + case DATA_CHAMPIONS_COUNT: + m_uiChampionsCount = uiData; + break; + case DATA_ARGENT_CHALLENGER: + m_uiArgentChallengerID = uiData; + break; + case DATA_BLACK_KNIGHT_MINION: + m_uiBlackKnightMinionGUID = uiData; + break; + case TYPE_GRAND_CHAMPIONS: + m_auiEncounter[0] = uiData; + if (uiData == DONE) + { + if (GameObject* pChest = instance->GetGameObject(m_uiChampionsLootGUID)) + if (pChest && !pChest->isSpawned()) + pChest->SetRespawnTime(DAY); + } + if (uiData == FAIL) + { + m_auiEncounter[0] = NOT_STARTED; + } + break; + case TYPE_ARGENT_CHALLENGE: + m_auiEncounter[1] = uiData; + if (uiData == DONE) + { + if (m_uiArgentChallenger == m_uiEadricGUID) + if (GameObject* pChest = instance->GetGameObject(m_uiEadricLootGUID)) + if (pChest && !pChest->isSpawned()) + pChest->SetRespawnTime(DAY); + if (m_uiArgentChallenger == m_uiPaletressGUID) + if (GameObject* pChest = instance->GetGameObject(m_uiPaletressLootGUID)) + if (pChest && !pChest->isSpawned()) + pChest->SetRespawnTime(DAY); + } + if (uiData == FAIL) + { + m_auiEncounter[1] = NOT_STARTED; + } + break; + case TYPE_BLACK_KNIGHT: + m_auiEncounter[2] = uiData; + if (uiData == FAIL) + { + m_auiEncounter[2] = NOT_STARTED; + } + break; + } + + if (uiData == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + saveStream << m_auiEncounter[i] << " "; + + m_strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case DATA_CHAMPION_1: + return m_uiChampion1; + case DATA_CHAMPION_2: + return m_uiChampion2; + case DATA_CHAMPION_3: + return m_uiChampion3; + case DATA_MEMORY: + return m_uiMemoryGUID; + case DATA_ARGENT_CHALLENGER: + return m_uiArgentChallenger; + case DATA_BLACK_KNIGHT: + return m_uiBlackKnightGUID; + } + + return 0; + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case DATA_CHAMPIONID_1: + return m_uiChampionId1; + case DATA_CHAMPIONID_2: + return m_uiChampionId2; + case DATA_CHAMPIONID_3: + return m_uiChampionId3; + case DATA_CHAMPIONS_COUNT: + return m_uiChampionsCount; + case DATA_ARGENT_CHALLENGER: + return m_uiArgentChallengerID; + case DATA_BLACK_KNIGHT_MINION: + return m_uiBlackKnightMinionGUID; + case DATA_TOC5_ANNOUNCER: + return m_uiAnnouncerGUID; + case DATA_JAEREN: + return m_uiJaerenGUID; + case DATA_ARELAS: + return m_uiArelasGUID; + case TYPE_GRAND_CHAMPIONS: return m_auiEncounter[0]; + case TYPE_ARGENT_CHALLENGE: return m_auiEncounter[1]; + case TYPE_BLACK_KNIGHT: return m_auiEncounter[2]; + } + + return 0; + } + + const char* Save() + { + return m_strInstData.c_str(); + } + + void Load(const char* strIn) + { + if (!strIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(strIn); + + std::istringstream loadStream(strIn); + + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + loadStream >> m_auiEncounter[i]; + + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + 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/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp index 454af4d..7226fac 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* 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 @@ -15,11 +15,235 @@ */ /* ScriptData -SDName: trial_of_the_champion -SD%Complete: 0 -SDComment: -SDCategory: Crusader Coliseum, Trial of the Champion +SDName: Trial Of the Champion +SD%Complete: 80% +SDComment: event script. modified by /dev/rsa +SDCategory: trial_of_the_champion EndScriptData */ +/* ContentData +npc_toc5_announcer +EndContentData */ + #include "precompiled.h" #include "trial_of_the_champion.h" + +#define GOSSIP_START_EVENT "Im ready for the next challenge." + +/*###### +## npc_toc5_announcer +######*/ +struct _Messages +{ + char const* name; + uint32 id; + bool state; + uint32 encounter; +}; + +static _Messages _GossipMessage[]= +{ +{"Sind Sie bereit gegen die Champions der gegnerischen Fraktion zu kämpfen?",GOSSIP_ACTION_INFO_DEF+1,false,TYPE_GRAND_CHAMPIONS}, // +{"Sind Sie bereit gegen den Meister der Argentumdämmerung zu kämpfen?",GOSSIP_ACTION_INFO_DEF+2,false,TYPE_ARGENT_CHALLENGE}, // +{"Sind Sie bereit gegen den schwarzen Ritter zu kämpfen?",GOSSIP_ACTION_INFO_DEF+3,false,TYPE_BLACK_KNIGHT}, // +{"Es besteht eine Notwendigkeit hier herumzulungern. Heute ist die Arena geschlossen.",GOSSIP_ACTION_INFO_DEF+4,true,TYPE_BLACK_KNIGHT}, // +}; + +struct MANGOS_DLL_DECL npc_toc5_announcerAI : public ScriptedAI +{ + npc_toc5_announcerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_pInstance) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + } +}; + +CreatureAI* GetAI_npc_toc5_announcer(Creature* pCreature) +{ + return new npc_toc5_announcerAI(pCreature); +} + +bool GossipHello_npc_toc5_announcer(Player* pPlayer, Creature* pCreature) +{ + + ScriptedInstance* m_pInstance; + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + + if (!m_pInstance) return false; + + if(!pPlayer->getAttackers().empty()) return true; + + for(uint8 i = 0; i < MAX_ENCOUNTER+1; i++) { + if (!_GossipMessage[i].state && (m_pInstance->GetData(_GossipMessage[i].encounter) == NOT_STARTED || m_pInstance->GetData(_GossipMessage[i].encounter) == IN_PROGRESS)) + {pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _GossipMessage[i].name, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); + break; + } + if (_GossipMessage[i].state && m_pInstance->GetData(_GossipMessage[i].encounter) == DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _GossipMessage[i].name, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); + }; + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_toc5_announcer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance* m_pInstance; + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + +pPlayer->CLOSE_GOSSIP_MENU(); + +switch(uiAction) { + case GOSSIP_ACTION_INFO_DEF+1: { + if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == 0) { + m_pInstance->SetData(DATA_TOC5_ANNOUNCER, pCreature->GetGUID()); + + if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == m_pInstance->GetData(DATA_ARELAS)) + { + m_pInstance->SetData(DATA_BLACK_KNIGHT_MINION, 35564); + switch(urand(0, 4)) + { + case 0: m_pInstance->SetData(DATA_CHAMPIONID_1, 35572); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_1, 35569); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_1, 35571); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_1, 35570); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_1, 35617); break; + }; + do{ + switch(urand(0, 4)) + { + case 0: m_pInstance->SetData(DATA_CHAMPIONID_2, 35572); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_2, 35569); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_2, 35571); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_2, 35570); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_2, 35617); break; + } + } while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_2)); + do{ + switch(urand(0, 4)) + { + case 0: m_pInstance->SetData(DATA_CHAMPIONID_3, 35572); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_3, 35569); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_3, 35571); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_3, 35570); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_3, 35617); break; + } + } while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_3) || m_pInstance->GetData(DATA_CHAMPIONID_2) == m_pInstance->GetData(DATA_CHAMPIONID_3)); + }; + + if (m_pInstance->GetData(DATA_TOC5_ANNOUNCER) == m_pInstance->GetData(DATA_JAEREN)) + { + m_pInstance->SetData(DATA_BLACK_KNIGHT_MINION, 123); + + switch(urand(0, 4)) + { + case 0: m_pInstance->SetData(DATA_CHAMPIONID_1, 34705); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_1, 34702); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_1, 34701); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_1, 34657); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_1, 34703); break; + } + do{ + switch(urand(0, 4)) + { + case 0: m_pInstance->SetData(DATA_CHAMPIONID_2, 34705); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_2, 34702); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_2, 34701); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_2, 34657); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_2, 34703); break; + } + } while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_2)); + do{ + switch(urand(0, 4)) + { + case 0: m_pInstance->SetData(DATA_CHAMPIONID_3, 34705); break; + case 1: m_pInstance->SetData(DATA_CHAMPIONID_3, 34702); break; + case 2: m_pInstance->SetData(DATA_CHAMPIONID_3, 34701); break; + case 3: m_pInstance->SetData(DATA_CHAMPIONID_3, 34657); break; + case 4: m_pInstance->SetData(DATA_CHAMPIONID_3, 34703); break; + } + } while(m_pInstance->GetData(DATA_CHAMPIONID_1) == m_pInstance->GetData(DATA_CHAMPIONID_3) || m_pInstance->GetData(DATA_CHAMPIONID_2) == m_pInstance->GetData(DATA_CHAMPIONID_3)); + + }; + + switch(urand(0, 1)) + { + case 0: m_pInstance->SetData(DATA_ARGENT_CHALLENGER, 35119); break; + case 1: m_pInstance->SetData(DATA_ARGENT_CHALLENGER, 34928); break; + }; + }; + + if (m_pInstance->GetData(TYPE_GRAND_CHAMPIONS) == NOT_STARTED || m_pInstance->GetData(TYPE_GRAND_CHAMPIONS) == IN_PROGRESS) + { + m_pInstance->SetData(DATA_CHAMPIONS_COUNT, 3); + if (Creature* pTemp = pCreature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_CHAMPION_1))) + pTemp->Respawn(); + else + pCreature->SummonCreature(m_pInstance->GetData(DATA_CHAMPIONID_1), 738.665771f, 661.031433f, 412.394623f, 4.698702f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pCreature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_CHAMPION_2))) + pTemp->Respawn(); + else + pCreature->SummonCreature(m_pInstance->GetData(DATA_CHAMPIONID_2), 746.864441f, 660.918762f, 411.695465f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = pCreature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_CHAMPION_3))) + pTemp->Respawn(); + else + pCreature->SummonCreature(m_pInstance->GetData(DATA_CHAMPIONID_3), 754.360779f, 660.816162f, 412.395996f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + m_pInstance->SetData(TYPE_GRAND_CHAMPIONS, IN_PROGRESS); + }; + }; + + case GOSSIP_ACTION_INFO_DEF+2: { + if ((m_pInstance->GetData(TYPE_ARGENT_CHALLENGE) == NOT_STARTED || m_pInstance->GetData(TYPE_ARGENT_CHALLENGE) == IN_PROGRESS) && m_pInstance->GetData(TYPE_GRAND_CHAMPIONS) == DONE) + { + if (Creature* pTemp = pCreature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ARGENT_CHALLENGER))) + pTemp->Respawn(); + else + pCreature->SummonCreature(m_pInstance->GetData(DATA_ARGENT_CHALLENGER), 746.864441f, 660.918762f, 411.695465f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + m_pInstance->SetData(TYPE_ARGENT_CHALLENGE, IN_PROGRESS); + }; + + }; + + case GOSSIP_ACTION_INFO_DEF+3: { + if ((m_pInstance->GetData(TYPE_BLACK_KNIGHT) == NOT_STARTED || m_pInstance->GetData(TYPE_BLACK_KNIGHT) == IN_PROGRESS) && m_pInstance->GetData(TYPE_ARGENT_CHALLENGE) == DONE) + { + pCreature->SummonCreature(NPC_BLACK_KNIGHT, 746.864441f, 660.918762f, 411.695465f, 4.698700f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + pCreature->DealDamage(pCreature, pCreature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_pInstance->SetData(TYPE_BLACK_KNIGHT, IN_PROGRESS); + }; + }; + + case GOSSIP_ACTION_INFO_DEF+4: { + if (m_pInstance->GetData(TYPE_BLACK_KNIGHT) == DONE) { + pCreature->DealDamage(pCreature, pCreature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }; + }; +}; + + return true; +} + +void AddSC_trial_of_the_champion() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "npc_toc5_announcer"; + NewScript->GetAI = &GetAI_npc_toc5_announcer; + NewScript->pGossipHello = &GossipHello_npc_toc5_announcer; + NewScript->pGossipSelect = &GossipSelect_npc_toc5_announcer; + NewScript->RegisterSelf(); +} diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h index d90fd44..e8d6338 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h @@ -1,17 +1,86 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 - * This program is free software licensed under GPL version 2 - * Please see the included DOCS/LICENSE.TXT for more information */ +/* 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_TRIAL_OF_THE_CHAMPION_H -#define DEF_TRIAL_OF_THE_CHAMPION_H +#ifndef DEF_TOC_H +#define DEF_TOC_H enum { - MAX_ENCOUNTER = 3, + MAX_ENCOUNTER = 3, + + TYPE_GRAND_CHAMPIONS = 0, + TYPE_ARGENT_CHALLENGE = 1, + TYPE_BLACK_KNIGHT = 2, + + DATA_CHAMPION_1 = 3, + DATA_CHAMPION_2 = 4, + DATA_CHAMPION_3 = 5, + DATA_BLACK_KNIGHT = 6, + DATA_BLACK_KNIGHT_MINION = 7, + DATA_TOC5_ANNOUNCER = 8, + DATA_JAEREN = 9, + DATA_ARELAS = 10, + DATA_CHAMPIONID_1 = 11, + DATA_CHAMPIONID_2 = 12, + DATA_CHAMPIONID_3 = 13, + DATA_MEMORY = 14, + DATA_ARGENT_CHALLENGER = 15, + DATA_CHAMPIONS_COUNT = 16, + + NPC_JACOB = 34705, + NPC_AMBROSE = 34702, + NPC_COLOSOS = 34701, + NPC_JAELYNE = 34657, + NPC_LANA = 34703, + NPC_MOKRA = 35572, + NPC_ERESSEA = 35569, + NPC_RUNOK = 35571, + NPC_ZULTORE = 35570, + NPC_VISCERI = 35617, + NPC_EADRIC = 35119, + NPC_PALETRESS = 34928, + NPC_BLACK_KNIGHT = 35451, + NPC_RISEN_JAEREN = 35545, + NPC_RISEN_ARELAS = 35564, + NPC_JAEREN = 35004, + + NPC_ARELAS = 35005, + MEMORY_ALGALON = 35052, + MEMORY_ARCHIMONDE = 35041, + MEMORY_CHROMAGGUS = 35033, + MEMORY_CYANIGOSA = 35046, + MEMORY_DELRISSA = 35043, + MEMORY_ECK = 35047, + MEMORY_ENTROPIUS = 35044, + MEMORY_GRUUL = 35039, + MEMORY_HAKKAR = 35034, + MEMORY_HEIGAN = 35049, + MEMORY_HEROD = 35030, + MEMORY_HOGGER = 34942, + MEMORY_IGNIS = 35050, + MEMORY_ILLIDAN = 35042, + MEMORY_INGVAR = 35045, + MEMORY_KALITHRESH = 35037, + MEMORY_LUCIFRON = 35031, + MEMORY_MALCHEZAAR = 35038, + MEMORY_MUTANUS = 35029, + MEMORY_ONYXIA = 35048, + MEMORY_THUNDERAAN = 35032, + MEMORY_VANCLEEF = 35028, + MEMORY_VASHJ = 35040, + MEMORY_VEKNILASH = 35036, + MEMORY_VEZAX = 35051, + + 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, + + DESPAWN_TIME = 300000 - TYPE_GRAND_CHAMPIONS = 0, - TYPE_ARGENT_CHAMPION = 1, - TYPE_BLACK_KNIGHT = 2, }; -#endif +#endif \ No newline at end of file diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp index 7558556..1fc973a 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_anubarak_trial.cpp @@ -16,52 +16,110 @@ /* ScriptData SDName: boss_anubarak_trial -SD%Complete: 0 -SDComment: +SD%Complete: 70% +SDComment: by /dev/rsa SDCategory: EndScriptData */ +// Anubarak - underground phase partially not worked, timers need correct +// Burrower - underground phase not implemented, buff not worked. +// Leecheng Swarm spell not worked - awaiting core support +// Anubarak spike aura worked only after 9750 + #include "precompiled.h" #include "trial_of_the_crusader.h" -enum +enum Summons { - SAY_AGGRO = -1649064, - SAY_SLAY_1 = -1649065, - SAY_SLAY_2 = -1649066, - SAY_DEATH = -1649067, - SAY_BERSERK = -1649068, - SAY_SUBMERGE = -1649069, - SAY_LEECHING_SWARM = -1649070, + NPC_FROST_SPHERE = 34606, + NPC_BURROWER = 34607, + NPC_SCARAB = 34605, + NPC_SPIKE = 34660, }; -struct MANGOS_DLL_DECL boss_anubarak_trialAI : public ScriptedAI +enum BossSpells { - boss_anubarak_trialAI(Creature* pCreature) : ScriptedAI(pCreature) +SPELL_COLD = 66013, +SPELL_MARK = 67574, +SPELL_LEECHING_SWARM = 66118, +SPELL_LEECHING_HEAL = 66125, +SPELL_LEECHING_DAMAGE = 66240, +SPELL_IMPALE = 65920, +SPELL_SPIKE_CALL = 66169, +SPELL_POUND = 66012, +SPELL_SHOUT = 67730, +SPELL_SUBMERGE_0 = 53421, +SPELL_SUBMERGE_1 = 67322, +SPELL_SUMMON_BEATLES = 66339, +SPELL_DETERMINATION = 66092, +SPELL_ACID_MANDIBLE = 67861, +SPELL_SPIDER_FRENZY = 66129, +SPELL_EXPOSE_WEAKNESS = 67847, +SUMMON_SCARAB = NPC_SCARAB, +SUMMON_BORROWER = NPC_BURROWER, +SUMMON_FROSTSPHERE = NPC_FROST_SPHERE, +SPELL_BERSERK = 26662, +SPELL_PERMAFROST = 66193, +}; + +struct MANGOS_DLL_DECL boss_anubarak_trialAI : public BSWScriptedAI +{ + boss_anubarak_trialAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } ScriptedInstance* m_pInstance; + uint8 stage; + bool intro; + Unit* pTarget; + + void Reset() { + if(!m_pInstance) return; + stage = 0; + intro = true; + m_creature->SetRespawnDelay(DAY); + pTarget = NULL; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } - void Reset() {} + + void KilledUnit(Unit* pVictim) + { + DoScriptText(-1713563,m_creature); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!intro) return; + DoScriptText(-1713554,m_creature); + intro = false; + m_creature->SetInCombatWithZone(); + } void JustReachedHome() { if (m_pInstance) - m_pInstance->SetData(TYPE_ANUBARAK, NOT_STARTED); + m_pInstance->SetData(TYPE_ANUBARAK, FAIL); +// m_creature->ForcedDespawn(); } void JustDied(Unit* pKiller) { - if (m_pInstance) + if (!m_pInstance) return; + DoScriptText(-1713564,m_creature); m_pInstance->SetData(TYPE_ANUBARAK, DONE); } void Aggro(Unit* pWho) { + if (!intro) DoScriptText(-1713555,m_creature); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); m_creature->SetInCombatWithZone(); + m_pInstance->SetData(TYPE_ANUBARAK, IN_PROGRESS); } void UpdateAI(const uint32 uiDiff) @@ -69,6 +127,66 @@ struct MANGOS_DLL_DECL boss_anubarak_trialAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + switch(stage) + { + case 0: { + timedCast(SPELL_POUND, uiDiff); + timedCast(SPELL_COLD, uiDiff); + if (timedQuery(SUMMON_BORROWER, uiDiff)) { + doCast(SUMMON_BORROWER); + DoScriptText(-1713556,m_creature); + }; + if (timedQuery(SPELL_SUBMERGE_0, uiDiff)) stage = 1; + + break;} + case 1: { + doCast(SPELL_SUBMERGE_0); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + stage = 2; + DoScriptText(-1713557,m_creature); + break;} + case 2: { + if (timedQuery(SPELL_SPIKE_CALL, uiDiff)) { + pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0); +// doCast(SPELL_SPIKE_CALL); +// This summon not supported in database. Temporary override. + Unit* spike = doSummon(NPC_SPIKE,TEMPSUMMON_TIMED_DESPAWN,60000); + if (spike) { spike->AddThreat(pTarget, 1000.0f); + DoScriptText(-1713558,m_creature,pTarget); + doCast(SPELL_MARK,pTarget); + spike->GetMotionMaster()->MoveChase(pTarget); + } + }; + if (timedQuery(SPELL_SUMMON_BEATLES, uiDiff)) { + doCast(SPELL_SUMMON_BEATLES); + doCast(SUMMON_SCARAB); + DoScriptText(-1713560,m_creature); + }; + if (timedQuery(SPELL_SUBMERGE_0, uiDiff)) stage = 3; + break;} + case 3: { + stage = 0; + DoScriptText(-1713559,m_creature); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + doRemove(SPELL_SUBMERGE_0,m_creature); + break;} + case 4: { + doCast(SPELL_LEECHING_SWARM); + DoScriptText(-1713561,m_creature); + stage = 5; + break;} + case 5: { + timedCast(SPELL_POUND, uiDiff); + timedCast(SPELL_COLD, uiDiff); + break;} + + } + timedCast(SUMMON_FROSTSPHERE, uiDiff); + + timedCast(SPELL_BERSERK, uiDiff); + + if (m_creature->GetHealthPercent() < 30.0f && stage == 0) stage = 4; + DoMeleeAttackIfReady(); } }; @@ -78,6 +196,216 @@ CreatureAI* GetAI_boss_anubarak_trial(Creature* pCreature) return new boss_anubarak_trialAI(pCreature); } +struct MANGOS_DLL_DECL mob_swarm_scarabAI : public BSWScriptedAI +{ + mob_swarm_scarabAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(DAY); + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; + } + + void JustDied(Unit* Killer) + { + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_DETERMINATION, uiDiff); + + timedCast(SPELL_ACID_MANDIBLE, uiDiff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_swarm_scarab(Creature* pCreature) +{ + return new mob_swarm_scarabAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_nerubian_borrowerAI : public BSWScriptedAI +{ + mob_nerubian_borrowerAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool submerged; + Unit* currentTarget; + + void Reset() + { + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(DAY); + submerged = false; + currentTarget = NULL; + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; + } + + void JustDied(Unit* Killer) + { + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_EXPOSE_WEAKNESS, uiDiff); + + if (timedQuery(SPELL_SPIDER_FRENZY, uiDiff)) + if(Creature* pTemp = GetClosestCreatureWithEntry(m_creature, NPC_BURROWER, 50.0f)) + { + currentTarget = pTemp; + doCast(SPELL_SPIDER_FRENZY); + }; + + if (m_creature->GetHealthPercent() < 20.0f && timedQuery(SPELL_SUBMERGE_1, uiDiff) && !submerged) + { + doCast(SPELL_SUBMERGE_1); + submerged = true; + DoScriptText(-1713557,m_creature); + }; + + if (m_creature->GetHealthPercent() > 50.0f && submerged) + { + doRemove(SPELL_SUBMERGE_1,m_creature); + submerged = false; + DoScriptText(-1713559,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_nerubian_borrower(Creature* pCreature) +{ + return new mob_nerubian_borrowerAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_frost_sphereAI : public BSWScriptedAI +{ + mob_frost_sphereAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + m_creature->SetSpeedRate(MOVE_RUN, 0.1f); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MoveRandom(); + } + + void EnterCombat(Unit* attacker) + { + doCast(SPELL_PERMAFROST); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) + m_creature->ForcedDespawn(); + } +}; + +CreatureAI* GetAI_mob_frost_sphere(Creature* pCreature) +{ + return new mob_frost_sphereAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_anubarak_spikeAI : public BSWScriptedAI +{ + mob_anubarak_spikeAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + Unit* defaultTarget; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + m_creature->SetSpeedRate(MOVE_RUN, 0.5f); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + defaultTarget = NULL; + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + doCast(SPELL_IMPALE); + defaultTarget = who; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_ANUBARAK) != IN_PROGRESS) + m_creature->ForcedDespawn(); + if (defaultTarget) + if (!defaultTarget->isAlive() || !hasAura(SPELL_MARK,defaultTarget)) + m_creature->ForcedDespawn(); + +/* if (timedQuery(SPELL_IMPALE,uiDiff)) { + if (m_creature->IsWithinDist(m_creature->getVictim(), 4.0f) + && !hasAura(SPELL_PERMAFROST,m_creature->getVictim())) + { + doCast(SPELL_IMPALE); + } else doRemove(SPELL_IMPALE); + }*/ + } +}; + +CreatureAI* GetAI_mob_anubarak_spike(Creature* pCreature) +{ + return new mob_anubarak_spikeAI(pCreature); +}; + void AddSC_boss_anubarak_trial() { Script* newscript; @@ -86,4 +414,25 @@ void AddSC_boss_anubarak_trial() newscript->Name = "boss_anubarak_trial"; newscript->GetAI = &GetAI_boss_anubarak_trial; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_swarm_scarab"; + newscript->GetAI = &GetAI_mob_swarm_scarab; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nerubian_borrower"; + newscript->GetAI = &GetAI_mob_nerubian_borrower; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_anubarak_spike"; + newscript->GetAI = &GetAI_mob_anubarak_spike; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_sphere"; + newscript->GetAI = &GetAI_mob_frost_sphere; + newscript->RegisterSelf(); + } \ No newline at end of file diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp index 733c5d8..16ae1e7 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_faction_champions.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* 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 @@ -11,28 +11,1095 @@ * * 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 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* ScriptData SDName: faction_champions -SD%Complete: 0 -SDComment: +SD%Complete: 60% +SDComment: Scripts by Selector, modified by /dev/rsa SDCategory: Crusader Coliseum EndScriptData */ #include "precompiled.h" #include "trial_of_the_crusader.h" -enum +#define AI_MELEE 0 +#define AI_RANGED 1 +#define AI_HEALER 2 + +#define SPELL_ANTI_AOE 68595 +#define SPELL_PVP_TRINKET 65547 + +struct MANGOS_DLL_DECL boss_faction_championsAI : public BSWScriptedAI +{ + boss_faction_championsAI(Creature* pCreature, uint32 aitype) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + mAIType = aitype; + Init(); + } + + ScriptedInstance* m_pInstance; + + uint32 mAIType; + uint32 ThreatTimer; + uint32 CCTimer; + + void Init() + { + CCTimer = rand()%10000; + ThreatTimer = 5000; + resetTimers(); + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(DAY); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_CRUSADERS, FAIL); + m_creature->ForcedDespawn(); + } + + float CalculateThreat(float distance, float armor, uint32 health) + { + float dist_mod = (mAIType == AI_MELEE) ? 15.0f/(15.0f + distance) : 1.0f; + float armor_mod = (mAIType == AI_MELEE) ? armor / 16635.0f : 0.0f; + float eh = (health+1) * (1.0f + armor_mod); + return dist_mod * 30000.0f / eh; + } + + void UpdateThreat() + { + ThreatList const& tList = m_creature->getThreatManager().getThreatList(); + ThreatList::const_iterator itr; + bool empty = true; + for(itr = tList.begin(); itr!=tList.end(); ++itr) + { + Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); + if (pUnit && m_creature->getThreatManager().getThreat(pUnit)) + { + if(pUnit->GetTypeId()==TYPEID_PLAYER) + { + float threat = CalculateThreat(m_creature->GetDistance2d(pUnit), (float)pUnit->GetArmor(), pUnit->GetHealth()); + m_creature->getThreatManager().modifyThreatPercent(pUnit, -100); + m_creature->AddThreat(pUnit, 1000000.0f * threat); + empty = false; + } + } + } + } + + void UpdatePower() + { + if(m_creature->getPowerType() == POWER_MANA) + m_creature->ModifyPower(POWER_MANA, m_creature->GetMaxPower(POWER_MANA) / 3); + //else if(m_creature->getPowerType() == POWER_ENERGY) + // m_creature->ModifyPower(POWER_ENERGY, 100); + } + + void RemoveCC() + { + m_creature->RemoveSpellsCausingAura(SPELL_AURA_MOD_STUN); + m_creature->RemoveSpellsCausingAura(SPELL_AURA_MOD_FEAR); + m_creature->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT); + m_creature->RemoveSpellsCausingAura(SPELL_AURA_MOD_PACIFY); + m_creature->RemoveSpellsCausingAura(SPELL_AURA_MOD_CONFUSE); + //DoCast(m_creature, SPELL_PVP_TRINKET); + } + + void JustDied(Unit *killer) + { + if(m_pInstance) m_pInstance->SetData(TYPE_CRUSADERS_COUNT, 0); + } + + void Aggro(Unit *who) + { + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_CRUSADERS, IN_PROGRESS); + DoCast(m_creature, SPELL_ANTI_AOE, true); + if(who->GetTypeId() != TYPEID_PLAYER) + if (Unit* player = doSelectRandomPlayerAtRange(80.0f)) + m_creature->AddThreat(player, 100.0f); + } + + void Reset() + { + if(m_pInstance) m_pInstance->SetData(TYPE_CRUSADERS, NOT_STARTED); + } + + Creature* SelectRandomFriendlyMissingBuff(uint32 spell) + { + std::list lst = DoFindFriendlyMissingBuff(40.0f, spell); + std::list::const_iterator itr = lst.begin(); + if(lst.empty()) + return NULL; + advance(itr, rand()%lst.size()); + return (*itr); + } + + Unit* SelectEnemyCaster(bool casting) + { + ThreatList const& tList = m_creature->getThreatManager().getThreatList(); + ThreatList::const_iterator iter; + for(iter = tList.begin(); iter!=tList.end(); ++iter) + { + Unit *target; + if(target = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid())) + if(target->getPowerType() == POWER_MANA) + return target; + } + return NULL; + } + + uint32 EnemiesInRange(float distance) + { + ThreatList const& tList = m_creature->getThreatManager().getThreatList(); + ThreatList::const_iterator iter; + uint32 count = 0; + for(iter = tList.begin(); iter!=tList.end(); ++iter) + { + Unit *target; + if(target = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid())) + if(m_creature->GetDistance2d(target) < distance) + ++count; + } + return count; + } + + void AttackStart(Unit* pWho) + { + if (!pWho) return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + + if(mAIType==AI_MELEE) + DoStartMovement(pWho); + else + DoStartMovement(pWho, 20.0f); + + SetCombatMovement(true); + + } + } + + void UpdateAI(const uint32 diff) + { + if(ThreatTimer < diff) + { + UpdatePower(); + UpdateThreat(); + ThreatTimer = 4000; + } + else ThreatTimer -= diff; + + if(CCTimer < diff) + { + RemoveCC(); + CCTimer = 8000+rand()%2000; + } + else CCTimer -= diff; + + if(mAIType == AI_MELEE) DoMeleeAttackIfReady(); + } +}; + +/******************************************************************** + HEALERS +********************************************************************/ + +#define SPELL_LIFEBLOOM 66093 +#define SPELL_NOURISH 66066 +#define SPELL_REGROWTH 66067 +#define SPELL_REJUVENATION 66065 +#define SPELL_TRANQUILITY 66086 +#define SPELL_BARKSKIN 65860 //1 min cd +#define SPELL_THORNS 66068 +#define SPELL_NATURE_GRASP 66071 //1 min cd, self buff + +struct MANGOS_DLL_DECL mob_toc_druidAI : public boss_faction_championsAI +{ + mob_toc_druidAI(Creature* pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) {Init();} + + void Init() + { + SetEquipmentSlots(false, 51799, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + timedCast(SPELL_NATURE_GRASP, diff); + + timedCast(SPELL_TRANQUILITY, diff); + + if(timedQuery(SPELL_BARKSKIN, diff)) + if(m_creature->GetHealthPercent() < 50.0f) + doCast(SPELL_BARKSKIN); + + if(timedQuery(SPELL_LIFEBLOOM, diff)) + switch(urand(0,4)) + { + case 0: + doCast(SPELL_LIFEBLOOM); + break; + case 1: + doCast(SPELL_NOURISH); + break; + case 2: + doCast(SPELL_REGROWTH); + break; + case 3: + doCast(SPELL_REJUVENATION); + break; + case 4: + if(Creature* target = SelectRandomFriendlyMissingBuff(SPELL_THORNS)) + doCast(SPELL_THORNS, target); + break; + } + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_HEALING_WAVE 66055 +#define SPELL_RIPTIDE 66053 +#define SPELL_SPIRIT_CLEANSE 66056 //friendly only +#define SPELL_HEROISM 65983 +#define SPELL_BLOODLUST 65980 +#define SPELL_HEX 66054 +#define SPELL_EARTH_SHIELD 66063 +#define SPELL_EARTH_SHOCK 65973 + +struct MANGOS_DLL_DECL mob_toc_shamanAI : public boss_faction_championsAI +{ + mob_toc_shamanAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) {Init();} + + void Init() + { + SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + timedCast(SPELL_HEROISM, diff); + + timedCast(SPELL_HEX, diff); + + if(timedQuery(SPELL_HEALING_WAVE, diff)) + { + switch(urand(0,5)) + { + case 0: case 1: + doCast(SPELL_HEALING_WAVE); + break; + case 2: + doCast(SPELL_RIPTIDE); + break; + case 3: + doCast(SPELL_EARTH_SHOCK); + break; + case 4: + doCast(SPELL_SPIRIT_CLEANSE); + break; + case 5: + if(Unit *target = SelectRandomFriendlyMissingBuff(SPELL_EARTH_SHIELD)) + doCast(target, SPELL_EARTH_SHIELD); + break; + } + } + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_HAND_OF_FREEDOM 68757 //25 sec cd +#define SPELL_BUBBLE 66010 //5 min cd +#define SPELL_CLEANSE 66116 +#define SPELL_FLASH_OF_LIGHT 66113 +#define SPELL_HOLY_LIGHT 66112 +#define SPELL_HOLY_SHOCK 66114 +#define SPELL_HAND_OF_PROTECTION 66009 +#define SPELL_HAMMER_OF_JUSTICE 66613 + +struct MANGOS_DLL_DECL mob_toc_paladinAI : public boss_faction_championsAI +{ + mob_toc_paladinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) {Init();} + + void Init() + { + SetEquipmentSlots(false, 50771, 47079, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + //cast bubble at 20% hp + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_BUBBLE, diff); + + if(Unit *target = DoSelectLowestHpFriendly(40.0f)) + if(target->GetHealthPercent() < 15.0f) + timedCast(SPELL_HAND_OF_PROTECTION, diff); + + timedCast(SPELL_HOLY_SHOCK, diff); + + if(Unit *target = SelectRandomFriendlyMissingBuff(SPELL_HAND_OF_FREEDOM)) + timedCast(SPELL_HAND_OF_FREEDOM, diff, target); + + timedCast(SPELL_HAMMER_OF_JUSTICE, diff); + + if(timedQuery(SPELL_FLASH_OF_LIGHT, diff)) + { + switch(urand(0,4)) + { + case 0: case 1: + doCast(SPELL_FLASH_OF_LIGHT); + break; + case 2: case 3: + doCast(SPELL_HOLY_LIGHT); + break; + case 4: + doCast(SPELL_CLEANSE); + break; + } + } + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_RENEW 66177 +#define SPELL_SHIELD 66099 +#define SPELL_FLASH_HEAL 66104 +#define SPELL_DISPEL 65546 +#define SPELL_PSYCHIC_SCREAM 65543 +#define SPELL_MANA_BURN 66100 + +struct MANGOS_DLL_DECL mob_toc_priestAI : public boss_faction_championsAI +{ + mob_toc_priestAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_HEALER) {Init();} + + void Init() + { + SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + if(EnemiesInRange(10.0f) > 2) + timedCast(SPELL_PSYCHIC_SCREAM, diff); + + if(timedQuery(SPELL_RENEW, diff)) + { + switch(urand(0,5)) + { + case 0: + doCast(SPELL_RENEW); + break; + case 1: + doCast(SPELL_SHIELD); + break; + case 2: case 3: + doCast(SPELL_FLASH_HEAL); + break; + case 4: + if(Unit *target = urand(0,1) ? m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0) : DoSelectLowestHpFriendly(40.0f)) + doCast(target, SPELL_DISPEL); + break; + case 5: + doCast(SPELL_MANA_BURN); + break; + } + } + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +/******************************************************************** + RANGED +********************************************************************/ + +#define SPELL_SILENCE 65542 +#define SPELL_VAMPIRIC_TOUCH 65490 +#define SPELL_SW_PAIN 65541 +#define SPELL_MIND_FLAY 65488 +#define SPELL_MIND_BLAST 65492 +#define SPELL_HORROR 65545 +#define SPELL_DISPERSION 65544 +#define SPELL_SHADOWFORM 16592 + +struct MANGOS_DLL_DECL mob_toc_shadow_priestAI : public boss_faction_championsAI +{ + mob_toc_shadow_priestAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) {Init();} + + void Init() + { + SetEquipmentSlots(false, 50040, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void Aggro(Unit *who) + { + boss_faction_championsAI::Aggro(who); + doCast(SPELL_SHADOWFORM); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + if(EnemiesInRange(10.0f) > 2) + timedCast(SPELL_PSYCHIC_SCREAM, diff); + + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_DISPERSION, diff); + + if(Unit *target = SelectEnemyCaster(false)) + timedCast(SPELL_SILENCE, diff, target); + + timedCast(SPELL_MIND_BLAST, diff); + + if(timedQuery(SPELL_MIND_FLAY, diff)) + { + switch(urand(0,4)) + { + case 0: case 1: + doCast(SPELL_MIND_FLAY); + break; + case 2: + doCast(SPELL_VAMPIRIC_TOUCH); + break; + case 3: + doCast(SPELL_SW_PAIN); + break; + case 4: + doCast(SPELL_DISPEL); + break; + } + } + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_HELLFIRE 65816 +#define SPELL_CORRUPTION 65810 +#define SPELL_Curse_of_Agony 65814 +#define SPELL_Curse_of_Exhaustion 65815 +#define SPELL_Fear 65809 //8s +#define SPELL_Searing_Pain 65819 +#define SPELL_Shadow_Bolt 65821 +#define SPELL_Unstable_Affliction 65812 +#define H_SPELL_Unstable_Affliction 68155 //15s + +struct MANGOS_DLL_DECL mob_toc_warlockAI : public boss_faction_championsAI +{ + mob_toc_warlockAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) {Init();} + + void Init() + { + SetEquipmentSlots(false, 49992, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + timedCast(SPELL_Fear, diff); + + if(EnemiesInRange(10.0f) > 2) + timedCast(SPELL_HELLFIRE, diff); + + timedCast(SPELL_Unstable_Affliction, diff); + + if(timedQuery(SPELL_Shadow_Bolt, diff)) + { + switch(urand(0,5)) + { + case 0: + doCast(SPELL_Searing_Pain); + break; + case 1: case 2: + doCast(SPELL_Shadow_Bolt); + break; + case 3: + doCast(SPELL_CORRUPTION); + break; + case 4: + doCast(SPELL_Curse_of_Agony); + break; + case 5: + doCast(SPELL_Curse_of_Exhaustion); + break; + } + } + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_Arcane_Barrage 65799 //3s +#define SPELL_Arcane_Blast 65791 +#define SPELL_Arcane_Explosion 65800 +#define SPELL_Blink 65793 //15s +#define SPELL_Counterspell 65790 //24s +#define SPELL_Frost_Nova 65792 //25s +#define SPELL_Frostbolt 65807 +#define SPELL_Ice_Block 65802 //5min +#define SPELL_Polymorph 65801 //15s + +struct MANGOS_DLL_DECL mob_toc_mageAI : public boss_faction_championsAI { - SAY_GARROSH_PVP_A_SLAY_1 = -1649048, - SAY_GARROSH_PVP_A_SLAY_2 = -1649049, - SAY_GARROSH_PVP_A_SLAY_3 = -1649050, - SAY_GARROSH_PVP_A_SLAY_4 = -1649051, + mob_toc_mageAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) {Init();} - SAY_VARIAN_PVP_H_SLAY_1 = -1649052, - SAY_VARIAN_PVP_H_SLAY_2 = -1649053, - SAY_VARIAN_PVP_H_SLAY_3 = -1649054, - SAY_VARIAN_PVP_H_SLAY_4 = -1649055, + void Init() + { + SetEquipmentSlots(false, 47524, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + if(Unit *target = SelectEnemyCaster(false)) + timedCast(SPELL_Counterspell, diff, target); + + if(m_creature->GetHealthPercent() < 50.0f + && EnemiesInRange(10.0f)>3 ) + { + timedCast(SPELL_Frost_Nova, diff); + timedCast(SPELL_Blink, diff); + } + + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_Ice_Block, diff); + + timedCast(SPELL_Polymorph, diff); + + if(timedQuery(SPELL_Arcane_Barrage, diff)) + { + switch(urand(0,2)) + { + case 0: + doCast(SPELL_Arcane_Barrage); + break; + case 1: + doCast(SPELL_Arcane_Blast); + break; + case 2: + doCast(SPELL_Frostbolt); + break; + } + } + boss_faction_championsAI::UpdateAI(diff); + } }; + + +#define SPELL_AIMED_SHOT 65883 +#define SPELL_Deterrence 65871 //90s +#define SPELL_Disengage 65869 //30s +#define SPELL_EXPLOSIVE_SHOT 65866 +#define SPELL_Frost_Trap 65880 //30s +#define SPELL_SHOOT 65868 //1.7s +#define SPELL_Steady_Shot 65867 //3s +#define SPELL_WING_CLIP 66207 //6s +#define SPELL_Wyvern_Sting 65877 //60s + +struct MANGOS_DLL_DECL mob_toc_hunterAI : public boss_faction_championsAI +{ + mob_toc_hunterAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) {Init();} + + void Init() + { + SetEquipmentSlots(false, 47156, EQUIP_NO_CHANGE, 48711); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + if(EnemiesInRange(10.0f) > 3) + timedCast(SPELL_Disengage, diff); + + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_Deterrence, diff); + + timedCast(SPELL_Wyvern_Sting, diff); + + timedCast(SPELL_Frost_Trap, diff ); + + if(m_creature->GetDistance2d(m_creature->getVictim()) < 5.0f) + timedCast(SPELL_WING_CLIP, diff); + + if(timedQuery(SPELL_SHOOT, diff)) + { + switch(urand(0,3)) + { + case 0: case 1: + doCast(SPELL_SHOOT); + break; + case 2: + doCast(SPELL_EXPLOSIVE_SHOT); + break; + case 3: + doCast(SPELL_AIMED_SHOT); + break; + } + } + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_Cyclone 65859 //6s +#define SPELL_Entangling_Roots 65857 //10s +#define SPELL_Faerie_Fire 65863 +#define SPELL_Force_of_Nature 65861 //180s +#define SPELL_Insect_Swarm 65855 +#define SPELL_Moonfire 65856 //5s +#define SPELL_Starfire 65854 +#define SPELL_Wrath 65862 + +struct MANGOS_DLL_DECL mob_toc_boomkinAI : public boss_faction_championsAI +{ + mob_toc_boomkinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_RANGED) {Init();} + + void Init() + { + SetEquipmentSlots(false, 50966, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + if(m_creature->GetHealthPercent() < 50.0f) + timedCast(SPELL_BARKSKIN, diff); + + timedCast(SPELL_Cyclone, diff); + + timedCast(SPELL_Entangling_Roots, diff); + + timedCast(SPELL_Faerie_Fire, diff); + + if(timedQuery(SPELL_Moonfire, diff)) + { + switch(urand(0,6)) + { + case 0: case 1: + doCast(SPELL_Moonfire); + break; + case 2: + doCast(SPELL_Insect_Swarm); + break; + case 3: + doCast(SPELL_Starfire); + break; + case 4: case 5: case 6: + doCast(SPELL_Wrath); + break; + } + } + boss_faction_championsAI::UpdateAI(diff); + } +}; + +/******************************************************************** + MELEE +********************************************************************/ + +#define SPELL_BLADESTORM 65947 +#define SPELL_INTIMIDATING_SHOUT 65930 +#define SPELL_MORTAL_STRIKE 65926 +#define SPELL_CHARGE 68764 +#define SPELL_DISARM 65935 +#define SPELL_OVERPOWER 65924 +#define SPELL_SUNDER_ARMOR 65936 +#define SPELL_SHATTERING_THROW 65940 +#define SPELL_RETALIATION 65932 + +struct MANGOS_DLL_DECL mob_toc_warriorAI : public boss_faction_championsAI +{ + mob_toc_warriorAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {Init();} + + void Init() + { + SetEquipmentSlots(false, 47427, 46964, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + timedCast(SPELL_BLADESTORM, diff); + + timedCast(SPELL_INTIMIDATING_SHOUT, diff); + + timedCast(SPELL_MORTAL_STRIKE, diff); + + timedCast(SPELL_SUNDER_ARMOR, diff); + + timedCast(SPELL_CHARGE, diff); + + timedCast(SPELL_RETALIATION, diff); + + timedCast(SPELL_OVERPOWER, diff); + + timedCast(SPELL_SHATTERING_THROW, diff); + + timedCast(SPELL_DISARM, diff); + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_Chains_of_Ice 66020 //8sec +#define SPELL_Death_Coil 66019 //5sec +#define SPELL_Death_Grip 66017 //35sec +#define SPELL_Frost_Strike 66047 //6sec +#define SPELL_Icebound_Fortitude 66023 //1min +#define SPELL_Icy_Touch 66021 //8sec +#define SPELL_Strangulate 66018 //2min + +struct MANGOS_DLL_DECL mob_toc_dkAI : public boss_faction_championsAI +{ + mob_toc_dkAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {Init();} + + void Init() + { + SetEquipmentSlots(false, 47518, 51021, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + if(m_creature->GetHealthPercent() < 50.0f) + timedCast(SPELL_Icebound_Fortitude, diff); + + timedCast(SPELL_Chains_of_Ice, diff); + + timedCast(SPELL_Death_Coil, diff); + + if(Unit *target = SelectEnemyCaster(false)) + timedCast(SPELL_Strangulate, diff, target); + + timedCast(SPELL_Frost_Strike, diff); + + timedCast(SPELL_Icy_Touch, diff); + + if(m_creature->IsInRange(m_creature->getVictim(), 10.0f, 30.0f, false)) + timedCast(SPELL_Death_Grip, diff); + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_FAN_OF_KNIVES 65955 //2sec +#define SPELL_BLIND 65960 //2min +#define SPELL_CLOAK 65961 //90sec +#define SPELL_Blade_Flurry 65956 //2min +#define SPELL_SHADOWSTEP 66178 //30sec +#define SPELL_HEMORRHAGE 65954 +#define SPELL_EVISCERATE 65957 + +struct MANGOS_DLL_DECL mob_toc_rogueAI : public boss_faction_championsAI +{ + mob_toc_rogueAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {Init();} + + void Init() + { + SetEquipmentSlots(false, 47422, 49982, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + if(EnemiesInRange(15.0f) > 2) + timedCast(SPELL_FAN_OF_KNIVES, diff); + + timedCast(SPELL_HEMORRHAGE, diff); + + timedCast(SPELL_EVISCERATE, diff); + + if(m_creature->IsInRange(m_creature->getVictim(), 10.0f, 40.0f)) + timedCast(SPELL_SHADOWSTEP, diff); + + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) + if(m_creature->IsInRange(target, 0.0f, 15.0f, false)) + timedCast(SPELL_BLIND, diff, target); + + if(m_creature->GetHealthPercent() < 50.0f) + timedCast(SPELL_CLOAK, diff); + + timedCast(SPELL_Blade_Flurry, diff); + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_EARTH_SHOCK 65973 +#define SPELL_LAVA_LASH 65974 +#define SPELL_STORMSTRIKE 65970 + +struct MANGOS_DLL_DECL mob_toc_enh_shamanAI : public boss_faction_championsAI +{ + mob_toc_enh_shamanAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {Init();} + + void Init() + { + SetEquipmentSlots(false, 51803, 48013, EQUIP_NO_CHANGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + timedCast(SPELL_HEROISM, diff); + + timedCast(SPELL_EARTH_SHOCK, diff); + + timedCast(SPELL_STORMSTRIKE, diff); + + timedCast(SPELL_LAVA_LASH, diff); + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_Avenging_Wrath 66011 //3min cd +#define SPELL_Crusader_Strike 66003 //6sec cd +#define SPELL_Divine_Shield 66010 //5min cd +#define SPELL_Divine_Storm 66006 //10sec cd +#define SPELL_Hammer_of_Justice 66007 //40sec cd +#define SPELL_Hand_of_Protection 66009 //5min cd +#define SPELL_Judgement_of_Command 66005 //8sec cd +#define SPELL_REPENTANCE 66008 //60sec cd +#define SPELL_Seal_of_Command 66004 //no cd + +struct MANGOS_DLL_DECL mob_toc_retro_paladinAI : public boss_faction_championsAI +{ + mob_toc_retro_paladinAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {Init();} + + void Init() + { + SetEquipmentSlots(false, 47519, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE); + } + + void Aggro(Unit *who) + { + boss_faction_championsAI::Aggro(who); + doCast(SPELL_Seal_of_Command); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + timedCast(SPELL_REPENTANCE, diff); + + timedCast(SPELL_Crusader_Strike, diff); + + timedCast(SPELL_Avenging_Wrath, diff); + + if(m_creature->GetHealthPercent() < 20.0f) + timedCast(SPELL_Divine_Shield, diff); + + timedCast(SPELL_Divine_Storm, diff); + + timedCast(SPELL_Judgement_of_Command, diff); + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_WPET0 67518 +#define SPELL_WPET1 67519 + +struct MANGOS_DLL_DECL mob_toc_pet_warlockAI : public boss_faction_championsAI +{ + mob_toc_pet_warlockAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {Init();} + + void Aggro(Unit *who) + { + boss_faction_championsAI::Aggro(who); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + timedCast(SPELL_WPET0, diff); + + timedCast(SPELL_WPET1, diff); + + boss_faction_championsAI::UpdateAI(diff); + } +}; + +#define SPELL_HPET0 67793 +struct MANGOS_DLL_DECL mob_toc_pet_hunterAI : public boss_faction_championsAI +{ + mob_toc_pet_hunterAI(Creature *pCreature) : boss_faction_championsAI(pCreature, AI_MELEE) {Init();} + + void Aggro(Unit *who) + { + boss_faction_championsAI::Aggro(who); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + + timedCast(SPELL_HPET0, diff); + + boss_faction_championsAI::UpdateAI(diff); + } +}; + + +/*========================================================*/ +CreatureAI* GetAI_mob_toc_druid(Creature *pCreature) { + return new mob_toc_druidAI (pCreature); +} +CreatureAI* GetAI_mob_toc_shaman(Creature *pCreature) { + return new mob_toc_shamanAI (pCreature); +} +CreatureAI* GetAI_mob_toc_paladin(Creature *pCreature) { + return new mob_toc_paladinAI (pCreature); +} +CreatureAI* GetAI_mob_toc_priest(Creature *pCreature) { + return new mob_toc_priestAI (pCreature); +} +CreatureAI* GetAI_mob_toc_shadow_priest(Creature *pCreature) { + return new mob_toc_shadow_priestAI (pCreature); +} +CreatureAI* GetAI_mob_toc_warlock(Creature *pCreature) { + return new mob_toc_warlockAI (pCreature); +} +CreatureAI* GetAI_mob_toc_mage(Creature *pCreature) { + return new mob_toc_mageAI (pCreature); +} +CreatureAI* GetAI_mob_toc_hunter(Creature *pCreature) { + return new mob_toc_hunterAI (pCreature); +} +CreatureAI* GetAI_mob_toc_boomkin(Creature *pCreature) { + return new mob_toc_boomkinAI (pCreature); +} +CreatureAI* GetAI_mob_toc_warrior(Creature *pCreature) { + return new mob_toc_warriorAI (pCreature); +} +CreatureAI* GetAI_mob_toc_dk(Creature *pCreature) { + return new mob_toc_dkAI (pCreature); +} +CreatureAI* GetAI_mob_toc_rogue(Creature *pCreature) { + return new mob_toc_rogueAI (pCreature); +} +CreatureAI* GetAI_mob_toc_enh_shaman(Creature *pCreature) { + return new mob_toc_enh_shamanAI (pCreature); +} +CreatureAI* GetAI_mob_toc_retro_paladin(Creature *pCreature) { + return new mob_toc_retro_paladinAI (pCreature); +} +CreatureAI* GetAI_mob_toc_pet_warlock(Creature *pCreature) { + return new mob_toc_pet_warlockAI (pCreature); +} +CreatureAI* GetAI_mob_toc_pet_hunter(Creature *pCreature) { + return new mob_toc_pet_hunterAI (pCreature); +} + +void AddSC_boss_faction_champions() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_toc_druid"; + newscript->GetAI = &GetAI_mob_toc_druid; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_shaman"; + newscript->GetAI = &GetAI_mob_toc_shaman; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_paladin"; + newscript->GetAI = &GetAI_mob_toc_paladin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_priest"; + newscript->GetAI = &GetAI_mob_toc_priest; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_shadow_priest"; + newscript->GetAI = &GetAI_mob_toc_shadow_priest; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_mage"; + newscript->GetAI = &GetAI_mob_toc_mage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_warlock"; + newscript->GetAI = &GetAI_mob_toc_warlock; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_hunter"; + newscript->GetAI = &GetAI_mob_toc_hunter; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_boomkin"; + newscript->GetAI = &GetAI_mob_toc_boomkin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_warrior"; + newscript->GetAI = &GetAI_mob_toc_warrior; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_dk"; + newscript->GetAI = &GetAI_mob_toc_dk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_rogue"; + newscript->GetAI = &GetAI_mob_toc_rogue; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_enh_shaman"; + newscript->GetAI = &GetAI_mob_toc_enh_shaman; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_retro_paladin"; + newscript->GetAI = &GetAI_mob_toc_retro_paladin; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_pet_warlock"; + newscript->GetAI = &GetAI_mob_toc_pet_warlock; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toc_pet_hunter"; + newscript->GetAI = &GetAI_mob_toc_pet_hunter; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp index 1d1dd75..c2335a3 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_jaraxxus.cpp @@ -13,60 +13,112 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +// Jaraxxus - Magic aura (from start?) not fully offlike implemented. +// Legion flame visual effect not imlemented /* ScriptData SDName: trial_of_the_crusader -SD%Complete: 0 -SDComment: +SD%Complete: 80% +SDComment: by /dev/rsa SDCategory: Crusader Coliseum EndScriptData */ #include "precompiled.h" #include "trial_of_the_crusader.h" +enum Equipment +{ + EQUIP_MAIN = 47266, + EQUIP_OFFHAND = 46996, + EQUIP_RANGED = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; -/*###### -## boss_jaraxxus -######*/ +enum Summons +{ + NPC_LEGION_FLAME = 34784, + NPC_INFERNAL_VOLCANO = 34813, + NPC_FEL_INFERNAL = 34815, + NPC_NETHER_PORTAL = 34825, + NPC_MISTRESS = 34826, +}; -enum +enum BossSpells { - SAY_AGGRO = -1649040, - SAY_SLAY_1 = -1649041, - SAY_SLAY_2 = -1649042, - SAY_DEATH = -1649043, - SAY_BERSERK = -1649044, - SAY_INCINERATE = -1649045, - SAY_MISTRESS = -1649046, - SAY_INFERNO = -1649047, +SPELL_NETHER_POWER = 67108, +SPELL_INFERNAL = 66258, +SPELL_INFERNAL_ERUPTION = 66255, +SPELL_FEL_FIREBALL = 66532, +SPELL_FEL_LIGHTING = 66528, +SPELL_INCINERATE_FLESH = 66237, +SPELL_BURNING_INFERNO = 66242, +SPELL_NETHER_PORTAL = 66264, +SPELL_LEGION_FLAME_0 = 66199, +SPELL_LEGION_FLAME_1 = 66197, +SPELL_SHIVAN_SLASH = 67098, +SPELL_SPINNING_STRIKE = 66316, +SPELL_FEL_INFERNO = 67047, +SPELL_FEL_STREAK = 66494, +SPELL_BERSERK = 26662, }; -struct MANGOS_DLL_DECL boss_jaraxxusAI : public ScriptedAI +/*###### +## boss_jaraxxus +######*/ + +struct MANGOS_DLL_DECL boss_jaraxxusAI : public BSWScriptedAI { - boss_jaraxxusAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_jaraxxusAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } ScriptedInstance* m_pInstance; + uint8 stage; + uint8 substage; + uint8 m_portalsCount; + uint8 m_volcanoCount; - void Reset() {} + void Reset() { + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_JARAXXUS, NOT_STARTED); +// SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); + m_portalsCount = 1; + if (currentDifficulty == RAID_DIFFICULTY_10MAN_HEROIC || currentDifficulty == RAID_DIFFICULTY_25MAN_HEROIC) + { + m_portalsCount = 2; + m_volcanoCount = 4; + } else { + m_portalsCount = 1; + m_volcanoCount = 4; + } + DoScriptText(-1713517,m_creature); + m_creature->SetRespawnDelay(DAY); + } void JustReachedHome() { - if (m_pInstance) - m_pInstance->SetData(TYPE_JARAXXUS, NOT_STARTED); + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_JARAXXUS, FAIL); + m_creature->ForcedDespawn(); } void JustDied(Unit* pKiller) { - if (m_pInstance) + if (!m_pInstance) return; + DoScriptText(-1713525,m_creature); m_pInstance->SetData(TYPE_JARAXXUS, DONE); + m_pInstance->SetData(TYPE_EVENT,2000); + m_pInstance->SetData(TYPE_STAGE,0); } void Aggro(Unit* pWho) { + if (!m_pInstance) return; m_creature->SetInCombatWithZone(); + m_pInstance->SetData(TYPE_JARAXXUS, IN_PROGRESS); + DoScriptText(-1713514,m_creature); + doCast(SPELL_NETHER_POWER); } void UpdateAI(const uint32 uiDiff) @@ -74,6 +126,37 @@ struct MANGOS_DLL_DECL boss_jaraxxusAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + timedCast(SPELL_FEL_FIREBALL, uiDiff); + + timedCast(SPELL_FEL_LIGHTING, uiDiff); + + if (timedQuery(SPELL_INCINERATE_FLESH, uiDiff)) { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) + { + DoScriptText(-1713522,m_creature,pTarget); + doCast(SPELL_INCINERATE_FLESH,pTarget); + } + } + + if (timedQuery(SPELL_LEGION_FLAME_1, uiDiff)) { + DoScriptText(-1713518,m_creature); + doCast(SPELL_LEGION_FLAME_1); + }; + + if (timedQuery(SPELL_INFERNAL_ERUPTION, uiDiff) + && m_volcanoCount > 0) { + DoScriptText(-1713520,m_creature); + if (doCast(NPC_INFERNAL_VOLCANO) == CAST_OK) --m_volcanoCount; + }; + + if (timedQuery(SPELL_NETHER_PORTAL, uiDiff) + && m_portalsCount > 0 + && m_creature->GetHealthPercent() <= 90.0f) + { + DoScriptText(-1713519,m_creature); + if (doCast(NPC_NETHER_PORTAL) == CAST_OK) --m_portalsCount; + }; + DoMeleeAttackIfReady(); } }; @@ -83,6 +166,320 @@ CreatureAI* GetAI_boss_jaraxxus(Creature* pCreature) return new boss_jaraxxusAI(pCreature); } +struct MANGOS_DLL_DECL mob_legion_flameAI : public BSWScriptedAI +{ + mob_legion_flameAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_uiRangeCheck_Timer; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(DAY); + + if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0) ) { + m_creature->GetMotionMaster()->MoveChase(pTarget); + m_creature->SetSpeedRate(MOVE_RUN, 0.5); + } + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; + } + + void JustDied(Unit* Killer) + { + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiRangeCheck_Timer < uiDiff) + { + if (m_pInstance) + { + if (m_creature->IsWithinDist(m_creature->getVictim(), 4.0f, false)) + { + DoCast(m_creature,SPELL_LEGION_FLAME_0); + } + } + m_uiRangeCheck_Timer = 1000; + if (m_creature->getVictim()) { + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->SetSpeedRate(MOVE_RUN, 0.5); + } + } + else m_uiRangeCheck_Timer -= uiDiff; + + } +}; + +CreatureAI* GetAI_mob_legion_flame(Creature* pCreature) +{ + return new mob_legion_flameAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_infernal_volcanoAI : public BSWScriptedAI +{ + mob_infernal_volcanoAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint8 m_Count; + uint32 m_Timer; + + void Reset() + { + m_Timer = 15000; + m_creature->SetRespawnDelay(DAY); + if (currentDifficulty != RAID_DIFFICULTY_10MAN_HEROIC && currentDifficulty != RAID_DIFFICULTY_25MAN_HEROIC) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_Count = 3; + } else + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_Count = 6; + } + } + + void AttackStart(Unit *who) + { + return; + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; + } + + void JustDied(Unit* Killer) + { + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + } + + void UpdateAI(const uint32 diff) + { + if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (timedQuery(SPELL_INFERNAL_ERUPTION,diff) && m_Count > 0) { + doCast(SPELL_INFERNAL_ERUPTION); + DoScriptText(-1713524,m_creature); + --m_Count; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + } +}; + +CreatureAI* GetAI_mob_infernal_volcano(Creature* pCreature) +{ + return new mob_infernal_volcanoAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_fel_infernalAI : public BSWScriptedAI +{ + mob_fel_infernalAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(DAY); + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; + } + + void JustDied(Unit* Killer) + { + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_FEL_INFERNO, uiDiff); + + timedCast(SPELL_FEL_STREAK, uiDiff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_fel_infernal(Creature* pCreature) +{ + return new mob_fel_infernalAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_nether_portalAI : public BSWScriptedAI +{ + mob_nether_portalAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_Timer; + uint8 m_Count; + + void Reset() + { + m_Timer = 10000; + m_creature->SetRespawnDelay(DAY); + if (currentDifficulty != RAID_DIFFICULTY_10MAN_HEROIC && currentDifficulty != RAID_DIFFICULTY_25MAN_HEROIC) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_Count = 1; + } else + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_Count = 2; + } + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; + } + + void AttackStart(Unit *who) + { + return; + } + + void JustDied(Unit* Killer) + { + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + } + + void UpdateAI(const uint32 diff) + { + if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_Timer < diff && m_Count > 0) { + DoCast(m_creature,SPELL_NETHER_PORTAL,false); + DoScriptText(-1713521,m_creature); + --m_Count; + m_Timer = 60000; + } else m_Timer -= diff; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + } +}; + +CreatureAI* GetAI_mob_nether_portal(Creature* pCreature) +{ + return new mob_nether_portalAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_mistress_of_painAI : public BSWScriptedAI +{ + mob_mistress_of_painAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(DAY); + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim->GetTypeId() != TYPEID_PLAYER) return; + } + + void JustDied(Unit* Killer) + { + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + DoScriptText(-1713523,m_creature, who); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + if (m_pInstance->GetData(TYPE_JARAXXUS) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_SHIVAN_SLASH, uiDiff); + + timedCast(SPELL_SPINNING_STRIKE, uiDiff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_mistress_of_pain(Creature* pCreature) +{ + return new mob_mistress_of_painAI(pCreature); +} + void AddSC_boss_jaraxxus() { Script* newscript; @@ -91,4 +488,29 @@ void AddSC_boss_jaraxxus() newscript->Name = "boss_jaraxxus"; newscript->GetAI = &GetAI_boss_jaraxxus; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_legion_flame"; + newscript->GetAI = &GetAI_mob_legion_flame; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_infernal_volcano"; + newscript->GetAI = &GetAI_mob_infernal_volcano; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fel_infernal"; + newscript->GetAI = &GetAI_mob_fel_infernal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nether_portal"; + newscript->GetAI = &GetAI_mob_nether_portal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_mistress_of_pain"; + newscript->GetAI = &GetAI_mob_mistress_of_pain; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp index ed9e8b3..24e891b 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_northrend_beasts.cpp @@ -13,42 +13,113 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +// Gormok - Firebomb not implemented, timers need correct +// Snakes - Underground phase not worked, timers need correct +// Icehowl - Trample&Crash event not implemented, timers need correct /* ScriptData -SDName: -SD%Complete: 0 -SDComment: +SDName: northrend_beasts +SD%Complete: 90% +SDComment: by /dev/rsa SDCategory: EndScriptData */ +// not implemented: +// snobolds link +// snakes underground cast (not support in core) + #include "precompiled.h" #include "trial_of_the_crusader.h" -/*###### -## boss_gormok -######*/ +enum Equipment +{ + EQUIP_MAIN = 50760, + EQUIP_OFFHAND = 48040, + EQUIP_RANGED = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; + +enum Summons +{ + NPC_SNOBOLD_VASSAL = 34800, + NPC_SLIME_POOL = 35176, + NPC_FIRE_BOMB = 34854, +}; + +enum BossSpells +{ +SPELL_IMPALE = 66331, +SPELL_STAGGERING_STOMP = 67648, +SPELL_RISING_ANGER = 66636, +SUMMON_SNOBOLD = NPC_SNOBOLD_VASSAL, +SPELL_ACID_SPIT = 66880, +SPELL_PARALYTIC_SPRAY = 66901, +SPELL_ACID_SPEW = 66819, +SPELL_PARALYTIC_BITE = 66824, +SPELL_SWEEP_0 = 66794, +SPELL_SLIME_POOL = 66883, +SPELL_FIRE_SPIT = 66796, +SPELL_MOLTEN_SPEW = 66821, +SPELL_BURNING_BITE = 66879, +SPELL_BURNING_SPRAY = 66902, +SPELL_SWEEP_1 = 67646, +SPELL_FEROCIOUS_BUTT = 66770, +SPELL_MASSIVE_CRASH = 66683, +SPELL_WHIRL = 67345, +SPELL_ARCTIC_BREATH = 66689, +SPELL_TRAMPLE = 66734, +SPELL_ADRENALINE = 68667, +SPELL_SNOBOLLED = 66406, +SPELL_BATTER = 66408, +SPELL_FIRE_BOMB = 66313, +SPELL_FIRE_BOMB_1 = 66317, +SPELL_FIRE_BOMB_DOT = 66318, +SPELL_HEAD_CRACK = 66407, +SPELL_SUBMERGE_0 = 53421, +SPELL_ENRAGE = 68335, +SPELL_FROTHING_RAGE = 66759, +SPELL_STAGGERED_DAZE = 66758, +SPELL_SLIME_POOL_1 = 66881, +SPELL_SLIME_POOL_2 = 66882, +SPELL_SLIME_POOL_VISUAL = 63084, +}; -struct MANGOS_DLL_DECL boss_gormokAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_gormokAI : public BSWScriptedAI { - boss_gormokAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_gormokAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } ScriptedInstance* m_pInstance; + uint8 SnoboldsCount; - void Reset() {} + void Reset() { + + if(!m_pInstance) return; + SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetInCombatWithZone(); + SnoboldsCount = 4; + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_DONE); + } void JustReachedHome() { - if (m_pInstance) - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, NOT_STARTED); + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); + m_creature->ForcedDespawn(); } void Aggro(Unit* pWho) { - m_creature->SetInCombatWithZone(); + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, GORMOK_IN_PROGRESS); } void UpdateAI(const uint32 uiDiff) @@ -56,6 +127,16 @@ struct MANGOS_DLL_DECL boss_gormokAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + timedCast(SPELL_IMPALE, uiDiff); + + timedCast(SPELL_STAGGERING_STOMP, uiDiff); + + if (timedQuery(SUMMON_SNOBOLD, uiDiff) && SnoboldsCount > 0 ) { + doCast(SUMMON_SNOBOLD); + DoScriptText(-1713601,m_creature); + --SnoboldsCount; + }; + DoMeleeAttackIfReady(); } }; @@ -65,38 +146,175 @@ CreatureAI* GetAI_boss_gormok(Creature* pCreature) return new boss_gormokAI(pCreature); } -/*###### -## boss_acidmaw -######*/ +struct MANGOS_DLL_DECL mob_snobold_vassalAI : public BSWScriptedAI +{ + mob_snobold_vassalAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + Unit* pBoss; + Unit* defaultTarget; + + void Reset() + { + pBoss = NULL; + defaultTarget = NULL; + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(DAY); + pBoss = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_GORMOK)); + if (pBoss) doCast(SPELL_RISING_ANGER,pBoss); + } + + void Aggro(Unit *who) + { + if (!m_pInstance) return; + defaultTarget = who; + doCast(SPELL_SNOBOLLED, defaultTarget); + } + + void JustReachedHome() + { + if (!m_pInstance) return; + m_creature->ForcedDespawn(); + } + + void JustDied(Unit* pKiller) + { + if (defaultTarget && defaultTarget->isAlive()) doRemove(SPELL_SNOBOLLED, defaultTarget); +// if (pBoss && pBoss->isAlive()) doRemove(SPELL_RISING_ANGER,pBoss); +// This string - not offlike, in off this buff not removed! especially for small servers. + } + + void UpdateAI(const uint32 uiDiff) + { + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_BATTER, uiDiff); + + if (timedCast(SPELL_FIRE_BOMB, uiDiff, m_creature->getVictim()) == CAST_OK) { + doCast(SPELL_FIRE_BOMB_1, m_creature->getVictim()); + doCast(SPELL_FIRE_BOMB_DOT, m_creature->getVictim()); + } + + timedCast(SPELL_HEAD_CRACK, uiDiff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_snobold_vassal(Creature* pCreature) +{ + return new mob_snobold_vassalAI(pCreature); +} -struct MANGOS_DLL_DECL boss_acidmawAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_acidmawAI : public BSWScriptedAI { - boss_acidmawAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_acidmawAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } ScriptedInstance* m_pInstance; + uint8 stage; + bool enraged; - void Reset() {} + void Reset() + { + stage = 1; + enraged = false; + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(7*DAY); + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ACIDMAW_SUBMERGED); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + if (Creature* pSister = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_DREADSCALE))) + if (!pSister->isAlive()) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_DONE); + else m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_SPECIAL); + } void JustReachedHome() { - if (m_pInstance) - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, NOT_STARTED); + if (!m_pInstance) return; + if (m_pInstance->GetData(TYPE_BEASTS) == IN_PROGRESS + && m_pInstance->GetData(TYPE_NORTHREND_BEASTS) != FAIL) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); + m_creature->ForcedDespawn(); } void Aggro(Unit* pWho) { - m_creature->SetInCombatWithZone(); } void UpdateAI(const uint32 uiDiff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + + if ((!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + && (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) != ACIDMAW_SUBMERGED)) return; + switch (stage) + { + case 0: { + timedCast(SPELL_ACID_SPEW, uiDiff); + + timedCast(SPELL_PARALYTIC_BITE, uiDiff); + + timedCast(SPELL_ACID_SPIT, uiDiff); + + timedCast(SPELL_PARALYTIC_SPRAY, uiDiff); + + timedCast(SPELL_SWEEP_0, uiDiff); + + if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == ACIDMAW_SUBMERGED) + stage = 1; + + break;} + case 1: { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_SUBMERGE_0); + stage = 2; + DoScriptText(-1713557,m_creature); + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ACIDMAW_SUBMERGED); + break;} + case 2: { + if (timedQuery(SPELL_SLIME_POOL, uiDiff)) + doCast(NPC_SLIME_POOL); + + if ((timedQuery(SPELL_SUBMERGE_0, uiDiff) && m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == ACIDMAW_SUBMERGED) + || m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == DREADSCALE_SUBMERGED) + stage = 3; + break;} + case 3: { + DoScriptText(-1713559,m_creature); + doRemove(SPELL_SUBMERGE_0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + stage = 0; + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, DREADSCALE_SUBMERGED); + break;} + } + + if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL && !enraged) + { + DoScriptText(-1713559,m_creature); + doRemove(SPELL_SUBMERGE_0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + doCast(SPELL_ENRAGE); + enraged = true; + stage = 0; + DoScriptText(-1713504,m_creature); + }; + DoMeleeAttackIfReady(); } }; @@ -106,38 +324,108 @@ CreatureAI* GetAI_boss_acidmaw(Creature* pCreature) return new boss_acidmawAI(pCreature); } -/*###### -## boss_dreadscale -######*/ - -struct MANGOS_DLL_DECL boss_dreadscaleAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_dreadscaleAI : public BSWScriptedAI { - boss_dreadscaleAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_dreadscaleAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } ScriptedInstance* m_pInstance; + uint8 stage; + bool enraged; + + void Reset() + { + stage = 0; + enraged = false; + m_creature->SetInCombatWithZone(); + m_creature->SetRespawnDelay(7*DAY); + } - void Reset() {} + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + if (Creature* pSister = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_ACIDMAW))) + if (!pSister->isAlive()) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_DONE); + else m_pInstance->SetData(TYPE_NORTHREND_BEASTS, SNAKES_SPECIAL); + } void JustReachedHome() { - if (m_pInstance) - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, NOT_STARTED); + if (!m_pInstance) return; + if (m_pInstance->GetData(TYPE_BEASTS) == IN_PROGRESS + && m_pInstance->GetData(TYPE_NORTHREND_BEASTS) != FAIL) + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); + m_creature->ForcedDespawn(); } void Aggro(Unit* pWho) { - m_creature->SetInCombatWithZone(); } void UpdateAI(const uint32 uiDiff) { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if ((!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + && (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) != DREADSCALE_SUBMERGED)) return; + switch (stage) + { + case 0: { + timedCast(SPELL_BURNING_BITE, uiDiff); + + timedCast(SPELL_MOLTEN_SPEW, uiDiff); + + timedCast(SPELL_FIRE_SPIT, uiDiff); + + timedCast(SPELL_BURNING_SPRAY, uiDiff); + + timedCast(SPELL_SWEEP_0, uiDiff); + + if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == DREADSCALE_SUBMERGED) + stage = 1; + + break;} + case 1: { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_SUBMERGE_0); + stage = 2; + DoScriptText(-1713557,m_creature); + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, DREADSCALE_SUBMERGED); + break;} + case 2: { + + if (timedQuery(SPELL_SLIME_POOL, uiDiff)) + doCast(NPC_SLIME_POOL); + + if ((timedQuery(SPELL_SUBMERGE_0, uiDiff) && m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == DREADSCALE_SUBMERGED) + || m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == ACIDMAW_SUBMERGED) + stage = 3; + break;} + case 3: { + DoScriptText(-1713559,m_creature); + doRemove(SPELL_SUBMERGE_0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + stage = 0; + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ACIDMAW_SUBMERGED); + break;} + } + + if (m_pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_SPECIAL && !enraged) + { + DoScriptText(-1713559,m_creature); + doRemove(SPELL_SUBMERGE_0); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + doCast(SPELL_ENRAGE); + enraged = true; + stage = 0; + DoScriptText(-1713504,m_creature); + }; + DoMeleeAttackIfReady(); } }; @@ -147,36 +435,113 @@ CreatureAI* GetAI_boss_dreadscale(Creature* pCreature) return new boss_dreadscaleAI(pCreature); } -/*###### -## boss_icehowl -######*/ - -enum +struct MANGOS_DLL_DECL mob_slime_poolAI : public BSWScriptedAI { - EMOTE_MASSIVE_CRASH = -1649039, + mob_slime_poolAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance *m_pInstance; + float m_Size; + bool cloudcasted; + + void Reset() + { + if(!m_pInstance) return; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWithZone(); + m_creature->SetSpeedRate(MOVE_RUN, 0.05f); + SetCombatMovement(false); + m_creature->GetMotionMaster()->MoveRandom(); + doCast(SPELL_SLIME_POOL_2); + m_Size = m_creature->GetFloatValue(OBJECT_FIELD_SCALE_X); + cloudcasted = false; + } + + void AttackStart(Unit *who) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!cloudcasted) { + doCast(SPELL_SLIME_POOL_VISUAL); + cloudcasted = true; + } + + if (timedQuery(SPELL_SLIME_POOL_2,uiDiff)) { + m_Size = m_Size*1.035; + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_Size); + } + // Override especially for clean core + if (m_Size >= 6.0f) m_creature->ForcedDespawn(); + } + }; -struct MANGOS_DLL_DECL boss_icehowlAI : public ScriptedAI +CreatureAI* GetAI_mob_slime_pool(Creature* pCreature) { - boss_icehowlAI(Creature* pCreature) : ScriptedAI(pCreature) + return new mob_slime_poolAI(pCreature); +} + +struct MANGOS_DLL_DECL boss_icehowlAI : public BSWScriptedAI +{ + boss_icehowlAI(Creature* pCreature) : BSWScriptedAI(pCreature) { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } ScriptedInstance* m_pInstance; + bool MovementStarted; + bool TrampleCasted; + uint8 stage; + float fPosX, fPosY, fPosZ; + Unit* pTarget; + + void Reset() { + if(!m_pInstance) return; + m_creature->SetRespawnDelay(7*DAY); + MovementStarted = false; + stage = 0; + } - void Reset() {} + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_DONE); + } + + void MovementInform(uint32 type, uint32 id) + { + if(!m_pInstance) return; + if(type != POINT_MOTION_TYPE) return; + if(id != 1 && MovementStarted) + { + m_creature->GetMotionMaster()->MovePoint(1, fPosX, fPosY, fPosZ); + } + else { + m_creature->GetMotionMaster()->MovementExpired(); + MovementStarted = false; + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + } void JustReachedHome() { - if (m_pInstance) - m_pInstance->SetData(TYPE_NORTHREND_BEASTS, NOT_STARTED); + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, FAIL); + m_creature->ForcedDespawn(); } void Aggro(Unit* pWho) { m_creature->SetInCombatWithZone(); + m_pInstance->SetData(TYPE_NORTHREND_BEASTS, ICEHOWL_IN_PROGRESS); } void UpdateAI(const uint32 uiDiff) @@ -184,7 +549,95 @@ struct MANGOS_DLL_DECL boss_icehowlAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - DoMeleeAttackIfReady(); + switch (stage) + { + case 0: { + timedCast(SPELL_FEROCIOUS_BUTT, uiDiff); + + timedCast(SPELL_ARCTIC_BREATH, uiDiff); + + timedCast(SPELL_WHIRL, uiDiff); + + if (timedQuery(SPELL_MASSIVE_CRASH, uiDiff)) stage = 1; + + timedCast(SPELL_FROTHING_RAGE, uiDiff); + + DoMeleeAttackIfReady(); + + break; + } + case 1: { + if (doCast(SPELL_MASSIVE_CRASH) == CAST_OK) + stage = 2; + break; + } + case 2: { + if (pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0)) { + TrampleCasted = false; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + stage = 3; + resetTimer(SPELL_TRAMPLE); + DoScriptText(-1713506,m_creature,pTarget); + SetCombatMovement(false); + m_creature->GetMotionMaster()->MoveIdle(); + } + break; + } + case 3: { + if (timedQuery(SPELL_TRAMPLE,uiDiff)) { + if (pTarget && pTarget->isAlive() && (pTarget->IsWithinDistInMap(m_creature, 200.0f))) { + pTarget->GetPosition(fPosX, fPosY, fPosZ); + TrampleCasted = false; + MovementStarted = true; + m_creature->GetMotionMaster()->MovePoint(1, fPosX, fPosY, fPosZ); + DoScriptText(-1713508,m_creature); + doCast(SPELL_ADRENALINE); + stage = 4; + } + else { + TrampleCasted = true; + stage = 5; + } + } + break; + } + case 4: { + if (MovementStarted) + { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) continue; + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 5.0f)) { + doCast(SPELL_TRAMPLE, pPlayer); + TrampleCasted = true; + MovementStarted = false; + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + } + + } else stage = 5; + if (TrampleCasted) stage = 5; + break; + } + case 5: { + if (!TrampleCasted) { + doCast(SPELL_STAGGERED_DAZE); + DoScriptText(-1713507,m_creature); + } + MovementStarted = false; + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + SetCombatMovement(true); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + stage = 0; + break; + } + } + } }; @@ -217,4 +670,14 @@ void AddSC_northrend_beasts() newscript->GetAI = &GetAI_boss_icehowl; newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "mob_snobold_vassal"; + newscript->GetAI = &GetAI_mob_snobold_vassal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_slime_pool"; + newscript->GetAI = &GetAI_mob_slime_pool; + newscript->RegisterSelf(); + } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp index 5923e63..a1f7075 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/boss_twin_valkyr.cpp @@ -16,48 +16,211 @@ /* ScriptData SDName: trial_of_the_crusader -SD%Complete: 0 -SDComment: +SD%Complete: 80% +SDComment: by /dev/rsa SDCategory: Crusader Coliseum EndScriptData */ +// Twin pact - heal part not worked now by undefined reason. Need override? +// timers need correct + #include "precompiled.h" #include "trial_of_the_crusader.h" -enum +enum Equipment { - SAY_AGGRO = -1649056, - SAY_BERSERK = -1649057, - SAY_COLORSWITCH = -1649058, - SAY_DEATH = -1649059, - SAY_SLAY_1 = -1649060, - SAY_SLAY_2 = -1649061, - SAY_TO_BLACK = -1649062, - SAY_TO_WHITE = -1649063, + EQUIP_MAIN_1 = 49303, + EQUIP_OFFHAND_1 = 47146, + EQUIP_RANGED_1 = 47267, + EQUIP_MAIN_2 = 45990, + EQUIP_OFFHAND_2 = 47470, + EQUIP_RANGED_2 = 47267, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; + +enum Summons +{ + NPC_DARK_ESSENCE = 34567, + NPC_LIGHT_ESSENCE = 34568, + + NPC_UNLEASHED_DARK = 34628, + NPC_UNLEASHED_LIGHT = 34630, }; -/*###### -## boss_fjola -######*/ +enum BossSpells +{ + SPELL_TWIN_SPIKE_L = 66075, + SPELL_LIGHT_SURGE = 65766, + SPELL_SHIELD_LIGHT = 65858, + SPELL_TWIN_PACT_L = 65875, + SPELL_LIGHT_VORTEX = 66046, + SPELL_LIGHT_TOUCH = 67297, + SPELL_TWIN_SPIKE_H = 66069, + SPELL_DARK_SURGE = 65768, + SPELL_SHIELD_DARK = 65874, + SPELL_TWIN_PACT_H = 65876, + SPELL_DARK_VORTEX = 66058, + SPELL_DARK_TOUCH = 67282, + SPELL_TWIN_POWER = 65916, + SPELL_LIGHT_ESSENCE = 65686, + SPELL_DARK_ESSENCE = 65684, + SPELL_BERSERK = 64238, + SPELL_REMOVE_TOUCH = 68084, + SPELL_NONE = 0, +// + SPELL_UNLEASHED_DARK = 65808, + SPELL_UNLEASHED_LIGHT = 65795, +}; -struct MANGOS_DLL_DECL boss_fjolaAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_fjolaAI : public BSWScriptedAI { - boss_fjolaAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + boss_fjolaAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } ScriptedInstance* m_pInstance; + uint8 stage; - void Reset() {} + void Reset() { + if(!m_pInstance) return; + SetEquipmentSlots(false, EQUIP_MAIN_1, EQUIP_OFFHAND_1, EQUIP_RANGED_1); + m_creature->SetRespawnDelay(7*DAY); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + } + + void JustReachedHome() + { + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_VALKIRIES, FAIL); + m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetMaxHealth()); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + m_creature->ForcedDespawn(); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + DoScriptText(-1713547,m_creature); + if (Creature* pSister = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_DARKBANE))) + if (!pSister->isAlive()) + m_pInstance->SetData(TYPE_VALKIRIES, DONE); + else m_pInstance->SetData(TYPE_VALKIRIES, SPECIAL); + m_pInstance->SetData(DATA_HEALTH_FJOLA, 0); + } + + void KilledUnit(Unit* pVictim) + { + if (!m_pInstance) return; + DoScriptText(-1713544,m_creature,pVictim); + } void Aggro(Unit* pWho) { + if (!m_pInstance) return; m_creature->SetInCombatWithZone(); + m_pInstance->SetData(TYPE_VALKIRIES, IN_PROGRESS); + if (m_creature->isAlive()) m_creature->SummonCreature(NPC_LIGHT_ESSENCE, SpawnLoc[24].x, SpawnLoc[24].y, SpawnLoc[24].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + if (m_creature->isAlive()) m_creature->SummonCreature(NPC_LIGHT_ESSENCE, SpawnLoc[25].x, SpawnLoc[25].y, SpawnLoc[25].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + DoScriptText(-1713541,m_creature); + m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetMaxHealth()); + doCast(SPELL_LIGHT_SURGE); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!m_pInstance) return; + if (!m_creature || !m_creature->isAlive()) + return; + + if(pDoneBy->GetGUID() == m_creature->GetGUID()) return; + + if(pDoneBy->GetTypeId() == TYPEID_PLAYER) + { + if(pDoneBy->HasAura(SPELL_LIGHT_ESSENCE)) + uiDamage /= 2; + else if(pDoneBy->HasAura(SPELL_DARK_ESSENCE)) + uiDamage += uiDamage/2; + } + + m_pInstance->SetData(DATA_HEALTH_FJOLA, m_creature->GetHealth() >= uiDamage ? m_creature->GetHealth() - uiDamage : 0); } void UpdateAI(const uint32 uiDiff) { + if (!m_pInstance) return; if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if (m_creature->GetHealth() > m_pInstance->GetData(DATA_HEALTH_EYDIS) && + m_pInstance->GetData(DATA_HEALTH_EYDIS) != 0) + m_creature->SetHealth(m_pInstance->GetData(DATA_HEALTH_EYDIS)); + + switch (stage) + { + case 0: + timedCast(SPELL_TWIN_SPIKE_L, uiDiff); + + if (timedQuery(SPELL_LIGHT_TOUCH, uiDiff)) + { + if (Unit* pTarget = doSelectRandomPlayer(SPELL_LIGHT_ESSENCE, false, 50.0f)) + doCast(SPELL_LIGHT_TOUCH, pTarget); + doCast(NPC_UNLEASHED_LIGHT); + }; + if (m_pInstance->GetData(DATA_CASTING_VALKYRS) == SPELL_NONE ) + { + if (timedQuery(SPELL_LIGHT_VORTEX, uiDiff)) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_LIGHT_VORTEX); + DoScriptText(-1713538,m_creature); + stage = 1; + break; + }; + if (timedQuery(SPELL_TWIN_PACT_L, uiDiff) + && m_creature->GetHealthPercent() <= 50.0f) + { + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_SHIELD_LIGHT); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_TWIN_PACT_L); + DoScriptText(-1713539,m_creature); + stage = 3; + }; + }; + if (m_pInstance->GetData(DATA_CASTING_VALKYRS) == SPELL_TWIN_PACT_H) + if (!m_creature->HasAura(SPELL_TWIN_POWER)) + doCast(SPELL_TWIN_POWER); + break; + case 1: + doCast(SPELL_LIGHT_VORTEX); + stage = 2; + break; + case 2: + if (!m_creature->HasAura(SPELL_LIGHT_VORTEX) + && timedQuery(SPELL_SHIELD_LIGHT, uiDiff)) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + }; + break; + case 3: + doCast(SPELL_TWIN_PACT_L); + stage = 4; + break; + case 4: + if (!m_creature->HasAura(SPELL_SHIELD_LIGHT) + && timedQuery(SPELL_SHIELD_LIGHT, uiDiff)) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + }; + default: + break; + } + + timedCast(SPELL_BERSERK, uiDiff); + DoMeleeAttackIfReady(); } }; @@ -67,19 +230,80 @@ CreatureAI* GetAI_boss_fjola(Creature* pCreature) return new boss_fjolaAI(pCreature); } -/*###### -## boss_eydis -######*/ - -struct MANGOS_DLL_DECL boss_eydisAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_eydisAI : public BSWScriptedAI { - boss_eydisAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + boss_eydisAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint8 stage; + + void Reset() + { + if(!m_pInstance) return; + SetEquipmentSlots(false, EQUIP_MAIN_2, EQUIP_OFFHAND_2, EQUIP_RANGED_2); + m_creature->SetRespawnDelay(7*DAY); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + } - void Reset() {} + void JustReachedHome() + { + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_VALKIRIES, FAIL); + m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetMaxHealth()); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + m_creature->ForcedDespawn(); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + DoScriptText(-1713547,m_creature); + if (Creature* pSister = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_LIGHTBANE))) + if (!pSister->isAlive()) + m_pInstance->SetData(TYPE_VALKIRIES, DONE); + else m_pInstance->SetData(TYPE_VALKIRIES, SPECIAL); + m_pInstance->SetData(DATA_HEALTH_EYDIS, 0); + } + + void KilledUnit(Unit* pVictim) + { + DoScriptText(-1713543,m_creature,pVictim); + } void Aggro(Unit* pWho) { + if (!m_pInstance) return; m_creature->SetInCombatWithZone(); + m_pInstance->SetData(TYPE_VALKIRIES, IN_PROGRESS); + DoScriptText(-1713741,m_creature); + if (m_creature->isAlive()) m_creature->SummonCreature(NPC_DARK_ESSENCE, SpawnLoc[22].x, SpawnLoc[22].y, SpawnLoc[22].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + if (m_creature->isAlive()) m_creature->SummonCreature(NPC_DARK_ESSENCE, SpawnLoc[23].x, SpawnLoc[23].y, SpawnLoc[23].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetMaxHealth()); + doCast(SPELL_DARK_SURGE); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!m_pInstance) return; + if (!m_creature || !m_creature->isAlive()) + return; + + if(pDoneBy->GetGUID() == m_creature->GetGUID()) return; + + if(pDoneBy->GetTypeId() == TYPEID_PLAYER) + { + if(pDoneBy->HasAura(SPELL_DARK_ESSENCE)) + uiDamage /= 2; + else if(pDoneBy->HasAura(SPELL_LIGHT_ESSENCE)) + uiDamage += uiDamage/2; + } + + m_pInstance->SetData(DATA_HEALTH_EYDIS, m_creature->GetHealth() >= uiDamage ? m_creature->GetHealth() - uiDamage : 0); } void UpdateAI(const uint32 uiDiff) @@ -87,6 +311,74 @@ struct MANGOS_DLL_DECL boss_eydisAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if (m_creature->GetHealth() > m_pInstance->GetData(DATA_HEALTH_FJOLA) && + m_pInstance->GetData(DATA_HEALTH_FJOLA) != 0) + m_creature->SetHealth(m_pInstance->GetData(DATA_HEALTH_FJOLA)); + + switch (stage) + { + case 0: + timedCast(SPELL_TWIN_SPIKE_H, uiDiff); + + if (timedQuery(SPELL_DARK_TOUCH, uiDiff)) + { + if (Unit* pTarget = doSelectRandomPlayer(SPELL_DARK_ESSENCE, false, 50.0f)) + doCast(SPELL_DARK_TOUCH, pTarget); + doCast(NPC_UNLEASHED_DARK); + }; + if (m_pInstance->GetData(DATA_CASTING_VALKYRS) == SPELL_NONE ) + { + if (timedQuery(SPELL_DARK_VORTEX, uiDiff)) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_DARK_VORTEX); + DoScriptText(-1713540,m_creature); + stage = 1; + break; + }; + if (timedQuery(SPELL_TWIN_PACT_H, uiDiff) + && m_creature->GetHealthPercent() <= 50.0f) + { + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_SHIELD_DARK); + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_TWIN_PACT_H); + DoScriptText(-1713539,m_creature); + stage = 3; + break; + }; + }; + if (m_pInstance->GetData(DATA_CASTING_VALKYRS) == SPELL_TWIN_PACT_L) + if (!m_creature->HasAura(SPELL_TWIN_POWER)) + doCast(SPELL_TWIN_POWER); + break; + case 1: + doCast(SPELL_DARK_VORTEX); + stage = 2; + break; + case 2: + if (!m_creature->HasAura(SPELL_DARK_VORTEX) + && timedQuery(SPELL_SHIELD_DARK, uiDiff)) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + }; + break; + case 3: + doCast(SPELL_TWIN_PACT_H); + stage = 4; + break; + case 4: + if (!m_creature->HasAura(SPELL_SHIELD_DARK) + && timedQuery(SPELL_SHIELD_DARK, uiDiff)) + { + m_pInstance->SetData(DATA_CASTING_VALKYRS, SPELL_NONE); + stage = 0; + }; + default: + break; + } + + timedCast(SPELL_BERSERK, uiDiff); + DoMeleeAttackIfReady(); } }; @@ -96,6 +388,250 @@ CreatureAI* GetAI_boss_eydis(Creature* pCreature) return new boss_eydisAI(pCreature); } +struct MANGOS_DLL_DECL mob_light_essenceAI : public ScriptedAI +{ + mob_light_essenceAI(Creature* pCreature) : ScriptedAI(pCreature) { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + ScriptedInstance* m_pInstance; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MoveRandom(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) m_creature->ForcedDespawn(); + if (m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) continue; + if (pPlayer->isAlive()) + pPlayer->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE); + } + + m_creature->ForcedDespawn(); + } + return; + } +}; + +CreatureAI* GetAI_mob_light_essence(Creature* pCreature) +{ + return new mob_light_essenceAI(pCreature); +}; + +bool GossipHello_mob_light_essence(Player *player, Creature* pCreature) +{ + ScriptedInstance *pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + if(!pInstance) return true; + player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + player->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE); +// player->CastSpell(player,SPELL_REMOVE_TOUCH,false); // Not worked now + player->CastSpell(player,SPELL_LIGHT_ESSENCE,false); + player->RemoveAurasDueToSpell(SPELL_LIGHT_TOUCH); // Override for REMOVE_TOUCH + player->CLOSE_GOSSIP_MENU(); + return true; +}; + +struct MANGOS_DLL_DECL mob_dark_essenceAI : public ScriptedAI +{ + mob_dark_essenceAI(Creature* pCreature) : ScriptedAI(pCreature) { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + ScriptedInstance* m_pInstance; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MoveRandom(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) m_creature->ForcedDespawn(); + if (m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) continue; + if (pPlayer->isAlive()) + pPlayer->RemoveAurasDueToSpell(SPELL_DARK_ESSENCE); + } + m_creature->ForcedDespawn(); + } + return; + } +}; + +CreatureAI* GetAI_mob_dark_essence(Creature* pCreature) +{ + return new mob_dark_essenceAI(pCreature); +}; + +bool GossipHello_mob_dark_essence(Player *player, Creature* pCreature) +{ + ScriptedInstance *pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + if(!pInstance) return true; + player->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, pCreature->GetGUID()); + player->RemoveAurasDueToSpell(SPELL_LIGHT_ESSENCE); +// player->CastSpell(player,SPELL_REMOVE_TOUCH,false); // Not worked now + player->CastSpell(player,SPELL_DARK_ESSENCE,false); + player->RemoveAurasDueToSpell(SPELL_DARK_TOUCH); // Override for REMOVE_TOUCH + player->CLOSE_GOSSIP_MENU(); + return true; +} + +struct MANGOS_DLL_DECL mob_unleashed_darkAI : public ScriptedAI +{ + mob_unleashed_darkAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_uiRangeCheck_Timer; + Creature* pboss1; + Creature* pboss2; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + m_creature->GetMotionMaster()->MoveRandom(); + m_uiRangeCheck_Timer = 1000; + pboss1 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_DARKBANE)); + pboss2 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_LIGHTBANE)); + } + + void AttackStart(Unit *pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_uiRangeCheck_Timer < uiDiff) + { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) continue; + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 2.0f)) + { + m_creature->CastSpell(m_creature, SPELL_UNLEASHED_DARK, true); + m_creature->ForcedDespawn(); + } + + } + if (pboss1 && pboss1->isAlive() && pboss1->IsWithinDistInMap(m_creature, 2.0f)) + { + m_creature->CastSpell(m_creature, SPELL_UNLEASHED_DARK, true); + m_creature->ForcedDespawn(); + } + if (pboss2 && pboss2->isAlive() && pboss2->IsWithinDistInMap(m_creature, 2.0f)) + { + m_creature->CastSpell(m_creature, SPELL_UNLEASHED_DARK, true); + m_creature->ForcedDespawn(); + } + m_uiRangeCheck_Timer = 1000; + } + else m_uiRangeCheck_Timer -= uiDiff; + } + +}; + +CreatureAI* GetAI_mob_unleashed_dark(Creature *pCreature) +{ + return new mob_unleashed_darkAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_unleashed_lightAI : public ScriptedAI +{ + mob_unleashed_lightAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_uiRangeCheck_Timer; + Creature* pboss1; + Creature* pboss2; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + m_creature->GetMotionMaster()->MoveRandom(); + m_uiRangeCheck_Timer = 1000; + pboss1 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_DARKBANE)); + pboss2 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_LIGHTBANE)); + } + + void AttackStart(Unit *pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_VALKIRIES) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_uiRangeCheck_Timer < uiDiff) + { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + Unit* pPlayer = itr->getSource(); + if (!pPlayer) continue; + if (pPlayer->isAlive() && pPlayer->IsWithinDistInMap(m_creature, 2.0f)) + { + m_creature->CastSpell(m_creature, SPELL_UNLEASHED_LIGHT, true); + m_creature->ForcedDespawn(); + } + } + if (pboss1 && pboss1->isAlive() && pboss1->IsWithinDistInMap(m_creature, 2.0f)) + { + m_creature->CastSpell(m_creature, SPELL_UNLEASHED_LIGHT, true); + m_creature->ForcedDespawn(); + } + if (pboss2 && pboss2->isAlive() && pboss2->IsWithinDistInMap(m_creature, 2.0f)) + { + m_creature->CastSpell(m_creature, SPELL_UNLEASHED_LIGHT, true); + m_creature->ForcedDespawn(); + } + m_uiRangeCheck_Timer = 1000; + } + else m_uiRangeCheck_Timer -= uiDiff; + } + +}; + +CreatureAI* GetAI_mob_unleashed_light(Creature *pCreature) +{ + return new mob_unleashed_lightAI(pCreature); +} + void AddSC_twin_valkyr() { Script* newscript; @@ -107,6 +643,29 @@ void AddSC_twin_valkyr() newscript = new Script; newscript->Name = "boss_eydis"; - newscript->GetAI = &GetAI_boss_fjola; + newscript->GetAI = &GetAI_boss_eydis; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_unleashed_light"; + newscript->GetAI = &GetAI_mob_unleashed_light; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_unleashed_dark"; + newscript->GetAI = &GetAI_mob_unleashed_dark; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_light_essence"; + newscript->GetAI = &GetAI_mob_light_essence; + newscript->pGossipHello = &GossipHello_mob_light_essence; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_essence"; + newscript->GetAI = &GetAI_mob_dark_essence; + newscript->pGossipHello = &GossipHello_mob_dark_essence; + newscript->RegisterSelf(); + } diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp index 9fba55a..4388690 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/instance_trial_of_the_crusader.cpp @@ -1,185 +1,606 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_trial_of_the_crusader -SD%Complete: 100 -SDComment: -SDCategory: Crusader Coliseum +SD%Complete: 80% +SDComment: by /dev/rsa +SDCategory: Trial of the Crusader EndScriptData */ #include "precompiled.h" #include "trial_of_the_crusader.h" -/* Trial Of The Crusader encounters: -0 - Northrend Beasts -1 - Jaraxxus -2 - Faction Champions -3 - Twin Valkyr -4 - Anubarak -*/ - struct MANGOS_DLL_DECL instance_trial_of_the_crusader : public ScriptedInstance { - instance_trial_of_the_crusader(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + instance_trial_of_the_crusader(Map* pMap) : ScriptedInstance(pMap) { + Difficulty = pMap->GetDifficulty(); + Initialize(); + } + + uint32 m_auiEncounter[MAX_ENCOUNTERS+1]; + uint32 m_auiEventTimer; + uint32 m_auiEventNPCId; + uint32 m_auiNorthrendBeasts; + uint8 Difficulty; + std::string m_strInstData; + bool needsave; + + uint32 m_uiDataDamageFjola; + uint32 m_uiDataDamageEydis; + uint32 m_uiValkyrsCasting; + + uint32 m_auiCrusadersCount; + + uint64 m_uiBarrentGUID; + uint64 m_uiTirionGUID; + uint64 m_uiFizzlebangGUID; + uint64 m_uiGarroshGUID; + uint64 m_uiRinnGUID; + uint64 m_uiLich0GUID; + uint64 m_uiLich1GUID; + + uint64 m_uiGormokGUID; + uint64 m_uiAcidmawGUID; + uint64 m_uiDreadscaleGUID; + uint64 m_uiIcehowlGUID; + uint64 m_uiJaraxxusGUID; + uint64 m_uiDarkbaneGUID; + uint64 m_uiLightbaneGUID; + uint64 m_uiAnubarakGUID; + + uint64 m_uiCrusader11Guid; + uint64 m_uiCrusader12Guid; + uint64 m_uiCrusader13Guid; + uint64 m_uiCrusader14Guid; + uint64 m_uiCrusader15Guid; + uint64 m_uiCrusader16Guid; + uint64 m_uiCrusader17Guid; + uint64 m_uiCrusader18Guid; + uint64 m_uiCrusader19Guid; + uint64 m_uiCrusader1aGuid; + uint64 m_uiCrusader1bGuid; + uint64 m_uiCrusader1cGuid; + uint64 m_uiCrusader1dGuid; + uint64 m_uiCrusader1eGuid; - uint32 m_auiEncounter[MAX_ENCOUNTER]; - std::string strInstData; + uint64 m_uiCrusader21Guid; + uint64 m_uiCrusader22Guid; + uint64 m_uiCrusader23Guid; + uint64 m_uiCrusader24Guid; + uint64 m_uiCrusader25Guid; + uint64 m_uiCrusader26Guid; + uint64 m_uiCrusader27Guid; + uint64 m_uiCrusader28Guid; + uint64 m_uiCrusader29Guid; + uint64 m_uiCrusader2aGuid; + uint64 m_uiCrusader2bGuid; + uint64 m_uiCrusader2cGuid; + uint64 m_uiCrusader2dGuid; + uint64 m_uiCrusader2eGuid; + + uint64 m_uiCrusader01Guid; + uint64 m_uiCrusader02Guid; + + uint64 m_uiCrusadersCacheGUID; + uint64 m_uiFloorGUID; + + uint64 m_uiTC10h25GUID; + uint64 m_uiTC10h45GUID; + uint64 m_uiTC10h50GUID; + uint64 m_uiTC10h99GUID; + + uint64 m_uiTC25h25GUID; + uint64 m_uiTC25h45GUID; + uint64 m_uiTC25h50GUID; + uint64 m_uiTC25h99GUID; + + uint64 m_uiTributeChest1GUID; + uint64 m_uiTributeChest2GUID; + uint64 m_uiTributeChest3GUID; + uint64 m_uiTributeChest4GUID; + + uint64 m_uiMainGateDoorGUID; + + uint64 m_uiWestPortcullisGUID; + uint64 m_uiNorthPortcullisGUID; + uint64 m_uiSouthPortcullisGUID; - uint32 m_uiGormokGUID; - uint32 m_uiAcidmawGUID; - uint32 m_uiDreadscaleGUID; - uint32 m_uiIcehowlGUID; - uint32 m_uiJaraxxusGUID; - uint32 m_uiFjolaGUID; - uint32 m_uiEydisGUID; - uint32 m_uiAnubarakGUID; void Initialize() { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + m_auiEncounter[i] = NOT_STARTED; + + m_auiEncounter[0] = 0; + m_auiEncounter[7] = 50; + m_auiEncounter[8] = 0; + + m_uiTributeChest1GUID = 0; + m_uiTributeChest2GUID = 0; + m_uiTributeChest3GUID = 0; + m_uiTributeChest4GUID = 0; + m_uiDataDamageFjola = 0; + m_uiDataDamageEydis = 0; + m_uiLich0GUID = 0; + m_uiLich1GUID = 0; + + m_auiNorthrendBeasts = NOT_STARTED; - m_uiGormokGUID = 0; - m_uiAcidmawGUID = 0; - m_uiDreadscaleGUID = 0; - m_uiIcehowlGUID = 0; - m_uiJaraxxusGUID = 0; - m_uiFjolaGUID = 0; - m_uiEydisGUID = 0; - m_uiAnubarakGUID = 0; + m_auiEventTimer = 1000; + m_auiCrusadersCount = 6; + + needsave = false; } bool IsEncounterInProgress() const { - for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + for(uint8 i = 1; i < MAX_ENCOUNTERS-2 ; ++i) if (m_auiEncounter[i] == IN_PROGRESS) return true; return false; } - void OnCreatureCreate(Creature* pCreature) + void OnPlayerEnter(Player *m_player) + { + if (Difficulty == RAID_DIFFICULTY_10MAN_HEROIC || Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) + { + m_player->SendUpdateWorldState(UPDATE_STATE_UI_SHOW,1); + m_player->SendUpdateWorldState(UPDATE_STATE_UI_COUNT, GetData(TYPE_COUNTER)); + } + } + + bool IsRaidWiped() { + Map::PlayerList const &players = instance->GetPlayers(); + + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + if(Player* pPlayer = i->getSource()) + { + if(pPlayer->isAlive()) + return false; + } + } + return true; + } + + void OpenDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + } + + void CloseDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_READY); + } + + void OnCreatureCreate(Creature* pCreature) + { switch(pCreature->GetEntry()) { - case 34796: m_uiGormokGUID = pCreature->GetGUID(); break; - case 35144: m_uiAcidmawGUID = pCreature->GetGUID(); break; - case 34799: m_uiDreadscaleGUID = pCreature->GetGUID(); break; - case 34797: m_uiIcehowlGUID = pCreature->GetGUID(); break; - case 34780: m_uiJaraxxusGUID = pCreature->GetGUID(); break; - case 34497: m_uiFjolaGUID = pCreature->GetGUID(); break; - case 34496: m_uiEydisGUID = pCreature->GetGUID(); break; - case 34564: m_uiAnubarakGUID = pCreature->GetGUID(); break; + case NPC_BARRENT: m_uiBarrentGUID = pCreature->GetGUID(); break; + case NPC_TIRION: m_uiTirionGUID = pCreature->GetGUID(); break; + case NPC_FIZZLEBANG: m_uiFizzlebangGUID = pCreature->GetGUID(); break; + case NPC_GARROSH: m_uiGarroshGUID = pCreature->GetGUID(); break; + case NPC_RINN: m_uiRinnGUID = pCreature->GetGUID(); break; + case NPC_LICH_KING_0: m_uiLich0GUID = pCreature->GetGUID(); break; + case NPC_LICH_KING_1: m_uiLich1GUID = pCreature->GetGUID(); break; + + case NPC_GORMOK: m_uiGormokGUID = pCreature->GetGUID(); break; + case NPC_ACIDMAW: m_uiAcidmawGUID = pCreature->GetGUID(); break; + case NPC_DREADSCALE: m_uiDreadscaleGUID = pCreature->GetGUID(); break; + case NPC_ICEHOWL: m_uiIcehowlGUID = pCreature->GetGUID(); break; + case NPC_JARAXXUS: m_uiJaraxxusGUID = pCreature->GetGUID(); break; + case NPC_DARKBANE: m_uiDarkbaneGUID = pCreature->GetGUID(); break; + case NPC_LIGHTBANE: m_uiLightbaneGUID = pCreature->GetGUID(); break; + case NPC_ANUBARAK: m_uiAnubarakGUID = pCreature->GetGUID(); break; + + case NPC_CRUSADER_1_1: m_uiCrusader11Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_2: m_uiCrusader12Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_3: m_uiCrusader13Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_4: m_uiCrusader14Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_5: m_uiCrusader15Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_6: m_uiCrusader16Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_7: m_uiCrusader17Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_8: m_uiCrusader18Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_9: m_uiCrusader19Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_10: m_uiCrusader1aGuid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_11: m_uiCrusader1bGuid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_12: m_uiCrusader1cGuid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_13: m_uiCrusader1dGuid = pCreature->GetGUID(); break; + case NPC_CRUSADER_1_14: m_uiCrusader1eGuid = pCreature->GetGUID(); break; + + case NPC_CRUSADER_2_1: m_uiCrusader21Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_2: m_uiCrusader22Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_3: m_uiCrusader23Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_4: m_uiCrusader24Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_5: m_uiCrusader25Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_6: m_uiCrusader26Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_7: m_uiCrusader27Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_8: m_uiCrusader28Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_9: m_uiCrusader29Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_10: m_uiCrusader2aGuid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_11: m_uiCrusader2bGuid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_12: m_uiCrusader2cGuid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_13: m_uiCrusader2dGuid = pCreature->GetGUID(); break; + case NPC_CRUSADER_2_14: m_uiCrusader2eGuid = pCreature->GetGUID(); break; + + case NPC_CRUSADER_0_1: m_uiCrusader01Guid = pCreature->GetGUID(); break; + case NPC_CRUSADER_0_2: m_uiCrusader02Guid = pCreature->GetGUID(); break; } } - void SetData(uint32 uiType, uint32 uiData) + void OnObjectCreate(GameObject *pGo) { - debug_log("SD2: Instance Trial Of The Crusader: SetData received for type %u with data %u",uiType,uiData); + switch(pGo->GetEntry()) + { + case GO_CRUSADERS_CACHE_10: + if(Difficulty == RAID_DIFFICULTY_10MAN_NORMAL) + m_uiCrusadersCacheGUID = pGo->GetGUID(); + break; + case GO_CRUSADERS_CACHE_25: + if(Difficulty == RAID_DIFFICULTY_25MAN_NORMAL) + m_uiCrusadersCacheGUID = pGo->GetGUID(); + break; + case GO_CRUSADERS_CACHE_10_H: + if(Difficulty == RAID_DIFFICULTY_10MAN_HEROIC) + m_uiCrusadersCacheGUID = pGo->GetGUID(); + break; + case GO_CRUSADERS_CACHE_25_H: + if(Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) + m_uiCrusadersCacheGUID = pGo->GetGUID(); + break; + case GO_ARGENT_COLISEUM_FLOOR: + m_uiFloorGUID = pGo->GetGUID(); + break; + case GO_MAIN_GATE_DOOR: m_uiMainGateDoorGUID = pGo->GetGUID(); break; + + case GO_SOUTH_PORTCULLIS: m_uiSouthPortcullisGUID = pGo->GetGUID(); break; + case GO_WEST_PORTCULLIS: m_uiWestPortcullisGUID = pGo->GetGUID(); break; + case GO_NORTH_PORTCULLIS: m_uiNorthPortcullisGUID = pGo->GetGUID(); break; + + case GO_TRIBUTE_CHEST_10H_25: m_uiTC10h25GUID = pGo->GetGUID(); break; + case GO_TRIBUTE_CHEST_10H_45: m_uiTC10h45GUID = pGo->GetGUID(); break; + case GO_TRIBUTE_CHEST_10H_50: m_uiTC10h50GUID = pGo->GetGUID(); break; + case GO_TRIBUTE_CHEST_10H_99: m_uiTC10h99GUID = pGo->GetGUID(); break; + + case GO_TRIBUTE_CHEST_25H_25: m_uiTC25h25GUID = pGo->GetGUID(); break; + case GO_TRIBUTE_CHEST_25H_45: m_uiTC25h45GUID = pGo->GetGUID(); break; + case GO_TRIBUTE_CHEST_25H_50: m_uiTC25h50GUID = pGo->GetGUID(); break; + case GO_TRIBUTE_CHEST_25H_99: m_uiTC25h99GUID = pGo->GetGUID(); break; + } + } + void SetData(uint32 uiType, uint32 uiData) + { switch(uiType) { - case TYPE_NORTHREND_BEASTS: - m_auiEncounter[0] = uiData; - break; - case TYPE_JARAXXUS: - m_auiEncounter[1] = uiData; - break; - case TYPE_FACTION_CHAMPIONS: - m_auiEncounter[2] = uiData; - break; - case TYPE_TWIN_VALKYR: - m_auiEncounter[3] = uiData; - break; - case TYPE_ANUBARAK: - m_auiEncounter[4] = uiData; - break; - default: - error_log("SD2: Instance Trial of The Crusader: ERROR SetData = %u for type %u does not exist/not implemented.",uiType,uiData); - break; + case TYPE_STAGE: m_auiEncounter[0] = uiData; break; + case TYPE_BEASTS: m_auiEncounter[1] = uiData; break; + case TYPE_JARAXXUS: m_auiEncounter[2] = uiData; break; + case TYPE_CRUSADERS: if (uiData == FAIL && (m_auiEncounter[3] == FAIL || m_auiEncounter[3] == NOT_STARTED)) + m_auiEncounter[3] = NOT_STARTED; + else m_auiEncounter[3] = uiData; + if (uiData == DONE) { + if (GameObject* pChest = instance->GetGameObject(m_uiCrusadersCacheGUID)) + if (pChest && !pChest->isSpawned()) + pChest->SetRespawnTime(7*DAY); + }; + break; + case TYPE_CRUSADERS_COUNT: if (uiData == 0) --m_auiCrusadersCount; + else m_auiCrusadersCount = uiData; + break; + case TYPE_VALKIRIES: if (m_auiEncounter[4] == SPECIAL && uiData == SPECIAL) uiData = DONE; + m_auiEncounter[4] = uiData; break; + case TYPE_LICH_KING: m_auiEncounter[5] = uiData; break; + case TYPE_ANUBARAK: m_auiEncounter[6] = uiData; + if (uiData == DONE) { + if(Difficulty == RAID_DIFFICULTY_10MAN_HEROIC){ + if ( m_auiEncounter[7] >= 25) m_uiTributeChest1GUID = m_uiTC10h25GUID; + if ( m_auiEncounter[7] >= 45) m_uiTributeChest2GUID = m_uiTC10h45GUID; + if ( m_auiEncounter[7] >= 49) m_uiTributeChest3GUID = m_uiTC10h50GUID; + m_uiTributeChest4GUID = m_uiTC10h99GUID; + } + if(Difficulty == RAID_DIFFICULTY_25MAN_HEROIC){ + if ( m_auiEncounter[7] >= 25) m_uiTributeChest1GUID = m_uiTC25h25GUID; + if ( m_auiEncounter[7] >= 45) m_uiTributeChest2GUID = m_uiTC25h45GUID; + if ( m_auiEncounter[7] >= 49) m_uiTributeChest3GUID = m_uiTC25h50GUID; + m_uiTributeChest4GUID = m_uiTC25h99GUID; + } + // Attention! It is (may be) not off-like, but spawning all Tribute Chests is real + // reward for clearing TOC instance + if (m_uiTributeChest1GUID) + if (GameObject* pChest1 = instance->GetGameObject(m_uiTributeChest1GUID)) + if (pChest1 && !pChest1->isSpawned()) pChest1->SetRespawnTime(7*DAY); + if (m_uiTributeChest2GUID) + if (GameObject* pChest2 = instance->GetGameObject(m_uiTributeChest2GUID)) + if (pChest2 && !pChest2->isSpawned()) pChest2->SetRespawnTime(7*DAY); + if (m_uiTributeChest3GUID) + if (GameObject* pChest3 = instance->GetGameObject(m_uiTributeChest3GUID)) + if (pChest3 && !pChest3->isSpawned()) pChest3->SetRespawnTime(7*DAY); + if (m_uiTributeChest4GUID) + if (GameObject* pChest4 = instance->GetGameObject(m_uiTributeChest4GUID)) + if (pChest4 && !pChest4->isSpawned()) pChest4->SetRespawnTime(7*DAY); + }; + break; + case TYPE_COUNTER: m_auiEncounter[7] = uiData; uiData = DONE; break; + case TYPE_EVENT: m_auiEncounter[8] = uiData; uiData = NOT_STARTED; break; + case TYPE_EVENT_TIMER: m_auiEventTimer = uiData; uiData = NOT_STARTED; break; + case TYPE_NORTHREND_BEASTS: m_auiNorthrendBeasts = uiData; break; + case DATA_HEALTH_FJOLA: m_uiDataDamageFjola = uiData; uiData = NOT_STARTED; break; + case DATA_HEALTH_EYDIS: m_uiDataDamageEydis = uiData; uiData = NOT_STARTED; break; + case DATA_CASTING_VALKYRS: m_uiValkyrsCasting = uiData; uiData = NOT_STARTED; break; + } + + if (IsEncounterInProgress()) { + CloseDoor(GetData64(GO_WEST_PORTCULLIS)); + CloseDoor(GetData64(GO_NORTH_PORTCULLIS)); +// CloseDoor(GetData64(GO_SOUTH_PORTCULLIS)); + } + else { + OpenDoor(GetData64(GO_WEST_PORTCULLIS)); + OpenDoor(GetData64(GO_NORTH_PORTCULLIS)); +// OpenDoor(GetData64(GO_SOUTH_PORTCULLIS)); + }; + + if (uiData == FAIL && uiType != TYPE_STAGE + && uiType != TYPE_EVENT + && uiType != TYPE_COUNTER + && uiType != TYPE_EVENT_TIMER) + { if (IsRaidWiped()) { --m_auiEncounter[7]; + needsave = true; + } + uiData = NOT_STARTED; } - if (uiData == DONE) + if ((uiData == DONE && uiType != TYPE_STAGE + && uiType != TYPE_EVENT + && uiType != TYPE_EVENT_TIMER) + || needsave == true) { OUT_SAVE_INST_DATA; std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4]; - strInstData = saveStream.str(); + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + saveStream << m_auiEncounter[i] << " "; + + m_strInstData = saveStream.str(); SaveToDB(); OUT_SAVE_INST_DATA_COMPLETE; + needsave = false; } } - uint32 GetData(uint32 uiType) + uint64 GetData64(uint32 uiData) { - switch(uiType) + switch(uiData) { - case TYPE_NORTHREND_BEASTS: return m_auiEncounter[0]; - case TYPE_JARAXXUS: return m_auiEncounter[1]; - case TYPE_FACTION_CHAMPIONS: return m_auiEncounter[2]; - case TYPE_TWIN_VALKYR: return m_auiEncounter[3]; - case TYPE_ANUBARAK: return m_auiEncounter[4]; + case NPC_BARRENT: return m_uiBarrentGUID; + case NPC_TIRION: return m_uiTirionGUID; + case NPC_FIZZLEBANG: return m_uiFizzlebangGUID; + case NPC_GARROSH: return m_uiGarroshGUID; + case NPC_RINN: return m_uiRinnGUID; + case NPC_LICH_KING_0: return m_uiLich0GUID; + case NPC_LICH_KING_1: return m_uiLich1GUID; + + case NPC_GORMOK: return m_uiGormokGUID; + case NPC_ACIDMAW: return m_uiAcidmawGUID; + case NPC_DREADSCALE: return m_uiDreadscaleGUID; + case NPC_ICEHOWL: return m_uiIcehowlGUID; + case NPC_JARAXXUS: return m_uiJaraxxusGUID; + case NPC_DARKBANE: return m_uiDarkbaneGUID; + case NPC_LIGHTBANE: return m_uiLightbaneGUID; + case NPC_ANUBARAK: return m_uiAnubarakGUID; + + case NPC_CRUSADER_1_1: return m_uiCrusader11Guid; + case NPC_CRUSADER_1_2: return m_uiCrusader12Guid; + case NPC_CRUSADER_1_3: return m_uiCrusader13Guid; + case NPC_CRUSADER_1_4: return m_uiCrusader14Guid; + case NPC_CRUSADER_1_5: return m_uiCrusader15Guid; + case NPC_CRUSADER_1_6: return m_uiCrusader16Guid; + case NPC_CRUSADER_1_7: return m_uiCrusader17Guid; + case NPC_CRUSADER_1_8: return m_uiCrusader18Guid; + case NPC_CRUSADER_1_9: return m_uiCrusader19Guid; + case NPC_CRUSADER_1_10: return m_uiCrusader1aGuid; + case NPC_CRUSADER_1_11: return m_uiCrusader1bGuid; + case NPC_CRUSADER_1_12: return m_uiCrusader1cGuid; + case NPC_CRUSADER_1_13: return m_uiCrusader1dGuid; + case NPC_CRUSADER_1_14: return m_uiCrusader1eGuid; + + case NPC_CRUSADER_2_1: return m_uiCrusader21Guid; + case NPC_CRUSADER_2_2: return m_uiCrusader22Guid; + case NPC_CRUSADER_2_3: return m_uiCrusader23Guid; + case NPC_CRUSADER_2_4: return m_uiCrusader24Guid; + case NPC_CRUSADER_2_5: return m_uiCrusader25Guid; + case NPC_CRUSADER_2_6: return m_uiCrusader26Guid; + case NPC_CRUSADER_2_7: return m_uiCrusader27Guid; + case NPC_CRUSADER_2_8: return m_uiCrusader28Guid; + case NPC_CRUSADER_2_9: return m_uiCrusader29Guid; + case NPC_CRUSADER_2_10: return m_uiCrusader2aGuid; + case NPC_CRUSADER_2_11: return m_uiCrusader2bGuid; + case NPC_CRUSADER_2_12: return m_uiCrusader2cGuid; + case NPC_CRUSADER_2_13: return m_uiCrusader2dGuid; + case NPC_CRUSADER_2_14: return m_uiCrusader2eGuid; + + case NPC_CRUSADER_0_1: return m_uiCrusader01Guid; + case NPC_CRUSADER_0_2: return m_uiCrusader02Guid; + + case GO_ARGENT_COLISEUM_FLOOR: return m_uiFloorGUID; + case GO_MAIN_GATE_DOOR: return m_uiMainGateDoorGUID; + + case GO_SOUTH_PORTCULLIS: return m_uiSouthPortcullisGUID; + case GO_WEST_PORTCULLIS: return m_uiWestPortcullisGUID; + case GO_NORTH_PORTCULLIS: return m_uiNorthPortcullisGUID; + } return 0; } - uint64 GetData64(uint32 uiData) + uint32 GetData(uint32 uiType) { - switch(uiData) + switch(uiType) { - case DATA_GORMOK: return m_uiGormokGUID; - case DATA_ACIDMAW: return m_uiAcidmawGUID; - case DATA_DREADSCALE: return m_uiDreadscaleGUID; - case DATA_ICEHOWL: return m_uiIcehowlGUID; - case DATA_JARAXXUS: return m_uiJaraxxusGUID; - case DATA_FJOLA: return m_uiFjolaGUID; - case DATA_EYDIS: return m_uiEydisGUID; - case DATA_ANUBARAK: return m_uiAnubarakGUID; + case TYPE_STAGE: return m_auiEncounter[0]; + case TYPE_BEASTS: return m_auiEncounter[1]; + case TYPE_JARAXXUS: return m_auiEncounter[2]; + case TYPE_CRUSADERS: return m_auiEncounter[3]; + case TYPE_VALKIRIES: return m_auiEncounter[4]; + case TYPE_LICH_KING: return m_auiEncounter[5]; + case TYPE_ANUBARAK: return m_auiEncounter[6]; + case TYPE_COUNTER: return m_auiEncounter[7]; + case TYPE_EVENT: return m_auiEncounter[8]; + case TYPE_DIFFICULTY: return Difficulty; + case TYPE_NORTHREND_BEASTS: return m_auiNorthrendBeasts; + case TYPE_EVENT_TIMER: return m_auiEventTimer; + case TYPE_CRUSADERS_COUNT: return m_auiCrusadersCount; + case TYPE_EVENT_NPC: switch (m_auiEncounter[8]) + { + case 110: + case 140: + case 150: + case 200: + case 205: + case 210: + case 300: + case 305: + case 310: + case 400: + case 666: + case 1010: + case 1180: + case 2000: + case 2030: + case 3000: + case 3001: + case 3060: + case 3061: + case 3090: + case 3091: + case 3100: + case 3110: + case 4000: + case 4010: + case 4015: + case 4040: + case 4050: + case 5000: + case 5005: + case 5020: + case 6000: + case 6005: + case 6010: + m_auiEventNPCId = NPC_TIRION; + break; + + case 5010: + case 5030: + case 5040: + case 5050: + case 5060: + case 5070: + case 5080: + m_auiEventNPCId = NPC_LICH_KING_1; + break; + + case 130: + case 132: + case 2020: + case 3080: + case 3051: + case 3071: + case 4020: + m_auiEventNPCId = NPC_RINN; + break; + + case 120: + case 122: + case 2010: + case 3050: + case 3070: + case 3081: + case 4030: + m_auiEventNPCId = NPC_GARROSH; + break; + + case 1110: + case 1120: + case 1130: + case 1132: + case 1134: + case 1135: + case 1140: + case 1142: + case 1144: + case 1145: + case 1150: + case 1160: + m_auiEventNPCId = NPC_FIZZLEBANG; + break; + + default: + m_auiEventNPCId = NPC_TIRION; + break; + + }; + return m_auiEventNPCId; + + case DATA_HEALTH_FJOLA: return m_uiDataDamageFjola; + case DATA_HEALTH_EYDIS: return m_uiDataDamageEydis; + case DATA_CASTING_VALKYRS: return m_uiValkyrsCasting; } return 0; } const char* Save() { - return strInstData.c_str(); + return m_strInstData.c_str(); } - void Load(const char* chrIn) + void Load(const char* strIn) { - if (!chrIn) + if (!strIn) { OUT_LOAD_INST_DATA_FAIL; return; } - OUT_LOAD_INST_DATA(chrIn); + OUT_LOAD_INST_DATA(strIn); - std::istringstream loadStream(chrIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] - >> m_auiEncounter[4]; + std::istringstream loadStream(strIn); - 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. + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + { + loadStream >> m_auiEncounter[i]; + + if (m_auiEncounter[i] == IN_PROGRESS) m_auiEncounter[i] = NOT_STARTED; + } + m_auiEncounter[TYPE_EVENT] = 0; + m_auiEncounter[TYPE_STAGE] = 0; OUT_LOAD_INST_DATA_COMPLETE; + } }; @@ -190,8 +611,7 @@ InstanceData* GetInstanceData_instance_trial_of_the_crusader(Map* pMap) void AddSC_instance_trial_of_the_crusader() { - Script* newscript; - + Script *newscript; newscript = new Script; newscript->Name = "instance_trial_of_the_crusader"; newscript->GetInstanceData = &GetInstanceData_instance_trial_of_the_crusader; diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp index 48ac55f..de3f3a8 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* 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 @@ -15,123 +15,1383 @@ */ /* ScriptData -SDName: trial_of_the_crusader -SD%Complete: 0 -SDComment: -SDCategory: Crusader Coliseum +SDName: Trial Of the crusader +SD%Complete: 60% +SDComment: event script by /dev/rsa +SDCategory: trial_of_the_crusader EndScriptData */ #include "precompiled.h" #include "trial_of_the_crusader.h" +struct _Messages +{ + AnnounserMessages msgnum; + uint32 id; + bool state; + uint32 encounter; +}; + +static _Messages _GossipMessage[]= +{ +{MSG_BEASTS,GOSSIP_ACTION_INFO_DEF+1,false,TYPE_BEASTS}, // +{MSG_JARAXXUS,GOSSIP_ACTION_INFO_DEF+2,false,TYPE_JARAXXUS}, // +{MSG_CRUSADERS,GOSSIP_ACTION_INFO_DEF+3,false,TYPE_CRUSADERS}, // +{MSG_VALKIRIES,GOSSIP_ACTION_INFO_DEF+4,false,TYPE_VALKIRIES}, // +{MSG_LICH_KING,GOSSIP_ACTION_INFO_DEF+5,false,TYPE_ANUBARAK}, // +{MSG_ANUBARAK,GOSSIP_ACTION_INFO_DEF+6,true,TYPE_ANUBARAK}, // +}; + enum { - SAY_TIRION_RAID_INTRO_LONG = -1649000, - SAY_RAID_TRIALS_INTRO = -1649001, - - // Northrend Beasts - SAY_TIRION_BEAST_1 = -1649002, - SAY_VARIAN_BEAST_1 = -1649003, - SAY_GARROSH_BEAST_1 = -1649004, - SAY_TIRION_BEAST_2 = -1649005, - SAY_TIRION_BEAST_3 = -1649006, - SAY_TIRION_BEAST_SLAY = -1649007, - SAY_TIRION_BEAST_WIPE = -1649008, - - // Jaraxxus Encounter - SAY_TIRION_JARAXXUS_INTRO_1 = -1649009, - SAY_WILFRED_JARAXXUS_INTRO_1 = -1649010, - SAY_WILFRED_JARAXXUS_INTRO_2 = -1649011, - SAY_WILFRED_JARAXXUS_INTRO_3 = -1649012, - SAY_JARAXXUS_JARAXXAS_INTRO_1 = -1649013, - SAY_WILFRED_DEATH = -1649014, - SAY_TIRION_JARAXXUS_INTRO_2 = -1649015, - SAY_TIRION_JARAXXUS_EXIT_1 = -1649016, - SAY_GARROSH_JARAXXUS_EXIT_1 = -1649017, - SAY_VARIAN_JARAXXUS_SLAY = -1649018, - SAY_TIRION_JARAXXUS_EXIT_2 = -1649019, - - // Faction-Champions - SAY_TIRION_PVP_INTRO_1 = -1649020, - SAY_GARROSH_PVP_A_INTRO_1 = -1649021, - SAY_VARIAN_PVP_H_INTRO_1 = -1649022, - SAY_TIRION_PVP_INTRO_2 = -1649023, - SAY_VARIAN_PVP_A_INTRO_2 = -1649024, - SAY_GARROSH_PVP_H_INTRO_2 = -1649025, - SAY_VARIAN_PVP_A_WIN = -1649026, - SAY_GARROSH_PVP_H_WIN = -1649027, - SAY_TIRION_PVP_WIN = -1649028, - - // Twin Valkyrs - SAY_TIRION_TWINS_INTRO = -1649029, - SAY_RAID_INTRO_SHORT = -1649030, - SAY_VARIAN_TWINS_A_WIN = -1649031, - SAY_GARROSH_TWINS_H_WIN = -1649032, - SAY_TIRION_TWINS_WIN = -1649033, - - // Anub'Arak Encounter - SAY_LKING_ANUB_INTRO_1 = -1649034, - SAY_TIRION_ABUN_INTRO_1 = -1649035, - SAY_LKING_ANUB_INTRO_2 = -1649036, - SAY_LKING_ANUB_INTRO_3 = -1649037, - SAY_ANUB_ANUB_INTRO_1 = -1649038, - - NPC_GORMOK = 34796, - NPC_JARAXXUS = 34780, - - GOSSIP_ITEM_START_EVENT1 = -3649000 + NUM_MESSAGES = 6, + SPELL_WILFRED_PORTAL = 68424, + SPELL_JARAXXUS_CHAINS = 67924, }; -/*###### -## npc_barrett_ramsey -######*/ -struct MANGOS_DLL_DECL npc_barrett_ramseyAI : public ScriptedAI +struct MANGOS_DLL_DECL npc_toc_announcerAI : public ScriptedAI { - npc_barrett_ramseyAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + npc_toc_announcerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } - ScriptedInstance* m_pInstance; + ScriptedInstance* pInstance; + uint32 DelayTimer; + uint32 substage; - void Reset() {} + void Reset() + { + if (!pInstance) return; + pInstance->SetData(TYPE_STAGE,0); + DelayTimer = 0; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(Creature *pAlly = GetClosestCreatureWithEntry(m_creature, NPC_THRALL, 300.0f)) + pAlly->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(Creature *pAlly = GetClosestCreatureWithEntry(m_creature, NPC_PROUDMOORE, 300.0f)) + pAlly->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetRespawnDelay(DAY); + } - void StartEvent(Player* pPlayer) + void AttackStart(Unit *who) { - // code starting the event here + //ignore all attackstart commands + return; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) return; + + if(DelayTimer < diff) { + switch (pInstance->GetData(TYPE_STAGE)) { + case 0: break; + case 1: { + if (pInstance->GetData(TYPE_NORTHREND_BEASTS) == GORMOK_DONE) { + pInstance->SetData(TYPE_STAGE,2); + pInstance->SetData(TYPE_EVENT,200); + pInstance->SetData(TYPE_NORTHREND_BEASTS,SNAKES_IN_PROGRESS); + pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); + }; + if (pInstance->GetData(TYPE_NORTHREND_BEASTS) == FAIL) { + pInstance->SetData(TYPE_STAGE,0); + pInstance->SetData(TYPE_EVENT,666); + pInstance->SetData(TYPE_BEASTS,NOT_STARTED); + }; + break; + }; + case 2: { + if (pInstance->GetData(TYPE_NORTHREND_BEASTS) == SNAKES_DONE) { + pInstance->SetData(TYPE_STAGE,3); + pInstance->SetData(TYPE_EVENT,300); + pInstance->SetData(TYPE_NORTHREND_BEASTS,ICEHOWL_IN_PROGRESS); + pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); + }; + if (pInstance->GetData(TYPE_NORTHREND_BEASTS) == FAIL) { + pInstance->SetData(TYPE_STAGE,0); + pInstance->SetData(TYPE_EVENT,666); + pInstance->SetData(TYPE_BEASTS,NOT_STARTED); + }; + break; + } + case 3: { + if (pInstance->GetData(TYPE_NORTHREND_BEASTS) == ICEHOWL_DONE) { + pInstance->SetData(TYPE_STAGE,0); + pInstance->SetData(TYPE_BEASTS,DONE); + pInstance->SetData(TYPE_EVENT,400); + pInstance->SetData(TYPE_NORTHREND_BEASTS,DONE); + } + if (pInstance->GetData(TYPE_NORTHREND_BEASTS) == FAIL) { + pInstance->SetData(TYPE_STAGE,0); + pInstance->SetData(TYPE_EVENT,666); + pInstance->SetData(TYPE_BEASTS,NOT_STARTED); + }; + break; + }; + + case 4: { + break; + }; + + case 5: { + break; + }; + + case 6: { + if (pInstance->GetData(TYPE_CRUSADERS_COUNT) == 0 + && pInstance->GetData(TYPE_CRUSADERS) == IN_PROGRESS) + { + pInstance->SetData(TYPE_STAGE,0); + pInstance->SetData(TYPE_CRUSADERS,DONE); + pInstance->SetData(TYPE_EVENT,3100); + } + break; + }; + + case 7: { + if (pInstance->GetData(TYPE_VALKIRIES) == DONE) { + pInstance->SetData(TYPE_STAGE,0); + pInstance->SetData(TYPE_EVENT,4020); + } + if (pInstance->GetData(TYPE_VALKIRIES) == FAIL) { + pInstance->SetData(TYPE_STAGE,0); + pInstance->SetData(TYPE_EVENT,0); + } + break; + }; + case 8: { + break; + }; + case 9: { + if (pInstance->GetData(TYPE_ANUBARAK) == DONE) { + pInstance->SetData(TYPE_STAGE,10); + pInstance->SetData(TYPE_EVENT,6000); + } + if (pInstance->GetData(TYPE_ANUBARAK) == FAIL) { + pInstance->SetData(TYPE_STAGE,0); + pInstance->SetData(TYPE_EVENT,0); + } + break; + }; + case 10: { +// m_creature->ForcedDespawn(); + break; + }; + + } + } else DelayTimer -= diff; } }; -bool GossipHello_npc_barrett_ramsey(Player* pPlayer, Creature* pCreature) +CreatureAI* GetAI_npc_toc_announcer(Creature* pCreature) { - pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_START_EVENT1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); - pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return new npc_toc_announcerAI(pCreature); +} + +bool GossipHello_npc_toc_announcer(Player* pPlayer, Creature* pCreature) +{ + + ScriptedInstance* pInstance; + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + char const* _message; + uint8 i; + + if (!pInstance) return false; + + if( !pPlayer->getAttackers().empty() || + pInstance->IsEncounterInProgress() || + pInstance->GetData(TYPE_EVENT)) + return true; + + switch (LocaleConstant currentlocale = pPlayer->GetSession()->GetSessionDbcLocale()) + { + case LOCALE_enUS: + case LOCALE_koKR: + case LOCALE_frFR: + case LOCALE_deDE: + case LOCALE_zhCN: + case LOCALE_zhTW: + case LOCALE_esES: + case LOCALE_esMX: + _message = "We are ready!"; + break; + case LOCALE_ruRU: + _message = "Ð’Ñегда готовы!"; + break; + default: + _message = "We are ready!"; + break; + }; + + for(i = 0; i < NUM_MESSAGES; i++) { + if (!_GossipMessage[i].state && (pInstance->GetData(_GossipMessage[i].encounter) != DONE )) { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _message, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); + break; + } + if (_GossipMessage[i].state && pInstance->GetData(_GossipMessage[i].encounter) == DONE) { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, _message, GOSSIP_SENDER_MAIN,_GossipMessage[i].id); + break; + } + }; + + pPlayer->SEND_GOSSIP_MENU(_GossipMessage[i].msgnum, pCreature->GetGUID()); + return true; } -bool GossipSelect_npc_barrett_ramsey(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +bool GossipSelect_npc_toc_announcer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) { - if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + ScriptedInstance* pInstance; + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + if (!pInstance) return false; + +pPlayer->CLOSE_GOSSIP_MENU(); + +switch(uiAction) { + case GOSSIP_ACTION_INFO_DEF+1: { + if (pInstance->GetData(TYPE_BEASTS) != DONE) { + pInstance->SetData(TYPE_EVENT,110); + pInstance->SetData(TYPE_NORTHREND_BEASTS,NOT_STARTED); + pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); + }; + break; + }; + + case GOSSIP_ACTION_INFO_DEF+2: { + if (pInstance->GetData(TYPE_JARAXXUS) != DONE) + pInstance->SetData(TYPE_EVENT,1010); + break; + }; + + case GOSSIP_ACTION_INFO_DEF+3: { + if (pInstance->GetData(TYPE_CRUSADERS) != DONE) { + if (pPlayer->GetTeam() == ALLIANCE) pInstance->SetData(TYPE_EVENT,3000); + else pInstance->SetData(TYPE_EVENT,3001); + }; + break; + }; + + case GOSSIP_ACTION_INFO_DEF+4: { + if (pInstance->GetData(TYPE_VALKIRIES) != DONE) + pInstance->SetData(TYPE_EVENT,4000); + break; + }; + + case GOSSIP_ACTION_INFO_DEF+5: { + if (pInstance->GetData(TYPE_LICH_KING) != DONE) return false; + if (GameObject* pGoFloor = pInstance->instance->GetGameObject(pInstance->GetData64(GO_ARGENT_COLISEUM_FLOOR))) + { + pGoFloor->SetUInt32Value(GAMEOBJECT_DISPLAYID,9060); + pGoFloor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); + pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1,8449); + } + pCreature->CastSpell(pCreature,69016,false); + + Creature* pTemp = pCreature->GetMap()->GetCreature(pInstance->GetData64(NPC_ANUBARAK)); + if (!pTemp || !pTemp->isAlive()) + pCreature->SummonCreature(NPC_ANUBARAK, SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (pTemp) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[20].x, SpawnLoc[20].y, SpawnLoc[20].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetInCombatWithZone(); + } + pInstance->SetData(TYPE_STAGE,9); + pInstance->SetData(TYPE_ANUBARAK,IN_PROGRESS); + if (pCreature->GetVisibility() == VISIBILITY_ON) + pCreature->SetVisibility(VISIBILITY_OFF); + break; + }; + + case GOSSIP_ACTION_INFO_DEF+6: { + pInstance->SetData(TYPE_STAGE,10); + break; + }; + + }; + +return true; +} + +struct MANGOS_DLL_DECL boss_lich_king_tocAI : public ScriptedAI +{ + boss_lich_king_tocAI(Creature *pCreature) : ScriptedAI(pCreature) { - pPlayer->CLOSE_GOSSIP_MENU(); - if (npc_barrett_ramseyAI* pBarrettAI = dynamic_cast(pCreature->AI())) - pBarrettAI->StartEvent(pPlayer); + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + WayPointList.clear(); + JustRespawned(); } - return true; + ScriptedInstance* pInstance; + uint32 UpdateTimer; + uint32 event_state_lich_king; + bool Event; + bool MovementStarted; + std::list WayPointList; + std::list::iterator WayPoint; + uint32 WalkTimer; + bool IsWalking; + Creature* pPortal; + + void Reset() + { + UpdateTimer = 0; + event_state_lich_king = 0; + Event = false; + MovementStarted = false; + m_creature->SetRespawnDelay(DAY); + pPortal = m_creature->SummonCreature(NPC_TRIGGER, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + pPortal->SetRespawnDelay(DAY); + pPortal->CastSpell(pPortal, 51807, false); + pPortal->SetDisplayId(17612); + if(pInstance) pInstance->SetData(TYPE_LICH_KING,IN_PROGRESS); + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void JustRespawned() + { + Reset(); + } + + void MoveInLineOfSight(Unit *who) + { + } + + void StartMovement() + { + if(!WayPointList.empty() || MovementStarted) + return; + + AddWaypoint(0, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z); + AddWaypoint(1, SpawnLoc[17].x, SpawnLoc[17].y, SpawnLoc[17].z); + AddWaypoint(2, SpawnLoc[18].x, SpawnLoc[18].y, SpawnLoc[18].z); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + WayPoint = WayPointList.begin(); + MovementStarted = true; + IsWalking = true; + WalkTimer = 200; + event_state_lich_king = 1; + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + } + + void AddWaypoint(uint32 id, float x, float y, float z) + { + WayPoints wp(id, x, y, z); + WayPointList.push_back(wp); + } + + void UpdateAI(const uint32 diff) + { + + if(!pInstance) return; + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_LICH_KING_1) return; + if (!MovementStarted) StartMovement(); + + if (IsWalking && WalkTimer) + { + if (WalkTimer <= diff) + { + if (WayPoint != WayPointList.end()) + { + m_creature->GetMotionMaster()->MovePoint(WayPoint->id, WayPoint->x, WayPoint->y,WayPoint->z); + WalkTimer = 0; + } + }else WalkTimer -= diff; + } + + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + + if (UpdateTimer <= diff) + { + switch (pInstance->GetData(TYPE_EVENT)) + { + case 5010: + DoScriptText(-1713550,m_creature); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,5020); + break; + case 5030: + DoScriptText(-1713552,m_creature); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,5040); + break; + case 5040: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + UpdateTimer = 1000; + pInstance->SetData(TYPE_EVENT,5050); + break; + case 5050: + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_EXCLAMATION); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,5060); + break; + case 5060: if (Event) { + DoScriptText(-1713553,m_creature); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL); + UpdateTimer = 2500; + pInstance->SetData(TYPE_EVENT,5070); + } + break; + case 5070: + m_creature->CastSpell(m_creature,68198,false); + UpdateTimer = 1500; + pInstance->SetData(TYPE_EVENT,5080); + break; + case 5080: + if (GameObject* pGoFloor = pInstance->instance->GetGameObject(pInstance->GetData64(GO_ARGENT_COLISEUM_FLOOR))) + { + pGoFloor->SetUInt32Value(GAMEOBJECT_DISPLAYID,9060); + pGoFloor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); + pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1,8449); + } + m_creature->CastSpell(m_creature,69016,false); + if(pInstance) pInstance->SetData(TYPE_LICH_KING,DONE); + + pInstance->SetData(TYPE_ANUBARAK,IN_PROGRESS); + m_creature->SummonCreature(NPC_ANUBARAK, SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_ANUBARAK))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[20].x, SpawnLoc[20].y, SpawnLoc[20].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetInCombatWithZone(); + } + pInstance->SetData(TYPE_STAGE,9); + Event=false; + m_creature->ForcedDespawn(); + pPortal->ForcedDespawn(); + pInstance->SetData(TYPE_EVENT,0); + UpdateTimer = 20000; + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + + } + + void MovementInform(uint32 type, uint32 id) + { + if(pInstance) + { + if(id == 2) + { + Event = true; + } + } + if(type != POINT_MOTION_TYPE) return; + if(WayPoint->id != id) return; + ++WayPoint; + WalkTimer = 200; + } +}; + +CreatureAI* GetAI_boss_lich_king_toc(Creature* pCreature) +{ + return new boss_lich_king_tocAI(pCreature); +}; + +struct MANGOS_DLL_DECL npc_fizzlebang_tocAI : public ScriptedAI +{ + npc_fizzlebang_tocAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); + Reset(); + } + + InstanceData* pInstance; + uint32 UpdateTimer; + Creature* pPortal; + Creature* pTrigger; + + void JustDied(Unit* pKiller) + { + DoScriptText(-1713715, m_creature, pKiller); + pInstance->SetData(TYPE_EVENT, 1180); + if (pPortal) pPortal->ForcedDespawn(); + } + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + m_creature->GetMotionMaster()->MovePoint(1, SpawnLoc[27].x, SpawnLoc[27].y, SpawnLoc[27].z); + pPortal = NULL; + } + + void UpdateAI(const uint32 diff) + { + if(!pInstance) return; + + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_FIZZLEBANG) return; + + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + if(UpdateTimer <= diff) + { + switch(pInstance->GetData(TYPE_EVENT)) + { + case 1110: + pInstance->SetData(TYPE_EVENT, 1120); + UpdateTimer = 3000; + pInstance->SetData(TYPE_JARAXXUS,IN_PROGRESS); + break; + case 1120: + DoScriptText(-1713511, m_creature); + pInstance->SetData(TYPE_EVENT, 1130); + UpdateTimer = 12000; + break; + case 1130: + m_creature->GetMotionMaster()->MovementExpired(); + m_creature->HandleEmoteCommand(EMOTE_STATE_SPELL_CHANNEL_OMNI); + pPortal = m_creature->SummonCreature(NPC_WILFRED_PORTAL, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 5, TEMPSUMMON_MANUAL_DESPAWN, 5000); + if (pPortal) { + pPortal->SetRespawnDelay(DAY); + pPortal->SetDisplayId(22862); + } + DoScriptText(-1713512, m_creature); + pInstance->SetData(TYPE_EVENT, 1132); + UpdateTimer = 4000; + break; + case 1132: + m_creature->GetMotionMaster()->MovementExpired(); + if (pPortal) pPortal->SetFloatValue(OBJECT_FIELD_SCALE_X, 1.5f); + pInstance->SetData(TYPE_EVENT, 1134); + UpdateTimer = 4000; + break; + case 1134: + if (pPortal) pPortal->SetDisplayId(15900); + pTrigger = m_creature->SummonCreature(NPC_TRIGGER, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 5.0f, TEMPSUMMON_MANUAL_DESPAWN, 5000); + if (pTrigger) { + pTrigger->SetDisplayId(17612); + pTrigger->CastSpell(pTrigger, SPELL_WILFRED_PORTAL, false); + pTrigger->SetRespawnDelay(DAY); + } + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST_OMNI); + UpdateTimer = 4000; + pInstance->SetData(TYPE_EVENT, 1135); + break; + case 1135: + if (pTrigger) pTrigger->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.0f); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SPELLCAST_OMNI); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT, 1140); + break; + case 1140: + pInstance->SetData(TYPE_STAGE,4); + m_creature->SummonCreature(NPC_JARAXXUS, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_JARAXXUS))) { + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->CastSpell(pTemp, SPELL_JARAXXUS_CHAINS, false); + } + pInstance->SetData(TYPE_EVENT, 1142); + UpdateTimer = 5000; + break; + case 1142: + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT, 1144); + DoScriptText(-1713513, m_creature); + break; + case 1144: + if (pTrigger) pTrigger->ForcedDespawn(); + pInstance->SetData(TYPE_EVENT, 1150); + UpdateTimer = 5000; + break; + case 1150: + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_JARAXXUS))) { + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->RemoveAurasDueToSpell(SPELL_JARAXXUS_CHAINS); + pTemp->SetInCombatWithZone(); + m_creature->SetInCombatWith(pTemp); + pTemp->AddThreat(m_creature, 1000.0f); + pTemp->AI()->AttackStart(m_creature); + } + DoScriptText(-1713515, m_creature); + pInstance->SetData(TYPE_EVENT, 1160); + UpdateTimer = 3000; + break; + case 1160: + pInstance->SetData(TYPE_EVENT, 1170); + UpdateTimer = 1000; + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + } +}; + +CreatureAI* GetAI_npc_fizzlebang_toc(Creature* pCreature) +{ + return new npc_fizzlebang_tocAI(pCreature); } -CreatureAI* GetAI_npc_barrett_ramsey(Creature* pCreature) +struct MANGOS_DLL_DECL npc_tirion_tocAI : public ScriptedAI +{ + npc_tirion_tocAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + uint32 UpdateTimer; + uint32 crusader[12]; + uint8 crusaderscount; + + void Reset() + { + crusaderscount = 0; + memset(&crusader, 0, sizeof(crusader)); + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) return; + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_TIRION) return; + + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + + if (UpdateTimer <= diff) + { + switch (pInstance->GetData(TYPE_EVENT)) + { + case 110: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1713500, m_creature); + UpdateTimer = 12000; + pInstance->SetData(TYPE_EVENT,120); +// pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_WEST_PORTCULLIS)); + break; + case 140: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1713501, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,150); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 150: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + if (pInstance->GetData(TYPE_BEASTS) != DONE) { + m_creature->SummonCreature(NPC_GORMOK, SpawnLoc[26].x, SpawnLoc[26].y, SpawnLoc[26].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_GORMOK))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetInCombatWithZone(); + } + } + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,160); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + pInstance->SetData(TYPE_STAGE,1); + pInstance->SetData(TYPE_BEASTS,IN_PROGRESS); + break; + + case 200: + DoScriptText(-1713503, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,205); + break; + + case 205: + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT,210); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + + case 210: + if (pInstance->GetData(TYPE_BEASTS) != DONE){ + m_creature->SummonCreature(NPC_DREADSCALE, SpawnLoc[3].x, SpawnLoc[3].y, SpawnLoc[3].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + m_creature->SummonCreature(NPC_ACIDMAW, SpawnLoc[4].x, SpawnLoc[4].y, SpawnLoc[4].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_DREADSCALE))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetInCombatWithZone(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_ACIDMAW))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetInCombatWithZone(); + } + } + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,220); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 300: + DoScriptText(-1713505, m_creature); + UpdateTimer = 15000; + pInstance->SetData(TYPE_EVENT,305); + break; + case 305: + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT,310); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 310: + if (pInstance->GetData(TYPE_BEASTS) != DONE) { + m_creature->SummonCreature(NPC_ICEHOWL, SpawnLoc[26].x, SpawnLoc[26].y, SpawnLoc[26].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_ICEHOWL))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetInCombatWithZone(); + } + } + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,320); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 400: + DoScriptText(-1713509, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,0); +// pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_WEST_PORTCULLIS)); + break; + + case 666: + DoScriptText(-1713709, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,0); + pInstance->SetData(TYPE_NORTHREND_BEASTS,NOT_STARTED); +// pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_WEST_PORTCULLIS)); + break; + + case 1010: + DoScriptText(-1713510, m_creature); + UpdateTimer = 5000; + m_creature->SummonCreature(NPC_FIZZLEBANG, SpawnLoc[21].x, SpawnLoc[21].y, SpawnLoc[21].z, 2, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + pInstance->SetData(TYPE_EVENT,1110); + break; + + case 1180: + DoScriptText(-1713516, m_creature); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,0); + break; + + case 2000: + DoScriptText(-1713526, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,2010); + break; + case 2030: + DoScriptText(-1713529, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,0); + break; + case 3000: + DoScriptText(-1713530, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3050); + break; + case 3001: + DoScriptText(-1713530, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3051); + break; + case 3060: + DoScriptText(-1713532, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3070); + break; + case 3061: + DoScriptText(-1713532, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3071); + break; +//Summoning crusaders + case 3091: + pInstance->SetData(TYPE_STAGE,6); + if (pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_NORMAL + || pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) + { + crusaderscount = 12; + switch (urand(0,3)){ // Healers, 3 in 25-mode + case 0: crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_12; + crusader[2] = NPC_CRUSADER_1_13; + break; + case 1: crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_2; + crusader[2] = NPC_CRUSADER_1_13; + break; + case 2: crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_2; + crusader[2] = NPC_CRUSADER_1_12; + break; + case 3: crusader[0] = NPC_CRUSADER_1_2; + crusader[1] = NPC_CRUSADER_1_12; + crusader[2] = NPC_CRUSADER_1_13; + break; + } + switch (urand(0,5)){ // Random melee DD, 2 in 25-mode + case 0: crusader[3] = NPC_CRUSADER_1_3; + crusader[4] = NPC_CRUSADER_1_4; + break; + case 1: crusader[3] = NPC_CRUSADER_1_3; + crusader[4] = NPC_CRUSADER_1_5; + break; + case 2: crusader[3] = NPC_CRUSADER_1_3; + crusader[4] = NPC_CRUSADER_1_6; + break; + case 3: crusader[3] = NPC_CRUSADER_1_4; + crusader[4] = NPC_CRUSADER_1_5; + break; + case 4: crusader[3] = NPC_CRUSADER_1_4; + crusader[4] = NPC_CRUSADER_1_6; + break; + case 5: crusader[3] = NPC_CRUSADER_1_5; + crusader[4] = NPC_CRUSADER_1_6; + break; + } + + switch (urand(0,3)){ // Random magic DD, 3 in 25-mode + case 0: crusader[5] = NPC_CRUSADER_1_7; + crusader[6] = NPC_CRUSADER_1_8; + crusader[7] = NPC_CRUSADER_1_11; + break; + case 1: crusader[5] = NPC_CRUSADER_1_7; + crusader[6] = NPC_CRUSADER_1_8; + crusader[7] = NPC_CRUSADER_1_14; + break; + case 2: crusader[5] = NPC_CRUSADER_1_8; + crusader[6] = NPC_CRUSADER_1_11; + crusader[7] = NPC_CRUSADER_1_14; + break; + case 3: crusader[5] = NPC_CRUSADER_1_7; + crusader[6] = NPC_CRUSADER_1_11; + crusader[7] = NPC_CRUSADER_1_14; + break; + } + crusader[8] = NPC_CRUSADER_1_9; //Hunter+warlock + crusader[9] = NPC_CRUSADER_1_10; + crusader[10] = NPC_CRUSADER_0_1; + crusader[11] = NPC_CRUSADER_0_2; + + } else { + crusaderscount = 6; + switch (urand(0,5)){ // Healers, 2 in 10-mode + case 0: crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_12; + break; + case 1: crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_2; + break; + case 2: crusader[0] = NPC_CRUSADER_1_2; + crusader[1] = NPC_CRUSADER_1_12; + break; + case 3: crusader[0] = NPC_CRUSADER_1_1; + crusader[1] = NPC_CRUSADER_1_13; + break; + case 4: crusader[0] = NPC_CRUSADER_1_2; + crusader[1] = NPC_CRUSADER_1_13; + break; + case 5: crusader[0] = NPC_CRUSADER_1_12; + crusader[1] = NPC_CRUSADER_1_13; + break; + } + switch (urand(0,5)){ // Random melee DD, 2 in 10-mode + case 0: crusader[3] = NPC_CRUSADER_1_3; + crusader[2] = NPC_CRUSADER_1_4; + break; + case 1: crusader[3] = NPC_CRUSADER_1_3; + crusader[2] = NPC_CRUSADER_1_5; + break; + case 2: crusader[3] = NPC_CRUSADER_1_3; + crusader[2] = NPC_CRUSADER_1_6; + break; + case 3: crusader[3] = NPC_CRUSADER_1_4; + crusader[2] = NPC_CRUSADER_1_5; + break; + case 4: crusader[3] = NPC_CRUSADER_1_4; + crusader[2] = NPC_CRUSADER_1_6; + break; + case 5: crusader[3] = NPC_CRUSADER_1_5; + crusader[2] = NPC_CRUSADER_1_6; + break; + } + + switch (urand(0,5)){ // Random magic DD, 2 in 10-mode + case 0: crusader[4] = NPC_CRUSADER_1_7; + crusader[5] = NPC_CRUSADER_1_8; + break; + case 1: crusader[5] = NPC_CRUSADER_1_7; + crusader[4] = NPC_CRUSADER_1_14; + break; + case 2: crusader[5] = NPC_CRUSADER_1_7; + crusader[4] = NPC_CRUSADER_1_11; + break; + case 3: crusader[5] = NPC_CRUSADER_1_8; + crusader[4] = NPC_CRUSADER_1_11; + break; + case 4: crusader[5] = NPC_CRUSADER_1_8; + crusader[4] = NPC_CRUSADER_1_14; + break; + case 5: crusader[5] = NPC_CRUSADER_1_11; + crusader[4] = NPC_CRUSADER_1_14; + break; + } + + } + for(uint8 i = 0; i < crusaderscount; ++i) + { + m_creature->SummonCreature(crusader[i], SpawnLoc[i+2].x, SpawnLoc[i+2].y, SpawnLoc[i+2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(crusader[i]))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + } + pInstance->SetData(TYPE_CRUSADERS_COUNT,crusaderscount); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,0); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + pInstance->SetData(TYPE_CRUSADERS,IN_PROGRESS); + break; + +//summoning crusaders + case 3090: + pInstance->SetData(TYPE_STAGE,6); + if (pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_NORMAL + || pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) + { + crusaderscount = 12; + switch (urand(0,3)){ // Healers, 3 in 25-mode + case 0: crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_12; + crusader[2] = NPC_CRUSADER_2_13; + break; + case 1: crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_2; + crusader[2] = NPC_CRUSADER_2_13; + break; + case 2: crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_2; + crusader[2] = NPC_CRUSADER_2_12; + break; + case 3: crusader[0] = NPC_CRUSADER_2_2; + crusader[1] = NPC_CRUSADER_2_12; + crusader[2] = NPC_CRUSADER_2_13; + break; + } + switch (urand(0,5)){ // Random melee DD, 2 in 25-mode + case 0: crusader[3] = NPC_CRUSADER_2_3; + crusader[4] = NPC_CRUSADER_2_4; + break; + case 1: crusader[3] = NPC_CRUSADER_2_3; + crusader[4] = NPC_CRUSADER_2_5; + break; + case 2: crusader[3] = NPC_CRUSADER_2_3; + crusader[4] = NPC_CRUSADER_2_6; + break; + case 3: crusader[3] = NPC_CRUSADER_2_4; + crusader[4] = NPC_CRUSADER_2_5; + break; + case 4: crusader[3] = NPC_CRUSADER_2_4; + crusader[4] = NPC_CRUSADER_2_6; + break; + case 5: crusader[3] = NPC_CRUSADER_2_5; + crusader[4] = NPC_CRUSADER_2_6; + break; + } + + switch (urand(0,3)){ // Random magic DD, 3 in 25-mode + case 0: crusader[5] = NPC_CRUSADER_2_7; + crusader[6] = NPC_CRUSADER_2_8; + crusader[7] = NPC_CRUSADER_2_11; + break; + case 1: crusader[5] = NPC_CRUSADER_2_7; + crusader[6] = NPC_CRUSADER_2_8; + crusader[7] = NPC_CRUSADER_2_14; + break; + case 2: crusader[5] = NPC_CRUSADER_2_8; + crusader[6] = NPC_CRUSADER_2_11; + crusader[7] = NPC_CRUSADER_2_14; + break; + case 3: crusader[5] = NPC_CRUSADER_2_7; + crusader[6] = NPC_CRUSADER_2_11; + crusader[7] = NPC_CRUSADER_2_14; + break; + } + crusader[8] = NPC_CRUSADER_2_9; //Hunter+warlock + crusader[9] = NPC_CRUSADER_2_10; + crusader[10] = NPC_CRUSADER_0_1; + crusader[11] = NPC_CRUSADER_0_2; + + } else { + crusaderscount = 6; + switch (urand(0,5)){ // Healers, 2 in 10-mode + case 0: crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_12; + break; + case 1: crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_2; + break; + case 2: crusader[0] = NPC_CRUSADER_2_2; + crusader[1] = NPC_CRUSADER_2_12; + break; + case 3: crusader[0] = NPC_CRUSADER_2_1; + crusader[1] = NPC_CRUSADER_2_13; + break; + case 4: crusader[0] = NPC_CRUSADER_2_2; + crusader[1] = NPC_CRUSADER_2_13; + break; + case 5: crusader[0] = NPC_CRUSADER_2_12; + crusader[1] = NPC_CRUSADER_2_13; + break; + } + switch (urand(0,5)){ // Random melee DD, 2 in 10-mode + case 0: crusader[3] = NPC_CRUSADER_2_3; + crusader[2] = NPC_CRUSADER_2_4; + break; + case 1: crusader[3] = NPC_CRUSADER_2_3; + crusader[2] = NPC_CRUSADER_2_5; + break; + case 2: crusader[3] = NPC_CRUSADER_2_3; + crusader[2] = NPC_CRUSADER_2_6; + break; + case 3: crusader[3] = NPC_CRUSADER_2_4; + crusader[2] = NPC_CRUSADER_2_5; + break; + case 4: crusader[3] = NPC_CRUSADER_2_4; + crusader[2] = NPC_CRUSADER_2_6; + break; + case 5: crusader[3] = NPC_CRUSADER_2_5; + crusader[2] = NPC_CRUSADER_2_6; + break; + } + + switch (urand(0,5)){ // Random magic DD, 2 in 10-mode + case 0: crusader[4] = NPC_CRUSADER_2_7; + crusader[5] = NPC_CRUSADER_2_8; + break; + case 1: crusader[5] = NPC_CRUSADER_2_7; + crusader[4] = NPC_CRUSADER_2_14; + break; + case 2: crusader[5] = NPC_CRUSADER_2_7; + crusader[4] = NPC_CRUSADER_2_11; + break; + case 3: crusader[5] = NPC_CRUSADER_2_8; + crusader[4] = NPC_CRUSADER_2_11; + break; + case 4: crusader[5] = NPC_CRUSADER_2_8; + crusader[4] = NPC_CRUSADER_2_14; + break; + case 5: crusader[5] = NPC_CRUSADER_2_11; + crusader[4] = NPC_CRUSADER_2_14; + break; + } + + } + for(uint8 i = 0; i < crusaderscount; ++i) + { + m_creature->SummonCreature(crusader[i], SpawnLoc[i+2].x, SpawnLoc[i+2].y, SpawnLoc[i+2].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(crusader[i]))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + } + pInstance->SetData(TYPE_CRUSADERS_COUNT,crusaderscount); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,0); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + pInstance->SetData(TYPE_CRUSADERS,IN_PROGRESS); + break; + +//Crusaders battle end + case 3100: + DoScriptText(-1713535, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,0); + break; + + case 4000: + DoScriptText(-1713536, m_creature); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,4010); + break; + case 4010: + DoScriptText(-1713537, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,4015); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + + case 4015: + pInstance->SetData(TYPE_STAGE,7); + pInstance->SetData(TYPE_VALKIRIES,IN_PROGRESS); + m_creature->SummonCreature(NPC_LIGHTBANE, SpawnLoc[3].x, SpawnLoc[3].y, SpawnLoc[3].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_LIGHTBANE))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetInCombatWithZone(); + } + m_creature->SummonCreature(NPC_DARKBANE, SpawnLoc[4].x, SpawnLoc[4].y, SpawnLoc[4].z, 5, TEMPSUMMON_CORPSE_TIMED_DESPAWN, DESPAWN_TIME); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_DARKBANE))) { + pTemp->GetMotionMaster()->MovePoint(0, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetInCombatWithZone(); + } + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,4016); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + + case 4040: + UpdateTimer = 60000; + pInstance->SetData(TYPE_EVENT,5000); + break; + + case 5000: + DoScriptText(-1713549, m_creature); + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT,5005); + break; + case 5005: + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT,5010); + pInstance->SetData(TYPE_STAGE,8); + m_creature->SummonCreature(NPC_LICH_KING_1, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z, 5, TEMPSUMMON_MANUAL_DESPAWN, 0); + break; + case 5020: + DoScriptText(-1713551, m_creature); + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT,5030); + break; + case 6000: + m_creature->NearTeleportTo(SpawnLoc[19].x, SpawnLoc[19].y, SpawnLoc[19].z, 4.0f); + UpdateTimer = 20000; + pInstance->SetData(TYPE_EVENT,6005); + break; + case 6005: + DoScriptText(-1713565, m_creature); + UpdateTimer = 20000; + pInstance->SetData(TYPE_EVENT,6010); + break; + case 6010: + if (pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_10MAN_HEROIC + || pInstance->GetData(TYPE_DIFFICULTY) == RAID_DIFFICULTY_25MAN_HEROIC) + DoScriptText(-1713566, m_creature); + UpdateTimer = 60000; + pInstance->SetData(TYPE_EVENT,6020); + break; + case 6020: + pInstance->SetData(TYPE_STAGE,10); + m_creature->ForcedDespawn(); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,6030); + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + + } +}; + +CreatureAI* GetAI_npc_tirion_toc(Creature* pCreature) { - return new npc_barrett_ramseyAI(pCreature); + return new npc_tirion_tocAI(pCreature); } +struct MANGOS_DLL_DECL npc_garrosh_tocAI : public ScriptedAI +{ + npc_garrosh_tocAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + uint32 UpdateTimer; + + void Reset() + { + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) return; + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_GARROSH) return; + + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + + if (UpdateTimer <= diff) + { + switch (pInstance->GetData(TYPE_EVENT)) + { + case 120: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1713702, m_creature); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,122); + break; + case 122: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,130); + break; + case 2010: + DoScriptText(-1713527, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,2020); + break; + case 3050: + DoScriptText(-1713531, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3060); + break; + case 3070: + DoScriptText(-1713533, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3080); + break; + case 3081: + DoScriptText(-1713734, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3091); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 4030: + DoScriptText(-1713748, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,4040); + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + } +}; + +CreatureAI* GetAI_npc_garrosh_toc(Creature* pCreature) +{ + return new npc_garrosh_tocAI(pCreature); +}; + +struct MANGOS_DLL_DECL npc_rinn_tocAI : public ScriptedAI +{ + npc_rinn_tocAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)m_creature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + uint32 UpdateTimer; + + void Reset() + { + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance) return; + if (pInstance->GetData(TYPE_EVENT_NPC) != NPC_RINN) return; + + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + + if (UpdateTimer <= diff) + { + switch (pInstance->GetData(TYPE_EVENT)) + { + case 130: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1713502, m_creature); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,132); + break; + case 132: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,140); + break; + case 2020: + DoScriptText(-1713528, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,2030); + break; + case 3051: + DoScriptText(-1713731, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3061); + break; + case 3071: + DoScriptText(-1713733, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3081); + break; + case 3080: + DoScriptText(-1713534, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,3090); + pInstance->DoUseDoorOrButton(pInstance->GetData64(GO_MAIN_GATE_DOOR)); + break; + case 4020: + DoScriptText(-1713548, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,4030); + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER,UpdateTimer); + } +}; + +CreatureAI* GetAI_npc_rinn_toc(Creature* pCreature) +{ + return new npc_rinn_tocAI(pCreature); +}; + void AddSC_trial_of_the_crusader() { - Script* pNewScript; + Script* NewScript; - pNewScript = new Script; - pNewScript->Name = "npc_barrett_ramsey"; - pNewScript->GetAI = &GetAI_npc_barrett_ramsey; - pNewScript->pGossipHello = &GossipHello_npc_barrett_ramsey; - pNewScript->pGossipSelect = &GossipSelect_npc_barrett_ramsey; - pNewScript->RegisterSelf(); -} + NewScript = new Script; + NewScript->Name = "npc_toc_announcer"; + NewScript->GetAI = &GetAI_npc_toc_announcer; + NewScript->pGossipHello = &GossipHello_npc_toc_announcer; + NewScript->pGossipSelect = &GossipSelect_npc_toc_announcer; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_lich_king_toc"; + NewScript->GetAI = &GetAI_boss_lich_king_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_fizzlebang_toc"; + NewScript->GetAI = &GetAI_npc_fizzlebang_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_tirion_toc"; + NewScript->GetAI = &GetAI_npc_tirion_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_garrosh_toc"; + NewScript->GetAI = &GetAI_npc_garrosh_toc; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_rinn_toc"; + NewScript->GetAI = &GetAI_npc_rinn_toc; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h index 4a2b680..f5f5f71 100644 --- a/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h +++ b/scripts/northrend/crusaders_coliseum/trial_of_the_crusader/trial_of_the_crusader.h @@ -1,29 +1,177 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* Copyright (C) 2009 - 2010 by /dev/rsa for ScriptDev2 * This program is free software licensed under GPL version 2 * Please see the included DOCS/LICENSE.TXT for more information */ -#ifndef DEF_TRIAL_OF_THE_CRUSADER_H -#define DEF_TRIAL_OF_THE_CRUSADER_H +#ifndef DEF_CRUSADER_H +#define DEF_CRUSADER_H +#include "BSW_ai.h" enum { - MAX_ENCOUNTER = 5, - - TYPE_NORTHREND_BEASTS = 1, - TYPE_JARAXXUS = 2, - TYPE_FACTION_CHAMPIONS = 3, - TYPE_TWIN_VALKYR = 4, - TYPE_ANUBARAK = 5, - - DATA_GORMOK = 6, - DATA_ACIDMAW = 7, - DATA_DREADSCALE = 8, - DATA_ICEHOWL = 9, - DATA_JARAXXUS = 10, - DATA_FACTION_CHAMPIONS = 11, - DATA_FJOLA = 12, - DATA_EYDIS = 13, - DATA_ANUBARAK = 14, + TYPE_STAGE = 0, + TYPE_BEASTS = 1, + TYPE_JARAXXUS = 2, + TYPE_CRUSADERS = 3, + TYPE_VALKIRIES = 4, + TYPE_LICH_KING = 5, + TYPE_ANUBARAK = 6, + TYPE_COUNTER = 7, + TYPE_EVENT = 8, + MAX_ENCOUNTERS = 9, + + NPC_BARRENT = 34816, + NPC_TIRION = 34996, + NPC_FIZZLEBANG = 35458, + NPC_GARROSH = 34995, + NPC_RINN = 34990, + NPC_LICH_KING_0 = 16980, + NPC_LICH_KING_1 = 35877, + + NPC_THRALL = 34994, + NPC_PROUDMOORE = 34992, + NPC_TRIGGER = 22517, + NPC_WILFRED_PORTAL = 35651, + + NPC_ICEHOWL = 34797, + NPC_GORMOK = 34796, + NPC_DREADSCALE = 34799, + NPC_ACIDMAW = 35144, + + NPC_JARAXXUS = 34780, + + NPC_CRUSADER_1_1 = 34460, //Druid + NPC_CRUSADER_1_2 = 34463, //Shaman + NPC_CRUSADER_1_3 = 34461, //DK + NPC_CRUSADER_1_4 = 34472, //Rogue + NPC_CRUSADER_1_5 = 34475, //Warrior + NPC_CRUSADER_1_6 = 34471, //Retro pal + NPC_CRUSADER_1_7 = 34473, //Shadow priest + NPC_CRUSADER_1_8 = 34468, //Mage + NPC_CRUSADER_1_9 = 34467, //Hunter + NPC_CRUSADER_1_10 = 34474, //Warlock + NPC_CRUSADER_1_11 = 34470, //Enh shaman + NPC_CRUSADER_1_12 = 34466, //Priest + NPC_CRUSADER_1_13 = 34465, //Holy paladin + NPC_CRUSADER_1_14 = 34469, //Moonkin + + NPC_CRUSADER_2_1 = 34451, //Druid + NPC_CRUSADER_2_2 = 34455, //Shaman + NPC_CRUSADER_2_3 = 34458, //DK + NPC_CRUSADER_2_4 = 34454, //Rogue + NPC_CRUSADER_2_5 = 34453, //Warrior + NPC_CRUSADER_2_6 = 34456, //Retro pal + NPC_CRUSADER_2_7 = 34441, //Shadow Priest + NPC_CRUSADER_2_8 = 34449, //Mage + NPC_CRUSADER_2_9 = 34448, //Hunter + NPC_CRUSADER_2_10 = 34450, //Warlock + NPC_CRUSADER_2_11 = 34444, //Enh shaman + NPC_CRUSADER_2_12 = 34447, //Priest + NPC_CRUSADER_2_13 = 34445, //Holy paladin + NPC_CRUSADER_2_14 = 34459, //Moonkin + + NPC_CRUSADER_0_1 = 35465, + NPC_CRUSADER_0_2 = 35610, + + NPC_LIGHTBANE = 34497, + NPC_DARKBANE = 34496, + + NPC_ANUBARAK = 34564, + + GO_CRUSADERS_CACHE_10 = 195631, + GO_CRUSADERS_CACHE_25 = 195632, + GO_CRUSADERS_CACHE_10_H = 195633, + GO_CRUSADERS_CACHE_25_H = 195635, + + GO_TRIBUTE_CHEST_10H_25 = 195665, + GO_TRIBUTE_CHEST_10H_45 = 195666, + GO_TRIBUTE_CHEST_10H_50 = 195667, + GO_TRIBUTE_CHEST_10H_99 = 195668, + + GO_TRIBUTE_CHEST_25H_25 = 195669, + GO_TRIBUTE_CHEST_25H_45 = 195670, + GO_TRIBUTE_CHEST_25H_50 = 195671, + GO_TRIBUTE_CHEST_25H_99 = 195672, + + GO_ARGENT_COLISEUM_FLOOR = 195527, //20943 + GO_MAIN_GATE_DOOR = 195647, + + GO_WEST_PORTCULLIS = 195589, + GO_SOUTH_PORTCULLIS = 195590, + GO_NORTH_PORTCULLIS = 195591, + + TYPE_DIFFICULTY = 101, + TYPE_EVENT_TIMER = 102, + TYPE_EVENT_NPC = 103, + TYPE_NORTHREND_BEASTS = 104, + TYPE_CRUSADERS_COUNT = 105, + + DATA_HEALTH_EYDIS = 201, + DATA_HEALTH_FJOLA = 202, + DATA_CASTING_VALKYRS = 203, + + DESPAWN_TIME = 300000, + +}; + +static Locations SpawnLoc[]= +{ + {559.257996f, 90.266197f, 395.122986f}, // 0 Barrent + {563.672974f, 139.571f, 393.837006f}, // 1 Center + {563.833008f, 187.244995f, 394.5f}, // 2 Backdoor + {577.347839f, 195.338888f, 395.14f}, // 3 - Right + {550.955933f, 195.338888f, 395.14f}, // 4 - Left + {575.042358f, 195.260727f, 395.137146f}, // 5 + {552.248901f, 195.331955f, 395.132658f}, // 6 + {573.342285f, 195.515823f, 395.135956f}, // 7 + {554.239929f, 195.825577f, 395.137909f}, // 8 + {571.042358f, 195.260727f, 395.137146f}, // 9 + {556.720581f, 195.015472f, 395.132658f}, // 10 + {569.534119f, 195.214478f, 395.139526f}, // 11 + {569.231201f, 195.941071f, 395.139526f}, // 12 + {558.811610f, 195.985779f, 394.671661f}, // 13 + {567.641724f, 195.351501f, 394.659943f}, // 14 + {560.633972f, 195.391708f, 395.137543f}, // 15 + {565.816956f, 195.477921f, 395.136810f}, // 16 + {563.549f, 152.474f, 394.393f}, // 17 - Lich king start + {563.547f, 141.613f, 393.908f}, // 18 - Lich king end + {787.932556f, 133.28978f, 142.612152f}, // 19 - Anub'arak start location + {618.157898f, 132.640869f, 139.559769f}, // 20 - Anub'arak move point location + {508.104767f, 138.247345f, 395.128052f}, // 21 - Fizzlebang start location + {586.060242f, 117.514809f, 394.314026f}, // 22 - Dark essence 1 + {541.602112f, 161.879837f, 394.587952f}, // 23 - Dark essence 2 + {541.021118f, 117.262932f, 395.314819f}, // 24 - Light essence 1 + {586.200562f, 162.145523f, 394.626129f}, // 25 - Light essence 2 + {563.833008f, 195.244995f, 394.585561f}, // 26 - outdoor + {548.610596f, 139.807800f, 394.321838f}, // 27 - fizzlebang end +}; + +enum uiWorldStates +{ + UPDATE_STATE_UI_SHOW = 4390, + UPDATE_STATE_UI_COUNT = 4389, +}; + +enum NorthrendBeasts +{ + GORMOK_IN_PROGRESS = 1000, + GORMOK_DONE = 1001, + SNAKES_IN_PROGRESS = 2000, + DREADSCALE_SUBMERGED = 2001, + ACIDMAW_SUBMERGED = 2002, + SNAKES_SPECIAL = 2003, + SNAKES_DONE = 2004, + ICEHOWL_IN_PROGRESS = 3000, + ICEHOWL_DONE = 3001, +}; + +enum AnnounserMessages +{ + MSG_BEASTS = 724001, + MSG_JARAXXUS = 724002, + MSG_CRUSADERS = 724003, + MSG_VALKIRIES = 724004, + MSG_LICH_KING = 724005, + MSG_ANUBARAK = 724006, }; #endif diff --git a/scripts/northrend/draktharon_keep/boss_dred.cpp b/scripts/northrend/draktharon_keep/boss_dred.cpp new file mode 100644 index 0000000..c10ee39 --- /dev/null +++ b/scripts/northrend/draktharon_keep/boss_dred.cpp @@ -0,0 +1,196 @@ +/* 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_Tharonja +SD%Complete: 80% +SDComment: Timers +SDCategory: Drak'Tharon Keep +EndScriptData */ + +#include "precompiled.h" +#include "draktharon_keep.h" + +enum +{ + SAY_KING_DRED_TALON = -1600020, + SAY_CALL_FOR_RAPTOR = -1600021, + + SPELL_BELLOWING_ROAR = 22686, + SPELL_FEARSOME_ROAR = 48849, + H_SPELL_FEARSOME_ROAR = 59422, + SPELL_GRIEVOUS_BITE = 48920, + SPELL_MANGLING_SLASH = 48873, + SPELL_PIERCING_SLASH = 48878, + SPELL_RAPTOR_CALL = 59416, //not yet implemented + +}; + +const float PosSummon1[3] = {-528.8f, -690.58f, 30.25f}; +/*###### +## boss_dred +######*/ + +struct MANGOS_DLL_DECL boss_dredAI : public ScriptedAI +{ + boss_dredAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 FearsomeRoar_Timer; + uint32 ManglingSlash_Timer; + uint32 PiercingSlash_Timer; + uint32 GrievousBite_Timer; + uint32 BellowingRoar_Timer; + uint32 Check_Timer; + uint32 CallForRaptor_Timer; + uint32 CallForRaptorSpawn_Timer; + uint32 CallForRaptorSpawn_Check; + + void Reset() + { + FearsomeRoar_Timer = 15000; + ManglingSlash_Timer = urand(5000, 10000); + PiercingSlash_Timer = urand(10000, 15000); + GrievousBite_Timer = urand (15000, 20000); + BellowingRoar_Timer = 60000; + Check_Timer = 15000; + CallForRaptor_Timer = 25000; + CallForRaptorSpawn_Check = 0; + } + + void Aggro(Unit* pWho) + { + + } + + void KilledUnit(Unit* pVictim) + { + + } + + void JustDied(Unit* pKiller) + { + + } + + void CallForRaptorSpawnCheck() + { + CallForRaptorSpawn_Timer = 1000; + CallForRaptorSpawn_Check = 1; + } + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + //Fearsome Roar + if (FearsomeRoar_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FEARSOME_ROAR : H_SPELL_FEARSOME_ROAR, true); + FearsomeRoar_Timer = 15000; + }else FearsomeRoar_Timer -= uiDiff; + + //Piercing Slash + if (PiercingSlash_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_PIERCING_SLASH, true); + PiercingSlash_Timer = urand(20000, 25000); + }else PiercingSlash_Timer -= uiDiff; + + //Mangling Slash + if (ManglingSlash_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_MANGLING_SLASH, true); + ManglingSlash_Timer = urand(20000, 25000); + }else ManglingSlash_Timer -= uiDiff; + + //Mangling Slash + if (GrievousBite_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_GRIEVOUS_BITE, true); + GrievousBite_Timer = urand(20000, 25000); + }else GrievousBite_Timer -= uiDiff; + + //Grievous Bite remove + if (Check_Timer < uiDiff) + { + Unit* pPlayer = m_creature->getVictim(); + if (pPlayer->GetHealth() == pPlayer->GetMaxHealth()) + if (pPlayer->HasAura(SPELL_GRIEVOUS_BITE)) + pPlayer->RemoveAura(SPELL_GRIEVOUS_BITE, EFFECT_INDEX_0); + Check_Timer = 1000; + }else Check_Timer -= uiDiff; + + //Bellowing Roar + if (BellowingRoar_Timer < uiDiff) + { + DoCast(m_creature, SPELL_BELLOWING_ROAR); + BellowingRoar_Timer = 60000; + }else BellowingRoar_Timer -= uiDiff; + + //Call For Raptor - spell + if (CallForRaptor_Timer < uiDiff) + { + DoScriptText(SAY_CALL_FOR_RAPTOR, m_creature); + m_creature->CastSpell(m_creature, SAY_CALL_FOR_RAPTOR, true); + CallForRaptor_Timer = 25000; + CallForRaptorSpawnCheck(); + }else CallForRaptor_Timer -= uiDiff; + + //Call For Raptor - spawn + if (CallForRaptorSpawn_Timer < uiDiff && CallForRaptorSpawn_Check == 1) + { + switch(urand(0, 1)) + { + case 0: + { + if (Creature* pRaptor1 = m_creature->SummonCreature(NPC_DRAKKARI_GUTRIPPER, PosSummon1[0], PosSummon1[1], PosSummon1[2], 0 , TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240000)) + pRaptor1->AI()->AttackStart(m_creature->getVictim()); + } + case 1: + { + if (Creature* pRaptor2 = m_creature->SummonCreature(NPC_DRAKKARI_SCYTHECLAW, PosSummon1[0], PosSummon1[1], PosSummon1[2], 0 , TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240000)) + pRaptor2->AI()->AttackStart(m_creature->getVictim()); + } + } + CallForRaptorSpawn_Check = 0; + }else CallForRaptorSpawn_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_dred(Creature* pCreature) +{ + return new boss_dredAI(pCreature); +} + +void AddSC_boss_dred() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_dred"; + newscript->GetAI = &GetAI_boss_dred; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/draktharon_keep/boss_novos.cpp b/scripts/northrend/draktharon_keep/boss_novos.cpp index 5ea06c7..6cfada9 100644 --- a/scripts/northrend/draktharon_keep/boss_novos.cpp +++ b/scripts/northrend/draktharon_keep/boss_novos.cpp @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss_Novos -SD%Complete: 20% -SDComment: +SD%Complete: 80% +SDComment: Timers SDCategory: Drak'Tharon Keep EndScriptData */ @@ -35,12 +35,32 @@ enum EMOTE_ASSISTANCE = -1600011, - NPC_CRYSTAL_HANDLER = 26627, - NPC_HULKING_CORPSE = 27597, - NPC_FETID_TROLL_CORPSE = 27598, - NPC_RISON_SHADOWCASTER = 27600 + POS = 3, + + SPELL_ARCANE_FIELD = 47346, + SPELL_FROSTBOLT = 49037, + H_SPELL_FROSTBOLT = 59855, + SPELL_ARCANE_BLAST = 49198, + H_SPELL_ARCANE_BLAST = 59909, + SPELL_BLIZZARD = 49034, + H_SPELL_BLIZZARD = 59854, + SPELL_WRATH_OF_MISERY = 50089, + H_SPELL_WRATH_OF_MISERY = 59856, + + SPELL_RITUAL_CRYSTAL_KEY = 51404, + SPELL_EFFECT = 52106, + SPELL_DEAD_EFFECT = 47336, + + SPELL_SHADOW_BOLT = 51363, + H_SPELL_SHADOW_BOLT = 59016, }; +const float PosSummonHandler[POS][3] = +{ + {-337.78f, -720.39f, 28.58f}, + {-379.31f, -818.36f, 59.70f}, + {-412.45f, -726.96f, 28.58f}, +}; /*###### ## boss_novos ######*/ @@ -57,14 +77,29 @@ struct MANGOS_DLL_DECL boss_novosAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; + bool Phase1; + bool Phase2; + uint32 Start_Check; + uint32 Handler_Spawn; + uint32 Handler_Count; + uint32 Cast_Timer; + uint32 ArcaneBlast_Timer; + uint32 SpecialCast_Timer; + uint32 SummonMinion_Timer; + void Reset() { + Start_Check = 1; + Handler_Spawn = 5000; + Handler_Count = 0; + Phase1 = false; + Phase2 = false; } void MoveInLineOfSight(Unit* pWho) { // An Add reached the ground, if its z-pos is near the z pos of Novos - if (pWho->GetEntry() == NPC_HULKING_CORPSE || pWho->GetEntry() == NPC_FETID_TROLL_CORPSE || pWho->GetEntry() == NPC_RISON_SHADOWCASTER) + if (pWho->GetEntry() == NPC_HULKING_CORPSE || pWho->GetEntry() == NPC_FETID_TROLL_CORPSE || pWho->GetEntry() == NPC_RISEN_SHADOWCASTER) { // Add reached ground, and the failure has not yet been reported if (pWho->GetPositionZ() < m_creature->GetPositionZ() + 1.5f && m_pInstance && m_pInstance->GetData(TYPE_NOVOS) == IN_PROGRESS) @@ -79,6 +114,9 @@ struct MANGOS_DLL_DECL boss_novosAI : public ScriptedAI { DoScriptText(SAY_AGGRO, m_creature); + m_creature->SummonCreature(NPC_CRYSTAL_CHANNEL_TARGET, -379.269f, -737.728f, 39.313f, 0 , TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000); + m_creature->CallForHelp(50.0f); + if (m_pInstance) m_pInstance->SetData(TYPE_NOVOS, IN_PROGRESS); } @@ -102,26 +140,236 @@ struct MANGOS_DLL_DECL boss_novosAI : public ScriptedAI m_pInstance->SetData(TYPE_NOVOS, FAIL); } + void EnterPhase1() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetInCombatWithZone(); + Phase1 = true; + } + + void EnterPhase2() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->InterruptSpell(CURRENT_CHANNELED_SPELL); + SummonMinion_Timer = urand (15000,20000); + SpecialCast_Timer = urand(15000, 20000); + ArcaneBlast_Timer = urand(25000, 30000); + Cast_Timer = 500; + Phase1 = false; + Phase2 = true; + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if (Phase2 == true) + { + //Arcane Blast + if (ArcaneBlast_Timer < uiDiff) + { + m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); + m_creature->CastSpell(m_creature, m_bIsRegularMode ? SPELL_ARCANE_BLAST : H_SPELL_ARCANE_BLAST, true); + ArcaneBlast_Timer = urand(25000, 30000); + }else ArcaneBlast_Timer -= uiDiff; + + //Wrath Of Misery or Blizzard + if (SpecialCast_Timer < uiDiff) + { + m_creature->InterruptSpell(CURRENT_GENERIC_SPELL); + switch(urand(0, 1)) + { + case 0: + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_WRATH_OF_MISERY : H_SPELL_WRATH_OF_MISERY); + case 1: + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_BLIZZARD : H_SPELL_BLIZZARD); + } + SpecialCast_Timer = urand(10000, 15000); + }else ArcaneBlast_Timer -= uiDiff; + + //Regual cast - frostbolt + if (Cast_Timer < uiDiff && ArcaneBlast_Timer > uiDiff && SpecialCast_Timer > uiDiff) + { + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_FROSTBOLT : H_SPELL_FROSTBOLT); + Cast_Timer = 1000; + }else Cast_Timer -= uiDiff; + + //Summon Minions (Heroic) + if (SummonMinion_Timer < uiDiff) + { + if(m_bIsRegularMode) + return; + + uint8 SummonLoc = rand()%POS; + if (Creature* pAdd1 = m_creature->SummonCreature(NPC_FETID_TROLL_CORPSE, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd1->AI()->AttackStart(m_creature->getVictim()); + if (Creature* pAdd2 = m_creature->SummonCreature(NPC_FETID_TROLL_CORPSE, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd2->AI()->AttackStart(m_creature->getVictim()); + if (Creature* pAdd3 = m_creature->SummonCreature(NPC_FETID_TROLL_CORPSE, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd3->AI()->AttackStart(m_creature->getVictim()); + if (Creature* pAdd4 = m_creature->SummonCreature(NPC_FETID_TROLL_CORPSE, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd4->AI()->AttackStart(m_creature->getVictim()); + if (Creature* pAdd5 = m_creature->SummonCreature(NPC_FETID_TROLL_CORPSE, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd5->AI()->AttackStart(m_creature->getVictim()); + SummonMinion_Timer = urand (15000,20000); + }else SummonMinion_Timer -= uiDiff; + + } - DoMeleeAttackIfReady(); + if (m_creature->getVictim() && Start_Check == 1) + { + EnterPhase1(); + DoCast(m_creature, SPELL_ARCANE_FIELD); + Start_Check = 0; + } + + //Phase 1 Waves spawn + if (Handler_Spawn < uiDiff && Phase1 == true) + { + Handler_Count ++; + if(Handler_Count < 5) + { + uint8 SummonLoc = rand()%POS; + m_creature->SummonCreature(NPC_CRYSTAL_HANDLER, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000); + if (Creature* pAdd1 = m_creature->SummonCreature(NPC_HULKING_CORPSE, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd1->AI()->AttackStart(m_creature->getVictim()); + if (Creature* pAdd2 = m_creature->SummonCreature(NPC_RISEN_SHADOWCASTER, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd2->AI()->AttackStart(m_creature->getVictim()); + if (Creature* pAdd3 = m_creature->SummonCreature(NPC_FETID_TROLL_CORPSE, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd3->AI()->AttackStart(m_creature->getVictim()); + if (Creature* pAdd4 = m_creature->SummonCreature(NPC_FETID_TROLL_CORPSE, PosSummonHandler[SummonLoc][0],PosSummonHandler[SummonLoc][1],PosSummonHandler[SummonLoc][2],0, TEMPSUMMON_TIMED_DESPAWN, 120000)) + pAdd4->AI()->AttackStart(m_creature->getVictim()); + Handler_Spawn = 17500; + } + if(Handler_Count == 5) + { + EnterPhase2(); + if (Creature* pTrigger = GetClosestCreatureWithEntry(m_creature, NPC_CRYSTAL_CHANNEL, 85.0f)) + pTrigger->ForcedDespawn(); + } + }else Handler_Spawn -= uiDiff; } }; + + CreatureAI* GetAI_boss_novos(Creature* pCreature) { return new boss_novosAI(pCreature); } +struct MANGOS_DLL_DECL crystal_handlerAI : public ScriptedAI +{ + crystal_handlerAI(Creature* pCreature) : ScriptedAI(pCreature){Reset();} + void Reset(){} + void MoveInLineOfSight(Unit* who) + { + if (Unit* pNovos = GetClosestCreatureWithEntry(m_creature, NPC_NOVOS, 85.0f)) + m_creature->AI()->AttackStart(pNovos->getVictim()); + } + + void JustDied() + { + if (Creature* pDeadTrigger = m_creature->SummonCreature(NPC_TRIGGER_TARGET,0,0,0,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,10000)) + { + if (Unit* pTarget = GetClosestCreatureWithEntry(m_creature, NPC_CRYSTAL_CHANNEL, 85.0f)) + { + pDeadTrigger->CastSpell(pTarget, SPELL_DEAD_EFFECT, true); + } + } + if (Creature* pTrigger = GetClosestCreatureWithEntry(m_creature, NPC_CRYSTAL_CHANNEL, 85.0f)) + pTrigger->ForcedDespawn(); + } +}; + +CreatureAI* GetAI_crystal_handler(Creature* pCreature) +{ + return new crystal_handlerAI(pCreature); +} + +struct MANGOS_DLL_DECL crystal_channelAI : public ScriptedAI +{ + crystal_channelAI(Creature* pCreature) : ScriptedAI(pCreature){Reset();} + uint32 Check_Timer; + void Reset() + { + Check_Timer = 1000; + } + void AttackStart(Unit *pWho){} + void UpdateAI(const uint32 uiDiff) + { + if (Check_Timer < uiDiff) + { + Creature* pNovos = GetClosestCreatureWithEntry(m_creature, NPC_NOVOS, 85.0f); + if (Creature* pTarget = GetClosestCreatureWithEntry(m_creature, NPC_CRYSTAL_CHANNEL_TARGET , 85.0f)) + if (pNovos && ((boss_novosAI*)pNovos->AI())->Phase1 == true) + DoCast(pTarget, SPELL_EFFECT, true); + else + pTarget->ForcedDespawn(); + Check_Timer = 1000; + }else Check_Timer -= uiDiff; + } +}; + +CreatureAI* GetAI_crystal_channel(Creature* pCreature) +{ + return new crystal_channelAI(pCreature); +} + +struct MANGOS_DLL_DECL risen_shadowcasterAI : public ScriptedAI +{ + risen_shadowcasterAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 Check_Timer; + void Reset() + { + Check_Timer = 1000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (Check_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_BOLT : H_SPELL_SHADOW_BOLT); + Check_Timer = 1000; + }else Check_Timer -= uiDiff; + } +}; + +CreatureAI* GetAI_risen_shadowcaster(Creature* pCreature) +{ + return new risen_shadowcasterAI(pCreature); +} void AddSC_boss_novos() { - Script* pNewScript; + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_novos"; + newscript->GetAI = &GetAI_boss_novos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "crystal_handler"; + newscript->GetAI = &GetAI_crystal_handler; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "crystal_channel"; + newscript->GetAI = &GetAI_crystal_channel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "risen_shadowcaster"; + newscript->GetAI = &GetAI_risen_shadowcaster; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "boss_novos"; - pNewScript->GetAI = &GetAI_boss_novos; - pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/draktharon_keep/boss_tharonja.cpp b/scripts/northrend/draktharon_keep/boss_tharonja.cpp index ab2ad05..b2af3d0 100644 --- a/scripts/northrend/draktharon_keep/boss_tharonja.cpp +++ b/scripts/northrend/draktharon_keep/boss_tharonja.cpp @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss_Tharonja -SD%Complete: 20% -SDComment: +SD%Complete: 80% +SDComment: Timers, end event with drakuru SDCategory: Drak'Tharon Keep EndScriptData */ @@ -33,9 +33,53 @@ enum SAY_FLESH_2 = -1600016, SAY_SKELETON_1 = -1600017, SAY_SKELETON_2 = -1600018, - SAY_DEATH = -1600019 + SAY_DEATH = -1600019, + + //Phase 1 (Skeleton) Spells + SPELL_CURSE_OF_LIFE = 49527, + H_SPELL_CURSE_OF_LIFE = 59972, + + SPELL_SHADOW_VOLLEY = 49528, + H_SPELL_SHADOW_VOLLEY = 59973, + SPELL_RAIN_OF_FIRE = 49518, + H_SPELL_RAIN_OF_FIRE = 59971, + + SPELL_DECAY_FLESH = 49356, //not working + + //Phase 2 (Flesh) Spells + SPELL_GIFT_OF_THARONJA = 52509, + + SPELL_LIGHTNING_BREATH = 49537, + H_SPELL_LIGHTNING_BREATH = 59936, + SPELL_EYE_BEAM = 49544, + H_SPELL_EYE_BEAM = 59965, + + SPELL_POISON_CLOUD = 49548, + H_SPELL_POSION_CLOUD = 59969, + + SPELL_RETURN_FLESH = 53463, //not working + + //achie hacks + ACHIEVEMENT_NORMAL = 482, + ACHIEVEMENT_HEROIC = 493 + +}; + +//Phasses +enum Phase +{ + PHASE_SKELETON = 0, + PHASE_INTOFLESH = 1, + PHASE_FLESH = 2, + PHASE_INTOSKELETON = 3 }; +enum PhaseChangeTimer +{ + PHASE_CHANGE_SKELETON = 12000, + PHASE_CHANGE_REAL = 6000, + PHASE_CHANGE_FLESH = 20000 +}; /*###### ## boss_tharonja ######*/ @@ -51,9 +95,19 @@ struct MANGOS_DLL_DECL boss_tharonjaAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; + uint32 PhaseChangeTimer; + uint32 Phase; + uint32 CurseOfLife_Timer; + uint32 SkeletonSpells_Timer; + uint32 PoisonCloud_Timer; + uint32 FleshSpells_Timer; void Reset() { + PhaseChangeTimer = PHASE_CHANGE_SKELETON; + Phase = PHASE_SKELETON; + SkeletonSpells_Timer = urand (5000, 10000); + CurseOfLife_Timer = urand (5000, 10000); } void Aggro(Unit* pWho) @@ -88,7 +142,91 @@ struct MANGOS_DLL_DECL boss_tharonjaAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - DoMeleeAttackIfReady(); + if (Phase == PHASE_SKELETON) + { + if (CurseOfLife_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CURSE_OF_LIFE : H_SPELL_CURSE_OF_LIFE); + CurseOfLife_Timer = urand (5000, 10000); + }else CurseOfLife_Timer -= uiDiff; + + if (SkeletonSpells_Timer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_VOLLEY : H_SPELL_SHADOW_VOLLEY); + case 1: + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_RAIN_OF_FIRE : H_SPELL_RAIN_OF_FIRE); + } + SkeletonSpells_Timer = urand (5000, 10000); + }else SkeletonSpells_Timer -= uiDiff; + + if (PhaseChangeTimer < uiDiff) + { + m_creature->CastSpell(m_creature, SPELL_DECAY_FLESH, true); + PhaseChangeTimer = PHASE_CHANGE_REAL; + Phase = PHASE_INTOFLESH; + }else PhaseChangeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + if (Phase == PHASE_INTOFLESH) + { + if (PhaseChangeTimer < uiDiff) + { + m_creature->CastSpell(m_creature, SPELL_GIFT_OF_THARONJA, true); + m_creature->SetDisplayId(27073); + PhaseChangeTimer = PHASE_CHANGE_FLESH; + Phase = PHASE_FLESH; + FleshSpells_Timer = 1500; + PoisonCloud_Timer = 10000; + }else PhaseChangeTimer -= uiDiff; + } + + if (Phase == PHASE_FLESH) + { + if (PhaseChangeTimer < uiDiff) + { + DoCast(m_creature, SPELL_RETURN_FLESH); + PhaseChangeTimer = PHASE_CHANGE_REAL; + Phase = PHASE_INTOSKELETON; + }else PhaseChangeTimer -= uiDiff; + + if (PoisonCloud_Timer < uiDiff) + { + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_POISON_CLOUD : H_SPELL_POSION_CLOUD); + PoisonCloud_Timer = 10000; + }else PoisonCloud_Timer -= uiDiff; + + if (FleshSpells_Timer < uiDiff) + { + switch(urand(0, 3)) + { + case 0: + case 1: + case 2: + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_LIGHTNING_BREATH : H_SPELL_LIGHTNING_BREATH); + case 3: + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_EYE_BEAM : SPELL_EYE_BEAM); + } + FleshSpells_Timer = 1500; + }else FleshSpells_Timer -= uiDiff; + } + + if (Phase == PHASE_INTOSKELETON) + { + if (PhaseChangeTimer < uiDiff) + { + DoCast(m_creature, SPELL_DECAY_FLESH); + m_creature->SetDisplayId(27072); + PhaseChangeTimer = PHASE_CHANGE_SKELETON; + Phase = PHASE_SKELETON; + SkeletonSpells_Timer = urand (5000, 10000); + CurseOfLife_Timer = urand (5000, 10000); + }else PhaseChangeTimer -= uiDiff; + } } }; diff --git a/scripts/northrend/draktharon_keep/boss_trollgore.cpp b/scripts/northrend/draktharon_keep/boss_trollgore.cpp index 4dcd46f..6601e58 100644 --- a/scripts/northrend/draktharon_keep/boss_trollgore.cpp +++ b/scripts/northrend/draktharon_keep/boss_trollgore.cpp @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss_Trollgore -SD%Complete: 20% -SDComment: +SD%Complete: 90% +SDComment: Timers SDCategory: Drak'Tharon Keep EndScriptData */ @@ -30,9 +30,29 @@ enum SAY_CONSUME = -1600001, SAY_DEATH = -1600002, SAY_EXPLODE = -1600003, - SAY_KILL = -1600004 + SAY_KILL = -1600004, + + SPELL_CRUSH = 49639, + SPELL_INFECTED_WOUND = 49367, + SPELL_CORPSE_EXPLODE = 49555, + H_SPELL_CORPSE_EXPLODE = 59087, + SPELL_CONSUME = 49380, + H_SPELL_CONSUME = 59803, + SPELL_CONSUME_BUFF = 49381, + H_SPELL_CONSUME_BUFF = 59805, + + SPELL_CORPSE_EXPLODE_PROC = 49618, + H_SPELL_CORPSE_EXPLODE_PROC = 59809, + + NPC_DRAKKARI_INVADER = 27753, + NPC_TROLLGORE = 26630 }; +const float PosSummon1[3] = {-259.59f, -652.49f, 26.52f}; +const float PosSummon2[3] = {-261.60f, -658.71f, 26.51f}; +const float PosSummon3[3] = {-262.05f, -665.71f, 26.49f}; + + /*###### ## boss_trollgore ######*/ @@ -49,8 +69,19 @@ struct MANGOS_DLL_DECL boss_trollgoreAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; + uint32 Consume_Timer; + uint32 Crush_Timer; + uint32 InfectedWound_Timer; + uint32 Wave_Timer; + uint32 CorpseExplode_Timer; + void Reset() { + CorpseExplode_Timer = 10000; + Consume_Timer = 5000; + Crush_Timer = 10000; + InfectedWound_Timer = 30000; + Wave_Timer = 2000; } void Aggro(Unit* pWho) @@ -81,11 +112,78 @@ struct MANGOS_DLL_DECL boss_trollgoreAI : public ScriptedAI m_pInstance->SetData(TYPE_TROLLGORE, FAIL); } + void SummonWaves() + { + if (Creature* pInvader1 = m_creature->SummonCreature(NPC_DRAKKARI_INVADER,PosSummon1[0],PosSummon1[1],PosSummon1[2],0, TEMPSUMMON_TIMED_DESPAWN, 15000)) + pInvader1->AI()->AttackStart(m_creature); + if (Creature* pInvader2 = m_creature->SummonCreature(NPC_DRAKKARI_INVADER,PosSummon2[0],PosSummon2[1],PosSummon2[2],0, TEMPSUMMON_TIMED_DESPAWN, 15000)) + pInvader2->AI()->AttackStart(m_creature); + if (Creature* pInvader3 = m_creature->SummonCreature(NPC_DRAKKARI_INVADER,PosSummon3[0],PosSummon3[1],PosSummon3[2],0, TEMPSUMMON_TIMED_DESPAWN, 15000)) + pInvader3->AI()->AttackStart(m_creature); + } + void UpdateAI(const uint32 uiDiff) { if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + // Crush + if (Crush_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_CRUSH); + Crush_Timer = 10000; + }else Crush_Timer -= uiDiff; + + // Infected Wound + if (InfectedWound_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_CRUSH); + InfectedWound_Timer = 30000; + }else InfectedWound_Timer -= uiDiff; + + // Summon npcs + if (Wave_Timer < uiDiff) + { + SummonWaves(); + Wave_Timer = 15000; + }else Wave_Timer -= uiDiff; + + // Consume + if (Consume_Timer < uiDiff) + { + m_creature->CastSpell(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CONSUME : H_SPELL_CONSUME, true); + m_creature->CastSpell(m_creature, m_bIsRegularMode ? SPELL_CONSUME_BUFF : H_SPELL_CONSUME_BUFF, true); + Consume_Timer = 15000; + }else Consume_Timer -= uiDiff; + + //Corpse Explosion + if (CorpseExplode_Timer < uiDiff) + { + //DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CORPSE_EXPLODE : H_SPELL_CORPSE_EXPLODE); + + if (Creature* pCorpse = GetClosestCreatureWithEntry(m_creature, NPC_DRAKKARI_INVADER, 85.0f)) + { + if (!pCorpse->isAlive()) + { + Map *map = pCorpse->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && pCorpse->GetDistance2d(i->getSource()->GetPositionX(), i->getSource()->GetPositionY()) <= 5) + m_creature->DealDamage(i->getSource(), (m_bIsRegularMode ? urand(3770, 4230) : urand(9425, 10575)), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NATURE, NULL, false); + } + } + } + } + CorpseExplode_Timer = 15000; + }else CorpseExplode_Timer -= uiDiff; + DoMeleeAttackIfReady(); } }; diff --git a/scripts/northrend/draktharon_keep/draktharon_keep.h b/scripts/northrend/draktharon_keep/draktharon_keep.h index 4c36b6e..090b05d 100644 --- a/scripts/northrend/draktharon_keep/draktharon_keep.h +++ b/scripts/northrend/draktharon_keep/draktharon_keep.h @@ -16,6 +16,23 @@ enum NPC_KING_DRED = 27483, + TYPE_CRYSTAL_1 = 5, + TYPE_CRYSTAL_2 = 6, + TYPE_CRYSTAL_3 = 7, + TYPE_CRYSTAL_4 = 8, + TYPE_NOVOS_PHASE2_CHECK = 9, + TYPE_NOVOS_EVENT = 10, + + NPC_CRYSTAL_CHANNEL_TARGET = 26710, + NPC_CRYSTAL_CHANNEL = 26712, + NPC_TRIGGER_TARGET = 26714, + NPC_NOVOS = 26631, + + NPC_CRYSTAL_HANDLER = 26627, + NPC_HULKING_CORPSE = 27597, + NPC_FETID_TROLL_CORPSE = 27598, + NPC_RISEN_SHADOWCASTER = 27600, + // Adds of King Dred Encounter - deaths counted for achievement NPC_DRAKKARI_GUTRIPPER = 26641, NPC_DRAKKARI_SCYTHECLAW = 26628, diff --git a/scripts/northrend/howling_fjord.cpp b/scripts/northrend/howling_fjord.cpp index d165729..9c34eb5 100644 --- a/scripts/northrend/howling_fjord.cpp +++ b/scripts/northrend/howling_fjord.cpp @@ -229,6 +229,64 @@ bool GossipSelect_npc_dark_ranger_lyana(Player* pPlayer, Creature* pCreature, ui return true; } +/*###### +## npc_greer_orehammer +######*/ + +enum +{ + GOSSIP_ITEM_TAXI = -3000106, + GOSSIP_ITEM_GET_BOMBS = -3000107, + GOSSIP_ITEM_FLIGHT = -3000108, + + QUEST_MISSION_PLAGUE_THIS = 11332, + ITEM_PRECISION_BOMBS = 33634, + TAXI_PATH_PLAGUE_THIS = 745, +}; + +bool GossipHello_npc_greer_orehammer(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu(pCreature->GetGUID()); + + if (pPlayer->GetQuestStatus(QUEST_MISSION_PLAGUE_THIS) == QUEST_STATUS_INCOMPLETE) + { + if (!pPlayer->HasItemCount(ITEM_PRECISION_BOMBS, 1, true)) + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GET_BOMBS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1); + + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2); + } + + if (pCreature->isTaxi()) + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_TAXI, GOSSIP_ITEM_TAXI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_greer_orehammer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + switch(uiAction) + { + case GOSSIP_ACTION_INFO_DEF + 1: + if (Item* pItem = pPlayer->StoreNewItemInInventorySlot(ITEM_PRECISION_BOMBS, 10)) + pPlayer->SendNewItem(pItem, 10, true, false); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + break; + case GOSSIP_ACTION_INFO_DEF + 2: + pPlayer->CLOSE_GOSSIP_MENU(); + pPlayer->ActivateTaxiPathTo(TAXI_PATH_PLAGUE_THIS); + break; + case GOSSIP_ACTION_INFO_DEF + 3: + pPlayer->GetSession()->SendTaxiMenu(pCreature); + break; + } + + return true; +} + /*###### ## npc_mcgoyver - TODO, can be moved to database ######*/ @@ -489,6 +547,12 @@ void AddSC_howling_fjord() pNewScript->pGossipSelect = &GossipSelect_npc_dark_ranger_lyana; pNewScript->RegisterSelf(); + pNewScript = new Script; + pNewScript->Name = "npc_greer_orehammer"; + pNewScript->pGossipHello = &GossipHello_npc_greer_orehammer; + pNewScript->pGossipSelect = &GossipSelect_npc_greer_orehammer; + pNewScript->RegisterSelf(); + pNewScript = new Script; pNewScript->Name = "npc_mcgoyver"; pNewScript->pGossipHello = &GossipHello_npc_mcgoyver; diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp index 3a002cb..12ac976 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_bronjahm.cpp @@ -16,70 +16,211 @@ /* ScriptData SDName: boss_bronjahm -SD%Complete: 0% -SDComment: Placeholder -SDCategory: The Forge of Souls +SD%Complete: 10% +SDComment: by /dev/rsa +SDCategory: Icecrown - forge of souls EndScriptData */ #include "precompiled.h" -#include "forge_of_souls.h" +#include "def_forge.h" -enum +enum BossSpells { - SAY_AGGRO_1 = -1632000, // without sound, really correct? - SAY_AGGRO_2 = -1632001, - SAY_SLAY_1 = -1632002, - SAY_SLAY_2 = -1632003, - SAY_DEATH = -1632004, - SAY_SOULSTORM = -1632005, - SAY_CORRUPT_SOUL = -1632006, + //common + SPELL_BERSERK = 47008, + //yells + //summons + NPC_SOUL_FRAGMENT = 36535, + //Abilities + SPELL_MAGIC_BANE = 68793, + SPELL_CORRUPT_SOUL = 68839, + SPELL_CONSUME_SOUL = 68858, + SPELL_TELEPORT = 68988, + SPELL_SOULSTORM = 68872, + SPELL_SOULSTORM_2 = 68921, + SPELL_FEAR = 68950, + SPELL_SHADOW_BOLT = 70043, + + /*Music*/ + Battle01 = 6077, + Battle02 = 6078, + Battle03 = 6079, + }; -struct MANGOS_DLL_DECL boss_bronjahmAI : public ScriptedAI +struct MANGOS_DLL_DECL boss_bronjahmAI : public BSWScriptedAI { - boss_bronjahmAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_bronjahmAI(Creature* pCreature) : BSWScriptedAI(pCreature) { - m_pInstance = (instance_forge_of_souls*)pCreature->GetInstanceData(); - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_forge_of_souls* m_pInstance; - bool m_bIsRegularMode; + ScriptedInstance *pInstance; + uint8 stage; + uint32 BattleMusicTimer; + uint32 Music; void Reset() { + if(pInstance) pInstance->SetData(TYPE_BRONJAHM, NOT_STARTED); + resetTimers(); + stage = 0; + } + + void Aggro(Unit *who) + { + Music = (urand(0, 2)); + switch(Music) + { + case 0: + m_creature->PlayDirectSound(Battle01); + BattleMusicTimer = 48000; + break; + case 1: + m_creature->PlayDirectSound(Battle02); + BattleMusicTimer = 27000; + break; + case 2: + m_creature->PlayDirectSound(Battle03); + BattleMusicTimer = 36000; + break; + } + + if(pInstance) pInstance->SetData(TYPE_BRONJAHM, IN_PROGRESS); + DoScriptText(-1632001,m_creature,who); + SetCombatMovement(true); } - void Aggro(Unit* pWho) + void JustDied(Unit *killer) { - DoScriptText(urand(0, 1) ? SAY_AGGRO_1 : SAY_AGGRO_2, m_creature); - if (m_pInstance) - m_pInstance->SetData(TYPE_BRONJAHM, IN_PROGRESS); + if(pInstance) pInstance->SetData(TYPE_BRONJAHM, DONE); + doRemove(SPELL_SOULSTORM); + DoScriptText(-1632004,m_creature,killer); } void KilledUnit(Unit* pVictim) { - if (pVictim->GetTypeId() != TYPEID_PLAYER) + switch (urand(0,1)) { + case 0: + DoScriptText(-1632002,m_creature,pVictim); + break; + case 1: + DoScriptText(-1632003,m_creature,pVictim); + break; + }; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (urand(0, 1)) - DoScriptText(urand(0, 1) ? SAY_SLAY_1 : SAY_SLAY_2, m_creature); + switch(stage) + { + case 0: + if (timedQuery(SPELL_CORRUPT_SOUL, diff)) + { + if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if (doCast(SPELL_CORRUPT_SOUL, pTarget) == CAST_OK) + { + DoScriptText(-1632006,m_creature,pTarget); + float fPosX, fPosY, fPosZ; + pTarget->GetPosition(fPosX, fPosY, fPosZ); + doSummon(NPC_SOUL_FRAGMENT,fPosX, fPosY, fPosZ); + } + } + } + break; + case 1: + if (timedCast(SPELL_TELEPORT, diff) == CAST_OK) stage = 2; + break; + case 2: + if (timedCast(SPELL_SOULSTORM, diff) == CAST_OK) { + DoScriptText(-1632005,m_creature); + SetCombatMovement(false); + stage = 3; + } + break; + case 3: + timedCast(SPELL_FEAR, diff); + break; + } + + timedCast(SPELL_SHADOW_BOLT, diff); + + timedCast(SPELL_MAGIC_BANE, diff); + + if (m_creature->GetHealthPercent() <= 30.0f && stage == 0) stage = 1; + + DoMeleeAttackIfReady(); + + if (BattleMusicTimer < diff && m_creature->isAlive()) + { + switch(Music) + { + case 0: + m_creature->PlayDirectSound(Battle01); + BattleMusicTimer = 49000; + break; + case 1: + m_creature->PlayDirectSound(Battle02); + BattleMusicTimer = 28000; + break; + case 2: + m_creature->PlayDirectSound(Battle03); + BattleMusicTimer = 37000; + break; + } + } else BattleMusicTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL mob_soul_fragmentAI : public ScriptedAI +{ + mob_soul_fragmentAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); } - void JustDied(Unit* pKiller) + ScriptedInstance *m_pInstance; + Creature* pBoss; + uint32 m_uiRangeCheck_Timer; + + void Reset() { - DoScriptText(SAY_DEATH, m_creature); + m_uiRangeCheck_Timer = 1000; + if (!m_pInstance) return; + pBoss = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRONJAHM)); + m_creature->SetSpeedRate(MOVE_RUN, 0.2f); + m_creature->GetMotionMaster()->MoveChase(pBoss); + m_creature->SetRespawnDelay(DAY); + } - if (m_pInstance) - m_pInstance->SetData(TYPE_BRONJAHM, DONE); + void AttackStart(Unit* pWho) + { + return; } - void JustReachedHome() + void UpdateAI(const uint32 uiDiff) { - if (m_pInstance) - m_pInstance->SetData(TYPE_BRONJAHM, NOT_STARTED); + if (!m_pInstance || m_pInstance->GetData(TYPE_BRONJAHM) != IN_PROGRESS ) m_creature->ForcedDespawn(); + + if (m_uiRangeCheck_Timer < uiDiff) + { + if (pBoss->IsWithinDistInMap(m_creature, 2.0f)) + { + pBoss->CastSpell(pBoss, SPELL_CONSUME_SOUL, false); + m_creature->ForcedDespawn(); + } else m_creature->GetMotionMaster()->MoveChase(pBoss); + + m_uiRangeCheck_Timer = 1000; + } + else m_uiRangeCheck_Timer -= uiDiff; } + }; CreatureAI* GetAI_boss_bronjahm(Creature* pCreature) @@ -87,12 +228,23 @@ CreatureAI* GetAI_boss_bronjahm(Creature* pCreature) return new boss_bronjahmAI(pCreature); } +CreatureAI* GetAI_mob_soul_fragment(Creature* pCreature) +{ + return new mob_soul_fragmentAI (pCreature); +} + + void AddSC_boss_bronjahm() { - Script* pNewScript; + Script *newscript; + newscript = new Script; + newscript->Name = "boss_bronjahm"; + newscript->GetAI = &GetAI_boss_bronjahm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_soul_fragment"; + newscript->GetAI = &GetAI_mob_soul_fragment; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "boss_bronjahm"; - pNewScript->GetAI = &GetAI_boss_bronjahm; - pNewScript->RegisterSelf(); } diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp index 4ad33e8..d97bc66 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp @@ -16,105 +16,406 @@ /* ScriptData SDName: boss_devourer_of_souls -SD%Complete: 0% -SDComment: Placeholder +SD%Complete: 100% +SDComment: MaxXx2021, modified by /dev/rsa SDCategory: The Forge of Souls EndScriptData */ #include "precompiled.h" -#include "forge_of_souls.h" +#include "def_forge.h" enum { - // TODO, how to change the face on random?, how to know which face is shown, to use the additional entries - SAY_MALE_1_AGGRO = -1632007, - SAY_FEMALE_AGGRO = -1632008, - SAY_MALE_1_SLAY_1 = -1632009, - SAY_FEMALE_SLAY_1 = -1632010, - SAY_MALE_2_SLAY_1 = -1632011, - SAY_MALE_1_SLAY_2 = -1632012, - SAY_FEMALE_SLAY_2 = -1632013, - SAY_MALE_2_SLAY_2 = -1632014, - SAY_MALE_1_DEATH = -1632015, - SAY_FEMALE_DEATH = -1632016, - SAY_MALE_2_DEATH = -1632017, - SAY_MALE_1_SOUL_ATTACK = -1632018, - SAY_FEMALE_SOUL_ATTACK = -1632019, - SAY_MALE_2_SOUL_ATTACK = -1632020, - SAY_MALE_1_DARK_GLARE = -1632021, - SAY_FEMALE_DARK_GLARE = -1632022, - - EMOTE_MIRRORED_SOUL = -1632023, - EMOTE_UNLEASH_SOULS = -1632024, - EMOTE_WAILING_SOULS = -1632025, - - FACE_NORMAL = 0, - FACE_UNLEASHING = 1, - FACE_WAILING = 2, + /*Speach*/ + SAY_DEVOURER_AGGRO_MALE_01 = -1632010, + SAY_DEVOURER_SLAY_01_MALE_01 = -1632012, + SAY_DEVOURER_SLAY_02_MALE_01 = -1632015, + SAY_DEVOURER_DEATH_MALE_01 = -1632018, + SAY_DEVOURER_SUMMON_MALE_01 = -1632023, + SAY_DEVOURER_DARK_MALE_01 = -1632027, + SAY_DEVOURER_MIRRORED_SOUL = -1632021, + SAY_DEVOURER_UNLEASHED_SOULS = -1632022, + SAY_DEVOURER_WELL_OF_SOULS = -1632026, + + SAY_JAINA_FS09_EXTRO = -1632029, + SAY_SYLVANA_FS07_EXTRO = -1632030, + + /*Spell And Visual Effects*/ + SPELL_PHANTOM_BLAST = 68982, + SPELL_MIRRORED_SOUL = 69051, + SPELL_WELL_OF_SOULS = 68820, + SPELL_UNLEASHED_SOULS = 68939, + SPELL_WAILING_SOULS = 68912, //68873 + SPELL_WELL_OF_SOULS_VIS = 68854, + SPELL_WELL_OF_SOUL_DM = 68863, + + /*Units*/ + NPC_WELL_OF_SOUL = 36536, + NPC_UNLEASHED_SOUL = 36595, + + /*Others*/ + MODEL_FAT = 30149, + MODEL_WOMAN = 30150, + + /*Music*/ + Battle01 = 6077, + Battle02 = 6078, + Battle03 = 6079, + + MAX_POINTS = 22, }; -static const int aTexts[6][3] = +static Locations SpawnLoc[]= { - {SAY_MALE_1_AGGRO, SAY_FEMALE_AGGRO, 0}, // 0 - aggro - {SAY_MALE_1_SLAY_1, SAY_FEMALE_SLAY_1, SAY_MALE_2_SLAY_1}, // 1 - slay1 - {SAY_MALE_1_SLAY_2, SAY_FEMALE_SLAY_2, SAY_MALE_2_SLAY_2}, // 2 - slay2 - {SAY_MALE_1_DEATH, SAY_FEMALE_DEATH, SAY_MALE_2_DEATH}, // 3 - death - {SAY_MALE_1_SOUL_ATTACK, SAY_FEMALE_SOUL_ATTACK, SAY_MALE_2_SOUL_ATTACK}, // 4 - soul - {SAY_MALE_1_DARK_GLARE, SAY_FEMALE_DARK_GLARE, 0} // 5 - glare +{5618.139f, 2451.873f, 705.854f}, //0 - spawn +{5590.47f, 2427.79f, 705.935f}, +{5593.59f, 2428.34f, 705.935f}, +{5600.81f, 2429.31f, 705.935f}, +{5600.81f, 2421.12f, 705.935f}, +{5601.43f, 2426.53f, 705.935f}, +{5601.55f, 2418.36f, 705.935f}, +{5598.0f, 2429.14f, 705.935f}, +{5594.04f, 2424.87f, 705.935f}, +{5597.89f, 2421.54f, 705.935f}, +{5598.57f, 2434.62f, 705.935f}, +{5585.46f, 2417.99f, 705.935f}, +{5605.81f, 2428.42f, 705.935f}, +{5591.61f, 2412.66f, 705.935f}, +{5593.9f, 2410.64f, 705.935f}, +{5586.76f, 2416.73f, 705.935f}, +{5592.23f, 2419.14f, 705.935f}, +{5594.61f, 2416.87f, 705.935f}, +{5589.77f, 2421.03f, 705.935f}, +{5602.58f, 2435.95f, 705.935f}, +{5606.13f, 2433.16f, 705.935f}, +{5606.12f, 2436.6f, 705.935f}, //21 }; + + struct MANGOS_DLL_DECL boss_devourer_of_soulsAI : public ScriptedAI { - boss_devourer_of_soulsAI(Creature* pCreature) : ScriptedAI(pCreature) + boss_devourer_of_soulsAI(Creature *pCreature) : ScriptedAI(pCreature) { - m_pInstance = (instance_forge_of_souls*)pCreature->GetInstanceData(); - m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); Reset(); } - instance_forge_of_souls* m_pInstance; - uint8 m_uiFace; - bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + uint32 BattleMusicTimer; + uint32 PhantomBlastTimer; + uint32 SummonTimer; + uint32 WellOfSoulTimer; + uint32 MirroredTimer; + uint32 SoulBeamTimer; + uint32 Step; + uint32 StepTimer; + bool Summon; void Reset() { - m_uiFace = FACE_NORMAL; + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_DEVOURER, NOT_STARTED); + DespawnAllSummons(); + Summon = false; + Step = 0; + StepTimer = 100; + PhantomBlastTimer = 5000; + WellOfSoulTimer = 12000; + SummonTimer = 20000; + MirroredTimer = 28000; + SoulBeamTimer = 33000; } - void Aggro(Unit* pWho) + void Aggro(Unit *who) { - DoScriptText(aTexts[0][m_uiFace], m_creature); - if (m_pInstance) - m_pInstance->SetData(TYPE_DECOURER_OF_SOULS, IN_PROGRESS); + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_DEVOURER, IN_PROGRESS); + m_creature->PlayDirectSound(Battle01); + BattleMusicTimer = 48000; + DoScriptText(SAY_DEVOURER_AGGRO_MALE_01, m_creature); } - void KilledUnit(Unit* pVictim) + void DespawnAllSummons() { - if (pVictim->GetTypeId() != TYPEID_PLAYER) - return; + std::list m_pSouls; + GetCreatureListWithEntryInGrid(m_pSouls, m_creature, NPC_UNLEASHED_SOUL, DEFAULT_VISIBILITY_INSTANCE); + + if (!m_pSouls.empty()) + for(std::list::iterator itr = m_pSouls.begin(); itr != m_pSouls.end(); ++itr) + { + (*itr)->ForcedDespawn(); + } + + std::list m_pWells; + GetCreatureListWithEntryInGrid(m_pWells, m_creature, NPC_WELL_OF_SOUL, DEFAULT_VISIBILITY_INSTANCE); - if (urand(0, 1)) - DoScriptText(aTexts[urand(1, 2)][m_uiFace], m_creature); + if (!m_pWells.empty()) + for(std::list::iterator iter = m_pWells.begin(); iter != m_pWells.end(); ++iter) + { + (*iter)->ForcedDespawn(); + } + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + + Map *map = m_creature->GetMap(); + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_MIRRORED_SOUL)) + m_creature->DealDamage(i->getSource(), uiDamage/2,NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + void SpawnOutro(uint32 guid) + { + if (Creature *pSummon = m_creature->SummonCreature(guid, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z,0, TEMPSUMMON_TIMED_DESPAWN, 300000)) + { + uint8 i = urand(1,MAX_POINTS); + + pSummon->GetMotionMaster()->MovePoint(i, SpawnLoc[i].x, SpawnLoc[i].y, SpawnLoc[i].z); + + if (pSummon->GetEntry() == npc_jaina_extro) + DoScriptText(SAY_JAINA_FS09_EXTRO, pSummon); + else if (pSummon->GetEntry() == npc_sylvana_extro) + DoScriptText(SAY_SYLVANA_FS07_EXTRO, pSummon); + } } void JustDied(Unit* pKiller) { - DoScriptText(aTexts[3][m_uiFace], m_creature); + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_DEVOURER, DONE); + DoScriptText(SAY_DEVOURER_DEATH_MALE_01, m_creature); + DespawnAllSummons(); - if (m_pInstance) + Player* player = (Player*)pKiller; + + if(player->GetTeam() == ALLIANCE) + { + m_pInstance->SetData64(DATA_LIDER,0); + SpawnOutro(npc_jaina_extro); + SpawnOutro(npc_jaina_credit); + SpawnOutro(npc_mage); + SpawnOutro(npc_mage_woman); + SpawnOutro(npc_cc_a_01); + SpawnOutro(npc_cc_a_02); + SpawnOutro(npc_cc_a_03); + + } else + { + m_pInstance->SetData64(DATA_LIDER,1); + SpawnOutro(npc_sylvana_extro); + SpawnOutro(npc_sylvana_credit); + SpawnOutro(npc_mage); + SpawnOutro(npc_mage_woman); + SpawnOutro(npc_cc_h_01); + SpawnOutro(npc_cc_h_02); + SpawnOutro(npc_cc_h_03); + }; + } + + void KilledUnit(Unit* victim) + { + switch (urand(0,1)) { - m_pInstance->SetData(TYPE_DECOURER_OF_SOULS, DONE); + case 0: DoScriptText(SAY_DEVOURER_SLAY_01_MALE_01, m_creature); break; + case 1: DoScriptText(SAY_DEVOURER_SLAY_02_MALE_01, m_creature); break; } } - void JustReachedHome() + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(Summon != true) + { + if (PhantomBlastTimer < diff) + { + if (Unit* Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(Target, SPELL_PHANTOM_BLAST); + PhantomBlastTimer = 8000; + } + else + PhantomBlastTimer -= diff; + + if (WellOfSoulTimer < diff) + { + if (Unit* Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(Target, SPELL_WELL_OF_SOULS); + DoScriptText(SAY_DEVOURER_WELL_OF_SOULS, m_creature); + WellOfSoulTimer = urand(12000,24000); + } + else + WellOfSoulTimer -= diff; + + if (SummonTimer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + switch (urand(0,1)) + { + case 0: DoScriptText(SAY_DEVOURER_SUMMON_MALE_01, m_creature); break; + case 1: DoScriptText(SAY_DEVOURER_UNLEASHED_SOULS, m_creature); break; + } + DoCast(m_creature, SPELL_UNLEASHED_SOULS); + SummonTimer = 50000; + Summon = true; + } + else + SummonTimer -= diff; + + if (MirroredTimer < diff) + { + if (Unit* Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCast(Target, SPELL_MIRRORED_SOUL); + DoScriptText(SAY_DEVOURER_MIRRORED_SOUL, m_creature); + MirroredTimer = 25000; + } + } + else + MirroredTimer -= diff; + + if (SoulBeamTimer < diff) + { + DoScriptText(SAY_DEVOURER_DARK_MALE_01, m_creature); + DoCast(m_creature->getVictim(), SPELL_WAILING_SOULS); + SoulBeamTimer = (urand(35000, 45000)); + } + else + SoulBeamTimer -= diff; + + } + + if(Summon == true) + { + if (StepTimer < diff) + { + switch(Step) + { + case 0: + StepTimer = 900; + ++Step; + break; + case 1: + m_creature->SetDisplayId(MODEL_FAT); //this is huck, because this spell (SPELL_UNLEASHED_SOULS) morphed boss into PIG :D + StepTimer = 2000; + ++Step; + break; + case 2: + Summon = false; + Step = 0; + StepTimer = 100; + break; + } + } else StepTimer -= diff; + + } + + DoMeleeAttackIfReady(); + + if (BattleMusicTimer < diff && m_creature->isAlive()) + { + m_creature->PlayDirectSound(Battle01); + BattleMusicTimer = 49000; + } + else + BattleMusicTimer -= diff; + + return; + } +}; + +struct MANGOS_DLL_DECL npc_well_of_soulAI : public ScriptedAI +{ + npc_well_of_soulAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + +ScriptedInstance* m_pInstance; + +uint32 DamageTimer; +uint32 DeathTimer; + + void Reset() + { + m_creature->SetLevel(80); + m_creature->setFaction(14); + m_creature->SetDisplayId(11686); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DeathTimer = 60000; + DoCast(m_creature, SPELL_WELL_OF_SOULS_VIS); + DamageTimer = 1000; + } + + void AttackStart(Unit* who) + { + return; + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if(m_pInstance && m_pInstance->GetData(TYPE_DEVOURER) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (DeathTimer < diff) + { + m_creature->ForcedDespawn(); + } else DeathTimer -= diff; + + if (DamageTimer < diff) + { + DoCast(m_creature, SPELL_WELL_OF_SOUL_DM); + DamageTimer = 1000; + } else DamageTimer -= diff; + + return; + } +}; + +struct MANGOS_DLL_DECL npc_unleashed_soulAI : public ScriptedAI +{ + npc_unleashed_soulAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() { if (m_pInstance) { - m_pInstance->SetData(NPC_DEVOURER_OF_SOULS, NOT_STARTED); - // If we previously failed, set such that possible to try again - m_pInstance->SetData(TYPE_ACHIEV_PHANTOM_BLAST, IN_PROGRESS); + if (Creature* pDevourer = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_DEVOURER))) + if (pDevourer && pDevourer->isAlive()) + AttackStart(pDevourer->getVictim()); } + + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if(m_pInstance && m_pInstance->GetData(TYPE_DEVOURER) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } }; @@ -123,12 +424,32 @@ CreatureAI* GetAI_boss_devourer_of_souls(Creature* pCreature) return new boss_devourer_of_soulsAI(pCreature); } +CreatureAI* GetAI_npc_well_of_soul(Creature* pCreature) +{ + return new npc_well_of_soulAI(pCreature); +} + +CreatureAI* GetAI_npc_unleashed_soul(Creature* pCreature) +{ + return new npc_unleashed_soulAI(pCreature); +} + void AddSC_boss_devourer_of_souls() { - Script* pNewScript; + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_devourer_of_souls"; + newscript->GetAI = &GetAI_boss_devourer_of_souls; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_well_of_soul"; + newscript->GetAI = &GetAI_npc_well_of_soul; + newscript->RegisterSelf(); - pNewScript = new Script; - pNewScript->Name = "boss_devourer_of_souls"; - pNewScript->GetAI = &GetAI_boss_devourer_of_souls; - pNewScript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_unleashed_soul"; + newscript->GetAI = &GetAI_npc_unleashed_soul; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/def_forge.h b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/def_forge.h new file mode 100644 index 0000000..669cafe --- /dev/null +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/def_forge.h @@ -0,0 +1,35 @@ +#ifndef DEF_ICECROWN_FORGE_H +#define DEF_ICECROWN_FORGE_H +#include "BSW_ai.h" + +enum +{ + MAX_ENCOUNTERS = 3, + + TYPE_INTRO = 0, + TYPE_BRONJAHM = 1, + TYPE_DEVOURER = 2, + + NPC_BRONJAHM = 36497, + NPC_DEVOURER = 36502, + + DATA_LIDER = 101, + + npc_jaina = 37597, + npc_sylvana = 37596, + npc_jaina_extro = 38160, + npc_sylvana_extro = 38161, + npc_jaina_credit = 36955, + npc_sylvana_credit = 37554, + npc_mage = 37582, + npc_mage_woman = 37774, + npc_cc_a_01 = 37497, + npc_cc_a_02 = 37496, + npc_cc_a_03 = 37498, + npc_cc_h_01 = 37588, + npc_cc_h_02 = 37584, + npc_cc_h_03 = 37587, + +}; + +#endif diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.cpp new file mode 100644 index 0000000..b6d79b6 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/forge_of_souls.cpp @@ -0,0 +1,537 @@ +/* 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: Forge Of The Souls +SD%Complete: 90% +SDComment: event script! Need Add 6 Coliseum Champion after devourer death. +SDCategory: forge_of_the_souls +SDAuthor: MaxXx2021 aka Mioka +EndScriptData */ + +#include "precompiled.h" +#include "def_forge.h" + +enum +{ + SAY_JAINA_FS01 = -1632040, + SAY_JAINA_FS02 = -1632041, + SAY_JAINA_FS03 = -1632042, + SAY_JAINA_FS04 = -1632043, + SAY_JAINA_FS05 = -1632044, + SAY_JAINA_FS06 = -1632045, + SAY_JAINA_FS07 = -1632046, + SAY_JAINA_FS08 = -1632047, + SAY_JAINA_FS09_EXTRO = -1632029, + + SAY_SYLVANA_FS01 = -1632050, + SAY_SYLVANA_FS02 = -1632051, + SAY_SYLVANA_FS03 = -1632052, + SAY_SYLVANA_FS04 = -1632053, + SAY_SYLVANA_FS05 = -1632054, + SAY_SYLVANA_FS06 = -1632055, + SAY_SYLVANA_FS07_EXTRO = -1632030, + + GOSSIP_SPEECHINTRO = 13525, +}; + +struct MANGOS_DLL_DECL npc_jaina_and_sylvana_FSintroAI : public ScriptedAI +{ + npc_jaina_and_sylvana_FSintroAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + +ScriptedInstance* m_pInstance; + +uint32 StepTimer; +uint32 Step; +bool StartEvent; + + void Reset() + { + if(m_pInstance) + if(m_pInstance->GetData(TYPE_DEVOURER) == DONE) + m_creature->SetVisibility(VISIBILITY_OFF); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + Step = 0; + StepTimer = 100; + if(m_pInstance->GetData(TYPE_INTRO) == DONE) + { + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + Step = 8; + } + } + + void UpdateAI(const uint32 diff) + { + DoMeleeAttackIfReady(); + + if(!m_pInstance) return; + + if(StartEvent != true) return; + + if(StepTimer < diff) + { + switch(Step) + { + case 0: + m_pInstance->SetData(TYPE_INTRO, DONE); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + if(m_creature->GetEntry() == npc_jaina) + { + DoScriptText(SAY_JAINA_FS01, m_creature); + StepTimer = 7000; + } + if(m_creature->GetEntry() == npc_sylvana) + StepTimer = 100; + ++Step; + break; + case 1: + if(m_creature->GetEntry() == npc_jaina) + { + DoScriptText(SAY_JAINA_FS02, m_creature); + StepTimer = 9000; + } + if(m_creature->GetEntry() == npc_sylvana) + { + DoScriptText(SAY_SYLVANA_FS01, m_creature); + StepTimer = 12000; + } + ++Step; + break; + case 2: + if(m_creature->GetEntry() == npc_jaina) + { + DoScriptText(SAY_JAINA_FS03, m_creature); + StepTimer = 8000; + } + if(m_creature->GetEntry() == npc_sylvana) + { + DoScriptText(SAY_SYLVANA_FS02, m_creature); + StepTimer = 11000; + } + ++Step; + break; + case 3: + if(m_creature->GetEntry() == npc_jaina) + { + DoScriptText(SAY_JAINA_FS04, m_creature); + StepTimer = 10000; + } + if(m_creature->GetEntry() == npc_sylvana) + { + DoScriptText(SAY_SYLVANA_FS03, m_creature); + StepTimer = 11000; + } + ++Step; + break; + case 4: + if(m_creature->GetEntry() == npc_jaina) + { + DoScriptText(SAY_JAINA_FS05, m_creature); + StepTimer = 8000; + } + if(m_creature->GetEntry() == npc_sylvana) + { + DoScriptText(SAY_SYLVANA_FS04, m_creature); + StepTimer = 12000; + } + ++Step; + break; + case 5: + if(m_creature->GetEntry() == npc_jaina) + { + DoScriptText(SAY_JAINA_FS06, m_creature); + StepTimer = 12000; + } + if(m_creature->GetEntry() == npc_sylvana) + { + DoScriptText(SAY_SYLVANA_FS05, m_creature); + StepTimer = 7000; + } + ++Step; + break; + case 6: + if(m_creature->GetEntry() == npc_jaina) + { + DoScriptText(SAY_JAINA_FS07, m_creature); + StepTimer = 7000; + } + if(m_creature->GetEntry() == npc_sylvana) + { + DoScriptText(SAY_SYLVANA_FS06, m_creature); + StepTimer = 4000; + } + ++Step; + break; + case 7: + if(m_creature->GetEntry() == npc_jaina) + { + DoScriptText(SAY_JAINA_FS08, m_creature); + StepTimer = 5000; + } + ++Step; + break; + } + } else StepTimer -= diff; + } +}; + +bool GossipHello_npc_jaina_and_sylvana_FSintro(Player* pPlayer, Creature* pCreature) +{ + if (pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu( pCreature->GetGUID()); + switch(pCreature->GetEntry()) + { + case 37597: + if(((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->StartEvent != true) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What would you have of me, My Lady?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + break; + case 37596: + if(((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->StartEvent != true) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What would you have of me, Banshee Queen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + break; + } + + pPlayer->PlayerTalkClass->SendGossipMenu(907,pCreature->GetGUID()); //907 + return true; +} + +bool GossipSelect_npc_jaina_and_sylvana_FSintro(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + pPlayer->CLOSE_GOSSIP_MENU(); + ((npc_jaina_and_sylvana_FSintroAI*)pCreature->AI())->StartEvent = true; + + return true; +} + +struct MANGOS_DLL_DECL npc_jaina_and_sylvana_FSextroAI : public ScriptedAI +{ + npc_jaina_and_sylvana_FSextroAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + +ScriptedInstance* m_pInstance; + +uint32 StepTimer; +uint32 Step; +uint64 m_uiLiderGUID; +uint32 uiSummon_counter; + + void Reset() + { + if (m_pInstance) + if (m_pInstance->GetData(TYPE_DEVOURER) != DONE) + { + m_pInstance->SetData(TYPE_DEVOURER, NOT_STARTED); + Step = 0; + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } else Step = 10; + StepTimer = 100; + m_creature->SetVisibility(VISIBILITY_OFF); + } + + void UpdateAI(const uint32 diff) + { + DoMeleeAttackIfReady(); + + if (!m_pInstance) return; + + if (m_pInstance->GetData(TYPE_DEVOURER) == DONE) + { + + if(m_pInstance->GetData64(DATA_LIDER) == 1 && m_creature->GetEntry() == npc_sylvana_extro) return; + + if(m_pInstance->GetData64(DATA_LIDER) == 2 && m_creature->GetEntry() == npc_jaina_extro) return; + + if(StepTimer < diff) + { + switch(Step) + { + case 0: + m_creature->SetVisibility(VISIBILITY_ON); + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MovePoint(0, 5653.337f, 2496.407f, 708.829f); + uiSummon_counter = 0; + StepTimer = 400; + ++Step; + break; + case 1: + if(m_creature->GetEntry() == npc_jaina_extro) + { + StepTimer = 100; + if (uiSummon_counter < 4) + { + if (Creature* pTemp = m_creature->SummonCreature(npc_cc_a_01,5623.609f,2457.946f,705.891f,1.37f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000)) + { + pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + switch(uiSummon_counter) + { + case 0: + pTemp->GetMotionMaster()->MovePoint(0, 5659.251f, 2472.017f, 708.696f); + break; + case 1: + pTemp->GetMotionMaster()->MovePoint(0, 5627.611f, 2501.972f, 708.696f); + break; + case 2: + pTemp->GetMotionMaster()->MovePoint(0, 5680.920f, 2482.998f, 708.696f); + break; + case 3: + pTemp->GetMotionMaster()->MovePoint(0, 5641.398f, 2523.911f, 708.696f); + break; + } + uiSummon_counter++; + } + } + else + { + uiSummon_counter = 0; + Step++; + } + } + if(m_creature->GetEntry() == npc_sylvana_extro) + { + StepTimer = 100; + if (uiSummon_counter < 4) + { + if (Creature* pTemp = m_creature->SummonCreature(npc_cc_h_01,5623.609f,2457.946f,705.891f,1.37f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000)) + { + pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + switch(uiSummon_counter) + { + case 0: + pTemp->GetMotionMaster()->MovePoint(0, 5659.251f, 2472.017f, 708.696f); + break; + case 1: + pTemp->GetMotionMaster()->MovePoint(0, 5627.611f, 2501.972f, 708.696f); + break; + case 2: + pTemp->GetMotionMaster()->MovePoint(0, 5680.920f, 2482.998f, 708.696f); + break; + case 3: + pTemp->GetMotionMaster()->MovePoint(0, 5641.398f, 2523.911f, 708.696f); + break; + } + uiSummon_counter++; + } + } + else + { + uiSummon_counter = 0; + Step++; + } + } + break; + case 2: + if(m_creature->GetEntry() == npc_jaina_extro) + { + StepTimer = 100; + if (uiSummon_counter < 4) + { + if (Creature* pTemp = m_creature->SummonCreature(npc_cc_a_02,5623.609f,2457.946f,705.891f,1.37f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000)) + { + pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + switch(uiSummon_counter) + { + case 0: + pTemp->GetMotionMaster()->MovePoint(0, 5661.508f, 2473.066f, 708.696f); + break; + case 1: + pTemp->GetMotionMaster()->MovePoint(0, 5627.146f, 2499.098f, 708.696f); + break; + case 2: + pTemp->GetMotionMaster()->MovePoint(0, 5682.331f, 2485.985f, 708.696f); + break; + case 3: + pTemp->GetMotionMaster()->MovePoint(0, 5639.636f, 2521.228f, 708.696f); + break; + } + uiSummon_counter++; + } + } + else + { + uiSummon_counter = 0; + Step++; + } + } + if(m_creature->GetEntry() == npc_sylvana_extro) + { + StepTimer = 100; + if (uiSummon_counter < 4) + { + if (Creature* pTemp = m_creature->SummonCreature(npc_cc_h_02,5623.609f,2457.946f,705.891f,1.37f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000)) + { + pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + switch(uiSummon_counter) + { + case 0: + pTemp->GetMotionMaster()->MovePoint(0, 5661.508f, 2473.066f, 708.696f); + break; + case 1: + pTemp->GetMotionMaster()->MovePoint(0, 5627.146f, 2499.098f, 708.696f); + break; + case 2: + pTemp->GetMotionMaster()->MovePoint(0, 5682.331f, 2485.985f, 708.696f); + break; + case 3: + pTemp->GetMotionMaster()->MovePoint(0, 5639.636f, 2521.228f, 708.696f); + break; + } + uiSummon_counter++; + } + } + else + { + uiSummon_counter = 0; + Step++; + } + } + break; + case 3: + if(m_creature->GetEntry() == npc_jaina_extro) + { + StepTimer = 100; + if (uiSummon_counter < 4) + { + if (Creature* pTemp = m_creature->SummonCreature(npc_cc_a_03,5623.609f,2457.946f,705.891f,1.37f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000)) + { + pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + switch(uiSummon_counter) + { + case 0: + pTemp->GetMotionMaster()->MovePoint(0, 5664.265f, 2473.974f, 708.696f); + break; + case 1: + pTemp->GetMotionMaster()->MovePoint(0, 5626.768f, 2496.534f, 708.696f); + break; + case 2: + pTemp->GetMotionMaster()->MovePoint(0, 5683.696f, 2489.598f, 708.696f); + break; + case 3: + pTemp->GetMotionMaster()->MovePoint(0, 5637.580f, 2518.249f, 708.696f); + break; + } + uiSummon_counter++; + } + } + else + { + uiSummon_counter = 0; + StepTimer = 8000; + Step++; + } + } + if(m_creature->GetEntry() == npc_sylvana_extro) + { + StepTimer = 100; + if (uiSummon_counter < 4) + { + if (Creature* pTemp = m_creature->SummonCreature(npc_cc_h_03,5623.609f,2457.946f,705.891f,1.37f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000)) + { + pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + switch(uiSummon_counter) + { + case 0: + pTemp->GetMotionMaster()->MovePoint(0, 5664.265f, 2473.974f, 708.696f); + break; + case 1: + pTemp->GetMotionMaster()->MovePoint(0, 5626.768f, 2496.534f, 708.696f); + break; + case 2: + pTemp->GetMotionMaster()->MovePoint(0, 5683.696f, 2489.598f, 708.696f); + break; + case 3: + pTemp->GetMotionMaster()->MovePoint(0, 5637.580f, 2518.249f, 708.696f); + break; + } + uiSummon_counter++; + } + } + else + { + uiSummon_counter = 0; + StepTimer = 8000; + Step++; + } + } + break; + case 4: + if(m_creature->GetEntry() == npc_jaina_extro) + { + DoScriptText(SAY_JAINA_FS09_EXTRO, m_creature); + StepTimer = 6000; + } + if(m_creature->GetEntry() == npc_sylvana_extro) + { + DoScriptText(SAY_SYLVANA_FS07_EXTRO, m_creature); + StepTimer = 3000; + } + ++Step; + break; + case 5: + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + ++Step; + break; + } + } else StepTimer -= diff; + } + return; + } +}; + +CreatureAI* GetAI_npc_jaina_and_sylvana_FSintro(Creature* pCreature) +{ + return new npc_jaina_and_sylvana_FSintroAI(pCreature); +} + +CreatureAI* GetAI_npc_jaina_and_sylvana_FSextro(Creature* pCreature) +{ + return new npc_jaina_and_sylvana_FSextroAI(pCreature); +} + +void AddSC_forge_of_souls() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_jaina_and_sylvana_FSintro"; + newscript->GetAI = &GetAI_npc_jaina_and_sylvana_FSintro; + newscript->pGossipHello = &GossipHello_npc_jaina_and_sylvana_FSintro; + newscript->pGossipSelect = &GossipSelect_npc_jaina_and_sylvana_FSintro; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_and_sylvana_FSextro"; + newscript->GetAI = &GetAI_npc_jaina_and_sylvana_FSextro; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp index c600db6..cb2875a 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp @@ -1,237 +1,175 @@ /* Copyright (C) 2006 - 2010 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_forge_of_souls -SD%Complete: 90% -SDComment: TODO: Movement of the extro-event is missing, implementation unclear! -SDCategory: The Forge of Souls -EndScriptData */ +* 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 "precompiled.h" -#include "forge_of_souls.h" +#include "def_forge.h" -instance_forge_of_souls::instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap), - m_bCriteriaPhantomBlastFailed(false), - m_uiTeam(0), - m_uiBronjahmGUID(0), - m_uiDevourerOrSoulsGUID(0) +struct MANGOS_DLL_DECL instance_forge_of_souls : public ScriptedInstance { - Initialize(); -} + instance_forge_of_souls(Map* pMap) : ScriptedInstance(pMap) + { + Regular = pMap->IsRegularDifficulty(); + Initialize(); + } -void instance_forge_of_souls::Initialize() -{ - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); -} + bool Regular; + bool needSave; + std::string strSaveData; -void instance_forge_of_souls::OnCreatureCreate(Creature* pCreature) -{ - switch(pCreature->GetEntry()) + //Creatures GUID + uint32 m_auiEncounter[MAX_ENCOUNTERS+1]; + uint64 m_uiBronjahmGUID; + uint64 m_uiDevourerGUID; + uint64 m_uiLiderGUID; + + void OpenDoor(uint64 guid) { - case NPC_BRONJAHM: m_uiBronjahmGUID = pCreature->GetGUID(); break; - case NPC_DEVOURER_OF_SOULS: m_uiDevourerOrSoulsGUID = pCreature->GetGUID(); break; - case NPC_CORRUPTED_SOUL_FRAGMENT: m_luiSoulFragmentAliveGUIDs.push_back(pCreature->GetGUID()); break; + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_ACTIVE); } -} -void instance_forge_of_souls::OnPlayerEnter(Player* pPlayer) -{ - if (!m_uiTeam) // very first player to enter + void CloseDoor(uint64 guid) { - m_uiTeam = pPlayer->GetTeam(); - ProcessEventNpcs(pPlayer, false); + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_READY); } -} -void instance_forge_of_souls::ProcessEventNpcs(Player* pPlayer, bool bChanged) -{ - if (!pPlayer) - return; + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + m_auiEncounter[i] = NOT_STARTED; + m_uiBronjahmGUID =0; + m_uiDevourerGUID =0; + } - if (m_auiEncounter[0] != DONE || m_auiEncounter[1] != DONE) + void OnCreatureCreate(Creature* pCreature) { - // Spawn Begin Mobs - for (uint8 i = 0; i < sizeof(aEventBeginLocations)/sizeof(sIntoEventNpcSpawnLocations); i++) + switch(pCreature->GetEntry()) { - if (Creature* pSummon = pPlayer->SummonCreature(m_uiTeam == HORDE ? aEventBeginLocations[i].uiEntryHorde : aEventBeginLocations[i].uiEntryAlliance, - aEventBeginLocations[i].fSpawnX, aEventBeginLocations[i].fSpawnY, aEventBeginLocations[i].fSpawnZ, aEventBeginLocations[i].fSpawnO, TEMPSUMMON_DEAD_DESPAWN, 24*HOUR*IN_MILLISECONDS)) - m_lEventMobGUIDs.push_back(pSummon->GetGUID()); + case NPC_DEVOURER: + m_uiDevourerGUID = pCreature->GetGUID(); + break; + case NPC_BRONJAHM: + m_uiBronjahmGUID = pCreature->GetGUID(); + break; } } - else + + void OnObjectCreate(GameObject* pGo) { - // if bChanged, despawn Begin Mobs, spawn End Mobs at Spawn, else spawn EndMobs at End - if (bChanged) + switch(pGo->GetEntry()) { - for (std::list::const_iterator itr = m_lEventMobGUIDs.begin(); itr != m_lEventMobGUIDs.end(); itr++) - { - if (Creature* pSummoned = instance->GetCreature(*itr)) - pSummoned->ForcedDespawn(); - } - - for (uint8 i = 0; i < sizeof(aEventEndLocations)/sizeof(sExtroEventNpcLocations); i++) - { - pPlayer->SummonCreature(m_uiTeam == HORDE ? aEventEndLocations[i].uiEntryHorde : aEventEndLocations[i].uiEntryAlliance, - aEventEndLocations[i].fSpawnX, aEventEndLocations[i].fSpawnY, aEventEndLocations[i].fSpawnZ, aEventEndLocations[i].fStartO, TEMPSUMMON_DEAD_DESPAWN, 24*HOUR*IN_MILLISECONDS); - - // TODO: Let the NPCs Move along their paths - } - } - else - { // Summon at end, without event - for (uint8 i = 0; i < sizeof(aEventEndLocations)/sizeof(sExtroEventNpcLocations); i++) - { - pPlayer->SummonCreature(m_uiTeam == HORDE ? aEventEndLocations[i].uiEntryHorde : aEventEndLocations[i].uiEntryAlliance, - aEventEndLocations[i].fEndX, aEventEndLocations[i].fEndY, aEventEndLocations[i].fEndZ, aEventEndLocations[i].fEndO, TEMPSUMMON_DEAD_DESPAWN, 24*HOUR*IN_MILLISECONDS); - } } } -} - -Player* instance_forge_of_souls::GetPlayer() -{ - Map::PlayerList const& players = instance->GetPlayers(); - - if (!players.isEmpty()) + void SetData(uint32 uiType, uint32 uiData) { - for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) + switch(uiType) + { + case TYPE_INTRO: m_auiEncounter[0] = uiData; break; + case TYPE_BRONJAHM: m_auiEncounter[1] = uiData; break; + case TYPE_DEVOURER: m_auiEncounter[2] = uiData; break; + default: break; + } + + if (uiData == DONE) { - if (Player* plr = itr->getSource()) - return plr; + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + saveStream << m_auiEncounter[i] << " "; + + strSaveData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; } } - return NULL; -} -bool instance_forge_of_souls::CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/) -{ - switch (uiCriteriaId) + const char* Save() { - case ACHIEV_CRIT_SOUL_POWER: - return m_luiSoulFragmentAliveGUIDs.size() >= 4; - case ACHIEV_CRIT_PHANTOM_BLAST: - return !m_bCriteriaPhantomBlastFailed; - default: - return 0; + return strSaveData.c_str(); } -} -void instance_forge_of_souls::SetData(uint32 uiType, uint32 uiData) -{ - switch(uiType) + uint32 GetData(uint32 uiType) { - case TYPE_BRONJAHM: - m_auiEncounter[0] = uiData; - - // Despawn remaining adds and clear list - for (std::list::const_iterator itr = m_luiSoulFragmentAliveGUIDs.begin(); itr != m_luiSoulFragmentAliveGUIDs.end(); itr++) - { - if (Creature* pFragment = instance->GetCreature(*itr)) - pFragment->ForcedDespawn(); - } - m_luiSoulFragmentAliveGUIDs.clear(); - break; - case TYPE_DECOURER_OF_SOULS: - m_auiEncounter[1] = uiData; - if (uiData == DONE) - ProcessEventNpcs(GetPlayer(), true); - break; - case TYPE_ACHIEV_PHANTOM_BLAST: - m_bCriteriaPhantomBlastFailed = (uiData == FAIL); - return; + switch(uiType) + { + case TYPE_INTRO: return m_auiEncounter[0]; + case TYPE_BRONJAHM: return m_auiEncounter[1]; + case TYPE_DEVOURER: return m_auiEncounter[2]; + } + return 0; } - if (uiData == DONE) + uint64 GetData64(uint32 uiData) { - OUT_SAVE_INST_DATA; - - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1]; - - strInstData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; + switch(uiData) + { + case NPC_BRONJAHM: return m_uiBronjahmGUID; + case NPC_DEVOURER: return m_uiDevourerGUID; + case DATA_LIDER: return m_uiLiderGUID; + } + return 0; } -} -void instance_forge_of_souls::Load(const char* chrIn) -{ - if (!chrIn) + void SetData64(uint32 uiData, uint64 uiGuid) { - OUT_LOAD_INST_DATA_FAIL; - return; + switch(uiData) + { + case DATA_LIDER: m_uiLiderGUID = uiGuid; + } } - OUT_LOAD_INST_DATA(chrIn); + void Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } - std::istringstream loadStream(chrIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1]; + OUT_LOAD_INST_DATA(chrIn); - for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) - { - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; - } + std::istringstream loadStream(chrIn); - OUT_LOAD_INST_DATA_COMPLETE; -} + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + { + loadStream >> m_auiEncounter[i]; -uint32 instance_forge_of_souls::GetData(uint32 uiType) -{ - switch(uiType) - { - case TYPE_BRONJAHM: - return m_auiEncounter[0]; - case TYPE_DECOURER_OF_SOULS: - return m_auiEncounter[1]; - default: - return 0; - } -} + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } -uint64 instance_forge_of_souls::GetData64(uint32 uiData) -{ - switch(uiData) - { - case NPC_BRONJAHM: - return m_uiBronjahmGUID; - case NPC_DEVOURER_OF_SOULS: - return m_uiDevourerOrSoulsGUID; - default: - return 0; + OUT_LOAD_INST_DATA_COMPLETE; } -} - -void instance_forge_of_souls::SetData64(uint32 uiType, uint64 uiData) -{ - if (uiType == DATA_SOULFRAGMENT_REMOVE) - m_luiSoulFragmentAliveGUIDs.remove(uiData); -} +}; InstanceData* GetInstanceData_instance_forge_of_souls(Map* pMap) { return new instance_forge_of_souls(pMap); } + void AddSC_instance_forge_of_souls() { Script* pNewScript; - pNewScript = new Script; pNewScript->Name = "instance_forge_of_souls"; pNewScript->GetInstanceData = &GetInstanceData_instance_forge_of_souls; diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/trash_forge_of_souls.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/trash_forge_of_souls.cpp new file mode 100644 index 0000000..b617e41 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/trash_forge_of_souls.cpp @@ -0,0 +1,594 @@ +/* Copyright (C) 2006 - 2010 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: Trash Mobs +SD%Complete: 100% +SDComment: +SDCategory: The Forge of Souls +EndScriptData */ + +#include "precompiled.h" +#include "def_forge.h" + +enum +{ + //Spiteful Apparition + SPELL_SPITE_N = 68895, + SPELL_SPITE_H = 70212, + + //Spectral Warden + SPELL_VEIL_OF_SHADOWS = 69633, + SPELL_WAIL_OF_SOULS_N = 69148, + SPELL_WAIL_OF_SOULS_H = 70210, + + //Soulguard Watchman + SPELL_SHROUD_OF_RUNES = 69056, + SPELL_UNHOLY_RAGE = 69053, + + //Soulguard Reaper + SPELL_FROST_NOVA_N = 69060, + SPELL_FROST_NOVA_H = 70209, + SPELL_SHADOW_LANCE = 69058, + + //Soulguard Bonecaster + SPELL_BONE_VOLLEY_N = 69080, + SPELL_BONE_VOLLEY_H = 70206, + SPELL_RAISE_DEAD = 69562, + SPELL_SHIELD_OF_BONES_N = 69069, + SPELL_SHIELD_OF_BONES_H = 70207, + + //Soulguard Animator + // Raise dead 69562 + SPELL_SHADOW_BOLT_N = 69068, + SPELL_SHADOW_BOLT_H = 70208, + SPELL_SOUL_SICKNESS = 69131, + SPELL_SOUL_SIPHON = 69128, + + //Soulguard Adept + //Raise dead 69562 + //Shadow Bolt 69068/70208 + SPELL_DRAIN_LIFE_N = 69066, + SPELL_DRAIN_LIFE_H = 70213, + SPELL_SHADOW_MEND_N = 69564, + SPELL_SHADOW_MEND_H = 70205, + + //Soul Horror + SPELL_SOUL_STRIKE_N = 69088, + SPELL_SOUL_STRIKE_H = 70211, + + NPC_SOULGUARD_ADEPT = 36620 +}; + +struct MANGOS_DLL_DECL npc_soulguard_watchmanAI : public ScriptedAI +{ + npc_soulguard_watchmanAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + +ScriptedInstance* m_pInstance; +bool m_bIsRegularMode; + +uint32 ShieldTimer; + + void Reset() + { + ShieldTimer = (urand(2000, 15000)); + } + + void Aggro(Unit *who) + { + DoCast(m_creature, SPELL_UNHOLY_RAGE); + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (ShieldTimer < diff) + { + DoCast(m_creature, SPELL_SHROUD_OF_RUNES); + ShieldTimer = (urand(15000, 25000)); + } + else + ShieldTimer -= diff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +struct MANGOS_DLL_DECL npc_soulguard_reaperAI : public ScriptedAI +{ + npc_soulguard_reaperAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + +ScriptedInstance* m_pInstance; +bool m_bIsRegularMode; + +uint32 ShadowBoltTimer; +uint32 IceNovaTimer; +uint32 AdeptHealTimer; + + void Reset() + { + AdeptHealTimer = (urand(2000, 4000)); + ShadowBoltTimer = (urand(2000, 20000)); + IceNovaTimer = (urand(15000, 20000)); + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (ShadowBoltTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, SPELL_SHADOW_LANCE); + ShadowBoltTimer = (urand(2000, 15000)); + } + else + ShadowBoltTimer -= diff; + + if (IceNovaTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_FROST_NOVA_N : SPELL_FROST_NOVA_H); + IceNovaTimer = (urand(15000, 20000)); + } + else + IceNovaTimer -= diff; + + if(m_creature->GetHealth()*100 < m_creature->GetMaxHealth()*45) + { + if (AdeptHealTimer < diff) + { + if (Creature* pAdept = GetClosestCreatureWithEntry(m_creature, NPC_SOULGUARD_ADEPT, 25.0f)) + { + if(pAdept->GetHealth()*100 > pAdept->GetMaxHealth()*45) + { + pAdept->InterruptNonMeleeSpells(false); + pAdept->CastSpell(m_creature, m_bIsRegularMode ? SPELL_SHADOW_MEND_N : SPELL_SHADOW_MEND_H, false); + } + } + + AdeptHealTimer = (urand(9000, 20000)); + } + else + AdeptHealTimer -= diff; + } + + + DoMeleeAttackIfReady(); + + return; + } +}; + +struct MANGOS_DLL_DECL npc_soulguard_adeptAI : public ScriptedAI +{ + npc_soulguard_adeptAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + +ScriptedInstance* m_pInstance; +bool m_bIsRegularMode; + +bool Summon; +uint32 ShadowBoltTimer; +uint32 ShadowMendTimer; +uint32 DrainLifeTimer; +uint32 SummonTimer; +uint32 Say; + + void Reset() + { + Summon = false; + ShadowBoltTimer = (urand(2000, 20000)); + ShadowMendTimer = (urand(1000, 5000)); + DrainLifeTimer = (urand(1000, 2000)); + SummonTimer = (urand(1000, 10000)); + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (ShadowBoltTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_SHADOW_BOLT_N : SPELL_SHADOW_BOLT_H); + ShadowBoltTimer = (urand(2000, 15000)); + } + else + ShadowBoltTimer -= diff; + + if(m_creature->GetHealth()*100 < m_creature->GetMaxHealth()*45) + { + if (ShadowMendTimer < diff) + { + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHADOW_MEND_N : SPELL_SHADOW_MEND_H); + ShadowMendTimer = (urand(6000, 10000)); + } + else + ShadowMendTimer -= diff; + } + + if(m_creature->GetHealth()*100 < m_creature->GetMaxHealth()*75) + { + if (DrainLifeTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_DRAIN_LIFE_N : SPELL_DRAIN_LIFE_H); + DrainLifeTimer = (urand(5000, 15000)); + } + else + DrainLifeTimer -= diff; + } + + if(Summon != true) + { + if (SummonTimer < diff) + { + Summon = true; + Say = (urand(0, 3)); + switch(Say) + { + case 0: + m_creature->MonsterSay("Wake up deads!",LANG_UNIVERSAL); + break; + case 1: + m_creature->MonsterSay("Dead hear my call!",LANG_UNIVERSAL); + break; + case 2: + m_creature->MonsterSay("I command power of Dead!",LANG_UNIVERSAL); + break; + case 3: + m_creature->MonsterSay("A raise my servant!",LANG_UNIVERSAL); + break; + } + DoCast(m_creature, SPELL_RAISE_DEAD); + } + else + SummonTimer -= diff; + } + + DoMeleeAttackIfReady(); + + return; + } +}; + +struct MANGOS_DLL_DECL npc_soulguard_bonecasterAI : public ScriptedAI +{ + npc_soulguard_bonecasterAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + +ScriptedInstance* m_pInstance; +bool m_bIsRegularMode; + +uint32 BoneTimer; +uint32 ShieldTimer; + + void Reset() + { + BoneTimer = (urand(2000, 20000)); + ShieldTimer = (urand(15000, 20000)); + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (BoneTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_BONE_VOLLEY_N : SPELL_BONE_VOLLEY_H); + BoneTimer = (urand(2000, 15000)); + } + else + BoneTimer -= diff; + + if (ShieldTimer < diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHIELD_OF_BONES_N : SPELL_SHIELD_OF_BONES_H); + ShieldTimer = (urand(15000, 20000)); + } + else + ShieldTimer -= diff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +struct MANGOS_DLL_DECL npc_soulguard_animatorAI : public ScriptedAI +{ + npc_soulguard_animatorAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + +ScriptedInstance* m_pInstance; +bool m_bIsRegularMode; + +uint32 ShadowBoltTimer; +uint32 SoulSickTimer; +uint32 SoulSiphTimer; +uint32 AdeptHealTimer; + + void Reset() + { + AdeptHealTimer = (urand(1000, 6000)); + ShadowBoltTimer = (urand(2000, 20000)); + SoulSickTimer = (urand(15000, 20000)); + SoulSiphTimer = (urand(7500, 30000)); + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (ShadowBoltTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_SHADOW_BOLT_N : SPELL_SHADOW_BOLT_H); + ShadowBoltTimer = (urand(2000, 15000)); + } + else + ShadowBoltTimer -= diff; + + if (SoulSickTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, SPELL_SOUL_SICKNESS); + SoulSickTimer = (urand(15000, 20000)); + } + else + SoulSickTimer -= diff; + + if (SoulSiphTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_SOUL_SIPHON); + SoulSiphTimer = (urand(7500, 30000)); + } + else + SoulSiphTimer -= diff; + + if(m_creature->GetHealth()*100 < m_creature->GetMaxHealth()*45) + { + if (AdeptHealTimer < diff) + { + if (Creature* pAdept = GetClosestCreatureWithEntry(m_creature, NPC_SOULGUARD_ADEPT, 25.0f)) + { + if(pAdept->GetHealth()*100 > pAdept->GetMaxHealth()*45) + { + pAdept->InterruptNonMeleeSpells(false); + pAdept->CastSpell(m_creature, m_bIsRegularMode ? SPELL_SHADOW_MEND_N : SPELL_SHADOW_MEND_H, false); + } + } + + AdeptHealTimer = (urand(9000, 20000)); + } + else + AdeptHealTimer -= diff; + } + + DoMeleeAttackIfReady(); + + return; + } +}; + +struct MANGOS_DLL_DECL npc_soul_horrorAI : public ScriptedAI +{ + npc_soul_horrorAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + +ScriptedInstance* m_pInstance; +bool m_bIsRegularMode; + +uint32 SoulStrikeTimer; + + void Reset() + { + SoulStrikeTimer = (urand(2000, 5000)); + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (SoulStrikeTimer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_SOUL_STRIKE_N : SPELL_SOUL_STRIKE_H); + SoulStrikeTimer = (urand(2000, 10000)); + } + else + SoulStrikeTimer -= diff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +struct MANGOS_DLL_DECL npc_spectral_wardenAI : public ScriptedAI +{ + npc_spectral_wardenAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + +ScriptedInstance* m_pInstance; +bool m_bIsRegularMode; + +uint32 ShadowsTimer; +uint32 SoulsTimer; + + void Reset() + { + ShadowsTimer = (urand(2000, 5000)); + SoulsTimer = (urand(10000, 15000)); + } + + void UpdateAI(const uint32 diff) + { + if(!m_pInstance) return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (ShadowsTimer < diff) + { + DoCast(m_creature->getVictim(), SPELL_VEIL_OF_SHADOWS); + ShadowsTimer = (urand(10000, 15000)); + } + else + ShadowsTimer -= diff; + + if (SoulsTimer < diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_WAIL_OF_SOULS_N : SPELL_WAIL_OF_SOULS_H); + SoulsTimer = (urand(7000, 20000)); + } + else + SoulsTimer -= diff; + + DoMeleeAttackIfReady(); + + return; + } +}; + +CreatureAI* GetAI_npc_soulguard_watchman(Creature* pCreature) +{ + return new npc_soulguard_watchmanAI(pCreature); +} + +CreatureAI* GetAI_npc_soulguard_reaper(Creature* pCreature) +{ + return new npc_soulguard_reaperAI(pCreature); +} + +CreatureAI* GetAI_npc_soulguard_adept(Creature* pCreature) +{ + return new npc_soulguard_adeptAI(pCreature); +} + +CreatureAI* GetAI_npc_soulguard_bonecaster(Creature* pCreature) +{ + return new npc_soulguard_bonecasterAI(pCreature); +} + +CreatureAI* GetAI_npc_soulguard_animator(Creature* pCreature) +{ + return new npc_soulguard_animatorAI(pCreature); +} + +CreatureAI* GetAI_npc_soul_horror(Creature* pCreature) +{ + return new npc_soul_horrorAI(pCreature); +} + +CreatureAI* GetAI_npc_spectral_warden(Creature* pCreature) +{ + return new npc_spectral_wardenAI(pCreature); +} + +void AddSC_trash_forge_of_souls() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_soulguard_watchman"; + newscript->GetAI = &GetAI_npc_soulguard_watchman; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_soulguard_reaper"; + newscript->GetAI = &GetAI_npc_soulguard_reaper; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_soulguard_adept"; + newscript->GetAI = &GetAI_npc_soulguard_adept; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_soulguard_bonecaster"; + newscript->GetAI = &GetAI_npc_soulguard_bonecaster; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_soulguard_animator"; + newscript->GetAI = &GetAI_npc_soulguard_animator; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_soul_horror"; + newscript->GetAI = &GetAI_npc_soul_horror; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_spectral_warden"; + newscript->GetAI = &GetAI_npc_spectral_warden; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_falric.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_falric.cpp new file mode 100644 index 0000000..a5577f7 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_falric.cpp @@ -0,0 +1,230 @@ +/* Copyright (C) 2006 - 2010 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_falric +SD%Complete: 70% +SDComment: +SDAuthor: /dev/rsa, changed by MaxXx2021 aka Mioka +SDCategory: Halls of Reflection +EndScriptData */ + +#include "precompiled.h" +#include "def_halls.h" + +enum +{ + SAY_FALRIC_AGGRO = -1594507, + SAY_FALRIC_DEATH = -1594508, + SAY_FALRIC_SLAY01 = -1594509, + SAY_FALRIC_SLAY02 = -1594510, + SAY_FALRIC_SP01 = -1594511, + SAY_FALRIC_SP02 = -1594512, + + SPELL_HOPELESSNESS = 72395, + SPELL_IMPENDING_DESPAIR = 72426, + SPELL_DEFILING_HORROR = 72435, + SPELL_QUIVERING_STRIKE = 72422, + + SPELL_BERSERK = 47008 +}; + +struct MANGOS_DLL_DECL boss_falricAI : public BSWScriptedAI +{ + boss_falricAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsCall; + + uint32 m_uiSummonTimer; + uint32 m_uiLocNo; + uint64 m_uiSummonGUID[16]; + uint32 m_uiCheckSummon; + + uint8 SummonCount; + + uint64 pSummon; + + void Reset() + { + SummonCount = 0; + m_bIsCall = false; + m_uiSummonTimer = 11000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetVisibility(VISIBILITY_OFF); + } + + void Aggro(Unit* pVictim) + { + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + DoScriptText(SAY_FALRIC_AGGRO, m_creature); + DoCast(m_creature, SPELL_HOPELESSNESS); + } + + void KilledUnit(Unit* pVictim) + { + switch(urand(0,1)) + { + case 0: DoScriptText(SAY_FALRIC_SLAY01, m_creature); break; + case 1: DoScriptText(SAY_FALRIC_SLAY02, m_creature); break; + } + } + + void JustDied(Unit* pKiller) + { + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_MARWYN, SPECIAL); + DoScriptText(SAY_FALRIC_DEATH, m_creature); + } + + void AttackStart(Unit* who) + { + if(!m_pInstance) return; + + if(m_pInstance->GetData(TYPE_FALRIC) != IN_PROGRESS) + return; + + ScriptedAI::AttackStart(who); + } + + void Summon() + { + m_uiLocNo = 0; + + for(uint8 i = 0; i < 14; i++) + { + switch(urand(0,3)) + { + case 0: + switch(urand(1, 3)) + { + case 1: pSummon = NPC_DARK_1; break; + case 2: pSummon = NPC_DARK_3; break; + case 3: pSummon = NPC_DARK_6; break; + } + break; + case 1: + switch(urand(1, 3)) + { + case 1: pSummon = NPC_DARK_2; break; + case 2: pSummon = NPC_DARK_3; break; + case 3: pSummon = NPC_DARK_4; break; + } + break; + case 2: + switch(urand(1, 3)) + { + case 1: pSummon = NPC_DARK_2; break; + case 2: pSummon = NPC_DARK_5; break; + case 3: pSummon = NPC_DARK_6; break; + } + break; + case 3: + switch(urand(1, 3)) + { + case 1: pSummon = NPC_DARK_1; break; + case 2: pSummon = NPC_DARK_5; break; + case 3: pSummon = NPC_DARK_4; break; + } + break; + } + + m_uiCheckSummon = 0; + + if(Creature* Summon = m_creature->SummonCreature(pSummon, SpawnLoc[m_uiLocNo].x, SpawnLoc[m_uiLocNo].y, SpawnLoc[m_uiLocNo].z, SpawnLoc[m_uiLocNo].o, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000)) + { + m_uiSummonGUID[i] = Summon->GetGUID(); + Summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Summon->setFaction(974); + } + m_uiLocNo++; + } + } + + void CallFallSoldier() + { + for(uint8 i = 0; i < 4; i++) + { + if(Creature* Summon = m_pInstance->instance->GetCreature(m_uiSummonGUID[m_uiCheckSummon])) + { + Summon->setFaction(14); + Summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Summon->SetInCombatWithZone(); + } + m_uiCheckSummon++; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) + return; + + if (m_pInstance->GetData(TYPE_EVENT) == 5) + { + m_pInstance->SetData(TYPE_EVENT, 6); + Summon(); + } + + if (m_pInstance->GetData(TYPE_FALRIC) == SPECIAL) + { + + if (m_uiSummonTimer < uiDiff) + { + ++SummonCount; + if(SummonCount > 4) + { + m_pInstance->SetData(TYPE_FALRIC, IN_PROGRESS); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWithZone(); + } + else CallFallSoldier(); + m_uiSummonTimer = 60000; + } else m_uiSummonTimer -= uiDiff; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_QUIVERING_STRIKE, uiDiff); + timedCast(SPELL_IMPENDING_DESPAIR, uiDiff); + timedCast(SPELL_DEFILING_HORROR, uiDiff); + + timedCast(SPELL_BERSERK, uiDiff); + + 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/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_lich_king.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_lich_king.cpp index 0ed1ec9..7ae0902 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_lich_king.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_lich_king.cpp @@ -16,9 +16,663 @@ /* ScriptData SDName: boss_lich_king -SD%Complete: 0% +SD%Complete: 100% SDComment: +SDAuthor: MaxXx2021 aka Mioka SDCategory: Halls of Reflection EndScriptData */ #include "precompiled.h" +#include "def_halls.h" +#include "escort_ai.h" + +enum +{ + SPELL_WINTER = 69780, + SPELL_FURY_OF_FROSTMOURNE = 70063, + SPELL_SOUL_REAPER = 73797, + SPELL_ICE_PRISON = 69708, + SPELL_DARK_ARROW = 70194, + SPELL_EMERGE_VISUAL = 50142, + SPELL_DESTROY_ICE_WALL_02 = 70224, + SPELL_SILENCE = 69413, + SPELL_LICH_KING_CAST = 57561, + SPELL_GNOUL_JUMP = 70150, + SPELL_ABON_STRIKE = 40505, + + // summon spells + SPELL_WITCH_DOCTOR = 69836, + SPELL_SUMMON_ABOM = 69835, + SPELL_RAISE_DEAD = 69818, + + /*SPELLS - Witch Doctor, 36941 */ + SPELL_COURSE_OF_DOOM = 70144, + SPELL_SHADOW_BOLT_VALLEY = 70145, + SPELL_SHADOW_BOLT = 70080, + + /*SPELLS - abomination, 37069 */ + SPELL_CLEAVE = 40505, + + /*SPELLS - raging ghoul, 36940 */ + SPELL_LEAP = 70150, + + SAY_LICH_KING_WALL_01 = -1594486, + SAY_LICH_KING_WALL_02 = -1594491, + SAY_LICH_KING_GNOUL = -1594482, + SAY_LICH_KING_ABON = -1594483, + SAY_LICH_KING_WINTER = -1594481, + SAY_LICH_KING_END_DUN = -1594504, + SAY_LICH_KING_WIN = -1594485, + + /*INTRO - Lich King Arrive*/ + SAY_LICH_KING_17 = -1594468, + SAY_LICH_KING_18 = -1594469, + SAY_LICH_KING_19 = -1594470, + SAY_JAINA_20 = -1594471, + SAY_SYLVANA_20 = -1594472, + SAY_LICH_KING_A_21 = -1594473, + SAY_LICH_KING_H_21 = -1594474, + SAY_FALRIC_INTRO = -1594475, + SAY_MARWYN_INTRO = -1594476, + SAY_FALRIC_INTRO2 = -1594505, + + SPELL_TAKE_FROSTMOURNE = 72729, + SPELL_FROSTMOURNE_DESPAWN = 72726, + SPELL_FROSTMOURNE_SOUNDS = 70667, + SPELL_CAST_VISUAL = 65633, //Jaina And Sylavana cast this when summon uther. + SPELL_BOSS_SPAWN_AURA = 72712, //Falric and Marwyn + SPELL_UTHER_DESPAWN = 70693, + SPELL_FROSTMOURNE_VISUAL = 73220, + + /*INTRO - Pre Escape*/ + SAY_LICH_KING_AGGRO_A = -1594477, + SAY_LICH_KING_AGGRO_H = -1594478, + SAY_JAINA_AGGRO = -1594479, + SAY_SYLVANA_AGGRO = -1594480, + +}; + +struct MANGOS_DLL_DECL boss_lich_king_hrAI : public npc_escortAI +{ + boss_lich_king_hrAI(Creature *pCreature) : npc_escortAI(pCreature) + { + m_pInstance = (BSWScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + BSWScriptedInstance* m_pInstance; + bool StartEscort; + bool NonFight; + bool Finish; + + void Reset() + { + if(!m_pInstance) return; + NonFight = false; + StartEscort = false; + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, 36942); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (m_pInstance->GetData(TYPE_LICH_KING) == DONE) + m_creature->SetVisibility(VISIBILITY_OFF); + } + + void JustDied(Unit* pKiller) + { + } + + void MoveInLineOfSight(Unit* who) + { + if (!who || !m_pInstance) + return; + + if (who->GetTypeId() != TYPEID_PLAYER) + return; + + Player* pPlayer = (Player *)who; + + if (pPlayer->isGameMaster()) + return; + + if (m_pInstance->GetData(TYPE_PHASE) != 3 + || m_pInstance->GetData(TYPE_LICH_KING) == DONE + || !m_creature->IsWithinDistInMap(who, 50.0f) + || m_pInstance->GetData(TYPE_FROST_GENERAL) != DONE) + return; + + m_pInstance->DoOpenDoor(m_pInstance->GetData64(GO_ICECROWN_DOOR_2)); + + Team team; + if (Group* pGroup = pPlayer->GetGroup()) + { + ObjectGuid LeaderGuid = pGroup->GetLeaderGuid(); + if (!LeaderGuid.IsEmpty()) + if (Player* pLeader =m_creature->GetMap()->GetPlayer(LeaderGuid)) + team = pLeader->GetTeam(); + } + else + team = ((Player*)who)->GetTeam(); + + uint32 newLeader; + + if (team == ALLIANCE) + newLeader = NPC_JAINA_OUTRO; + else + newLeader = NPC_SYLVANA_OUTRO; + + if (Creature* pNewLeader = m_creature->SummonCreature(newLeader,WallLoc[6].x,WallLoc[6].y,WallLoc[6].z,WallLoc[6].o,TEMPSUMMON_MANUAL_DESPAWN,0,true)) + { + pNewLeader->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pNewLeader->SetSpeedRate(MOVE_RUN, 1.0f, true); + pNewLeader->SetRespawnDelay(DAY); + pNewLeader->SetHealth(pNewLeader->GetMaxHealth()/10); + m_pInstance->SetData64(DATA_ESCAPE_LIDER, pNewLeader->GetGUID()); + } + m_pInstance->DoOpenDoor(m_pInstance->GetData64(GO_ICECROWN_DOOR_2)); + m_pInstance->SetData(TYPE_PHASE, 4); + m_pInstance->SetNextEvent(100,GetLeader(),500); + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 20: + SetEscortPaused(true); + Finish = true; + DoCast(m_creature, SPELL_LICH_KING_CAST); + m_pInstance->SetData(TYPE_LICH_KING, SPECIAL); + DoScriptText(SAY_LICH_KING_END_DUN, m_creature); + if(Creature* pLider = (m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_ESCAPE_LIDER)))) + { + pLider->CastSpell(pLider, SPELL_SILENCE, false); + pLider->AddSplineFlag(SPLINEFLAG_FLYING); + pLider->SendMonsterMove(pLider->GetPositionX(), pLider->GetPositionY(), pLider->GetPositionZ() + 4, SPLINETYPE_NORMAL , pLider->GetSplineFlags(), 3000); + } + m_pInstance->SetData(TYPE_PHASE, 6); + m_pInstance->SetNextEvent(610,GetLeader(),5000); + m_creature->SetActiveObjectState(false); + break; + } + } + + void AttackStart(Unit* who) + { + if (!m_pInstance || !who || NonFight) + return; + + if (m_pInstance->GetData(TYPE_LICH_KING) == IN_PROGRESS || who->GetTypeId() == TYPEID_PLAYER) return; + + npc_escortAI::AttackStart(who); + } + + void SummonedCreatureJustDied(Creature* summoned) + { + if(!m_pInstance || !summoned) + return; + + if (summoned->GetEntry() == NPC_JAINA_OUTRO + || summoned->GetEntry() == NPC_SYLVANA_OUTRO) + { + m_creature->NearTeleportTo(5572.077f, 2283.1f, 734.976f, 3.89f); + if (boss_lich_king_hrAI* pEscortAI = dynamic_cast(m_creature->AI())) + pEscortAI->EnterEvadeMode(); + StartEscort = false; + } + else + m_pInstance->SetData(DATA_SUMMONS, 0); + } + + void JustSummoned(Creature* summoned) + { + if (!m_pInstance || !summoned) + return; + + if (summoned->GetEntry() == NPC_JAINA_OUTRO + || summoned->GetEntry() == NPC_SYLVANA_OUTRO) + { + summoned->SetCreatorGuid(ObjectGuid()); + summoned->setFaction(2076); + summoned->SetPhaseMask(65535, true); + m_creature->SetInCombatWith(summoned); + summoned->SetInCombatWith(m_creature); + } + else + { + summoned->SetPhaseMask(65535, true); + summoned->SetInCombatWithZone(); + summoned->SetActiveObjectState(true); + + m_pInstance->SetData(DATA_SUMMONS, 1); + + if (Creature* pLider = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ESCAPE_LIDER))) + { + summoned->GetMotionMaster()->MoveChase(pLider); + summoned->AddThreat(pLider, 100.0f); + } + } + } + + uint32 GetLeader() + { + if (Creature* pLider = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ESCAPE_LIDER))) + return pLider->GetEntry(); + else + return 0; + } + + void Event() + { + switch (m_pInstance->GetEvent(m_creature->GetEntry())) + { +// Intro phase + case 101: + if(GetLeader() == NPC_JAINA_OUTRO) + DoScriptText((GetLeader() == NPC_JAINA_OUTRO ? SAY_LICH_KING_AGGRO_A : SAY_LICH_KING_AGGRO_H), m_creature); + if (Creature* pLider = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ESCAPE_LIDER))) + AttackStart(pLider); + m_pInstance->SetNextEvent(102,GetLeader(),3000); + break; + +// Active phase + case 200: + SetEscortPaused(true); + m_pInstance->SetData(DATA_SUMMONS, 3); + DoScriptText(SAY_LICH_KING_WALL_01, m_creature); + m_pInstance->SetNextEvent(210,m_creature->GetEntry(),2000); + break; + case 210: + m_pInstance->SetNextEvent(220,m_creature->GetEntry(),2000); + break; + case 220: + DoCast(m_creature, SPELL_RAISE_DEAD); + DoScriptText(SAY_LICH_KING_GNOUL, m_creature); + m_pInstance->SetNextEvent(230,m_creature->GetEntry(),7000); + break; + case 230: + DoScriptText(SAY_LICH_KING_WINTER, m_creature); + DoCast(m_creature, SPELL_WINTER); + m_creature->SetSpeedRate(MOVE_WALK, 1.3f, true); + m_pInstance->SetNextEvent(240,m_creature->GetEntry(),1000); + break; + case 240: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + SetEscortPaused(false); + m_pInstance->SetNextEvent(250,m_creature->GetEntry(),2000); + break; + case 250: + m_pInstance->SetNextEvent(290,GetLeader(),1000); + DoCast(m_creature, SPELL_WITCH_DOCTOR); + break; + + case 300: + SetEscortPaused(true); + DoCast(m_creature, SPELL_SUMMON_ABOM); + m_pInstance->SetData(DATA_SUMMONS, 3); + DoScriptText(SAY_LICH_KING_GNOUL, m_creature); + m_pInstance->SetNextEvent(310,m_creature->GetEntry(),500); + break; + case 310: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(320,m_creature->GetEntry(),500); + break; + case 320: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(330,m_creature->GetEntry(),5000); + break; + case 330: + DoCast(m_creature, SPELL_RAISE_DEAD); + SetEscortPaused(false); + m_pInstance->SetNextEvent(390,GetLeader(),1000); + break; + + case 400: + SetEscortPaused(true); + DoCast(m_creature, SPELL_SUMMON_ABOM); + m_pInstance->SetData(DATA_SUMMONS, 3); + DoScriptText(SAY_LICH_KING_GNOUL, m_creature); + m_pInstance->SetNextEvent(410,m_creature->GetEntry(),500); + break; + case 410: + DoScriptText(SAY_LICH_KING_ABON, m_creature); + DoCast(m_creature, SPELL_SUMMON_ABOM); + m_pInstance->SetNextEvent(420,m_creature->GetEntry(),500); + break; + case 420: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(430,m_creature->GetEntry(),500); + break; + case 430: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(440,m_creature->GetEntry(),500); + break; + case 440: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(450,m_creature->GetEntry(),500); + break; + case 450: + DoCast(m_creature, SPELL_RAISE_DEAD); + m_pInstance->SetNextEvent(490,GetLeader(),5000); + SetEscortPaused(false); + break; + + case 500: + m_pInstance->SetData(DATA_SUMMONS, 3); + DoScriptText(SAY_LICH_KING_GNOUL, m_creature); + DoCast(m_creature, SPELL_SUMMON_ABOM); + m_pInstance->SetNextEvent(510,m_creature->GetEntry(),10000); + break; + case 510: + m_creature->SetSpeedRate(MOVE_WALK, 1.3f, true); + DoCast(m_creature, SPELL_SUMMON_ABOM); + m_pInstance->SetNextEvent(520,m_creature->GetEntry(),500); + break; + case 520: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(530,m_creature->GetEntry(),500); + break; + case 530: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(540,m_creature->GetEntry(),500); + break; + case 540: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(550,m_creature->GetEntry(),500); + break; + case 550: + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(570,m_creature->GetEntry(),2000); + break; + case 570: + DoScriptText(SAY_LICH_KING_ABON, m_creature); + DoCast(m_creature, SPELL_WITCH_DOCTOR); + m_pInstance->SetNextEvent(580,m_creature->GetEntry(),5000); + break; + case 580: + DoScriptText(SAY_LICH_KING_ABON, m_creature); + DoCast(m_creature, SPELL_RAISE_DEAD); + m_pInstance->SetNextEvent(590,GetLeader(),1000); + break; + + case 900: + if (Creature* pLider = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ESCAPE_LIDER))) + m_creature->DealDamage(pLider, pLider->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_pInstance->SetData(TYPE_LICH_KING, FAIL); + m_creature->SetActiveObjectState(false); + m_pInstance->SetData(TYPE_PHASE, 3); + m_pInstance->SetNextEvent(0,0); + break; + + default: + break; + } + } + + void UpdateEscortAI(const uint32 diff) + { + if(!m_pInstance) + return; + + if ( (m_pInstance->GetData(TYPE_PHASE) == 4 || m_pInstance->GetData(TYPE_PHASE) == 5 || m_pInstance->GetData(TYPE_PHASE) == 7) + && m_pInstance->GetEventTimer(m_creature->GetEntry(),diff)) + Event(); + + if(m_pInstance->GetData(TYPE_LICH_KING) != IN_PROGRESS) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + return; + } + + if(m_pInstance->GetData(TYPE_LICH_KING) == IN_PROGRESS && !StartEscort) + { + StartEscort = true; + if(m_creature->HasAura(SPELL_ICE_PRISON)) + m_creature->RemoveAurasDueToSpell(SPELL_ICE_PRISON); + if(m_creature->HasAura(SPELL_DARK_ARROW)) + m_creature->RemoveAurasDueToSpell(SPELL_DARK_ARROW); + + m_creature->SetActiveObjectState(true); + + NonFight = true; + m_creature->AttackStop(); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSpeedRate(MOVE_WALK, 2.7f, true); + if (boss_lich_king_hrAI* pEscortAI = dynamic_cast(m_creature->AI())) + pEscortAI->Start(); + } + if (m_pInstance->GetData(TYPE_PHASE) == 5) + if (Creature* pLider = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ESCAPE_LIDER))) + if (pLider->isAlive() && pLider->IsWithinDistInMap(m_creature, 2.0f)) + { + m_pInstance->SetData(TYPE_PHASE,7); + SetEscortPaused(true); + m_creature->GetMotionMaster()->Clear(); + DoScriptText(SAY_LICH_KING_WIN, m_creature); + m_pInstance->SetNextEvent(900,m_creature->GetEntry(),4000); + m_creature->CastSpell(m_creature, SPELL_FURY_OF_FROSTMOURNE, false); + }; + + return; + } +}; + +CreatureAI* GetAI_boss_lich_king_hr(Creature* pCreature) +{ + return new boss_lich_king_hrAI(pCreature); +} + +struct MANGOS_DLL_DECL boss_lich_king_intro_horAI : public ScriptedAI +{ + boss_lich_king_intro_horAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (BSWScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + BSWScriptedInstance* m_pInstance; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void JustDied(Unit* pKiller) + { + } + + void AttackStart(Unit* who) + { + } + + uint32 GetLeader() + { + if (Creature* pLider = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ESCAPE_LIDER))) + return pLider->GetEntry(); + else + return 0; + } + + void Event() + { + switch(m_pInstance->GetEvent(m_creature->GetEntry())) + { + case 24: + m_pInstance->DoOpenDoor(m_pInstance->GetData64(GO_IMPENETRABLE_DOOR)); + m_pInstance->SetNextEvent(25,GetLeader(),1000); + break; + case 25: + m_creature->GetMotionMaster()->MovePoint(0, 5314.881f, 2012.496f, 709.341f); + m_pInstance->SetNextEvent(26,m_creature->GetEntry(),3000); + break; + case 26: + m_pInstance->DoCloseDoor(m_pInstance->GetData64(GO_IMPENETRABLE_DOOR)); + m_pInstance->SetNextEvent(27,m_creature->GetEntry(),7000); + break; + case 27: + DoScriptText(SAY_LICH_KING_17, m_creature); + if (Creature* pUther = (m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_UTHER)))) + pUther->CastSpell(pUther, SPELL_UTHER_DESPAWN, false); + m_pInstance->SetNextEvent(28,m_creature->GetEntry(),1500); + break; + case 28: + if (Creature* pUther = (m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_UTHER)))) + pUther->ForcedDespawn(); + m_pInstance->SetNextEvent(29,m_creature->GetEntry(),10000); + break; + case 29: + DoScriptText(SAY_LICH_KING_18, m_creature); + m_pInstance->SetNextEvent(30,m_creature->GetEntry(),5000); + break; + case 30: + m_creature->CastSpell(m_creature, SPELL_TAKE_FROSTMOURNE, false); + m_pInstance->DoCloseDoor(m_pInstance->GetData64(GO_FROSTMOURNE)); + m_pInstance->SetNextEvent(31,m_creature->GetEntry(),1500); + break; + case 31: + if (GameObject* pFrostmourne = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_FROSTMOURNE))) + pFrostmourne->SetPhaseMask(0, true); + m_creature->CastSpell(m_creature, SPELL_FROSTMOURNE_VISUAL, false); + m_pInstance->SetNextEvent(31,GetLeader(),500); + break; + case 32: + DoScriptText(SAY_LICH_KING_19, m_creature); + m_pInstance->SetNextEvent(33,m_creature->GetEntry(),9000); + break; + case 33: + if (Creature* pFalric = (m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_FALRIC)))) + { + pFalric->SetVisibility(VISIBILITY_ON); + pFalric->CastSpell(pFalric, SPELL_BOSS_SPAWN_AURA, false); + pFalric->GetMotionMaster()->MovePoint(0, 5283.309f, 2031.173f, 709.319f); + } + if (Creature* pMarwyn = (m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_MARWYN)))) + { + pMarwyn->SetVisibility(VISIBILITY_ON); + pMarwyn->CastSpell(pMarwyn, SPELL_BOSS_SPAWN_AURA, false); + pMarwyn->GetMotionMaster()->MovePoint(0, 5335.585f, 1981.439f, 709.319f); + } + m_creature->GetMotionMaster()->MovePoint(0, 5402.286f, 2104.496f, 707.695f); + m_pInstance->SetNextEvent(34,m_creature->GetEntry(),1000); + break; + case 34: + if (Creature* pFalric = (m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_FALRIC)))) + DoScriptText(SAY_FALRIC_INTRO, pFalric); + if (Creature* pMarwyn = (m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_MARWYN)))) + DoScriptText(SAY_MARWYN_INTRO, pMarwyn); + m_pInstance->SetData(TYPE_EVENT, 5); + m_pInstance->SetNextEvent(35,m_creature->GetEntry(),3000); + break; + case 35: + if (GameObject* pGate = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_IMPENETRABLE_DOOR))) + pGate->SetGoState(GO_STATE_ACTIVE); + if (Creature* pFalric = (m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_FALRIC)))) + DoScriptText(SAY_FALRIC_INTRO2, pFalric); + m_pInstance->SetData(TYPE_FALRIC, SPECIAL); + m_pInstance->SetNextEvent(36,GetLeader(),4000); + break; + case 37: + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MovePoint(0, 5443.880f, 2147.095f, 707.695f); + if (GetLeader() == NPC_JAINA) + DoScriptText(SAY_LICH_KING_A_21, m_creature); + else if (GetLeader() == NPC_SYLVANA) + DoScriptText(SAY_LICH_KING_H_21, m_creature); + m_pInstance->SetNextEvent(38,m_creature->GetEntry(),8000); + break; + case 38: + m_pInstance->DoCloseDoor(m_pInstance->GetData64(GO_IMPENETRABLE_DOOR)); + m_pInstance->SetNextEvent(39,m_creature->GetEntry(),5000); + break; + case 39: + m_creature->SetVisibility(VISIBILITY_OFF); + m_pInstance->SetNextEvent(39,GetLeader(),1000); + break; + case 40: + m_pInstance->SetData(TYPE_PHASE, 2); + m_pInstance->SetNextEvent(0,0); + m_creature->ForcedDespawn(); + break; + default: + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_pInstance) + return; + + if (m_pInstance->GetEventTimer(m_creature->GetEntry(),diff) && m_pInstance->GetData(TYPE_PHASE) == 1) + Event(); + + } +}; + +CreatureAI* GetAI_boss_lich_king_intro_hor(Creature* pCreature) +{ + return new boss_lich_king_intro_horAI(pCreature); +} + +struct MANGOS_DLL_DECL npc_undead_horAI : public BSWScriptedAI +{ + npc_undead_horAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + } + + void EnterEvadeMode() + { + if (!m_pInstance) + return; + + m_creature->ForcedDespawn(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_LICH_KING) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + doCastAll(uiDiff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_undead_hor(Creature* pCreature) +{ + return new npc_undead_horAI(pCreature); +} + +void AddSC_boss_lich_king_hr() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_lich_king_hr"; + newscript->GetAI = &GetAI_boss_lich_king_hr; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_lich_king_intro_hor"; + newscript->GetAI = &GetAI_boss_lich_king_intro_hor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_undead_hor"; + newscript->GetAI = &GetAI_npc_undead_hor; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_marwyn.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_marwyn.cpp index b8b5e84..e55de0a 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_marwyn.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/boss_marwyn.cpp @@ -16,9 +16,222 @@ /* ScriptData SDName: boss_marwyn -SD%Complete: 0% +SD%Complete: 60% SDComment: +SDAuthor: /dev/rsa, changed by MaxXx2021 aka Mioka SDCategory: Halls of Reflection EndScriptData */ #include "precompiled.h" +#include "def_halls.h" + +enum +{ + SAY_MARWYN_INTRO = -1594506, + SAY_MARWYN_AGGRO = -1594513, + SAY_MARWYN_DEATH = -1594514, + SAY_MARWYN_SLAY01 = -1594515, + SAY_MARWYN_SLAY02 = -1594516, + SAY_MARWYN_SP01 = -1594517, + SAY_MARWYN_SP02 = -1594518, + + SPELL_OBLITERATE = 72360, + SPELL_SHARED_SUFFERING = 72368, + SPELL_WELL_OF_CORRUPTION = 72362, + SPELL_CORRUPTED_FLESH = 72436, + + SPELL_BERSERK = 47008, +}; + +struct MANGOS_DLL_DECL boss_marwynAI : public BSWScriptedAI +{ + boss_marwynAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsCall; + uint32 m_uiSummonTimer; + + uint32 m_uiLocNo; + uint64 m_uiSummonGUID[16]; + uint32 m_uiCheckSummon; + + uint8 SummonCount; + + uint64 pSummon; + + void Reset() + { + SummonCount = 0; + m_bIsCall = false; + m_uiSummonTimer = 15000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetVisibility(VISIBILITY_OFF); + } + + void Summon() + { + m_uiLocNo = 14; + + for(uint8 i = 0; i < 14; i++) + { + switch(urand(0,3)) + { + case 0: + switch(urand(1, 3)) + { + case 1: pSummon = NPC_DARK_1; break; + case 2: pSummon = NPC_DARK_3; break; + case 3: pSummon = NPC_DARK_6; break; + } + break; + case 1: + switch(urand(1, 3)) + { + case 1: pSummon = NPC_DARK_2; break; + case 2: pSummon = NPC_DARK_3; break; + case 3: pSummon = NPC_DARK_4; break; + } + break; + case 2: + switch(urand(1, 3)) + { + case 1: pSummon = NPC_DARK_2; break; + case 2: pSummon = NPC_DARK_5; break; + case 3: pSummon = NPC_DARK_6; break; + } + break; + case 3: + switch(urand(1, 3)) + { + case 1: pSummon = NPC_DARK_1; break; + case 2: pSummon = NPC_DARK_5; break; + case 3: pSummon = NPC_DARK_4; break; + } + break; + } + + m_uiCheckSummon = 0; + + if(Creature* Summon = m_creature->SummonCreature(pSummon, SpawnLoc[m_uiLocNo].x, SpawnLoc[m_uiLocNo].y, SpawnLoc[m_uiLocNo].z, SpawnLoc[m_uiLocNo].o, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000)) + { + m_uiSummonGUID[i] = Summon->GetGUID(); + Summon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Summon->setFaction(974); + } + m_uiLocNo++; + } + } + + void CallFallSoldier() + { + for(uint8 i = 0; i < 4; i++) + { + if(Creature* Summon = m_pInstance->instance->GetCreature(m_uiSummonGUID[m_uiCheckSummon])) + { + Summon->setFaction(14); + Summon->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Summon->SetInCombatWithZone(); + } + m_uiCheckSummon++; + } + } + + void JustDied(Unit* pKiller) + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_MARWYN, DONE); + m_pInstance->SetData(TYPE_PHASE, 3); + } + + DoScriptText(SAY_MARWYN_DEATH, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + switch(urand(0,1)) + { + case 0: DoScriptText(SAY_MARWYN_SLAY01, m_creature); break; + case 1: DoScriptText(SAY_MARWYN_SLAY02, m_creature); break; + } + } + + void Aggro(Unit* pVictim) + { + if (!m_pInstance) return; + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + DoScriptText(SAY_MARWYN_AGGRO, m_creature); + } + + void AttackStart(Unit* who) + { + if (!m_pInstance) return; + + if (m_pInstance->GetData(TYPE_MARWYN) != IN_PROGRESS) + return; + + ScriptedAI::AttackStart(who); + } + + void UpdateAI(const uint32 uiDiff) + { + if(!m_pInstance) return; + + if (m_pInstance->GetData(TYPE_EVENT) == 6) + { + m_pInstance->SetData(TYPE_EVENT, 7); + Summon(); + } + + if(m_pInstance->GetData(TYPE_MARWYN) == SPECIAL) + { + if(m_uiSummonTimer < uiDiff) + { + ++SummonCount; + if(SummonCount == 1) + DoScriptText(SAY_MARWYN_INTRO, m_creature); + + if(SummonCount > 4) + { + m_pInstance->SetData(TYPE_MARWYN, IN_PROGRESS); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetInCombatWithZone(); + } + else CallFallSoldier(); + m_uiSummonTimer = 60000; + } else m_uiSummonTimer -= uiDiff; + } + + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_OBLITERATE, uiDiff); + timedCast(SPELL_WELL_OF_CORRUPTION, uiDiff); + timedCast(SPELL_SHARED_SUFFERING, uiDiff); + timedCast(SPELL_CORRUPTED_FLESH, uiDiff); + + timedCast(SPELL_BERSERK, uiDiff); + + 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/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/def_halls.h b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/def_halls.h new file mode 100644 index 0000000..fc93923 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/def_halls.h @@ -0,0 +1,128 @@ +#ifndef DEF_HALL_OF_REFLECTION_H +#define DEF_HALL_OF_REFLECTION_H +#include "BSW_ai.h" +#include "BSW_instance.h" + +enum Data +{ + TYPE_PHASE = 0, + TYPE_EVENT = 1, + TYPE_FALRIC = 2, + TYPE_MARWYN = 3, + TYPE_FROST_GENERAL = 4, + TYPE_LICH_KING = 5, + TYPE_HALLS = 6, + MAX_ENCOUNTERS, + + DATA_ESCAPE_LIDER = 101, + DATA_SUMMONS = 102, + + /*UNITS*/ + NPC_DARK_1 = 38177, //Shadowy Mercenary + NPC_DARK_2 = 38176, //Tortured Rifleman + NPC_DARK_3 = 38173, //Spectral Footman + NPC_DARK_4 = 38172, //Phantom Mage + NPC_DARK_5 = 38567, //Phantom Hallucination + NPC_DARK_6 = 38175, //Ghostly Priest + NPC_JAINA = 37221, + NPC_SYLVANA = 37223, + NPC_JAINA_OUTRO = 36955, + NPC_SYLVANA_OUTRO = 37554, + NPC_ALTAR_TARGET = 37704, + NPC_UTHER = 37225, + NPC_LICH_KING = 36954, + BOSS_LICH_KING = 37226, + NPC_ICE_WALL = 37014, + NPC_FALRIC = 38112, + NPC_MARWYN = 38113, + NPC_GHOSTLY_ROGUE = 38177, + NPC_GHOSTLY_PRIEST = 38175, + NPC_GHOSTLY_MAGE = 38172, + NPC_GHOSTLY_FOOTMAN = 38173, + NPC_GHOSTLY_RIFLEMAN = 38176, + NPC_GLUK = 38567, + + NPC_RAGING_GNOUL = 36940, + NPC_RISEN_WITCH_DOCTOR = 36941, + NPC_ABON = 37069, + + NPC_FROST_GENERAL = 36723, + NPC_SPIRITUAL_REFLECTION = 37068, + +// NPC_QUEL_DELAR = 37704, + NPC_QUEL_DELAR = 37158, + + GO_ICECROWN_DOOR = 201976, //72802 + GO_ICECROWN_DOOR_2 = 197342, + GO_ICECROWN_DOOR_3 = 197343, + GO_IMPENETRABLE_DOOR = 197341, //72801 + GO_FROSTMOURNE_ALTAR = 202236, //3551 + GO_FROSTMOURNE = 202302, //364 + + GO_ICE_WALL = 201385, + GO_CAVE = 201596, + GO_PORTAL = 202079, + + GO_CAPTAIN_CHEST_1 = 202212, //3145 + GO_CAPTAIN_CHEST_2 = 201710, //30357 + GO_CAPTAIN_CHEST_3 = 202337, //3246 + GO_CAPTAIN_CHEST_4 = 202336, //3333 +}; + +struct _Locations +{ + float x, y, z, o; + uint32 id; +}; + +static _Locations SpawnLoc[]= +{ + //Wing 01 + {5277.409f, 1993.161f, 707.694f, 0.05f}, //27 + {5301.876f, 2041.699f, 707.694f, 4.71f}, //1 + {5339.830f, 2020.887f, 707.694f, 3.14f}, //13 + {5311.041f, 2042.935f, 707.694f, 4.71f}, //3 + {5314.750f, 2039.969f, 707.694f, 4.71f}, //4 + {5342.823f, 2003.801f, 707.694f, 3.14f}, //10 + {5311.579f, 1972.823f, 707.694f, 1.62f}, //16 + + //Wing 02 + {5272.491f, 2005.673f, 707.694f, 0.05f}, //23 + {5302.669f, 1973.050f, 707.694f, 1.62f}, //18 + {5346.187f, 2008.058f, 707.694f, 3.14f}, //9 + {5319.752f, 2041.321f, 707.694f, 4.71f}, //5 + {5344.882f, 1998.714f, 707.694f, 3.14f}, //11 + {5340.552f, 1994.735f, 707.694f, 3.14f}, //12 + {5306.441f, 2040.358f, 707.694f, 4.71f}, //2 + + //Wing 03 + {5273.297f, 2014.009f, 707.694f, 0.05f}, //25 + {5316.062f, 1970.777f, 707.694f, 1.62f}, //15 + {5322.498f, 2037.415f, 707.694f, 4.71f}, //6 + {5307.087f, 1970.065f, 707.694f, 1.62f}, //17 + {5342.460f, 2012.391f, 707.694f, 3.14f}, //8 + {5297.601f, 1971.420f, 707.694f, 1.62f}, //19 + {5295.668f, 1975.853f, 707.694f, 1.62f}, //20 + + //Wing 04 + {5273.661f, 1996.767f, 707.694f, 0.05f}, //21 + {5275.228f, 2001.275f, 707.694f, 0.05f}, //22 + {5344.153f, 2017.753f, 707.694f, 3.14f}, //7 + {5275.310f, 2009.686f, 707.694f, 0.05f}, //24 + {5319.835f, 1975.177f, 707.694f, 1.62f}, //14 + {5277.445f, 2017.197f, 707.694f, 0.05f}, //26 + {5298.198f, 2037.762f, 707.694f, 4.71f} //0 +}; + +static _Locations WallLoc[]= +{ + {5540.39f, 2086.48f, 731.066f, 1.00057f}, + {5494.3f, 1978.27f, 736.689f, 1.0885f}, + {5434.27f, 1881.12f, 751.303f, 0.923328f}, + {5323.61f, 1755.85f, 770.305f, 0.784186f}, + {5239.01f, 1932.64f, 707.695f, 0.8f}, // Spawn point for Jaina && Silvana intro + {5266.779785f, 1953.42f, 707.697f, 1.0f}, + {5547.27002f, 2256.949951f, 733.010986f, 0.9f}, // Spawn point for Jaina && Silvana outro +}; + +#endif \ No newline at end of file diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/halls_of_reflection.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/halls_of_reflection.cpp new file mode 100644 index 0000000..17bc8cc --- /dev/null +++ b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/halls_of_reflection.cpp @@ -0,0 +1,1348 @@ +/* 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: Hall Of Reflection +SD%Complete: Who knows? :D +SDComment: event script! +SDErrors: They have, but i dont know were it! :D +SDCategory: hall_of_reflection +SDAuthor: MaxXx2021 aka Mioka +EndScriptData */ + +#include "precompiled.h" +#include "def_halls.h" +#include "escort_ai.h" + +enum +{ + /*INTRO - Pre Uther*/ + SAY_JAINA_INTRO_01 = -1594433, + SAY_SYLVANA_INTRO_01 = -1594434, + SAY_JAINA_INTRO_02 = -1594435, + SAY_JAINA_INTRO_03 = -1594436, + SAY_SYLVANA_INTRO_03 = -1594437, + SAY_JAINA_INTRO_04 = -1594438, + SAY_SYLVANA_INTRO_04 = -1594439, + + /*INTRO - Uther Dialog*/ + SAY_UTHER_A_01 = -1594440, + SAY_UTHER_H_01 = -1594441, + SAY_JAINA_02 = -1594442, + SAY_SYLVANA_02 = -1594443, + SAY_UTHER_A_03 = -1594444, + SAY_UTHER_H_03 = -1594445, + SAY_JAINA_04 = -1594446, + SAY_SYLVANA_04 = -1594447, + SAY_UTHER_A_05 = -1594448, + SAY_UTHER_H_05 = -1594449, + SAY_JAINA_06 = -1594450, + SAY_SYLVANA_06 = -1594451, + SAY_UTHER_A_07 = -1594452, + SAY_UTHER_H_07 = -1594453, + SAY_JAINA_08 = -1594454, + SAY_SYLVANA_08 = -1594455, + SAY_UTHER_A_09 = -1594456, + SAY_UTHER_H_09 = -1594457, + SAY_JAINA_10 = -1594458, + SAY_UTHER_A_11 = -1594459, + SAY_UTHER_H_11 = -1594460, + SAY_JAINA_12 = -1594461, + SAY_SYLVANA_12 = -1594462, + SAY_UTHER_A_13 = -1594463, + SAY_UTHER_A_14 = -1594464, + SAY_JAINA_15 = -1594465, + + /*INTRO - Lich King Arrive*/ + SAY_UTHER_A_16 = -1594466, + SAY_UTHER_H_16 = -1594467, + SAY_LICH_KING_17 = -1594468, + SAY_LICH_KING_18 = -1594469, + SAY_LICH_KING_19 = -1594470, + SAY_JAINA_20 = -1594471, + SAY_SYLVANA_20 = -1594472, + SAY_LICH_KING_A_21 = -1594473, + SAY_LICH_KING_H_21 = -1594474, + SAY_FALRIC_INTRO = -1594475, + SAY_MARWYN_INTRO = -1594476, + SAY_FALRIC_INTRO2 = -1594505, + + /*INTRO - Pre Escape*/ + SAY_LICH_KING_AGGRO_A = -1594477, + SAY_LICH_KING_AGGRO_H = -1594478, + SAY_JAINA_AGGRO = -1594479, + SAY_SYLVANA_AGGRO = -1594480, + + /*ESCAPE*/ + SAY_JAINA_WALL_01 = -1594487, + SAY_SYLVANA_WALL_01 = -1594488, + SAY_JAINA_WALL_02 = -1594489, + SAY_SYLVANA_WALL_02 = -1594490, + SAY_LICH_KING_WALL_02 = -1594491, + SAY_LICH_KING_WALL_03 = -1594492, + SAY_LICH_KING_WALL_04 = -1594493, + SAY_JAINA_WALL_03 = -1594494, + SAY_JAINA_WALL_04 = -1594495, + SAY_SYLVANA_WALL_03 = -1594496, + SAY_SYLVANA_WALL_04 = -1594497, + SAY_JAINA_ESCAPE_01 = -1594498, + SAY_JAINA_ESCAPE_02 = -1594499, + SAY_SYLVANA_ESCAPE_01 = -1594500, + SAY_SYLVANA_ESCAPE_02 = -1594501, + SAY_JAINA_TRAP = -1594502, + SAY_SYLVANA_TRAP = -1594503, + SAY_LICH_KING_END_01 = -1594506, + SAY_LICH_KING_END_02 = -1594507, + SAY_LICH_KING_END_03 = -1594508, + + SAY_ESCAPE_01 = -1594531, + SAY_ESCAPE_02 = -1594532, + SAY_ESCAPE_03 = -1594533, + + + /*SPELLS AND VISUAL EFFECTS*/ + SPELL_TAKE_FROSTMOURNE = 72729, + SPELL_FROSTMOURNE_DESPAWN = 72726, + SPELL_FROSTMOURNE_SOUNDS = 70667, + SPELL_CAST_VISUAL = 65633, //Jaina And Sylavana cast this when summon uther. + SPELL_BOSS_SPAWN_AURA = 72712, //Falric and Marwyn + SPELL_UTHER_DESPAWN = 70693, + SPELL_WINTER = 69780, + SPELL_FURY_OF_FROSTMOURNE = 70063, + SPELL_SOUL_REAPER = 73797, + SPELL_RAISE_DEAD = 69818, + SPELL_ICE_PRISON = 69708, + SPELL_DARK_ARROW = 70194, + SPELL_ICE_BARRIER = 69787, + SPELL_DESTROY_ICE_WALL_01 = 69784, //Jaina + SPELL_DESTROY_ICE_WALL_02 = 70224, + SPELL_DESTROY_ICE_WALL_03 = 70225, //Sylvana + SPELL_DESTRUCT_ICE_WALL = 69784, + SPELL_SUMMON_ICE_WALL = 69768, + SPELL_SYLVANA_JUMP = 68339, + SPELL_SYLVANA_STEP = 69087, + SPELL_SILENCE = 69413, + SPELL_LICH_KING_CAST = 57561, + SPELL_FROSTMOURNE_VISUAL = 73220, + SPELL_SHIELD_DISRUPTION = 58291, + + FACTION = 2076, +}; + +struct MANGOS_DLL_DECL npc_jaina_and_sylvana_HRintroAI : public ScriptedAI +{ + npc_jaina_and_sylvana_HRintroAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (BSWScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + BSWScriptedInstance* m_pInstance; + + Creature* pUther; + bool Small; + + void Reset() + { + m_creature->SetPhaseMask(65535, true); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + Small = false; + } + + void Event() + { + switch(m_pInstance->GetEvent(m_creature->GetEntry())) + { + case 1: + if (m_pInstance->GetData(TYPE_EVENT) == 2) + Small = true; + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_pInstance->SetNextEvent(2,m_creature->GetEntry(),2000); + break; + case 2: + if(m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_INTRO_01, m_creature); + m_pInstance->SetNextEvent(3,m_creature->GetEntry(),5000); + } + else if(m_creature->GetEntry() == NPC_SYLVANA) + { + DoScriptText(SAY_SYLVANA_INTRO_01, m_creature); + m_pInstance->SetNextEvent(3,m_creature->GetEntry(),8000); + } + break; + case 3: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_INTRO_02, m_creature); + m_pInstance->SetNextEvent(4,m_creature->GetEntry(),5000); + } + else if(m_creature->GetEntry() == NPC_SYLVANA) + m_pInstance->SetNextEvent(4,m_creature->GetEntry(),500); + break; + case 4: + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MovePoint(0, 5307.031f, 1997.920f, 709.341f); + m_pInstance->SetNextEvent(5,m_creature->GetEntry(),10000); + break; + case 5: + if(Creature* pTarget = m_creature->SummonCreature(NPC_ALTAR_TARGET,5309.374f,2006.788f,711.615f,1.37f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,360000)) + { + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pTarget->GetGUID()); + pTarget->SetCreatorGuid(ObjectGuid()); + } + m_pInstance->SetNextEvent(6,m_creature->GetEntry(),1000); + break; + case 6: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_INTRO_03, m_creature); + m_pInstance->SetNextEvent(7,m_creature->GetEntry(),5000); + } + if (m_creature->GetEntry() == NPC_SYLVANA) + { + DoScriptText(SAY_SYLVANA_INTRO_03, m_creature); + m_pInstance->SetNextEvent(7,m_creature->GetEntry(),5000); + } + break; + case 7: + DoCast(m_creature, SPELL_CAST_VISUAL); + if (m_creature->GetEntry() == NPC_JAINA) + DoScriptText(SAY_JAINA_INTRO_04, m_creature); + else if (m_creature->GetEntry() == NPC_SYLVANA) + DoScriptText(SAY_SYLVANA_INTRO_04, m_creature); + m_pInstance->SetNextEvent(8,m_creature->GetEntry(),3000); + break; + case 8: + DoCast(m_creature, SPELL_FROSTMOURNE_SOUNDS); + if(GameObject* pFrostmourne = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_FROSTMOURNE))) + pFrostmourne->SetGoState(GO_STATE_ACTIVE); + if(m_creature->GetEntry() == NPC_JAINA) + m_pInstance->SetNextEvent(9,m_creature->GetEntry(),12000); + if(m_creature->GetEntry() == NPC_SYLVANA) + m_pInstance->SetNextEvent(9,m_creature->GetEntry(),8000); + break; + case 9: + if(Creature* Uther = m_creature->SummonCreature(NPC_UTHER,5308.228f,2003.641f,709.341f,4.17f,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,360000)) + { + pUther = Uther; + Uther->SetCreatorGuid(ObjectGuid()); + Uther->SetRespawnDelay(DAY); + Uther->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->GetGUID()); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, Uther->GetGUID()); + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_UTHER_A_01, Uther); + m_pInstance->SetNextEvent(10,m_creature->GetEntry(),3000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA) + { + DoScriptText(SAY_UTHER_H_01, Uther); + m_pInstance->SetNextEvent(10,m_creature->GetEntry(),10000); + } + } + break; + case 10: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_02, m_creature); + m_pInstance->SetNextEvent(11,m_creature->GetEntry(),5000); + } + else if(m_creature->GetEntry() == NPC_SYLVANA) + { + DoScriptText(SAY_SYLVANA_02, m_creature); + m_pInstance->SetNextEvent(11,m_creature->GetEntry(),3000); + } + break; + case 11: + if (m_creature->GetEntry() == NPC_JAINA && pUther) + { + DoScriptText(SAY_UTHER_A_03, pUther); + m_pInstance->SetNextEvent(Small ? 24 : 12, m_creature->GetEntry(),7000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA && pUther) + { + DoScriptText(SAY_UTHER_H_03, pUther); + m_pInstance->SetNextEvent(Small ? 24 : 12, m_creature->GetEntry(),6000); + } + break; + case 12: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_04, m_creature); + m_pInstance->SetNextEvent(13,m_creature->GetEntry(),2000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA) + { + DoScriptText(SAY_SYLVANA_04, m_creature); + m_pInstance->SetNextEvent(13,m_creature->GetEntry(),5000); + } + break; + case 13: + if (m_creature->GetEntry() == NPC_JAINA && pUther) + { + DoScriptText(SAY_UTHER_A_05, pUther); + m_pInstance->SetNextEvent(14,m_creature->GetEntry(),10000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA && pUther) + { + DoScriptText(SAY_UTHER_H_05, pUther); + m_pInstance->SetNextEvent(14,m_creature->GetEntry(),19000); + } + break; + case 14: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_06, m_creature); + m_pInstance->SetNextEvent(15,m_creature->GetEntry(),6000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA) + { + DoScriptText(SAY_SYLVANA_06, m_creature); + m_pInstance->SetNextEvent(15,m_creature->GetEntry(),2000); + } + break; + case 15: + if (m_creature->GetEntry() == NPC_JAINA && pUther) + { + DoScriptText(SAY_UTHER_A_07, pUther); + m_pInstance->SetNextEvent(16,m_creature->GetEntry(),12000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA && pUther) + { + DoScriptText(SAY_UTHER_H_07, pUther); + m_pInstance->SetNextEvent(16,m_creature->GetEntry(),6000); + } + break; + case 16: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_08, m_creature); + m_pInstance->SetNextEvent(17,m_creature->GetEntry(),6000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA) + { + DoScriptText(SAY_SYLVANA_08, m_creature); + m_pInstance->SetNextEvent(17,m_creature->GetEntry(),3000); + } + break; + case 17: + if (m_creature->GetEntry() == NPC_JAINA && pUther) + { + DoScriptText(SAY_UTHER_A_09, pUther); + m_pInstance->SetNextEvent(18,m_creature->GetEntry(),12000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA && pUther) + { + DoScriptText(SAY_UTHER_H_09, pUther); + m_pInstance->SetNextEvent(18,m_creature->GetEntry(),11000); + } + break; + case 18: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_10, m_creature); + m_pInstance->SetNextEvent(19,m_creature->GetEntry(),12000); + } + else if(m_creature->GetEntry() == NPC_SYLVANA) + { + m_pInstance->SetNextEvent(19,m_creature->GetEntry(),500); + } + break; + case 19: + if (m_creature->GetEntry() == NPC_JAINA && pUther) + { + DoScriptText(SAY_UTHER_A_11, pUther); + m_pInstance->SetNextEvent(20,m_creature->GetEntry(),24000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA && pUther) + { + DoScriptText(SAY_UTHER_H_11, pUther); + m_pInstance->SetNextEvent(20,m_creature->GetEntry(),9000); + } + break; + case 20: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_12, m_creature); + m_pInstance->SetNextEvent(21,m_creature->GetEntry(),2000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA) + { + DoScriptText(SAY_SYLVANA_12, m_creature); + m_pInstance->SetNextEvent(21,m_creature->GetEntry(),2100); + } + break; + case 21: + if (m_creature->GetEntry() == NPC_JAINA && pUther) + { + DoScriptText(SAY_UTHER_A_13, pUther); + m_pInstance->SetNextEvent(22,m_creature->GetEntry(),5000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA) + { + m_pInstance->SetNextEvent(22,m_creature->GetEntry(),500); + } + break; + case 22: + if (m_creature->GetEntry() == NPC_JAINA && pUther) + { + DoScriptText(SAY_UTHER_A_14, pUther); + m_pInstance->SetNextEvent(23,m_creature->GetEntry(),12000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA) + { + m_pInstance->SetNextEvent(23,m_creature->GetEntry(),500); + } + break; + case 23: + if (m_creature->GetEntry() == NPC_JAINA) + { + DoScriptText(SAY_JAINA_15, m_creature); + m_pInstance->SetNextEvent(24,m_creature->GetEntry(),2000); + } + else if (m_creature->GetEntry() == NPC_SYLVANA) + { + m_pInstance->SetNextEvent(24,m_creature->GetEntry(),500); + } + break; + case 24: + if (m_creature->GetEntry() == NPC_JAINA && pUther) + DoScriptText(SAY_UTHER_A_16, pUther); + else if (m_creature->GetEntry() == NPC_SYLVANA && pUther) + DoScriptText(SAY_UTHER_H_16, pUther); + if(Creature* LichKing = m_creature->SummonCreature(NPC_LICH_KING,5362.469f,2062.342f,707.695f,3.97f,TEMPSUMMON_MANUAL_DESPAWN,0,true)) + { + LichKing->SetRespawnDelay(DAY); + LichKing->SetCreatorGuid(ObjectGuid()); + } + m_pInstance->SetNextEvent(24,NPC_LICH_KING,2000); + break; + case 25: + if (pUther) + pUther->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_COWER); + m_pInstance->SetNextEvent(25,NPC_LICH_KING,2000); + break; + case 31: + m_creature->RemoveAurasDueToSpell(SPELL_FROSTMOURNE_SOUNDS); + m_pInstance->SetNextEvent(32,NPC_LICH_KING,4500); + break; + case 36: + if (m_creature->GetEntry() == NPC_JAINA) + DoScriptText(SAY_JAINA_20, m_creature); + else if(m_creature->GetEntry() == NPC_SYLVANA) + DoScriptText(SAY_SYLVANA_20, m_creature); + m_creature->GetMotionMaster()->MovePoint(0, 5443.880f, 2147.095f, 707.695f); + m_pInstance->SetNextEvent(37,NPC_LICH_KING,4000); + break; + case 39: + m_pInstance->SetNextEvent(40,NPC_LICH_KING,1000); + m_creature->ForcedDespawn(); + break; + default: + break; + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_pInstance) + return; + + if (m_pInstance->GetEventTimer(m_creature->GetEntry(),diff) && m_pInstance->GetData(TYPE_PHASE) == 1) + Event(); + + return; + } +}; + +bool GossipHello_npc_jaina_and_sylvana_HRintro(Player* pPlayer, Creature* pCreature) +{ + BSWScriptedInstance* m_pInstance = (BSWScriptedInstance*)pCreature->GetInstanceData(); + + if(pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu( pCreature->GetGUID()); + + switch(pCreature->GetEntry()) + { + case NPC_JAINA: + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, -3594536, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, -3594537, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + break; + case NPC_SYLVANA: + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, -3594538, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, -3594539, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + break; + } + + pPlayer->PlayerTalkClass->SendGossipMenu(907,pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_jaina_and_sylvana_HRintro(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + BSWScriptedInstance* m_pInstance = (BSWScriptedInstance*)pCreature->GetInstanceData(); + + if (!m_pInstance) return false; + + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + m_pInstance->SetData(TYPE_EVENT, 1); + m_pInstance->SetData(TYPE_PHASE, 1); + break; + case GOSSIP_ACTION_INFO_DEF+2: + pPlayer->CLOSE_GOSSIP_MENU(); + m_pInstance->SetData(TYPE_EVENT, 2); + m_pInstance->SetData(TYPE_PHASE, 1); + break; + } + + m_pInstance->SetNextEvent(1, pCreature->GetEntry(), 500); + + m_pInstance->SetData64(DATA_ESCAPE_LIDER,pCreature->GetGUID()); + + return true; +} + +struct MANGOS_DLL_DECL npc_jaina_and_sylvana_HRextroAI : public npc_escortAI +{ + npc_jaina_and_sylvana_HRextroAI(Creature *pCreature) : npc_escortAI(pCreature) + { + m_pInstance = (BSWScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + BSWScriptedInstance* m_pInstance; + + uint32 CastTimer; + int32 HoldTimer; + uint8 m_wallNum; + bool Fight; + ObjectGuid wallTarget; + uint32 m_chestID; + + void Reset() + { + if(!m_pInstance) return; + + if(m_pInstance->GetData(TYPE_LICH_KING) == IN_PROGRESS) return; + + HoldTimer = 10000; + Fight = true; + m_wallNum = 0; + wallTarget = ObjectGuid(); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + + if(m_creature->GetEntry() == NPC_JAINA_OUTRO) + { + m_creature->CastSpell(m_creature, SPELL_ICE_BARRIER, false); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2HL); + } + + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (m_creature->GetEntry() != NPC_SYLVANA_OUTRO) + return; + + if (m_pInstance->GetData(TYPE_LICH_KING) == IN_PROGRESS || Fight != true) + return; + + npc_escortAI::AttackStart(who); + + } + + void JustDied(Unit* pKiller) + { + if(!m_pInstance) + return; + DoDestructWall(); + } + + void DoSummonWall(uint8 wallNum) + { + if(!m_pInstance || wallNum > 3) + return; + + m_wallNum = wallNum+1; + HoldTimer = 20000; + + switch (wallNum) + { + case 0: m_pInstance->SetNextEvent(200,BOSS_LICH_KING,500); break; + case 1: m_pInstance->SetNextEvent(300,BOSS_LICH_KING,500); break; + case 2: m_pInstance->SetNextEvent(400,BOSS_LICH_KING,500); break; + case 3: m_pInstance->SetNextEvent(500,BOSS_LICH_KING,500); break; + default: + break; + } + + if (Creature* pWallTarget = m_creature->SummonCreature(NPC_ICE_WALL,WallLoc[wallNum].x,WallLoc[wallNum].y,WallLoc[wallNum].z,WallLoc[wallNum].o,TEMPSUMMON_MANUAL_DESPAWN,0, true)) + { + pWallTarget->SetPhaseMask(65535, true); + pWallTarget->setFaction(114); + pWallTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pWallTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + wallTarget = pWallTarget->GetObjectGuid(); + pWallTarget->CastSpell(pWallTarget, SPELL_SUMMON_ICE_WALL, false); + } + } + + void DoDestructWall() + { + m_pInstance->DoOpenDoor(m_pInstance->GetData64(GO_ICE_WALL)); + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + { + pWallTarget->ForcedDespawn(); + } + wallTarget = ObjectGuid(); + m_wallNum = 0; + } + + void WaypointReached(uint32 i) + { + switch(i) + { + case 0: + break; + case 1: + break; + case 2: + DoSummonWall(0); + break; + case 3: + break; + case 4: + if (m_creature->GetEntry() == NPC_JAINA_OUTRO) + DoScriptText(SAY_JAINA_WALL_01, m_creature); + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + DoScriptText(SAY_SYLVANA_WALL_01, m_creature); + CastTimer = 1000; + SetEscortPaused(true); + if(m_creature->GetEntry() == NPC_JAINA_OUTRO) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_01, false); + } + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_02, false); + } + break; + case 5: + break; + case 6: + DoSummonWall(1); + break; + case 7: + break; + case 8: + if (m_creature->GetEntry() == NPC_JAINA_OUTRO) + DoScriptText(SAY_JAINA_WALL_02, m_creature); + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + DoScriptText(SAY_SYLVANA_WALL_02, m_creature); + CastTimer = 1000; + SetEscortPaused(true); + if(m_creature->GetEntry() == NPC_JAINA_OUTRO) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_01, false); + } + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_02, false); + } + break; + case 9: + if (m_creature->GetEntry() == NPC_JAINA_OUTRO) + DoScriptText(SAY_JAINA_ESCAPE_01, m_creature); + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + DoScriptText(SAY_SYLVANA_ESCAPE_01, m_creature); + DoSummonWall(2); + break; + case 10: + break; + case 11: + break; + case 12: + if(m_creature->GetEntry() == NPC_JAINA_OUTRO) + DoScriptText(SAY_JAINA_WALL_03, m_creature); + if(m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + DoScriptText(SAY_SYLVANA_WALL_03, m_creature); + CastTimer = 1000; + SetEscortPaused(true); + if(m_creature->GetEntry() == NPC_JAINA_OUTRO) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_01, false); + } + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_02, false); + } + break; + case 13: + if (m_creature->GetEntry() == NPC_JAINA_OUTRO) + DoScriptText(SAY_JAINA_ESCAPE_02, m_creature); + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + DoScriptText(SAY_SYLVANA_ESCAPE_02, m_creature); + break; + case 14: + break; + case 15: + DoSummonWall(3); + break; + case 16: + if (m_creature->GetEntry() == NPC_JAINA_OUTRO) + DoScriptText(SAY_JAINA_WALL_04, m_creature); + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + DoScriptText(SAY_SYLVANA_WALL_04, m_creature); + CastTimer = 1000; + SetEscortPaused(true); + if(m_creature->GetEntry() == NPC_JAINA_OUTRO) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_01, false); + } + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_02, false); + } + break; + case 17: + break; + case 18: + break; + case 19: + if (m_creature->GetEntry() == NPC_JAINA_OUTRO) + DoScriptText(SAY_JAINA_TRAP, m_creature); + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + DoScriptText(SAY_SYLVANA_TRAP, m_creature); + break; + case 20: + SetEscortPaused(true); + if (m_creature->GetEntry() == NPC_JAINA_OUTRO) + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2HL); + else if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY1H); + break; + default: + break; + } + } + + void Intro() + { + switch(m_pInstance->GetEvent(m_creature->GetEntry())) + { + case 100: + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + { + if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + AttackStart(pLichKing); + } + m_pInstance->SetNextEvent(101,BOSS_LICH_KING,500); + break; + case 102: + if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + { + Fight = false; + m_creature->GetMotionMaster()->MovePoint(0, (m_creature->GetPositionX()-5)+rand()%10, (m_creature->GetPositionY()-5)+rand()%10, m_creature->GetPositionZ()); + m_pInstance->SetNextEvent(103,m_creature->GetEntry(),3000); + } + else + m_pInstance->SetNextEvent(103,m_creature->GetEntry(),500); + break; + case 103: + if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + Fight = true; + m_pInstance->SetNextEvent(104,m_creature->GetEntry(),500); + break; + case 104: + if(m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + { + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + m_creature->CastSpell(pLichKing, SPELL_SYLVANA_STEP, false); + m_pInstance->SetNextEvent(105,m_creature->GetEntry(),3000); + } + else + m_pInstance->SetNextEvent(105,m_creature->GetEntry(),500); + break; + case 105: + if(m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + { + Fight = false; + m_creature->GetMotionMaster()->MovePoint(0, (m_creature->GetPositionX()-5)+rand()%10, (m_creature->GetPositionY()-5)+rand()%10, m_creature->GetPositionZ()); + m_pInstance->SetNextEvent(106,m_creature->GetEntry(),3000); + } + else + m_pInstance->SetNextEvent(106,m_creature->GetEntry(),12000); + break; + case 106: + Fight = true; + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + m_creature->CastSpell(pLichKing,(m_creature->GetEntry() == NPC_JAINA_OUTRO ? SPELL_ICE_PRISON : SPELL_DARK_ARROW),true); + m_pInstance->SetNextEvent(107,m_creature->GetEntry(),2500); + break; + case 107: + if(m_creature->GetEntry() == NPC_JAINA_OUTRO) + { + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + if (!pLichKing->HasAura(SPELL_ICE_PRISON)) + pLichKing->CastSpell(pLichKing,SPELL_ICE_PRISON,true); + m_creature->RemoveAurasDueToSpell(SPELL_ICE_BARRIER); + DoScriptText(SAY_JAINA_AGGRO, m_creature); + } + else if(m_creature->GetEntry() == NPC_SYLVANA_OUTRO) + { + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + if (!pLichKing->HasAura(SPELL_DARK_ARROW)) + pLichKing->CastSpell(pLichKing,SPELL_DARK_ARROW,true); + DoScriptText(SAY_SYLVANA_AGGRO, m_creature); + } + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STAND); + m_creature->AttackStop(); + m_pInstance->SetNextEvent(108,m_creature->GetEntry(),3000); + break; + case 108: + m_creature->GetMotionMaster()->MovePoint(0, 5577.187f, 2236.003f, 733.012f); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, m_pInstance->GetData64(BOSS_LICH_KING)); + m_pInstance->SetNextEvent(109,m_creature->GetEntry(),10000); + break; + case 109: + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); +// Count = 1; + m_pInstance->SetNextEvent(110,m_creature->GetEntry(),10000); + break; + } + } + + void Outro() + { + switch(m_pInstance->GetEvent(m_creature->GetEntry())) + { + case 610: + m_creature->CastSpell(m_creature, SPELL_SHIELD_DISRUPTION,false); + m_pInstance->SetData(DATA_ESCAPE_LIDER,m_creature->GetEntry()); + m_creature->SummonGameobject(GO_CAVE, 5275.28f, 1694.23f, 786.147f, 0.981225f, 0); + m_pInstance->SetNextEvent(611,m_creature->GetEntry(),6000); + break; + case 611: + if (GameObject* pCave = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_CAVE))) + pCave->SetGoState(GO_STATE_READY); + m_creature->RemoveAurasDueToSpell(SPELL_SILENCE); + m_creature->RemoveSplineFlag(SPLINEFLAG_FLYING); + m_creature->CastSpell(m_creature, SPELL_SHIELD_DISRUPTION,false); + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MovePoint(0, 5258.911328f,1652.112f,784.295166f); + DoScriptText(SAY_ESCAPE_01, m_creature); + m_pInstance->SetNextEvent(612,m_creature->GetEntry(),10000); + break; + case 612: + m_pInstance->SetData(TYPE_LICH_KING, DONE); + DoScriptText(SAY_ESCAPE_02, m_creature); + m_pInstance->SetNextEvent(613,m_creature->GetEntry(),10000); + break; + case 613: + DoScriptText(SAY_ESCAPE_03, m_creature); + m_pInstance->SetNextEvent(614,m_creature->GetEntry(),10000); + break; + case 614: + m_creature->GetMotionMaster()->MovePoint(0, 5240.66f, 1646.93f, 784.302f); + m_pInstance->SetNextEvent(615,m_creature->GetEntry(),5000); + break; + case 615: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STAND); + m_creature->SetOrientation(0.68f); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_pInstance->SetNextEvent(616,m_creature->GetEntry(),5000); + break; + } + } + + void UpdateEscortAI(const uint32 diff) + { + if(!m_pInstance || m_pInstance->GetData(TYPE_PHASE) < 4) + return; + + if (m_pInstance->GetData(TYPE_PHASE) == 6 && m_pInstance->GetEventTimer(m_creature->GetEntry(),diff)) + { + Outro(); + return; + } + + DoMeleeAttackIfReady(); + + if (m_pInstance->GetData(TYPE_PHASE) == 4 && m_pInstance->GetEventTimer(m_creature->GetEntry(),diff)) + { + Intro(); + return; + } + + if (m_creature->GetEntry() == NPC_SYLVANA_OUTRO && !wallTarget.IsEmpty() && m_wallNum && CastTimer < diff) + { + if (Creature* pWallTarget = m_creature->GetMap()->GetCreature(wallTarget)) + m_creature->CastSpell(pWallTarget, SPELL_DESTROY_ICE_WALL_03, false); + CastTimer = 1000; + } + else + CastTimer -= diff; + + if (!wallTarget.IsEmpty() && m_wallNum && m_pInstance->GetData(DATA_SUMMONS) == 0 && HoldTimer < 1000) + { + m_creature->InterruptNonMeleeSpells(false); + SetEscortPaused(false); + + switch(m_wallNum) + { + case 1: + DoDestructWall(); + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + DoScriptText(SAY_LICH_KING_WALL_02, pLichKing); + break; + case 2: + DoDestructWall(); + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + DoScriptText(SAY_LICH_KING_WALL_03, pLichKing); + break; + case 3: + DoDestructWall(); + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + DoScriptText(SAY_LICH_KING_WALL_04, pLichKing); + break; + case 4: + DoDestructWall(); + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(BOSS_LICH_KING))) + { + pLichKing->RemoveAurasDueToSpell(SPELL_WINTER); + pLichKing->SetSpeedRate(MOVE_WALK, 2.5f, true); + } + break; + } + HoldTimer = 10000; + } + else + { + if (HoldTimer <= diff) + HoldTimer = 0; + else + HoldTimer -= diff; + } + } +}; + +bool GossipHello_npc_jaina_and_sylvana_HRextro(Player* pPlayer, Creature* pCreature) +{ + + ScriptedInstance* m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + + if(!m_pInstance) return false; + + if(m_pInstance->GetData(TYPE_LICH_KING) == DONE) return false; + + if(pCreature->isQuestGiver()) + pPlayer->PrepareQuestMenu( pCreature->GetGUID()); + + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, -3594540, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + + return true; +} + +bool GossipSelect_npc_jaina_and_sylvana_HRextro(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance* m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + switch (uiAction) + { + case GOSSIP_ACTION_INFO_DEF+1: + pPlayer->CLOSE_GOSSIP_MENU(); + ((npc_jaina_and_sylvana_HRextroAI*)pCreature->AI())->Start(true); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pCreature->SetUInt64Value(UNIT_FIELD_TARGET, 0); + + if(m_pInstance) + { + m_pInstance->SetData64(DATA_ESCAPE_LIDER, pCreature->GetGUID()); + m_pInstance->SetData(TYPE_LICH_KING, IN_PROGRESS); + m_pInstance->SetData(TYPE_PHASE, 5); + } + return true; + break; + default: return false; + } +} + +CreatureAI* GetAI_npc_jaina_and_sylvana_HRintro(Creature* pCreature) +{ + return new npc_jaina_and_sylvana_HRintroAI(pCreature); +} + +CreatureAI* GetAI_npc_jaina_and_sylvana_HRextro(Creature* pCreature) +{ + return new npc_jaina_and_sylvana_HRextroAI(pCreature); +} + +enum GENERAL_EVENT +{ + SAY_AGGRO = -1594519, + SAY_DEATH = -1594520, + + SPELL_SHIELD_THROWN = 69222, +}; + +struct MANGOS_DLL_DECL npc_frostworn_generalAI : public ScriptedAI +{ + npc_frostworn_generalAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiShieldTimer; + + void Reset() + { + if (!m_pInstance) + return; + m_uiShieldTimer = 5000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + DoScriptText(SAY_DEATH, m_creature); + m_pInstance->SetData(TYPE_FROST_GENERAL, DONE); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_pInstance) + return; + + if (m_creature->getVictim()) + return; + + if (pWho->GetTypeId() != TYPEID_PLAYER + || m_pInstance->GetData(TYPE_MARWYN) != DONE + || !m_creature->IsWithinDistInMap(pWho, 30.0f) + ) return; + + if (Player* pPlayer = (Player*)pWho) + if (pPlayer->isGameMaster()) return; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + AttackStart(pWho); + } + + void Aggro(Unit* pVictim) + { + if (!m_pInstance) + return; + DoScriptText(SAY_AGGRO, m_creature); + m_pInstance->SetData(TYPE_FROST_GENERAL, IN_PROGRESS); + + Map::PlayerList const &pList = m_creature->GetMap()->GetPlayers(); + for (Map::PlayerList::const_iterator i = pList.begin(); i != pList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer && pPlayer->isAlive() && pPlayer->IsInMap(m_creature)) + { + if (Creature* pMirror = m_creature->SummonCreature(NPC_SPIRITUAL_REFLECTION,0,0,0,0,TEMPSUMMON_DEAD_DESPAWN,0, true)) + { + pMirror->SetPhaseMask(65535, true); + pMirror->SetInCombatWith(pPlayer); + pMirror->AddThreat(pPlayer, 1000.0f); + } + + } + } + }; + + } + + void UpdateAI(const uint32 uiDiff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiShieldTimer < uiDiff) + { + if(Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget,SPELL_SHIELD_THROWN); + m_uiShieldTimer = urand(4000, 8000); + } + else m_uiShieldTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_frostworn_general(Creature* pCreature) +{ + return new npc_frostworn_generalAI(pCreature); +} + +enum spiritual_reflection +{ + SPELL_REFLECTION_GHOST = 69861, + SPELL_CLONE = 69828, + SPELL_CLONE2 = 69837, + + SPELL_BALEFUL_STRIKE = 69933, + SPELL_SPIRIT_BURST = 69900, + +}; + +struct MANGOS_DLL_DECL npc_spiritual_reflectionAI : public BSWScriptedAI +{ + npc_spiritual_reflectionAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool isMirror; + ObjectGuid victimGuid; + + void Reset() + { + if (!m_pInstance) + return; + isMirror = false; + victimGuid = ObjectGuid(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void Aggro(Unit* pVictim) + { + if (!m_pInstance || !pVictim || pVictim->GetTypeId() != TYPEID_PLAYER) + return; + + if (victimGuid.IsEmpty()) + victimGuid = pVictim->GetObjectGuid(); + + DoStartMovement(pVictim); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!m_pInstance || !m_creature ) + return; + + if (uiDamage >= m_creature->GetHealth()) + doCast(SPELL_SPIRIT_BURST); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_FROST_GENERAL) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (!isMirror) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit(victimGuid)) + if (m_creature->IsWithinDistInMap(pVictim, 5.0f)) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pVictim->CastSpell(m_creature, SPELL_CLONE, true); + pVictim->CastSpell(m_creature, SPELL_CLONE2, true); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, pVictim->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID)); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, pVictim->GetUInt32Value(PLAYER_VISIBLE_ITEM_17_ENTRYID)); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+2, pVictim->GetUInt32Value(PLAYER_VISIBLE_ITEM_18_ENTRYID)); + pVictim->CastSpell(m_creature, SPELL_REFLECTION_GHOST, true); + isMirror = true; + } + } + + if (!isMirror) + return; + + timedCast(SPELL_BALEFUL_STRIKE,uiDiff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_spiritual_reflection(Creature* pCreature) +{ + return new npc_spiritual_reflectionAI(pCreature); +} + +struct MANGOS_DLL_DECL npc_queldelar_horAI : public ScriptedAI +{ + npc_queldelar_horAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (BSWScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + BSWScriptedInstance* m_pInstance; + bool intro; + Team team; + uint32 newLeader; + + void Reset() + { + intro = false; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_pInstance || intro) + return; + + if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER || !pWho->IsWithinDistInMap(m_creature, 22.0f)) + return; + + debug_log("HOR event started"); + + intro = true; + + if (m_pInstance->GetData(TYPE_LICH_KING) == DONE) + return; + else if (m_pInstance->GetData(TYPE_FROST_GENERAL) == DONE) + { + m_pInstance->DoOpenDoor(m_pInstance->GetData64(GO_IMPENETRABLE_DOOR)); + m_pInstance->DoOpenDoor(m_pInstance->GetData64(GO_ICECROWN_DOOR_2)); + m_pInstance->SetData(TYPE_PHASE, 3); + return; + } + else if (m_pInstance->GetData(TYPE_MARWYN) == DONE) + { + m_pInstance->DoOpenDoor(m_pInstance->GetData64(GO_IMPENETRABLE_DOOR)); + return; + } + else if (m_pInstance->GetData(TYPE_FALRIC) == DONE) + { + if (Creature* pMarwyn = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_MARWYN))) + { + pMarwyn->SetVisibility(VISIBILITY_ON); + pMarwyn->CastSpell(pMarwyn, SPELL_BOSS_SPAWN_AURA, false); + m_pInstance->SetData(TYPE_EVENT, 7); + m_pInstance->SetData(TYPE_MARWYN, SPECIAL); + } + return; + } + + + if (Group* pGroup = ((Player*)pWho)->GetGroup()) + { + ObjectGuid LeaderGuid = pGroup->GetLeaderGuid(); + if (!LeaderGuid.IsEmpty()) + if (Player* pLeader =m_creature->GetMap()->GetPlayer(LeaderGuid)) + team = pLeader->GetTeam(); + } + else + team = ((Player*)pWho)->GetTeam(); + + + if (team == ALLIANCE) + newLeader = NPC_JAINA; + else + newLeader = NPC_SYLVANA; + + debug_log("HOR event: team %u, leader %u ",team,newLeader); + + if (Creature* pNewLeader = m_creature->SummonCreature(newLeader,WallLoc[4].x,WallLoc[4].y,WallLoc[4].z,WallLoc[4].o,TEMPSUMMON_MANUAL_DESPAWN,0,true)) + { + pNewLeader->SetCreatorGuid(ObjectGuid()); + pNewLeader->setFaction(35); + pNewLeader->SetPhaseMask(65535, true); + pNewLeader->GetMotionMaster()->MovePoint(0, WallLoc[5].x,WallLoc[5].y,WallLoc[5].z); + pNewLeader->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pNewLeader->SetSpeedRate(MOVE_RUN, 1.0f, true); + pNewLeader->SetRespawnDelay(DAY); + } +// m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 63135); + } + + void AttackStart(Unit* who) + { + return; + } + + void UpdateAI(const uint32 diff) + { + } +}; +CreatureAI* GetAI_npc_queldelar_hor(Creature* pCreature) +{ + return new npc_queldelar_horAI(pCreature); +} + + +void AddSC_halls_of_reflection() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "npc_jaina_and_sylvana_HRintro"; + newscript->GetAI = &GetAI_npc_jaina_and_sylvana_HRintro; + newscript->pGossipHello = &GossipHello_npc_jaina_and_sylvana_HRintro; + newscript->pGossipSelect = &GossipSelect_npc_jaina_and_sylvana_HRintro; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_jaina_and_sylvana_HRextro"; + newscript->GetAI = &GetAI_npc_jaina_and_sylvana_HRextro; + newscript->pGossipHello = &GossipHello_npc_jaina_and_sylvana_HRextro; + newscript->pGossipSelect = &GossipSelect_npc_jaina_and_sylvana_HRextro; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_frostworn_general"; + newscript->GetAI = &GetAI_npc_frostworn_general; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_spiritual_reflection"; + newscript->GetAI = &GetAI_npc_spiritual_reflection; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_queldelar_hor"; + newscript->GetAI = &GetAI_npc_queldelar_hor; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/halls_of_reflection.h b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/halls_of_reflection.h new file mode 100644 index 0000000..e592de1 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/halls_of_reflection.h @@ -0,0 +1,3 @@ +/* Copyright (C) 2006 - 2010 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp new file mode 100644 index 0000000..eb47fb2 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp @@ -0,0 +1,322 @@ +/* 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_reflection +SD%Complete: 70% +SDComment: +SDErrors: +SDCategory: instance script +SDAuthor: /dev/rsa, modified by MaxXx2021 aka Mioka +EndScriptData */ + +#include "precompiled.h" +#include "def_halls.h" +#include "World.h" + +struct MANGOS_DLL_DECL instance_halls_of_reflection : public BSWScriptedInstance +{ + instance_halls_of_reflection(Map* pMap) : BSWScriptedInstance(pMap) + { + Difficulty = pMap->GetDifficulty(); + Initialize(); + } + + uint32 m_auiEncounter[MAX_ENCOUNTERS+1]; + std::string strSaveData; + + uint8 Difficulty; + uint8 m_uiSummons; + + uint32 m_auiLeader; + + uint64 m_uiFalricGUID; + uint64 m_uiMarwynGUID; + uint64 m_uiLichKingGUID; + uint64 m_uiLiderGUID; + uint64 m_uiUtherGUID; + + uint64 m_uiQuelDelarGUID; + + uint64 m_uiMainGateGUID; + uint64 m_uiExitGateGUID; + uint64 m_uiDoor2GUID; + uint64 m_uiDoor3GUID; + + uint64 m_uiFrostGeneralGUID; + uint64 m_uiCaptainsChestHordeGUID; + uint64 m_uiCaptainsChestAllianceGUID; + uint64 m_uiFrostmourneGUID; + uint64 m_uiFrostmourneAltarGUID; + uint64 m_uiPortalGUID; + uint64 m_uiIceWallGUID; + uint64 m_uiCaveGUID; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + m_auiEncounter[i] = NOT_STARTED; + m_uiMainGateGUID = 0; + m_uiFrostmourneGUID = 0; + m_uiFalricGUID = 0; + m_uiLiderGUID = 0; + m_uiLichKingGUID = 0; + m_uiExitGateGUID = 0; + m_uiSummons = 0; + m_uiIceWallGUID = 0; + m_uiCaveGUID = 0; + } + + void OnCreatureCreate(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case NPC_FALRIC: + m_uiFalricGUID = pCreature->GetGUID(); + break; + case NPC_MARWYN: + m_uiMarwynGUID = pCreature->GetGUID(); + break; + case BOSS_LICH_KING: + m_uiLichKingGUID = pCreature->GetGUID(); + break; + case NPC_FROST_GENERAL: + m_uiFrostGeneralGUID = pCreature->GetGUID(); + break; + case NPC_QUEL_DELAR: + m_uiQuelDelarGUID = pCreature->GetGUID(); + break; + case NPC_UTHER: + m_uiUtherGUID = pCreature->GetGUID(); + break; + } + } + + void OnObjectCreate(GameObject* pGo) + { + switch(pGo->GetEntry()) + { + case GO_IMPENETRABLE_DOOR: m_uiMainGateGUID = pGo->GetGUID(); + if (GetData(TYPE_MARWYN) == DONE) + DoOpenDoor(m_uiMainGateGUID); + break; + case GO_FROSTMOURNE: m_uiFrostmourneGUID = pGo->GetGUID(); break; + case GO_ICECROWN_DOOR: m_uiExitGateGUID = pGo->GetGUID(); break; + case GO_ICECROWN_DOOR_2: m_uiDoor2GUID = pGo->GetGUID(); + if (GetData(TYPE_FROST_GENERAL) == DONE) + DoOpenDoor(m_uiDoor2GUID); + break; + case GO_ICECROWN_DOOR_3: m_uiDoor3GUID = pGo->GetGUID(); break; + case GO_PORTAL: m_uiPortalGUID = pGo->GetGUID(); break; + case GO_CAPTAIN_CHEST_1: + if (Difficulty == RAID_DIFFICULTY_10MAN_NORMAL) + m_uiCaptainsChestHordeGUID = pGo->GetGUID(); + break; + case GO_CAPTAIN_CHEST_3: + if (Difficulty == RAID_DIFFICULTY_25MAN_NORMAL) + m_uiCaptainsChestHordeGUID = pGo->GetGUID(); + break; + case GO_CAPTAIN_CHEST_2: + if (Difficulty == RAID_DIFFICULTY_10MAN_NORMAL) + m_uiCaptainsChestAllianceGUID = pGo->GetGUID(); + break; + case GO_CAPTAIN_CHEST_4: + if (Difficulty == RAID_DIFFICULTY_25MAN_NORMAL) + m_uiCaptainsChestAllianceGUID = pGo->GetGUID(); + break; + + case GO_ICE_WALL: m_uiIceWallGUID = pGo->GetGUID(); + pGo->SetPhaseMask(65535, true); + break; + case GO_CAVE: m_uiCaveGUID = pGo->GetGUID(); + DoOpenDoor(m_uiCaveGUID); + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_PHASE: m_auiEncounter[uiType] = uiData; break; + case TYPE_EVENT: m_auiEncounter[uiType] = uiData; + uiData = NOT_STARTED; + break; + case TYPE_FALRIC: m_auiEncounter[uiType] = uiData; + if (uiData == SPECIAL) + DoCloseDoor(m_uiExitGateGUID); + else if (uiData == FAIL) + DoOpenDoor(m_uiExitGateGUID); + break; + case TYPE_MARWYN: m_auiEncounter[uiType] = uiData; + if (uiData == SPECIAL) + DoCloseDoor(m_uiExitGateGUID); + else if (uiData == FAIL) + DoOpenDoor(m_uiExitGateGUID); + else if (uiData == DONE) + { + DoOpenDoor(m_uiMainGateGUID); + DoOpenDoor(m_uiExitGateGUID); + } + break; + case TYPE_FROST_GENERAL: m_auiEncounter[uiType] = uiData; + if(uiData == DONE) + DoOpenDoor(m_uiDoor2GUID); + break; + case TYPE_LICH_KING: m_auiEncounter[uiType] = uiData; + if(uiData == IN_PROGRESS) + DoOpenDoor(m_uiDoor3GUID); + if(uiData == DONE) + { + if (GameObject* pChest = instance->GetGameObject(m_uiCaptainsChestAllianceGUID)) + if (pChest && !pChest->isSpawned() && GetData(DATA_ESCAPE_LIDER) == NPC_JAINA_OUTRO) + { + pChest->SetRespawnTime(DAY); + } + if (GameObject* pChest = instance->GetGameObject(m_uiCaptainsChestHordeGUID)) + if (pChest && !pChest->isSpawned() && GetData(DATA_ESCAPE_LIDER) == NPC_SYLVANA_OUTRO) + { + pChest->SetRespawnTime(DAY); + }; + if (GameObject* pPortal = instance->GetGameObject(m_uiPortalGUID)) + if (pPortal && !pPortal->isSpawned()) + { + pPortal->SetRespawnTime(DAY); + }; + } + break; + case TYPE_HALLS: m_auiEncounter[uiType] = uiData; break; + case DATA_SUMMONS: if (uiData == 3) m_uiSummons = 0; + else if (uiData == 1) ++m_uiSummons; + else if (uiData == 0) --m_uiSummons; + uiData = NOT_STARTED; + break; + case DATA_ESCAPE_LIDER: m_auiLeader = uiData; + uiData = NOT_STARTED; + break; + default: + break; + } + + if (uiData == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + saveStream << m_auiEncounter[i] << " "; + + strSaveData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + const char* Save() + { + return strSaveData.c_str(); + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_PHASE: return m_auiEncounter[uiType]; + case TYPE_EVENT: return m_auiEncounter[uiType]; + case TYPE_FALRIC: return m_auiEncounter[uiType]; + case TYPE_MARWYN: return m_auiEncounter[uiType]; + case TYPE_LICH_KING: return m_auiEncounter[uiType]; + case TYPE_FROST_GENERAL: return m_auiEncounter[uiType]; + case TYPE_HALLS: return m_auiEncounter[uiType]; + case DATA_SUMMONS: return m_uiSummons; + case DATA_ESCAPE_LIDER: return m_auiLeader; + default: return 0; + } + return 0; + } + + void SetData64(uint32 uiData, uint64 uiGuid) + { + switch(uiData) + { + case DATA_ESCAPE_LIDER: + m_uiLiderGUID = uiGuid; + break; + } + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case GO_IMPENETRABLE_DOOR: return m_uiMainGateGUID; + case GO_FROSTMOURNE: return m_uiFrostmourneGUID; + case NPC_FALRIC: return m_uiFalricGUID; + case NPC_MARWYN: return m_uiMarwynGUID; + case NPC_UTHER: return m_uiUtherGUID; + case BOSS_LICH_KING: return m_uiLichKingGUID; + case DATA_ESCAPE_LIDER: return m_uiLiderGUID; + case NPC_FROST_GENERAL: return m_uiFrostGeneralGUID; + case NPC_QUEL_DELAR: return m_uiQuelDelarGUID; + case GO_ICECROWN_DOOR: return m_uiExitGateGUID; + case GO_ICECROWN_DOOR_2: return m_uiDoor2GUID; + case GO_ICECROWN_DOOR_3: return m_uiDoor3GUID; + case GO_ICE_WALL: return m_uiIceWallGUID; + case GO_CAVE: return m_uiCaveGUID; + } + return 0; + } + + void Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + { + loadStream >> m_auiEncounter[i]; + + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + } + +}; + +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/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_forgemaster_gafrost.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_forgemaster_gafrost.cpp index edb781e..437ca3f 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_forgemaster_gafrost.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_forgemaster_gafrost.cpp @@ -16,15 +16,48 @@ /* ScriptData SDName: boss_forgemaster_gafrost -SD%Complete: 0% -SDComment: +SD%Complete: 60% +SDComment: by Tacx SDCategory: Pit of Saron EndScriptData */ #include "precompiled.h" #include "pit_of_saron.h" +enum +{ + //common + SPELL_BERSERK = 47008, + //yells + SAY_AGGRO = -1658001, + SAY_SLAY_1 = -1658002, + SAY_SLAY_2 = -1658003, + SAY_DEATH = -1658004, + SAY_PHASE2 = -1658005, + SAY_PHASE3 = -1658006, + SAY_DEEPFREZE = -1658006, + SAY_TYRANNUS_DEATH = -1659007, + //summons + //Abilities + SPELL_PERMAFROST = 70326, + SPELL_PERMAFROST_TRIGGER = 68786, + SPELL_THROW_SARONITE = 68788, + SPELL_THUNDERING_STOMP = 68771, + SPELL_CHILLING_WAVE = 68778, + SPELL_CHILLING_WAVE_H = 70333, + SPELL_DEEP_FREEZE = 70381, + SPELL_DEEP_FREEZE_H = 72930, + SPELL_FORGE_MACE = 68785, + SPELL_FORGE_MACE_H = 70335, + SPELL_FORGE_BLADE = 68774, + SPELL_FORGE_BLADE_H = 70334, + EQUIP_ID_SWORD = 49345, + EQUIP_ID_MACE = 49344, + ACHIEV_DOESNT_GO_TO_ELEVEN = 4524 + +}; -enum +/* +enum saysSD2 { SAY_AGGRO = -1658014, SAY_SLAY_1 = -1658015, @@ -38,8 +71,173 @@ enum EMOTE_THROW_SARONITE = -1658022, EMOTE_DEEP_FREEZE = -1658023, }; +*/ -void AddSC_boss_gafrost() +struct MANGOS_DLL_DECL boss_forgemaster_gafrostAI : public ScriptedAI { + boss_forgemaster_gafrostAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *m_pInstance; + + + bool m_bIsRegularMode; + bool m_bIsPhase2; + bool m_bIsPhase3; + bool m_bIsAchievement; + + uint32 m_uiThrowSaronite_Timer; + uint32 m_uiChillingWave_Timer; + uint32 m_uiDeepFreeze_Timer; + uint32 m_uiBladeReturn_Timer; + uint32 m_uiMaceReturn_Timer; + + void Reset() + { + m_bIsPhase2 = false; + m_bIsPhase3 = false; + m_bIsAchievement = true; + m_uiThrowSaronite_Timer = 20000; + m_uiChillingWave_Timer = 9990000; + m_uiDeepFreeze_Timer = 9990000; + m_uiBladeReturn_Timer = 4500; + m_uiMaceReturn_Timer = 6000; + + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_GARFROST, NOT_STARTED); + } + + void Aggro(Unit *who) + { + DoScriptText(SAY_AGGRO, m_creature); + DoCast(m_creature, SPELL_PERMAFROST); + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_GARFROST, IN_PROGRESS); + } + + void KilledUnit(Unit* victim) + { + switch (urand(0,1)) + { + case 0: DoScriptText(SAY_SLAY_1, m_creature); break; + case 1: DoScriptText(SAY_SLAY_2, m_creature); break; + } + } + + void JustDied(Unit* pkiller) + { + DoScriptText(SAY_DEATH, m_creature); + if(!m_pInstance) return; + m_pInstance->SetData(TYPE_GARFROST, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 66) && !m_bIsPhase2) + { + m_bIsPhase2 = true; + DoScriptText(SAY_PHASE2, m_creature); + DoCast(m_creature, SPELL_THUNDERING_STOMP); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(0, 654.021, -201.438, 526.699); + } + + if (((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 33) && !m_bIsPhase3) + { + m_bIsPhase3 = true; + DoScriptText(SAY_PHASE3, m_creature); + DoCast(m_creature, SPELL_THUNDERING_STOMP); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(0, 718.009, -229.447, 526.847); + } + if (m_bIsPhase2) + { + if (m_uiBladeReturn_Timer < diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_FORGE_BLADE : SPELL_FORGE_BLADE_H); + SetEquipmentSlots(false, EQUIP_ID_SWORD, -1, -1); + m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + m_uiBladeReturn_Timer = 9900000; + } + else + m_uiBladeReturn_Timer -= diff; + + m_uiChillingWave_Timer = 10000; + } + + if (m_bIsPhase3) + { + if (m_uiMaceReturn_Timer < diff) + { + m_creature->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_FORGE_BLADE : SPELL_FORGE_BLADE_H); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FORGE_MACE : SPELL_FORGE_MACE_H); + SetEquipmentSlots(false, EQUIP_ID_MACE, -1, -1); + m_creature->SetByteValue(UNIT_FIELD_BYTES_2, 0, SHEATH_STATE_MELEE); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); + m_uiMaceReturn_Timer = 9900000; + } + else + m_uiMaceReturn_Timer -= diff; + m_uiChillingWave_Timer = 999000; + m_uiDeepFreeze_Timer = 10000; + } + + if (m_uiThrowSaronite_Timer < diff) + { + if (Unit* Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(Target, SPELL_THROW_SARONITE); + m_uiThrowSaronite_Timer = (m_bIsRegularMode ? 20000 : 25000); + } + else + m_uiThrowSaronite_Timer -= diff; + + if (m_uiChillingWave_Timer < diff) + { + DoCast(m_creature, SPELL_CHILLING_WAVE); + m_uiChillingWave_Timer = (m_bIsRegularMode ? 40000 : 30000); + } + else + m_uiChillingWave_Timer -= diff; + + if (m_uiDeepFreeze_Timer < diff) + { + if (Unit* Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(Target, m_bIsRegularMode ? SPELL_DEEP_FREEZE : SPELL_DEEP_FREEZE_H); + m_uiDeepFreeze_Timer = (m_bIsRegularMode ? 27500 : 25000); + } + else + m_uiDeepFreeze_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_boss_forgemaster_gafrost(Creature* pCreature) +{ + return new boss_forgemaster_gafrostAI(pCreature); +} + + +void AddSC_boss_gafrost() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_forgemaster_gafrost"; + newscript->GetAI = &GetAI_boss_forgemaster_gafrost; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_krick_and_ick.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_krick_and_ick.cpp index b558e18..4493d9c 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_krick_and_ick.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_krick_and_ick.cpp @@ -15,14 +15,156 @@ */ /* ScriptData -SDName: boss_krick_and_ick -SD%Complete: 0% -SDComment: +SDName: boss_ick && boss_krick +SD%Complete: 1% +SDComment: by ..., modified by /dev/rsa SDCategory: Pit of Saron EndScriptData */ #include "precompiled.h" #include "pit_of_saron.h" +enum +{ + //common + SPELL_BERSERK = 47008, + //yells + //summons + NPC_EXPLODING_ORB = 36610, + //Abilities + SPELL_FEAR = 68950, + SPELL_EXPLOSIVE_ORB = 69019, + SPELL_EXPLOSIVE = 69012, + SPELL_SHADOWBOLT = 69028, + SPELL_STRANGULATE = 69413, + SPELL_TOXIC = 69024, + SPELL_KICK = 69021, + SPELL_POISON = 68989, + SPELL_POISON_H = 70434, + SPELL_PURSUIT = 68987, + SPELL_PUSTULANT = 69581, + SPELL_CONFUSION = 69029, +}; + +struct MANGOS_DLL_DECL boss_krickAI : public ScriptedAI +{ + boss_krickAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Regular = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool Regular; + ScriptedInstance *pInstance; + + void Reset() + { + if(pInstance) pInstance->SetData(TYPE_KRICK, NOT_STARTED); + } + + void Aggro(Unit *who) + { + if(pInstance) pInstance->SetData(TYPE_KRICK, IN_PROGRESS); + } + + void JustDied(Unit *killer) + { + if(pInstance) pInstance->SetData(TYPE_KRICK, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL boss_ickAI : public ScriptedAI +{ + boss_ickAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Regular = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool Regular; + ScriptedInstance *pInstance; + + void Reset() + { + } + + void Aggro(Unit *who) + { + } + + void JustDied(Unit *killer) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_krick(Creature* pCreature) +{ + return new boss_krickAI(pCreature); +} + +CreatureAI* GetAI_boss_ick(Creature* pCreature) +{ + return new boss_ickAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_exploding_orbAI : public ScriptedAI +{ + mob_exploding_orbAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_creature->SetActiveObjectState(true); + Reset(); + } + + ScriptedInstance* pInstance; + uint32 ExplodeTimer; + + void Reset() + { + ExplodeTimer = 18000; + } + + void AttackStart(Unit* who) + { + return; + } + + void UpdateAI(const uint32 diff) + { + if(!pInstance) return; + + if (ExplodeTimer < diff) + { + DoCast(m_creature, SPELL_EXPLOSIVE_ORB); + m_creature->ForcedDespawn(); + } else ExplodeTimer -= diff; + return; + } + +}; + +CreatureAI* GetAI_mob_exploding_orb(Creature* pCreature) +{ + return new mob_exploding_orbAI(pCreature); +} + enum { @@ -55,5 +197,20 @@ enum void AddSC_boss_krick_and_ick() { + Script *newscript; + newscript = new Script; + newscript->Name = "boss_krick"; + newscript->GetAI = &GetAI_boss_krick; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_ick"; + newscript->GetAI = &GetAI_boss_ick; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_exploding_orb"; + newscript->GetAI = &GetAI_mob_exploding_orb; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp index 5338b35..5bffcbd 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp @@ -24,6 +24,16 @@ EndScriptData */ #include "precompiled.h" #include "pit_of_saron.h" +enum Spells +{ + //common + SPELL_BERSERK = 47008, + //yells + //summons + //Abilities + SPELL_FEAR = 68950 +}; + enum { SAY_PREFIGHT_1 = -1658050, @@ -40,7 +50,94 @@ enum EMOTE_SMASH = -1658060, }; + +struct MANGOS_DLL_DECL boss_scourgelord_tyrannusAI : public ScriptedAI +{ + boss_scourgelord_tyrannusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if(pInstance) pInstance->SetData(TYPE_TYRANNUS, NOT_STARTED); + } + + void Aggro(Unit *who) + { + if(pInstance) pInstance->SetData(TYPE_TYRANNUS, IN_PROGRESS); + } + + void JustDied(Unit *killer) + { + if(pInstance) pInstance->SetData(TYPE_TYRANNUS, DONE); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_rimefang_posAI : public ScriptedAI +{ + mob_rimefang_posAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + } + + void Aggro(Unit *who) + { + } + + void JustDied(Unit *killer) + { + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_boss_scourgelord_tyrannus(Creature* pCreature) +{ + return new boss_scourgelord_tyrannusAI(pCreature); +} + +CreatureAI* GetAI_mob_rimefang_pos(Creature* pCreature) +{ + return new mob_rimefang_posAI(pCreature); +} + + void AddSC_boss_tyrannus() { + Script *newscript; + newscript = new Script; + newscript->Name = "boss_scourgelord_tyrannus"; + newscript->GetAI = &GetAI_boss_scourgelord_tyrannus; + newscript->RegisterSelf(); + newscript = new Script; + newscript->Name="mob_rimefang_pos"; + newscript->GetAI = &GetAI_mob_rimefang_pos; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/pit_of_saron.cpp b/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/pit_of_saron.cpp index d09121c..b56ef56 100644 --- a/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/pit_of_saron.cpp +++ b/scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/pit_of_saron.cpp @@ -21,9 +21,6 @@ SD%Complete: 0 SDCategory: Pit of Saron EndScriptData */ -/* ContentData -EndContentData */ - #include "precompiled.h" #include "pit_of_saron.h" @@ -59,7 +56,57 @@ enum SAY_SYLVANAS_OUTRO_2 = -1658067, }; +struct MANGOS_DLL_DECL npc_jaina_or_sylvanas_POSintroAI : public ScriptedAI +{ + npc_jaina_or_sylvanas_POSintroAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + } +}; + +struct MANGOS_DLL_DECL npc_jaina_or_sylvanas_POSoutroAI : public ScriptedAI +{ + npc_jaina_or_sylvanas_POSoutroAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + } +}; + +CreatureAI* GetAI_npc_jaina_or_sylvanas_POSintro(Creature* pCreature) +{ + return new npc_jaina_or_sylvanas_POSintroAI(pCreature); +} + +CreatureAI* GetAI_npc_jaina_or_sylvanas_POSoutro(Creature* pCreature) +{ + return new npc_jaina_or_sylvanas_POSoutroAI(pCreature); +} + void AddSC_pit_of_saron() { + Script *newscript; + + newscript = new Script; + newscript->Name="npc_jaina_or_sylvanas_POSintro"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_POSintro; + newscript->RegisterSelf(); + newscript = new Script; + newscript->Name="npc_jaina_or_sylvana_POSoutro"; + newscript->GetAI = &GetAI_npc_jaina_or_sylvanas_POSoutro; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/blood_prince_council.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/blood_prince_council.cpp index b2f817b..8fb3a3c 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/blood_prince_council.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/blood_prince_council.cpp @@ -16,9 +16,913 @@ /* ScriptData SDName: blood_prince_council -SD%Complete: 0% -SDComment: +SD%Complete: 90% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - +// Need implement true movement for kinetic bomb, correct yells. #include "precompiled.h" +#include "def_spire.h" + +enum BossSpells +{ + SPELL_BERSERK = 47008, + SPELL_FAKE_DEATH = 71598, + + //Darkfallen Orb + SPELL_INVOCATION_OF_BLOOD_V = 70952, // + SPELL_INVOCATION_OF_BLOOD_K = 70981, // + SPELL_INVOCATION_OF_BLOOD_T = 70982, // + SPELL_INVOCATION_OF_BLOOD_AURA = 70983, // Triggered, override + + //Valanar + SPELL_KINETIC_BOMB = 72053, + NPC_KINETIC_BOMB_TARGET = 38458, + NPC_KINETIC_BOMB = 38454, + SPELL_KINETIC_BOMB_EXPLODE = 72052, + SPELL_SHOCK_VORTEX = 72037, + NPC_SHOCK_VORTEX = 38422, + SPELL_SHOCK_VORTEX_AURA = 71945, + SPELL_SHOCK_VORTEX_2 = 72039, + + //Taldaram + SPELL_GLITTERING_SPARKS = 71807, + SPELL_CONJURE_FLAME_1 = 71718, + SPELL_SUMMON_FLAME_1 = 71719, //Dummy effect + NPC_BALL_OF_FLAMES_1 = 38332, + SPELL_CONJURE_FLAME_2 = 72040, + SPELL_SUMMON_FLAME_2 = 72041, //Dummy effect + NPC_BALL_OF_FLAMES_2 = 38451, + SPELL_FLAMES_AURA = 71709, + SPELL_FLAMES = 71393, + + //Keleseth + SPELL_SHADOW_LANCE = 71405, + SPELL_SHADOW_LANCE_2 = 71815, + SPELL_SHADOW_RESONANCE = 71943, + SPELL_SHADOW_RESONANCE_AURA = 71822, + NPC_DARK_NUCLEUS = 38369, + + // Blood orb + SPELL_BLOOD_ORB_STATE_VISUAL = 72100, + +}; + +struct MANGOS_DLL_DECL boss_valanar_iccAI : public BSWScriptedAI +{ + boss_valanar_iccAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + Creature* pBrother1; + Creature* pBrother2; + bool invocated; + + void Reset() + { + if(!m_pInstance) return; + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + resetTimers(); + invocated = false; + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631302,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631303,m_creature,pVictim); + break; + } + } + + void JustReachedHome() + { + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, FAIL); + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + DoScriptText(-1631304,m_creature,pKiller); + if (pBrother1 && pBrother2 && !pBrother1->isAlive() && !pBrother2->isAlive()) + { + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, DONE); + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pBrother1->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pBrother2->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + else m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) return; + pBrother1 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_TALDARAM)); + pBrother2 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_KELESETH)); + if (pBrother1 && !pBrother1->isAlive()) pBrother1->Respawn(); + if (pBrother2 && !pBrother2->isAlive()) pBrother2->Respawn(); + if (pBrother1) pBrother1->SetInCombatWithZone(); + if (pBrother2) pBrother2->SetInCombatWithZone(); + + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, IN_PROGRESS); + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + doCast(urand(0,1) ? SPELL_INVOCATION_OF_BLOOD_T : SPELL_INVOCATION_OF_BLOOD_K); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!m_pInstance) return; + if (!m_creature || !m_creature->isAlive()) + return; + + if(pDoneBy->GetGUID() == m_creature->GetGUID()) return; + + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetHealth() >= uiDamage ? m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH) - uiDamage : 0); + + uiDamage /=3; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_creature->GetHealth() > m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH)/3 && + m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH) != 0) + m_creature->SetHealth(m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH)/3); + + if (hasAura(SPELL_INVOCATION_OF_BLOOD_V)) + { + if (!invocated) + { + DoScriptText(-1631307,m_creature); + invocated = true; + } + if (timedQuery(SPELL_INVOCATION_OF_BLOOD_V, uiDiff)) + { + if (doCast(urand(0,1) ? SPELL_INVOCATION_OF_BLOOD_K : SPELL_INVOCATION_OF_BLOOD_T) == CAST_OK) + doRemove(SPELL_INVOCATION_OF_BLOOD_V); + } + timedCast(SPELL_KINETIC_BOMB, uiDiff); + timedCast(SPELL_SHOCK_VORTEX_2, uiDiff); + } else + { + invocated = false; + + timedCast(SPELL_KINETIC_BOMB, uiDiff); + timedCast(SPELL_SHOCK_VORTEX, uiDiff); + } + + if (timedQuery(SPELL_BERSERK, uiDiff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631305,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_valanar_icc(Creature* pCreature) +{ + return new boss_valanar_iccAI(pCreature); +} + +struct MANGOS_DLL_DECL boss_taldaram_iccAI : public BSWScriptedAI +{ + boss_taldaram_iccAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + Creature* pBrother1; + Creature* pBrother2; + bool invocated; + uint8 ballscount; + + + void Reset() { + if(!m_pInstance) return; + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + resetTimers(); + invocated = false; + ballscount = 0; + } + + void JustReachedHome() + { + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, FAIL); + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + if (pBrother1 && pBrother2 && !pBrother1->isAlive() && !pBrother2->isAlive()) + { + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, DONE); + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pBrother1->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pBrother2->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + else m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void KilledUnit(Unit* pVictim) + { + if (!m_pInstance) return; + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) return; + pBrother1 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_VALANAR)); + pBrother2 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_KELESETH)); + if (pBrother1 && !pBrother1->isAlive()) pBrother1->Respawn(); + if (pBrother2 && !pBrother2->isAlive()) pBrother2->Respawn(); + if (pBrother1) pBrother1->SetInCombatWithZone(); + if (pBrother2) pBrother2->SetInCombatWithZone(); + + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, IN_PROGRESS); + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!m_pInstance) return; + if (!m_creature || !m_creature->isAlive()) + return; + + if(pDoneBy->GetGUID() == m_creature->GetGUID()) return; + + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetHealth() >= uiDamage ? m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH) - uiDamage : 0); + + uiDamage /=3; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_creature->GetHealth() > m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH)/3 && + m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH) != 0) + m_creature->SetHealth(m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH)/3); + + if (hasAura(SPELL_INVOCATION_OF_BLOOD_T)) + { + if (!invocated) + { + DoScriptText(-1631307,m_creature); + invocated = true; + } + if (timedQuery(SPELL_INVOCATION_OF_BLOOD_T, uiDiff)) + { + if (doCast(urand(0,1) ? SPELL_INVOCATION_OF_BLOOD_V : SPELL_INVOCATION_OF_BLOOD_K) == CAST_OK) + doRemove(SPELL_INVOCATION_OF_BLOOD_T); + } + if (ballscount > 0 && !m_creature->IsNonMeleeSpellCasted(false)) + { + doCast(SPELL_SUMMON_FLAME_2); + --ballscount; + }; + timedCast(SPELL_GLITTERING_SPARKS, uiDiff); + if (timedCast(SPELL_CONJURE_FLAME_2, uiDiff) == CAST_OK) ballscount = 1; + } else + { + invocated = false; + if (ballscount > 0 && !m_creature->IsNonMeleeSpellCasted(false)) + { + doCast(SPELL_SUMMON_FLAME_1); + --ballscount; + }; + timedCast(SPELL_GLITTERING_SPARKS, uiDiff); + if (timedCast(SPELL_CONJURE_FLAME_1, uiDiff) == CAST_OK) ballscount = 1; + } + + + if (timedQuery(SPELL_BERSERK, uiDiff)){ + doCast(SPELL_BERSERK); + DoScriptText(-1631305,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_taldaram_icc(Creature* pCreature) +{ + return new boss_taldaram_iccAI(pCreature); +} + +struct MANGOS_DLL_DECL boss_keleseth_iccAI : public BSWScriptedAI +{ + boss_keleseth_iccAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + Creature* pBrother1; + Creature* pBrother2; + bool invocated; + + void Reset() + { + if(!m_pInstance) return; + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + resetTimers(); + invocated = false; + } + + void JustReachedHome() + { + if (!m_pInstance) return; + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, FAIL); + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) return; + if (pBrother1 && pBrother2 && !pBrother1->isAlive() && !pBrother2->isAlive()) + { + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, DONE); + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pBrother1->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pBrother2->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + else m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void KilledUnit(Unit* pVictim) + { + if (!m_pInstance) return; + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) return; + pBrother1 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_TALDARAM)); + pBrother2 = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_VALANAR)); + if (pBrother1 && !pBrother1->isAlive()) pBrother1->Respawn(); + if (pBrother2 && !pBrother2->isAlive()) pBrother2->Respawn(); + if (pBrother1) pBrother1->SetInCombatWithZone(); + if (pBrother2) pBrother2->SetInCombatWithZone(); + + m_pInstance->SetData(TYPE_BLOOD_COUNCIL, IN_PROGRESS); + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetMaxHealth()*3); + DoStartMovement(pWho, 30.0f); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!m_pInstance) return; + if (!m_creature || !m_creature->isAlive()) + return; + + if(pDoneBy->GetGUID() == m_creature->GetGUID()) return; + + m_pInstance->SetData(DATA_BLOOD_COUNCIL_HEALTH, m_creature->GetHealth() >= uiDamage ? m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH) - uiDamage : 0); + + uiDamage /=3; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_creature->GetHealth() > m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH)/3 && + m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH) != 0) + m_creature->SetHealth(m_pInstance->GetData(DATA_BLOOD_COUNCIL_HEALTH)/3); + + if (hasAura(SPELL_INVOCATION_OF_BLOOD_K)) + { + if (!invocated) + { + DoScriptText(-1631307,m_creature); + invocated = true; + }; + + if (timedQuery(SPELL_INVOCATION_OF_BLOOD_K, uiDiff)) + { + if (doCast(urand(0,1) ? SPELL_INVOCATION_OF_BLOOD_V : SPELL_INVOCATION_OF_BLOOD_T) == CAST_OK) + doRemove(SPELL_INVOCATION_OF_BLOOD_K); + } + + timedCast(SPELL_SHADOW_LANCE_2, uiDiff); + timedCast(SPELL_SHADOW_RESONANCE, uiDiff); + } else + { + invocated = false; + timedCast(SPELL_SHADOW_LANCE, uiDiff); + timedCast(SPELL_SHADOW_RESONANCE, uiDiff); + } + + + if (timedQuery(SPELL_BERSERK, uiDiff)){ + doCast(SPELL_BERSERK); + DoScriptText(-1631305,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_keleseth_icc(Creature* pCreature) +{ + return new boss_keleseth_iccAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_dark_nucleusAI : public ScriptedAI +{ + mob_dark_nucleusAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_lifetimer; + uint32 m_casttimer; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetInCombatWithZone(); + m_lifetimer = 180000; + m_casttimer = 2000; + } + + void Aggro(Unit* pWho) + { + if (!m_pInstance) return; + m_creature->SetSpeedRate(MOVE_RUN, 0.5); + SetCombatMovement(true); + DoStartMovement(pWho); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_BLOOD_COUNCIL) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_casttimer <= uiDiff) + { + if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOW_RESONANCE_AURA) == CAST_OK) + m_lifetimer -= 4000; + + m_casttimer = 2000; + } else m_casttimer -= uiDiff; + + if (m_lifetimer <= uiDiff) + m_creature->ForcedDespawn(); + else m_lifetimer -= uiDiff; + + } +}; + +CreatureAI* GetAI_mob_dark_nucleus(Creature* pCreature) +{ + return new mob_dark_nucleusAI (pCreature); +}; + +struct MANGOS_DLL_DECL mob_ball_of_flamesAI : public ScriptedAI +{ + mob_ball_of_flamesAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 grow_timer; + float fPosX, fPosY, fPosZ; + float m_Size; + float m_Size0; + bool finita; + bool movementstarted; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetInCombatWithZone(); + finita = false; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + SetCombatMovement(false); + m_creature->GetPosition(fPosX, fPosY, fPosZ); + m_creature->GetRandomPoint(fPosX, fPosY, fPosZ, urand(40, 60), fPosX, fPosY, fPosZ); + m_creature->GetMotionMaster()->MovePoint(1, fPosX, fPosY, fPosZ); + movementstarted = true; + m_Size0 = m_creature->GetObjectScale(); + m_Size = m_Size0; + grow_timer = 500; + + m_creature->SetDisplayId(26767); +// if (m_creature->GetEntry() == NPC_BALL_OF_FLAMES_2) + DoCast(m_creature, SPELL_FLAMES_AURA); + } + + void MovementInform(uint32 type, uint32 id) + { + if (!m_pInstance || type != POINT_MOTION_TYPE) return; + if (id != 1) + m_creature->GetMotionMaster()->MovePoint(1, fPosX, fPosY, fPosZ); + else movementstarted = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_BLOOD_COUNCIL) != IN_PROGRESS || finita) + m_creature->ForcedDespawn(); + + if (!movementstarted) + { + DoCast(m_creature, SPELL_FLAMES); + finita = true; + return; + } + + if (m_creature->GetEntry() == NPC_BALL_OF_FLAMES_2) + { + if (!m_creature->HasAura(SPELL_FLAMES_AURA)) + DoCast(m_creature, SPELL_FLAMES_AURA); + + + if (grow_timer <= uiDiff) + { + m_Size = m_Size*1.03; + m_creature->SetObjectScale(m_Size); + grow_timer = 500; + } else grow_timer -= uiDiff; + } else return; + + } +}; + +CreatureAI* GetAI_mob_ball_of_flames(Creature* pCreature) +{ + return new mob_ball_of_flamesAI (pCreature); +}; + +struct MANGOS_DLL_DECL mob_kinetic_bombAI : public ScriptedAI +{ + mob_kinetic_bombAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_lifetimer; + float fPosX0, fPosY0, fPosZ0; + float fPosX1, fPosY1, fPosZ1; + bool finita; + Creature *owner; + + void Reset() + { + owner = m_creature->GetMap()->GetCreature(m_creature->GetCreatorGuid()); + + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetInCombatWithZone(); + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + m_creature->SetSpeedRate(MOVE_RUN, 0.2f); + m_creature->SetSpeedRate(MOVE_WALK, 0.2f); + SetCombatMovement(false); + + m_lifetimer = 60000; +// m_creature->SetDisplayId(31095); + + m_creature->GetPosition(fPosX0, fPosY0, fPosZ0); + + if (!owner) return; + owner->GetPosition(fPosX1, fPosY1, fPosZ1); + + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(1, fPosX1, fPosY1, fPosZ1); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE) return; + if ( id ==1 ) + { + finita = true; + DoCast(m_creature, SPELL_KINETIC_BOMB_EXPLODE); + } + else m_creature->GetMotionMaster()->MovePoint(1, fPosX1, fPosY1, fPosZ1); + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + +/* +Place shock bomb movement here +*/ + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_BLOOD_COUNCIL) != IN_PROGRESS || finita) + m_creature->ForcedDespawn(); + + } +}; + +CreatureAI* GetAI_mob_kinetic_bomb(Creature* pCreature) +{ + return new mob_kinetic_bombAI (pCreature); +}; + +struct MANGOS_DLL_DECL mob_shock_vortexAI : public ScriptedAI +{ + mob_shock_vortexAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_lifetimer; + bool finita; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetInCombatWithZone(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_lifetimer = 8000; + SetCombatMovement(false); + DoCast(m_creature, SPELL_SHOCK_VORTEX_AURA); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_BLOOD_COUNCIL) != IN_PROGRESS || finita) + m_creature->ForcedDespawn(); + + if (!m_creature->HasAura(SPELL_SHOCK_VORTEX_AURA)) + DoCast(m_creature, SPELL_SHOCK_VORTEX_AURA); + + if (m_lifetimer <= uiDiff) + finita = true; + else m_lifetimer -= uiDiff; + + } +}; + +CreatureAI* GetAI_mob_shock_vortex(Creature* pCreature) +{ + return new mob_shock_vortexAI (pCreature); +}; + +struct MANGOS_DLL_DECL mob_kinetic_bomb_targetAI : public ScriptedAI +{ + mob_kinetic_bomb_targetAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + Creature* bomb; + ScriptedInstance* m_pInstance; + + void Reset() + { + m_creature->SetDisplayId(21342); + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + SetCombatMovement(false); + bomb = NULL; + } + + void SummonedCreatureJustDied(Creature* summoned) + { + if (!m_pInstance || !summoned) return; + + if (summoned == bomb) + m_creature->ForcedDespawn(); + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_BLOOD_COUNCIL) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!bomb) + bomb = m_creature->SummonCreature(NPC_KINETIC_BOMB,m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+50.0f,0,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,60000); + + } +}; + +CreatureAI* GetAI_mob_kinetic_bomb_target(Creature* pCreature) +{ + return new mob_kinetic_bomb_targetAI (pCreature); +}; + +struct MANGOS_DLL_DECL boss_blood_queen_lanathel_introAI : public BSWScriptedAI +{ + boss_blood_queen_lanathel_introAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint32 UpdateTimer; + + void Reset() + { + if(!pInstance) + return; + + if (pInstance->GetData(TYPE_BLOOD_COUNCIL) == IN_PROGRESS) + return; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (pInstance->GetData(TYPE_BLOOD_COUNCIL) == DONE) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_OFF); + } + else + { + if (Creature* pPrince = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_TALDARAM))) + doCast(SPELL_FAKE_DEATH,pPrince); + if (Creature* pPrince = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_KELESETH))) + doCast(SPELL_FAKE_DEATH,pPrince); + if (Creature* pPrince = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_VALANAR))) + doCast(SPELL_FAKE_DEATH,pPrince); + pInstance->SetData(TYPE_BLOOD_COUNCIL, NOT_STARTED); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_ON); + } + } + + void AttackStart(Unit *who) + { + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pInstance) + return; + + if (pInstance->GetData(TYPE_BLOOD_COUNCIL) != NOT_STARTED) + return; + + if (pWho && pWho->GetTypeId() == TYPEID_PLAYER && pWho->IsWithinDistInMap(m_creature, 50.0f)) + { + pInstance->SetData(TYPE_EVENT, 800); + pInstance->SetData(TYPE_BLOOD_COUNCIL,IN_PROGRESS); + } + } + + void UpdateAI(const uint32 diff) + { + + if (pInstance->GetData(TYPE_BLOOD_COUNCIL) == FAIL) + { + Reset(); + return; + } + + if (pInstance->GetData(TYPE_EVENT_NPC) == NPC_LANATHEL_INTRO) + { + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + if (UpdateTimer <= diff) + { + debug_log("EventMGR: creature %u received signal %u ",m_creature->GetEntry(),pInstance->GetData(TYPE_EVENT)); + switch (pInstance->GetData(TYPE_EVENT)) + { + case 800: + DoScriptText(-1631301, m_creature); + UpdateTimer = 15000; + pInstance->SetData(TYPE_EVENT,810); + break; + case 810: + DoScriptText(-1631311, m_creature); + if (Creature* pPrince = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_TALDARAM))) + { + doRemove(SPELL_FAKE_DEATH,pPrince); + } + if (Creature* pPrince = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_KELESETH))) + { + doRemove(SPELL_FAKE_DEATH,pPrince); + } + if (Creature* pPrince = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_VALANAR))) + { + doRemove(SPELL_FAKE_DEATH,pPrince); + } + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,820); + break; + case 820: + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetVisibility(VISIBILITY_OFF); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,830); + break; + default: + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + } + + } +}; + +CreatureAI* GetAI_boss_blood_queen_lanathel_intro(Creature* pCreature) +{ + return new boss_blood_queen_lanathel_introAI(pCreature); +} + +void AddSC_blood_prince_council() +{ + Script* newscript; + + newscript = new Script; + newscript->Name = "boss_taldaram_icc"; + newscript->GetAI = &GetAI_boss_taldaram_icc; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_keleseth_icc"; + newscript->GetAI = &GetAI_boss_keleseth_icc; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_valanar_icc"; + newscript->GetAI = &GetAI_boss_valanar_icc; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_nucleus"; + newscript->GetAI = &GetAI_mob_dark_nucleus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ball_of_flames"; + newscript->GetAI = &GetAI_mob_ball_of_flames; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_kinetic_bomb"; + newscript->GetAI = &GetAI_mob_kinetic_bomb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_shock_vortex"; + newscript->GetAI = &GetAI_mob_shock_vortex; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_kinetic_bomb_target"; + newscript->GetAI = &GetAI_mob_kinetic_bomb_target; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_blood_queen_lanathel_intro"; + newscript->GetAI = &GetAI_boss_blood_queen_lanathel_intro; + newscript->RegisterSelf(); + +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_blood_queen_lanathel.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_blood_queen_lanathel.cpp index ce11b79..867d6f2 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_blood_queen_lanathel.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_blood_queen_lanathel.cpp @@ -16,9 +16,425 @@ /* ScriptData SDName: boss_blood_queen_lanathel -SD%Complete: 0% -SDComment: +SD%Complete: 70% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - +// Need correct work of spells and timers #include "precompiled.h" +#include "def_spire.h" + +enum BossSpells +{ + SPELL_BERSERK = 47008, + SPELL_SHROUD_OF_SORROW = 72981, + SPELL_DELRIOUS_SLASH = 71623, + SPELL_BLOOD_MIRROR_1 = 70821, + SPELL_BLOOD_MIRROR_2 = 71510, + SPELL_VAMPIRIC_BITE = 71726, + SPELL_ESSENCE_OF_BLOOD_QWEEN = 70867, + SPELL_FRENZIED_BLOODTHIRST = 70877, + SPELL_UNCONTROLLABLE_FRENZY = 70923, + SPELL_PACT_OF_DARKFALLEN = 71340, + SPELL_PACT_OF_DARKFALLEN_1 = 71341, + SPELL_SWARMING_SHADOWS = 71264, + SPELL_TWILIGHT_BLOODBOLT = 71446, + SPELL_BLOODBOLT_WHIRL = 71772, + SPELL_PRESENCE_OF_DARKFALLEN = 71952, + + NPC_SWARMING_SHADOWS = 38163, + SPELL_SWARMING_SHADOWS_VISUAL = 71267, + QUEST_24756 = 72934, +}; + +static Locations SpawnLoc[]= +{ + {4595.640137f, 2769.195557f, 400.137054f}, // 0 Phased + {4595.904785f, 2769.315918f, 421.838623f}, // 1 Fly +}; + + +struct MANGOS_DLL_DECL boss_blood_queen_lanathelAI : public BSWScriptedAI +{ + boss_blood_queen_lanathelAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 stage; + uint8 nextPoint; + uint8 bloodbolts; + uint32 UpdateTimer; + bool movementstarted; + Unit* MirrorMarked; + Unit* MirrorTarget; + Unit* Darkfallen[5]; + uint8 darkfallened; + uint32 MirrorDamage; + + void Reset() + { + if(!pInstance) return; + if (m_creature->isAlive()) pInstance->SetData(TYPE_LANATHEL, NOT_STARTED); + stage = 0; + UpdateTimer = 1000; + bloodbolts = 0; + movementstarted = false; + MirrorMarked = NULL; + MirrorTarget = NULL; + resetTimers(); + memset(&Darkfallen, 0, sizeof(Darkfallen)); + darkfallened = 0; + MirrorDamage = 0; + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + } + + void JustReachedHome() + { + if (pInstance) pInstance->SetData(TYPE_LANATHEL, FAIL); + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631330,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631331,m_creature,pVictim); + break; + } + + if (pVictim && pVictim->HasAura(SPELL_BLOOD_MIRROR_1)) + doRemove(SPELL_BLOOD_MIRROR_1,pVictim); + + if (pVictim && pVictim->HasAura(SPELL_BLOOD_MIRROR_2)) + doRemove(SPELL_BLOOD_MIRROR_2,pVictim); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || !movementstarted) return; + if (id == nextPoint) + { + movementstarted = false; + m_creature->GetMotionMaster()->MovementExpired(); + } + } + + void StartMovement(uint32 id) + { + nextPoint = id; + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(id, SpawnLoc[id].x, SpawnLoc[id].y, SpawnLoc[id].z); + movementstarted = true; + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + pInstance->SetData(TYPE_LANATHEL, IN_PROGRESS); + + doCast(SPELL_SHROUD_OF_SORROW); + + DoScriptText(-1631321,m_creature,who); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return; + doBloodMirror(false); + pInstance->SetData(TYPE_LANATHEL, DONE); + DoScriptText(-1631333,m_creature,killer); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + for (uint8 i = 0; i < 5; ++i) + { + if (Unit* pPlayer = doSelectRandomPlayer(SPELL_ESSENCE_OF_BLOOD_QWEEN, true, 100.0f)) + { + doCast(QUEST_24756, pPlayer); + doRemove(SPELL_ESSENCE_OF_BLOOD_QWEEN, pPlayer); + } + } + } + + void doPactOfDarkfallen(bool command) + { + if (command) + { + uint8 num = urand(3,5); + for(uint8 i = 0; i <= num; ++i) + if (Unit* pTarget = doSelectRandomPlayer(SPELL_PACT_OF_DARKFALLEN, false, 60.0f)) + { + if (doCast(SPELL_PACT_OF_DARKFALLEN,pTarget) == CAST_OK) + { + Darkfallen[i] = pTarget; + ++darkfallened; + }; + }; + } + else if (darkfallened > 0) + { + for(uint8 i = 0; i < darkfallened; ++i) + if (Darkfallen[i]) + { + if (hasAura(SPELL_PACT_OF_DARKFALLEN,Darkfallen[i])) + { + for(uint8 j = 0; j < darkfallened; ++j) + if (j != i && Darkfallen[j]) + { + if(Darkfallen[j]) + { + if (hasAura(SPELL_PACT_OF_DARKFALLEN,Darkfallen[j])) + { + if (!Darkfallen[j]->IsWithinDistInMap(Darkfallen[i], 5.0f)) return; + } else Darkfallen[j] = NULL; + } + } + } else Darkfallen[i] = NULL; + } + for(uint8 i = 0; i < darkfallened; ++i) + if (hasAura(SPELL_PACT_OF_DARKFALLEN,Darkfallen[i])) + doRemove(SPELL_PACT_OF_DARKFALLEN, Darkfallen[i]); + darkfallened = 0; + }; + } + + void doBloodMirror(bool command) + { + if (command) + { + if (MirrorMarked) + if (!hasAura(SPELL_BLOOD_MIRROR_1,MirrorMarked)) + MirrorMarked = NULL; + + if (MirrorTarget) + if (!hasAura(SPELL_BLOOD_MIRROR_2,MirrorTarget)) + MirrorTarget = NULL; + + if (!MirrorMarked && m_creature->getVictim()) + { + MirrorMarked = m_creature->getVictim(); + if (MirrorMarked) + doCast(SPELL_BLOOD_MIRROR_1, MirrorMarked); + } + + if (!MirrorTarget) + { + MirrorTarget = doSelectRandomPlayer(SPELL_BLOOD_MIRROR_1, false, 40.0f); + if (MirrorTarget) + doCast(SPELL_BLOOD_MIRROR_2, MirrorTarget); + } + } else + { + if (MirrorMarked) + if (hasAura(SPELL_BLOOD_MIRROR_1,MirrorMarked)) + { + doRemove(SPELL_BLOOD_MIRROR_1, MirrorMarked); + MirrorMarked = NULL; + } + + if (MirrorTarget) + if (hasAura(SPELL_BLOOD_MIRROR_2,MirrorTarget)) + { + doRemove(SPELL_BLOOD_MIRROR_2, MirrorTarget); + MirrorTarget = NULL; + } + } + + } + + void doMirrorDamage() + { + uint32 tempdamage = MirrorDamage; + + if (MirrorTarget) + if (MirrorTarget->isAlive()) + m_creature->DealDamage(MirrorTarget, tempdamage, NULL, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, NULL, false); + MirrorDamage -= tempdamage; + } + + void DamageDeal(Unit* target, uint32 &damage) + { + if (target) + if (MirrorMarked) + if (MirrorMarked->isAlive()) + if (target == MirrorMarked) + MirrorDamage += damage; + } + + void UpdateAI(const uint32 diff) + { + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(stage) + { + case 0: + + timedCast(SPELL_SWARMING_SHADOWS, diff); + + if (timedQuery(SPELL_TWILIGHT_BLOODBOLT, diff)) bloodbolts = 1; + + if (timedQuery(SPELL_DELRIOUS_SLASH, diff)) + if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1)) + doCast(SPELL_DELRIOUS_SLASH, pTarget); + + if (timedQuery(SPELL_PACT_OF_DARKFALLEN, diff)) + doPactOfDarkfallen(true); + + timedCast(SPELL_SWARMING_SHADOWS, diff); + + if (timedQuery(SPELL_VAMPIRIC_BITE,diff)) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631322,m_creature); + break; + case 1: + DoScriptText(-1631323,m_creature); + break; + } + doCast(SPELL_VAMPIRIC_BITE); + } + + if (timedQuery(SPELL_BLOODBOLT_WHIRL,diff) && m_creature->GetHealthPercent() > 10.0f) + { + stage = 1; + }; + + doBloodMirror(true); + + DoMeleeAttackIfReady(); + + break; + case 1: // Go in fly phase + m_creature->AttackStop(); + SetCombatMovement(false); + StartMovement(1); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + doBloodMirror(false); + stage = 2; + break; + case 2: + if (movementstarted) return; + DoScriptText(-1631327,m_creature); + doCast(SPELL_BLOODBOLT_WHIRL); + stage = 3; + return; + case 3: + if (m_creature->IsNonMeleeSpellCasted(false)) + return; + if (timedQuery(SPELL_TWILIGHT_BLOODBOLT,diff) || m_creature->GetHealthPercent() < 10.0f) + { + stage = 4; +// DoScriptText(-1631325,m_creature); + bloodbolts = 3; + }; + break; + case 4: // Go in grownd phase + m_creature->AttackStop(); + StartMovement(0); + stage = 5; + break; + case 5: + if (movementstarted) return; + DoScriptText(-1631325,m_creature); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->RemoveSplineFlag(SPLINEFLAG_FLYING); + stage = 0; + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + return; + default: + break; + } + + doPactOfDarkfallen(false); + + doMirrorDamage(); + + if (bloodbolts > 0) + { + doCast(SPELL_TWILIGHT_BLOODBOLT); + --bloodbolts; + }; + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631332,m_creature); + }; + + } +}; + + +CreatureAI* GetAI_boss_blood_queen_lanathel(Creature* pCreature) +{ + return new boss_blood_queen_lanathelAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_swarming_shadowsAI : public ScriptedAI +{ + mob_swarming_shadowsAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_lifetimer; + + void Reset() + { + m_creature->SetDisplayId(11686); + m_creature->SetRespawnDelay(7*DAY); + SetCombatMovement(false); + m_creature->SetInCombatWithZone(); + m_lifetimer = 10000; + DoCast(m_creature, SPELL_SWARMING_SHADOWS_VISUAL); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_LANATHEL) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->HasAura(SPELL_SWARMING_SHADOWS_VISUAL)) + DoCast(m_creature, SPELL_SWARMING_SHADOWS_VISUAL); + + if (m_lifetimer <= uiDiff) + m_creature->ForcedDespawn(); + else m_lifetimer -= uiDiff; + + } +}; + +CreatureAI* GetAI_mob_swarming_shadows(Creature* pCreature) +{ + return new mob_swarming_shadowsAI (pCreature); +} + + +void AddSC_boss_blood_queen_lanathel() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_blood_queen_lanathel"; + newscript->GetAI = &GetAI_boss_blood_queen_lanathel; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_swarming_shadows"; + newscript->GetAI = &GetAI_mob_swarming_shadows; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_deathbringer_saurfang.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_deathbringer_saurfang.cpp index 2ebf1be..6467439 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_deathbringer_saurfang.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_deathbringer_saurfang.cpp @@ -16,9 +16,297 @@ /* ScriptData SDName: boss_deathbringer_saurfang -SD%Complete: 0% -SDComment: +SD%Complete: 75% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - #include "precompiled.h" +#include "def_spire.h" + +enum +{ + //common + SPELL_BERSERK = 47008, + //yells + //summons + NPC_BLOOD_BEASTS = 38508, + //Abilities + SPELL_BLOOD_LINK = 72178, + SPELL_BLOOD_POWER = 72371, + SPELL_MARK = 72293, + SPELL_MARK_SELF = 72256, + SPELL_FRENZY = 72737, + SPELL_BOILING_BLOOD = 72385, + SPELL_BLOOD_NOVA = 72380, + SPELL_RUNE_OF_BLOOD = 72408, + SPELL_CALL_BLOOD_BEAST_1 = 72172, + SPELL_CALL_BLOOD_BEAST_2 = 72173, + SPELL_CALL_BLOOD_BEAST_3 = 72356, + SPELL_CALL_BLOOD_BEAST_4 = 72357, + SPELL_CALL_BLOOD_BEAST_5 = 72358, + + SPELL_SCENT_OF_BLOOD = 72769, + SPELL_RESISTANT_SKIN = 72723, + SPELL_BLOOD_LINK_BEAST = 72176, + + SPELL_ZERO_REGEN = 72242, + +}; + +enum Equipment +{ + EQUIP_MAIN = 50798, + EQUIP_OFFHAND = 50798, + EQUIP_RANGED = EQUIP_NO_CHANGE, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; + +struct MANGOS_DLL_DECL boss_deathbringer_saurfangAI : public BSWScriptedAI +{ + boss_deathbringer_saurfangAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 beasts; + int32 oldPower; + + void Reset() + { + if(!pInstance) + return; + m_creature->SetRespawnDelay(7*DAY); + if (m_creature->isAlive()) + pInstance->SetData(TYPE_SAURFANG, NOT_STARTED); + setStage(0); + beasts = 0; + resetTimers(); + m_creature->SetPower(m_creature->getPowerType(), 0); + doCast(SPELL_ZERO_REGEN); + oldPower = 0; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pInstance) return; + + if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER) return; + + if (!m_creature->isInCombat() && pWho->IsWithinDistInMap(m_creature, 20.0f)) + { + m_creature->setFaction(21); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + AttackStart(pWho); + } + + ScriptedAI::MoveInLineOfSight(pWho); + } + + void Aggro(Unit *who) + { + if(!pInstance) + return; + + pInstance->SetData(TYPE_SAURFANG, IN_PROGRESS); + SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); + DoScriptText(-1631100,m_creature); + doCast(SPELL_BLOOD_LINK); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(TYPE_SAURFANG, FAIL); + } + + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) + { + case 0: + DoScriptText(-1631103,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631104,m_creature,pVictim); + break; + }; + } + + void JustSummoned(Creature* summoned) + { + if(!pInstance || !summoned) + return; + + summoned->SetOwnerGuid(m_creature->GetObjectGuid()); + + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0) ) + { + summoned->AddThreat(pTarget, 100.0f); + summoned->GetMotionMaster()->MoveChase(pTarget); + } + } + + void JustDied(Unit *killer) + { + if(!pInstance) + return; + pInstance->SetData(TYPE_SAURFANG, DONE); + DoScriptText(-1631106,m_creature); + doRemoveFromAll(SPELL_MARK); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (!m_creature->HasAura(SPELL_BLOOD_POWER)) + doCast(SPELL_BLOOD_POWER); + + if (!m_creature->HasAura(SPELL_BLOOD_LINK)) + doCast(SPELL_BLOOD_LINK); + + if (!m_creature->HasAura(SPELL_MARK_SELF)) + doCast(SPELL_MARK_SELF); + + switch(getStage()) + { + case 0: + if (m_creature->GetHealthPercent() <= 30.0f) setStage(1); + break; + + case 1: + doCast(SPELL_FRENZY); + setStage(2); + DoScriptText(-1631101,m_creature); + break; + + case 2: + break; + + default: + break; + } + + if (timedQuery(SPELL_MARK, diff)) + { + if (Unit* pTarget = doSelectRandomPlayer(SPELL_MARK,false,120.0f)) + doCast(SPELL_MARK, pTarget); + } + + timedCast(SPELL_BLOOD_NOVA, diff); + + timedCast(SPELL_BOILING_BLOOD, diff); + + timedCast(SPELL_RUNE_OF_BLOOD, diff); + + if (timedQuery(SPELL_CALL_BLOOD_BEAST_1, diff)) + { + beasts = getSpellData(SPELL_CALL_BLOOD_BEAST_1); + DoScriptText(-1631102,m_creature); + }; + + if (beasts > 0) + { + CanCastResult res = CAST_FAIL_OTHER; + switch (beasts) + { + case 1: res = doCast(SPELL_CALL_BLOOD_BEAST_1); break; + case 2: res = doCast(SPELL_CALL_BLOOD_BEAST_2); break; + case 3: res = doCast(SPELL_CALL_BLOOD_BEAST_3); break; + case 4: res = doCast(SPELL_CALL_BLOOD_BEAST_4); break; + case 5: res = doCast(SPELL_CALL_BLOOD_BEAST_5); break; + default: break; + }; + + if ( res == CAST_OK) + { + --beasts; + }; + }; + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631108,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_deathbringer_saurfang(Creature* pCreature) +{ + return new boss_deathbringer_saurfangAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_blood_beastAI : public BSWScriptedAI +{ + mob_blood_beastAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + Creature* pOwner; + bool scentcasted; + + void Reset() + { + pOwner = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_DEATHBRINGER_SAURFANG)); + resetTimers(); + scentcasted = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_SAURFANG) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (!m_creature->HasAura(SPELL_BLOOD_LINK_BEAST)) + doCast(SPELL_BLOOD_LINK_BEAST); + + if (!m_creature->HasAura(SPELL_RESISTANT_SKIN)) + doCast(SPELL_RESISTANT_SKIN); + + if (!scentcasted && (m_creature->GetHealthPercent() <= 20.0f)) + { + if (urand(0,1)) //50% + doCast(SPELL_SCENT_OF_BLOOD); + scentcasted = true; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_blood_beast(Creature* pCreature) +{ + return new mob_blood_beastAI(pCreature); +} + +void AddSC_boss_deathbringer_saurfang() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_deathbringer_saurfang"; + newscript->GetAI = &GetAI_boss_deathbringer_saurfang; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_blood_beast"; + newscript->GetAI = &GetAI_mob_blood_beast; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_festergut.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_festergut.cpp index 1156afd..ec4e05c 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_festergut.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_festergut.cpp @@ -16,9 +16,457 @@ /* ScriptData SDName: boss_festergut -SD%Complete: 0% -SDComment: +SD%Complete: 90% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - +// Need correct timers #include "precompiled.h" +#include "def_spire.h" + +enum BossSpells +{ + SPELL_GASEOUS_BLIGHT_1 = 69157, + SPELL_GASEOUS_BLIGHT_2 = 69162, + SPELL_GASEOUS_BLIGHT_3 = 69164, + SPELL_BLIGHT_VISUAL_1 = 69126, + SPELL_BLIGHT_VISUAL_2 = 69152, + SPELL_BLIGHT_VISUAL_3 = 69154, + SPELL_INHALE_BLIGHT = 69165, + SPELL_INHALED_BLIGHT = 69166, + SPELL_PUNGENT_BLIGHT = 69195, + SPELL_GAS_SPORE = 69278, + SPELL_SPORE_AURA_0 = 69279, + SPELL_SPORE_AURA_1 = 69290, + SPELL_INOCULATE = 69291, + SPELL_REMOVE_UNOCULATE = 69298, + SPELL_GASTRIC_BLOAT = 72219, + SPELL_GASTRIC_EXPLOSION = 72227, + SPELL_VILE_GAS = 72272, + SPELL_VILE_GAS_AURA = 69244, + SPELL_VILE_GAS_AURA_0 = 69248, + SPELL_BERSERK = 47008, + + SPELL_GASEOUS_SPIGOT = 71379, + + SPELL_SUMMON_VILE_STALKER = 72287, + + NPC_VILE_GAS_STALKER = 38548, + NPC_BLIGHT_STALKER = 36659, + NPC_PUDDLE_STALKER = 37013, + MAX_SPORE_TARGETS = 6, +}; + +static Locations SpawnLoc[]= +{ + {4267.9399f, 3137.32f, 360.385986f, 0.0f}, // 0 (start point) + {4317.067383f, 3136.99f, 360.385590f, 3.21f}, // 1 right + {4220.801758f, 3136.99f, 360.385590f, 0.39f}, // 2 left + {4269.084473f, 3186.306641f, 360.385590f, 4.72f}, // 3 rear +}; +struct MANGOS_DLL_DECL boss_festergutAI : public BSWScriptedAI +{ + boss_festergutAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + bool intro; + bool pet; + uint64 blightTargetGUID; +// uint64 pPuddleStalkerGUID[3]; + + void Reset() + { + if(!pInstance) return; + resetTimers(); + if (m_creature->isAlive()) + pInstance->SetData(TYPE_FESTERGUT, NOT_STARTED); + setStage(0); + intro = false; + pet = false; +/* for(uint8 i = 0; i < 3; ++i) + if (!pPuddleStalkerGUID[i]) + { + Unit* pTemp = doSummon(NPC_PUDDLE_STALKER,SpawnLoc[i].x, SpawnLoc[i].y, SpawnLoc[i].z, TEMPSUMMON_MANUAL_DESPAWN); + if (pTemp) + { + pPuddleStalkerGUID[i] = pTemp->GetGUID(); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + } +*/ + Creature* pBlightTarget = doSelectNearestCreature(NPC_BLIGHT_STALKER,60.0f); + if (pBlightTarget && !pBlightTarget->isAlive()) + pBlightTarget->Respawn(); + if (pBlightTarget) + { + blightTargetGUID = pBlightTarget->GetGUID(); + pBlightTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pBlightTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + doCast(SPELL_BLIGHT_VISUAL_1,pBlightTarget); + doCast(SPELL_BLIGHT_VISUAL_2,pBlightTarget); + doCast(SPELL_BLIGHT_VISUAL_3,pBlightTarget); + } + + } + + void MoveInLineOfSight(Unit* pWho) + { + ScriptedAI::MoveInLineOfSight(pWho); + if(!pInstance || intro) return; + if (pWho->GetTypeId() != TYPEID_PLAYER) return; + + pInstance->SetData(TYPE_EVENT, 500); + debug_log("EventMGR: creature %u send signal %u ",m_creature->GetEntry(),pInstance->GetData(TYPE_EVENT)); + intro = true; + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631204,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631205,m_creature,pVictim); + break; + } + } + + void JustReachedHome() + { + if (!pInstance) return; + pInstance->SetData(TYPE_FESTERGUT, FAIL); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_1); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_2); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_3); + if (Creature* pBlightTarget = m_creature->GetMap()->GetCreature(blightTargetGUID)) + { + doCast(SPELL_BLIGHT_VISUAL_1,pBlightTarget); + } + } + + void Aggro(Unit *pWho) + { + if(!pInstance) return; + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + + Creature* pBlightTarget = m_creature->GetMap()->GetCreature(blightTargetGUID); + + pInstance->SetData(TYPE_FESTERGUT, IN_PROGRESS); + DoScriptText(-1631203,m_creature,pWho); + if (pBlightTarget && !pBlightTarget->isAlive()) + pBlightTarget->Respawn(); + if (pBlightTarget) + { + pBlightTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pBlightTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + doRemove(SPELL_BLIGHT_VISUAL_1,pBlightTarget); + doRemove(SPELL_BLIGHT_VISUAL_2,pBlightTarget); + doRemove(SPELL_BLIGHT_VISUAL_3,pBlightTarget); + doCast(SPELL_BLIGHT_VISUAL_1,pBlightTarget); + } + doCast(SPELL_GASEOUS_BLIGHT_1); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_3); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_2); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_1); +/* for(uint8 i = 0; i < 3; ++i) + if (pPuddleStalkerGUID[i]) + doCast(SPELL_GASEOUS_SPIGOT, m_creature->GetMap()->GetCreature(pPuddleStalkerGUID[i])); +*/ + } + + void JustDied(Unit *killer) + { + if (!pInstance) return; + pInstance->SetData(TYPE_FESTERGUT, DONE); + pInstance->SetData(TYPE_EVENT, 550); + DoScriptText(-1631206,m_creature); + Creature* pBlightTarget = m_creature->GetMap()->GetCreature(blightTargetGUID); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_1); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_2); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_3); + if (pBlightTarget) + { + doCast(SPELL_BLIGHT_VISUAL_1,pBlightTarget); + } +/* for(uint8 i = 0; i < 3; ++i) + if (pPuddleStalkerGUID[i]) + { + Creature* pTemp = m_creature->GetMap()->GetCreature(pPuddleStalkerGUID[i]); + if (pTemp) pTemp->ForcedDespawn(); + pPuddleStalkerGUID[i] = NULL; + } +*/ + } + + void UpdateAI(const uint32 diff) + { + + if(!pInstance) return; + + if (!pet) + { + if (Creature* pGuard = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_STINKY))) + if (!pGuard->isAlive()) + { + pet = true; + if (pInstance->GetData(TYPE_STINKY) == NOT_STARTED) + { + DoScriptText(-1631209,m_creature); + pInstance->SetData(TYPE_STINKY,DONE); + } + } + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + Creature* pBlightTarget = m_creature->GetMap()->GetCreature(blightTargetGUID); + + switch(getStage()) + { + case 0: + if (timedQuery(SPELL_GASEOUS_BLIGHT_2, diff)) + setStage(1); + break; + case 1: + switch (urand(0,2)) + { + case 0: DoScriptText(-1631210,m_creature); break; + case 1: DoScriptText(-1631211,m_creature); break; + case 2: DoScriptText(-1631212,m_creature); break; + } + doCast(SPELL_INHALE_BLIGHT); + setStage(2); + break; + case 2: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + if (pBlightTarget) + { + doRemove(SPELL_GASEOUS_BLIGHT_1); + doRemove(SPELL_BLIGHT_VISUAL_1,pBlightTarget); + doRemove(SPELL_BLIGHT_VISUAL_1,m_creature); + doCast(SPELL_GASEOUS_BLIGHT_2); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_3); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_2); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_1); + } + setStage(3); + break; + case 3: + if (timedQuery(SPELL_GASEOUS_BLIGHT_3, diff)) + setStage(4); + break; + case 4: + switch (urand(0,2)) + { + case 0: DoScriptText(-1631210,m_creature); break; + case 1: DoScriptText(-1631211,m_creature); break; + case 2: DoScriptText(-1631212,m_creature); break; + } + doCast(SPELL_INHALE_BLIGHT); + setStage(5); + break; + case 5: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + if (pBlightTarget) + { + doRemove(SPELL_GASEOUS_BLIGHT_2); + doRemove(SPELL_BLIGHT_VISUAL_2,pBlightTarget); + doRemove(SPELL_BLIGHT_VISUAL_2,m_creature); + doCast(SPELL_GASEOUS_BLIGHT_3); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_3); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_2); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_1); + } + setStage(6); + break; + case 6: + if (timedQuery(SPELL_GASEOUS_BLIGHT_3, diff)) + setStage(7); + break; + case 7: + switch (urand(0,2)) + { + case 0: DoScriptText(-1631210,m_creature); break; + case 1: DoScriptText(-1631211,m_creature); break; + case 2: DoScriptText(-1631212,m_creature); break; + } + doCast(SPELL_INHALE_BLIGHT); + setStage(8); + break; + case 8: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + if (pBlightTarget) + { + doRemove(SPELL_GASEOUS_BLIGHT_3); + doRemove(SPELL_BLIGHT_VISUAL_3,pBlightTarget); + doRemove(SPELL_BLIGHT_VISUAL_3,m_creature); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_3); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_2); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_1); + } + setStage(9); + break; + case 9: + if (timedQuery(SPELL_PUNGENT_BLIGHT, diff)) + { + DoScriptText(-1631208,m_creature); + doCast(SPELL_PUNGENT_BLIGHT); + setStage(10); + } + break; + case 10: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + if (pBlightTarget) + { + doCast(SPELL_BLIGHT_VISUAL_1,pBlightTarget); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_3); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_2); + doRemoveFromAll(SPELL_BLIGHT_VISUAL_1); + } + m_creature->RemoveAurasDueToSpell(SPELL_INHALED_BLIGHT); + setStage(0); + break; + } + + + timedCast(SPELL_GAS_SPORE, diff); + + timedCast(SPELL_GASTRIC_BLOAT, diff); + + if (auraCount(SPELL_GASTRIC_BLOAT,m_creature->getVictim(),EFFECT_INDEX_1) > 9) + { + m_creature->getVictim()->RemoveAurasDueToSpell(SPELL_GASTRIC_BLOAT); + doCast(SPELL_GASTRIC_EXPLOSION,m_creature->getVictim()); + }; + + if (timedQuery(SPELL_VILE_GAS, diff)) + { + float fPosX, fPosY, fPosZ; + m_creature->GetPosition(fPosX, fPosY, fPosZ); + m_creature->GetRandomPoint(fPosX, fPosY, fPosZ, 30.0f, fPosX, fPosY, fPosZ); + if (Unit* pTemp = doSummon(NPC_VILE_GAS_STALKER,fPosX, fPosY, fPosZ)) + doCast(SPELL_VILE_GAS, pTemp); + DoScriptText(-1631213,m_creature); + }; + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631207,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_boss_festergut(Creature* pCreature) +{ + return new boss_festergutAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_vile_gas_stalkerAI : public ScriptedAI +{ + mob_vile_gas_stalkerAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint32 m_lifetimer; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWithZone(); + SetCombatMovement(false); + m_creature->SetDisplayId(11686); + m_lifetimer = 12000; + } + + void AttackStart(Unit *pWho) + { + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_FESTERGUT) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_lifetimer <= uiDiff) + m_creature->ForcedDespawn(); + else m_lifetimer -= uiDiff; + + } +}; + +CreatureAI* GetAI_mob_vile_gas_stalker(Creature* pCreature) +{ + return new mob_vile_gas_stalkerAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_orange_gas_stalkerAI : public ScriptedAI +{ + mob_orange_gas_stalkerAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + m_creature->SetDisplayId(11686); + } + + void AttackStart(Unit *pWho) + { + } + + void UpdateAI(const uint32 uiDiff) + { +// if (!pInstance || pInstance->GetData(TYPE_FESTERGUT) != IN_PROGRESS) +// m_creature->ForcedDespawn(); + } +}; + +CreatureAI* GetAI_mob_orange_gas_stalker(Creature* pCreature) +{ + return new mob_orange_gas_stalkerAI(pCreature); +} + +void AddSC_boss_festergut() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_festergut"; + newscript->GetAI = &GetAI_boss_festergut; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vile_gas_stalker"; + newscript->GetAI = &GetAI_mob_vile_gas_stalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_orange_gas_stalker"; + newscript->GetAI = &GetAI_mob_orange_gas_stalker; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lady_deathwhisper.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lady_deathwhisper.cpp index 8df083c..2628640 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lady_deathwhisper.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lady_deathwhisper.cpp @@ -16,9 +16,520 @@ /* ScriptData SDName: boss_lady_deathwhisper -SD%Complete: 0% -SDComment: +SD%Complete: 80% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - +// Need correct spells on adds and timers #include "precompiled.h" +#include "def_spire.h" +enum BossSpells +{ + //common + SPELL_BERSERK = 47008, + //yells + //summons + NPC_VENGEFUL_SHADE = 38222, + NPC_FANATIC = 37890, + NPC_REANIMATED_FANATIC = 38009, + NPC_ADHERENT = 37949, + NPC_REANIMATED_ADHERENT = 38010, + //Abilities + SPELL_MANA_BARRIER = 70842, + SPELL_SHADOW_BOLT = 71254, + SPELL_DEATH_AND_DECAY = 71001, + SPELL_DARK_EMPOWERMENT = 70901, + SPELL_FROSTBOLT = 71420, + SPELL_INSIGNIFICANCE = 71204, + + SPELL_DOMINATE_MIND = 71289, + + SPELL_VENGEFUL_BLAST = 71494, + SPELL_VENGEFUL_BLAST_0 = 71544, + // summons + SPELL_FROST_FEVER = 71129, + SPELL_DEATHCHILL_BOLT = 70594, + SPELL_DEATHCHILL_BLAST = 70906, + SPELL_DARK_MARTYRDROM = 70903, + SPELL_CURSE_OF_TOPOR = 71237, + SPELL_SHORUD_OF_THE_OCCULUT = 70768, + SPELL_ADHERENTS_DETERMINIATION = 71234, + SPELL_SUMMON_VISUAL = 41236, + + SPELL_NECROTIC_STRIKE = 70659, + SPELL_SHADOW_CLEAVE = 70670, + SPELL_VAMPIRIC_MIGHT = 70674, +}; + +static Locations SpawnLoc[]= +{ + {-623.055481f, 2211.326660f, 51.764259f}, // 0 Lady's stay point + {-620.197449f, 2272.062256f, 50.848679f}, // 1 Right Door 1 + {-598.636353f, 2272.062256f, 50.848679f}, // 2 Right Door 2 + {-578.495728f, 2272.062256f, 50.848679f}, // 3 Right Door 3 + {-578.495728f, 2149.211182f, 50.848679f}, // 4 Left Door 1 + {-598.636353f, 2149.211182f, 50.848679f}, // 5 Left Door 2 + {-620.197449f, 2149.211182f, 50.848679f}, // 6 Left Door 3 + {-517.652466f, 2216.611328f, 62.823681f}, // 7 Upper marsh 1 + {-517.652466f, 2211.611328f, 62.823681f}, // 8 Upper marsh 2 + {-517.652466f, 2206.611328f, 62.823681f}, // 9 Upper marsh 3 +}; + +struct MANGOS_DLL_DECL boss_lady_deathwhisperAI : public BSWScriptedAI +{ + boss_lady_deathwhisperAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 stage; + bool MovementStarted; + bool intro; + + void Reset() + { + if(!pInstance) return; + if (m_creature->isAlive()) pInstance->SetData(TYPE_DEATHWHISPER, NOT_STARTED); + stage = 0; + MovementStarted = false; + intro = false; + resetTimers(); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (m_creature->CanInitiateAttack() && pWho->isTargetableForAttack() && + m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature)) + { + if (m_creature->IsWithinDistInMap(pWho, m_creature->GetAttackDistance(pWho)) && m_creature->IsWithinLOSInMap(pWho)) + { + if (!m_creature->getVictim()) + { + pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH); + AttackStart(pWho); + } + else if (m_creature->GetMap()->IsDungeon()) + { + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho); + } + } + } + if (stage) return; + else intro = true; + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631029,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631030,m_creature,pVictim); + break; + }; + } + + void JustReachedHome() + { + if (pInstance) pInstance->SetData(TYPE_DEATHWHISPER, FAIL); + } + + void MovementInform(uint32 type, uint32 id) + { + if(!pInstance) return; + if(type != POINT_MOTION_TYPE) return; + if(MovementStarted && id != 1) + { + m_creature->GetMotionMaster()->MovePoint(1, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z); + } + else { + m_creature->GetMotionMaster()->MovementExpired(); + MovementStarted = false; + SetCombatMovement(false); + } + } + + void Aggro(Unit *who) + { + if(pInstance) pInstance->SetData(TYPE_DEATHWHISPER, IN_PROGRESS); + doCast(SPELL_MANA_BARRIER ); + MovementStarted = true; + SetCombatMovement(false); + DoScriptText(-1631023,m_creature); + m_creature->GetMotionMaster()->MovePoint(1, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z); + } + + void JustDied(Unit *killer) + { + if(pInstance) pInstance->SetData(TYPE_DEATHWHISPER, DONE); + DoScriptText(-1631032,m_creature,killer); + } + + void JustSummoned(Creature* summoned) + { + if(!pInstance || !summoned) return; + + if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0) ) { + summoned->AddThreat(pTarget, 100.0f); + } + } + + void CallGuard(uint8 place) + { + if (place < 2) + { + doSummon(urand(0,1) ? NPC_FANATIC : NPC_ADHERENT, SpawnLoc[3*place+1].x, SpawnLoc[3*place+1].y, SpawnLoc[3*place+1].z); + doSummon(urand(0,1) ? NPC_FANATIC : NPC_ADHERENT, SpawnLoc[3*place+3].x, SpawnLoc[3*place+3].y, SpawnLoc[3*place+3].z); + } + doSummon(urand(0,1) ? NPC_FANATIC : NPC_ADHERENT, SpawnLoc[3*place+2].x, SpawnLoc[3*place+2].y, SpawnLoc[3*place+2].z); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!m_creature || !m_creature->isAlive()) + return; + + if (hasAura(SPELL_MANA_BARRIER, m_creature)) { + if (m_creature->GetPower(POWER_MANA) > uiDamage) { + m_creature->SetPower(POWER_MANA,m_creature->GetPower(POWER_MANA)-uiDamage); + uiDamage = 0; + } + else { + m_creature->SetPower(POWER_MANA,0); + doRemove(SPELL_MANA_BARRIER); + }; + } else return; + } + + void UpdateAI(const uint32 diff) + { + if (intro && timedQuery(SPELL_SHADOW_BOLT,diff)) + switch (stage) { + case 0: + DoScriptText(-1631020,m_creature); + stage = 1; + break; + case 1: + DoScriptText(-1631021,m_creature); + stage = 2; + break; + case 2: + DoScriptText(-1631022,m_creature); + stage = 3; + break; + default: + break; + } + + if (hasAura(SPELL_MANA_BARRIER, m_creature)) { + if(m_creature->GetHealth() <= m_creature->GetMaxHealth()) { + if (m_creature->GetPower(POWER_MANA) > (m_creature->GetMaxHealth() - m_creature->GetHealth())) + { + m_creature->SetPower(POWER_MANA,m_creature->GetPower(POWER_MANA)-(m_creature->GetMaxHealth() - m_creature->GetHealth())); + m_creature->SetHealth(m_creature->GetMaxHealth()); + } + else m_creature->SetPower(POWER_MANA,0); + } + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (MovementStarted) return; + + switch(stage) + { + case 3: { + if (IsCombatMovement()) + SetCombatMovement(false); + + timedCast(SPELL_SHADOW_BOLT,diff); + + if (timedQuery(NPC_FANATIC, diff)) + { + DoScriptText(-1631028,m_creature); + switch (currentDifficulty) { + case RAID_DIFFICULTY_10MAN_NORMAL: + CallGuard(urand(0,1)); + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + CallGuard(urand(0,1)); + if (urand(0,1)) CallGuard(2); + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + CallGuard(0); + CallGuard(1); + if (urand(0,1)) CallGuard(2); + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + CallGuard(0); + CallGuard(1); + CallGuard(2); + break; + default: + break; + + } + } + + if (timedQuery(SPELL_DARK_EMPOWERMENT ,diff)) + { + switch (urand(0,1)) { + case 0: + if(Creature *pGuard = GetClosestCreatureWithEntry(m_creature, NPC_FANATIC, 100.0f)) + { + doCast(SPELL_DARK_EMPOWERMENT, pGuard); + DoScriptText(-1631026,m_creature); + }; + break; + case 1: + if(Creature *pGuard = GetClosestCreatureWithEntry(m_creature, NPC_ADHERENT, 100.0f)) + { + doCast(SPELL_DARK_EMPOWERMENT, pGuard); + DoScriptText(-1631027,m_creature); + }; + break; + } + } + + break;} + + case 4: { + timedCast(SPELL_FROSTBOLT, diff); + + timedCast(SPELL_INSIGNIFICANCE, diff); + + timedCast(NPC_VENGEFUL_SHADE, diff); + + if (is25()) timedCast(SPELL_DOMINATE_MIND, diff); + + if (timedQuery(NPC_FANATIC, diff)) + { + switch (currentDifficulty) { + case RAID_DIFFICULTY_10MAN_HEROIC: + CallGuard(urand(0,1)); + if (urand(0,1)) CallGuard(2); + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + CallGuard(0); + CallGuard(1); + CallGuard(2); + break; + default: + break; + + } + } + + break;} + } + + timedCast(SPELL_DEATH_AND_DECAY, diff); + + + if (!hasAura(SPELL_MANA_BARRIER, m_creature) && stage == 3) + { + stage = 4; + DoScriptText(-1631024,m_creature); + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631031,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_lady_deathwhisper(Creature* pCreature) +{ + return new boss_lady_deathwhisperAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_vengeful_shadeAI : public BSWScriptedAI +{ + mob_vengeful_shadeAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance *m_pInstance; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetInCombatWithZone(); + if (Unit* pTarget= m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0) ) { + m_creature->AddThreat(pTarget, 1000.0f); + m_creature->GetMotionMaster()->MoveChase(pTarget); + m_creature->SetSpeedRate(MOVE_RUN, 0.5); + } + doCast(SPELL_VENGEFUL_BLAST); + } + + + void UpdateAI(const uint32 uiDiff) + { + if(m_pInstance && m_pInstance->GetData(TYPE_DEATHWHISPER) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (timedQuery(SPELL_VENGEFUL_BLAST_0, uiDiff)) + { + if (m_creature->IsWithinDist(m_creature->getVictim(), 1.0f, false)) + { + doCast(SPELL_VENGEFUL_BLAST_0); + m_creature->ForcedDespawn(); + } + else + { + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->SetSpeedRate(MOVE_RUN, 0.5); + } + } + } + +}; + +CreatureAI* GetAI_mob_vengeful_shade(Creature* pCreature) +{ + return new mob_vengeful_shadeAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_cult_adherentAI : public BSWScriptedAI +{ + mob_cult_adherentAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + bool bone; + + void Reset() + { + resetTimers(); + m_creature->SetRespawnDelay(DAY); + doCast(SPELL_SUMMON_VISUAL); + bone = false; + } + + void Aggro(Unit *who) + { + doCast(SPELL_SHORUD_OF_THE_OCCULUT); + DoStartMovement(who, 20.0f); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_DEATHWHISPER) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_FROST_FEVER, uiDiff); + + timedCast(SPELL_DEATHCHILL_BOLT, uiDiff); + + timedCast( SPELL_DEATHCHILL_BLAST, uiDiff); + + if (m_creature->GetHealthPercent() < 15.0f && !bone) + { + if (!urand(0,3)) doCast(SPELL_DARK_MARTYRDROM); //30% + bone = true; + } + } +}; + +CreatureAI* GetAI_mob_cult_adherent(Creature* pCreature) +{ + return new mob_cult_adherentAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_cult_fanaticAI : public BSWScriptedAI +{ + mob_cult_fanaticAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + bool bone; + + void Reset() + { + resetTimers(); + m_creature->SetRespawnDelay(DAY); + bone = false; + } + + void Aggro(Unit *who) + { + doCast(SPELL_VAMPIRIC_MIGHT); + DoStartMovement(who); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_DEATHWHISPER) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_NECROTIC_STRIKE, uiDiff); + + timedCast(SPELL_SHADOW_CLEAVE, uiDiff); + + if (m_creature->GetHealthPercent() < 15.0f && !bone) + { + if (!urand(0,3)) doCast(SPELL_DARK_MARTYRDROM); //30% + bone = true; + } + } +}; + +CreatureAI* GetAI_mob_cult_fanatic(Creature* pCreature) +{ + return new mob_cult_fanaticAI(pCreature); +} + +void AddSC_boss_lady_deathwhisper() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lady_deathwhisper"; + newscript->GetAI = &GetAI_boss_lady_deathwhisper; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vengeful_shade"; + newscript->GetAI = &GetAI_mob_vengeful_shade; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_cult_adherent"; + newscript->GetAI = &GetAI_mob_cult_adherent; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_cult_fanatic"; + newscript->GetAI = &GetAI_mob_cult_fanatic; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lord_marrowgar.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lord_marrowgar.cpp index 1bd579d..8f3e2a8 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lord_marrowgar.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_lord_marrowgar.cpp @@ -16,9 +16,417 @@ /* ScriptData SDName: boss_lord_marrowgar -SD%Complete: 0% -SDComment: +SD%Complete: 85% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - #include "precompiled.h" +#include "def_spire.h" +enum +{ + //common + SPELL_BERSERK = 47008, + //yells + //summons + NPC_BONE_SPIKE = 38711, + NPC_COLD_FLAME = 36672, + //Abilities + SPELL_SABER_LASH = 71021, + SPELL_CALL_COLD_FLAME = 69138, + SPELL_CALL_COLD_FLAME_1 = 71580, + SPELL_COLD_FLAME = 69146, + SPELL_COLD_FLAME_0 = 69145, + SPELL_COLD_FLAME_1 = 69147, + SPELL_BONE_STRIKE = 69057, + SPELL_BONE_STORM = 69076, + SPELL_BONE_STRIKE_IMPALE = 69065, + SPELL_VEHICLE_HARDCODED = 46598, + SPELL_BONE_STORM_STRIKE = 69075, +}; + +struct MANGOS_DLL_DECL boss_lord_marrowgarAI : public BSWScriptedAI +{ + boss_lord_marrowgarAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + bool intro; + + void Reset() + { + if (!pInstance) return; + if (m_creature->isAlive()) pInstance->SetData(TYPE_MARROWGAR, NOT_STARTED); + resetTimers(); + m_creature->SetSpeedRate(MOVE_RUN, 1); + m_creature->SetSpeedRate(MOVE_WALK, 1); +// m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + + void MoveInLineOfSight(Unit* pWho) + { + ScriptedAI::MoveInLineOfSight(pWho); + if (intro) return; + DoScriptText(-1631000,m_creature); + intro = true; + } + + void JustSummoned(Creature* summoned) + { + if(!pInstance || !summoned) return; + summoned->SetCreatorGuid(m_creature->GetObjectGuid()); + } + + void JustReachedHome() + { + if (pInstance) pInstance->SetData(TYPE_MARROWGAR, FAIL); + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + pInstance->SetData(TYPE_MARROWGAR, IN_PROGRESS); + DoScriptText(-1631001,m_creature); + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631006,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631007,m_creature,pVictim); + break; + }; + } + + void JustDied(Unit *killer) + { + if(pInstance) pInstance->SetData(TYPE_MARROWGAR, DONE); + DoScriptText(-1631009,m_creature); + } + + void doSummonSpike(Unit* pTarget) + { + if (!pTarget || !pTarget->isAlive()) return; + float fPosX, fPosY, fPosZ; + pTarget->GetPosition(fPosX, fPosY, fPosZ); + if (Unit* pSpike = doSummon(NPC_BONE_SPIKE, fPosX, fPosY, fPosZ + 0.5f)) + { + pSpike->SetOwnerGuid(m_creature->GetObjectGuid()); + pSpike->SetInCombatWith(pTarget); + pSpike->AddThreat(pTarget, 1000.0f); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(getStage()) + { + case 0: + if (timedQuery(SPELL_BONE_STRIKE, diff)) + if (Unit* pTarget = doSelectRandomPlayer(SPELL_BONE_STRIKE_IMPALE, false, 60.0f)) + if (doCast(SPELL_BONE_STRIKE, pTarget) == CAST_OK) + { + doSummonSpike(pTarget); + switch (urand(0,1)) { + case 0: + DoScriptText(-1631003,m_creature,pTarget); + break; + case 1: + DoScriptText(-1631004,m_creature,pTarget); + break; + case 2: + DoScriptText(-1631005,m_creature,pTarget); + break; + }; + + }; + + if (timedQuery(SPELL_BONE_STORM, diff)) setStage(1); + + if (timedQuery(SPELL_CALL_COLD_FLAME, diff)) + { + if (urand(0,1)) doCast(SPELL_CALL_COLD_FLAME); + else doCast(SPELL_CALL_COLD_FLAME_1); + + if (m_creature->GetHealthPercent() <= 30.0f) + { + if (urand(0,1)) doCast(SPELL_CALL_COLD_FLAME); + else doCast(SPELL_CALL_COLD_FLAME_1); + } + } + + timedCast(SPELL_SABER_LASH, diff); + + DoMeleeAttackIfReady(); + + break; + case 1: + m_creature->InterruptNonMeleeSpells(true); + doCast(SPELL_BONE_STORM); + setStage(2); + DoScriptText(-1631002,m_creature); + DoResetThreat(); + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSpeedRate(MOVE_RUN, 3); + m_creature->SetSpeedRate(MOVE_WALK, 3); + break; + case 2: + if (!m_creature->IsNonMeleeSpellCasted(false)) setStage(3); + break; + case 3: + if (isHeroic()) + if (timedQuery(SPELL_BONE_STRIKE, diff, true)) + if (Unit* pTarget = doSelectRandomPlayer(SPELL_BONE_STRIKE_IMPALE, false, 60.0f)) + doSummonSpike(pTarget); + + if (timedQuery(SPELL_CALL_COLD_FLAME, diff, true) + && m_creature->IsWithinDistInMap(m_creature->getVictim(),2.0f)) + { + pInstance->SetData(DATA_DIRECTION, (uint32)(1000*2.0f*M_PI_F*((float)urand(1,16)/16.0f))); +// if (urand(0,1)) doCast(SPELL_CALL_COLD_FLAME); +// else doCast(SPELL_CALL_COLD_FLAME_1); + float fPosX, fPosY, fPosZ; + m_creature->GetPosition(fPosX, fPosY, fPosZ); + doSummon(NPC_COLD_FLAME, fPosX, fPosY, fPosZ); + DoResetThreat(); + if (Unit* pTarget = doSelectRandomPlayerAtRange(60.0f)) + AttackStart(pTarget); + } + if (!hasAura(SPELL_BONE_STORM_STRIKE, m_creature) && !hasAura(SPELL_BONE_STORM, m_creature)) setStage(4); + break; + case 4: + pInstance->SetData(DATA_DIRECTION, 0); + m_creature->SetSpeedRate(MOVE_RUN, 1); + m_creature->SetSpeedRate(MOVE_WALK, 1); +// m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + setStage(0); + break; + default: + break; + } + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631008,m_creature); + } + + + } +}; + +struct MANGOS_DLL_DECL mob_coldflameAI : public BSWScriptedAI +{ + mob_coldflameAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool isFirst; + bool isXmode; + float m_direction; + float x, y, radius; + bool isCreator; + + void Reset() + { + if(!m_pInstance) return; +// m_creature->SetDisplayId(10045); + m_creature->SetRespawnDelay(7*DAY); + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + setStage(0); + isCreator = false; + + SetCombatMovement(false); + doCast(SPELL_COLD_FLAME_0); + } + + void AttackStart(Unit *who) + { + } + + void JustSummoned(Creature* summoned) + { + if(!m_pInstance || !summoned) return; + summoned->SetCreatorGuid(m_creature->GetObjectGuid()); + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_pInstance && m_pInstance->GetData(TYPE_MARROWGAR) != IN_PROGRESS) + { + m_creature->ForcedDespawn(); + } + + if (m_creature->GetCreatorGuid().IsEmpty()) return; + + if (!isCreator) + { + if (m_creature->GetCreatorGuid() == m_pInstance->GetData64(NPC_LORD_MARROWGAR)) + { + isFirst = true; + uint32 m_tmpDirection = m_pInstance->GetData(DATA_DIRECTION); + m_pInstance->SetData(DATA_DIRECTION,0); + if (m_tmpDirection) + { + m_direction = m_tmpDirection/1000.0f; + isXmode = true; + } + else + { + m_direction = 2.0f*M_PI_F*((float)urand(1,16)/16.0f); + isXmode = false; + } + } else isFirst = false; + isCreator = true; + } + + if (timedQuery(SPELL_COLD_FLAME_0, uiDiff) && !isFirst) + m_creature->ForcedDespawn(); + + if (isFirst && timedQuery(SPELL_COLD_FLAME_1, uiDiff, true)) + { + if (getStage() < getSpellData(SPELL_COLD_FLAME_0)) + { + setStage(getStage()+1); + radius = getStage()*5; + m_creature->GetNearPoint2D(x, y, radius, m_direction); + doSummon(NPC_COLD_FLAME, x, y, m_creature->GetPositionZ(), TEMPSUMMON_TIMED_DESPAWN, getSpellData(SPELL_COLD_FLAME_1)); + if (isXmode) + { + m_creature->GetNearPoint2D(x, y, radius, m_direction+M_PI_F/2); + doSummon(NPC_COLD_FLAME, x, y, m_creature->GetPositionZ(), TEMPSUMMON_TIMED_DESPAWN, getSpellData(SPELL_COLD_FLAME_1)); + m_creature->GetNearPoint2D(x, y, radius, m_direction+M_PI_F); + doSummon(NPC_COLD_FLAME, x, y, m_creature->GetPositionZ(), TEMPSUMMON_TIMED_DESPAWN, getSpellData(SPELL_COLD_FLAME_1)); + m_creature->GetNearPoint2D(x, y, radius, m_direction+M_PI_F*1.5f); + doSummon(NPC_COLD_FLAME, x, y, m_creature->GetPositionZ(), TEMPSUMMON_TIMED_DESPAWN, getSpellData(SPELL_COLD_FLAME_1)); + } + } else m_creature->ForcedDespawn(); + } else timedCast(SPELL_COLD_FLAME, uiDiff); + + } +}; + +struct MANGOS_DLL_DECL mob_bone_spikeAI : public BSWScriptedAI +{ + mob_bone_spikeAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance* m_pInstance; + ObjectGuid victimGuid; + + void Reset() + { + SetCombatMovement(false); + m_creature->SetRespawnDelay(7*DAY); + victimGuid = ObjectGuid(); + m_creature->SetInCombatWithZone(); + } + + void Aggro(Unit* pWho) + { + if (victimGuid.IsEmpty() && pWho && pWho->GetTypeId() == TYPEID_PLAYER) + { + victimGuid = pWho->GetObjectGuid(); + m_creature->SetInCombatWith(pWho); + doCast(SPELL_BONE_STRIKE_IMPALE,pWho); + doCast(SPELL_VEHICLE_HARDCODED,pWho); + } + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > m_creature->GetHealth()) + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGuid)) + doRemove(SPELL_BONE_STRIKE_IMPALE,pVictim); + } + + void AttackStart(Unit *who) + { + } + + void KilledUnit(Unit* _Victim) + { + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGuid)) + if (pVictim->GetObjectGuid() == victimGuid) + doRemove(SPELL_BONE_STRIKE_IMPALE,pVictim); + } + + void JustDied(Unit* Killer) + { + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGuid)) + doRemove(SPELL_BONE_STRIKE_IMPALE,pVictim); + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_pInstance && m_pInstance->GetData(TYPE_MARROWGAR) != IN_PROGRESS) + { + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGuid)) + doRemove(SPELL_BONE_STRIKE_IMPALE,pVictim); + m_creature->ForcedDespawn(); + } + + if (victimGuid.IsEmpty()) + return; + + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGuid)) + { + if(!pVictim->isAlive()) + m_creature->ForcedDespawn(); + } + else + m_creature->ForcedDespawn(); + } +}; + +CreatureAI* GetAI_mob_bone_spike(Creature* pCreature) +{ + return new mob_bone_spikeAI(pCreature); +} + +CreatureAI* GetAI_mob_coldflame(Creature* pCreature) +{ + return new mob_coldflameAI(pCreature); +} + +CreatureAI* GetAI_boss_lord_marrowgar(Creature* pCreature) +{ + return new boss_lord_marrowgarAI(pCreature); +} + +void AddSC_boss_lord_marrowgar() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_lord_marrowgar"; + newscript->GetAI = &GetAI_boss_lord_marrowgar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_coldflame"; + newscript->GetAI = &GetAI_mob_coldflame; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_bone_spike"; + newscript->GetAI = &GetAI_mob_bone_spike; + newscript->RegisterSelf(); + +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_professor_putricide.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_professor_putricide.cpp index 21a1cb9..eccc914 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_professor_putricide.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_professor_putricide.cpp @@ -15,10 +15,755 @@ */ /* ScriptData -SDName: boss_professor_putricide -SD%Complete: 0% -SDComment: +SDName: boss_proffesor_putricide +SD%Complete: 70% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - +// Need implement model (aura?) for phase 2 and visual effects +// I don't know how do mutated_abomination :( #include "precompiled.h" +#include "def_spire.h" + +enum BossSpells +{ + SPELL_UNSTABLE_EXPERIMENT = 70351, // Script effect not work on 10154. Spawn manually. + SPELL_TEAR_GAS = 71617, + SPELL_TEAR_GAS_1 = 71615, + SPELL_TEAR_GAS_2 = 71618, + SPELL_CREATE_CONCOCTION = 71621, + SPELL_MALLEABLE_GOO = 70852, + SPELL_GUZZLE_POTIONS = 71893, + SPELL_MUTATED_STRENGTH = 71603, + SPELL_MUTATED_PLAGUE = 72672, + SPELL_OOZE_THROW = 70342, // is triggered spell +// + SPELL_GREEN_BOTTLE_0 = 71826, + SPELL_ORANGE_BOTTLE_0 = 71827, + SPELL_GREEN_BOTTLE_1 = 71702, + SPELL_ORANGE_BOTTLE_1 = 71703, +// + SPELL_THROW_BOTTLE_1 = 71273, + SPELL_THROW_BOTTLE_2 = 71275, + SPELL_THROW_BOTTLE_3 = 71276, +// + NPC_GAS_CLOUD = 37562, + SPELL_GASEOUS_BLOAT = 70672, + SPELL_EXPUNGED_GAS = 70701, + SPELL_SOUL_FEAST = 71203, +// + NPC_VOLATILE_OOZE = 37697, + SPELL_OOZE_ADHESIVE = 70447, + SPELL_OOZE_ERUPTION = 70492, +// + SPELL_OOZE_GAS_PROTECTION = 70812, + SPELL_OOZE_BEAM_PROTECTION = 71530, + SPELL_OOZE_TANK_PROTECTION = 71770, +// + NPC_MUTATED_ABOMINATION = 37672, + SPELL_MUTATED_TRANSFORMATION = 70311, + SPELL_EAT_OOZE = 72527, + SPELL_REGURGITATED_OOZE = 70539, + SPELL_MUTATED_SLASH = 70542, + SPELL_MUTATED_AURA = 70405, +// + NPC_CHOKING_GAS_BOMB = 38159, + SPELL_CHOKING_GAS = 71259, + SPELL_CHOKING_GAS_AURA = 71278, + SPELL_CHOKING_GAS_EXPLODE = 71279, + SPELL_CHOKING_GAS_EXPLODE_TRIGGER = 71280, + SPELL_ORANGE_RADIATION = 45857, //Additional visual +// + NPC_OOZE_PUDDLE = 37690, + SPELL_SLIME_PUDDLE = 70343, + SPELL_SLIME_PUDDLE_AURA = 70346, + + SPELL_BERSERK = 47008, + QUEST_24749 = 71518, +// + VIEW_1 = 30881, + VIEW_2 = 30881, + VIEW_3 = 30993, +}; + +static Locations SpawnLoc[]= +{ + {4356.779785f, 3263.510010f, 389.398010f, 1.586f}, // 0 Putricide start point o=1.586 + {4295.081055f, 3188.883545f, 389.330261f, 4.270f}, // 1 Puticide Festergut say, o=4.27 + {4417.302246f, 3188.219971f, 389.332520f, 5.102f}, // 2 Putricide Rotface say o=5.102 +}; + +struct MANGOS_DLL_DECL boss_proffesor_putricideAI : public BSWScriptedAI +{ + boss_proffesor_putricideAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 stage; + bool intro; + uint32 UpdateTimer; + bool movementstarted; + uint8 nextPoint; + uint8 slimetype; + + void Reset() + { + if (!pInstance) return; + if (m_creature->isAlive()) pInstance->SetData(TYPE_PUTRICIDE, NOT_STARTED); + stage = 0; + slimetype = 0; + intro = false; + movementstarted = false; + UpdateTimer = 1000; + resetTimers(); + m_creature->SetRespawnDelay(7*DAY); + } + + void MoveInLineOfSight(Unit* pWho) + { + ScriptedAI::MoveInLineOfSight(pWho); + + if (!pInstance || intro) return; + if (pInstance->GetData(TYPE_EVENT_NPC) == NPC_PROFESSOR_PUTRICIDE + || !pWho->IsWithinDistInMap(m_creature, 60.0f)) return; + + DoScriptText(-1631240,m_creature, pWho); + intro = true; + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631241,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631242,m_creature,pVictim); + break; + } + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || !movementstarted) return; + if (id == nextPoint) + { + movementstarted = false; + m_creature->GetMotionMaster()->MovementExpired(); + } + } + + void Aggro(Unit *pWho) + { + if (!pInstance) return; + if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER) + return; + + pInstance->SetData(TYPE_PUTRICIDE, IN_PROGRESS); + DoScriptText(-1631249,m_creature, pWho); + } + + void JustDied(Unit *killer) + { + if (!pInstance) return; + pInstance->SetData(TYPE_PUTRICIDE, DONE); + DoScriptText(-1631243,m_creature, killer); + for (uint8 i = 0; i < 5; i++) + { + if (Unit* pPlayer = doSelectRandomPlayer(SPELL_MUTATED_PLAGUE, true, 100.0f)) + { + doCast(QUEST_24749, pPlayer); + doRemove(SPELL_MUTATED_PLAGUE, pPlayer); + } + } + } + + void JustSummoned(Creature* summoned) + { + if(!pInstance || !summoned) return; + + if ( summoned->GetEntry() == NPC_VOLATILE_OOZE + || summoned->GetEntry() == NPC_GAS_CLOUD) + if (Unit* pTarget = doSelectRandomPlayer()) + { + summoned->SetInCombatWith(pTarget); + summoned->AddThreat(pTarget, 100.0f); + } + + } + + void StartMovement(uint32 id) + { + nextPoint = id; + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(id, SpawnLoc[id].x, SpawnLoc[id].y, SpawnLoc[id].z); + movementstarted = true; + } + + void CallOoze() + { + if (doCast(SPELL_UNSTABLE_EXPERIMENT) == CAST_OK) + switch(slimetype) + { + case 0: + doSummon(NPC_VOLATILE_OOZE); + slimetype = 1; + break; + case 1: + doSummon(NPC_GAS_CLOUD); + slimetype = 0; + break; + + default: break; + } + } + + void JustReachedHome() + { + if (pInstance) pInstance->SetData(TYPE_PUTRICIDE, FAIL); + } + + void UpdateAI(const uint32 diff) + { + if (pInstance->GetData(TYPE_EVENT_NPC) == NPC_PROFESSOR_PUTRICIDE) + { + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + if (UpdateTimer <= diff) + { + debug_log("EventMGR: creature %u received signal %u ",m_creature->GetEntry(),pInstance->GetData(TYPE_EVENT)); + switch (pInstance->GetData(TYPE_EVENT)) + { + case 500: + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->NearTeleportTo(SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, SpawnLoc[1].o); + DoScriptText(-1631201, m_creature); + UpdateTimer = 60000; + pInstance->SetData(TYPE_EVENT,510); + break; + case 510: + UpdateTimer = 5000; + if (pInstance->GetData(TYPE_FESTERGUT) == DONE) + pInstance->SetData(TYPE_EVENT,550); + if (pInstance->GetData(TYPE_FESTERGUT) == FAIL) + pInstance->SetData(TYPE_EVENT,630); + break; + case 550: + DoScriptText(-1631202, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,630); + break; + case 600: + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->NearTeleportTo(SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z, SpawnLoc[2].o); + DoScriptText(-1631220, m_creature); + UpdateTimer = 60000; + pInstance->SetData(TYPE_EVENT,610); + break; + case 610: + UpdateTimer = 5000; + if (pInstance->GetData(TYPE_ROTFACE) == DONE) + pInstance->SetData(TYPE_EVENT,620); + if (pInstance->GetData(TYPE_ROTFACE) == FAIL) + pInstance->SetData(TYPE_EVENT,630); + break; + case 620: + DoScriptText(-1631202, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,630); + break; + case 630: + m_creature->NearTeleportTo(SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, SpawnLoc[0].o); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,690); + break; + default: + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(stage) + { + case 0: + + if (timedQuery(SPELL_UNSTABLE_EXPERIMENT, diff)) + CallOoze(); + + timedCast(SPELL_OOZE_THROW, diff); + + if (timedQuery(SPELL_MALLEABLE_GOO, diff)) + { + doCast(SPELL_MALLEABLE_GOO); + } + + DoMeleeAttackIfReady(); + + if (m_creature->GetHealthPercent() < 80.0f ) stage = 1; + + break; + case 1: + m_creature->InterruptNonMeleeSpells(true); + m_creature->AttackStop(); + SetCombatMovement(false); + doCast(SPELL_TEAR_GAS_1); + DoScriptText(-1631245,m_creature); + StartMovement(0); + stage = 2; + break; + case 2: + if (movementstarted) return; + doCast(SPELL_CREATE_CONCOCTION); + stage = 3; + break; + case 3: + if (m_creature->IsNonMeleeSpellCasted(true,false,false) || + !doSelectRandomPlayer(SPELL_TEAR_GAS_1, false)) return; + DoScriptText(-1631246,m_creature); + m_creature->SetDisplayId(VIEW_2); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + SetCombatMovement(true); + stage = 4; + break; + case 4: + + if (timedQuery(SPELL_UNSTABLE_EXPERIMENT, diff)) + CallOoze(); + + if (timedQuery(SPELL_THROW_BOTTLE_1, diff)) + switch(urand(0,2)) + { + case 0: + doCast(SPELL_THROW_BOTTLE_1); + break; + case 1: + doCast(SPELL_THROW_BOTTLE_2); + break; + case 2: + doCast(SPELL_THROW_BOTTLE_3); + break; + default: break; + } + + timedCast(SPELL_OOZE_THROW, diff); + + timedCast(SPELL_MALLEABLE_GOO, diff); + + if (timedQuery(SPELL_MALLEABLE_GOO, diff)) + { + doCast(SPELL_MALLEABLE_GOO); + } + + if (m_creature->GetDisplayId() != VIEW_2) + m_creature->SetDisplayId(VIEW_2); + + DoMeleeAttackIfReady(); + + if (m_creature->GetHealthPercent() < 35.0f ) stage = 5; + + break; + case 5: + m_creature->InterruptNonMeleeSpells(true); + m_creature->AttackStop(); + SetCombatMovement(false); + doCast(SPELL_TEAR_GAS_1); + DoScriptText(-1631245,m_creature); + StartMovement(0); + stage = 6; + break; + case 6: + if (movementstarted) return; + doCast(SPELL_GUZZLE_POTIONS); + stage = 7; + break; + case 7: + if (m_creature->IsNonMeleeSpellCasted(true,false,false)) return; + if (m_creature->GetDisplayId() != VIEW_3) + m_creature->SetDisplayId(VIEW_3); + if (!doSelectRandomPlayer(SPELL_TEAR_GAS_1, false)) return; + DoScriptText(-1631247,m_creature); + m_creature->SetDisplayId(VIEW_3); + doCast(SPELL_MUTATED_STRENGTH); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + SetCombatMovement(true); + stage = 8; + break; + case 8: + timedCast(SPELL_MUTATED_PLAGUE, diff); + if (m_creature->GetDisplayId() != VIEW_3) + m_creature->SetDisplayId(VIEW_3); + DoMeleeAttackIfReady(); + + break; + default: + break; + } + + if (timedQuery(SPELL_BERSERK, diff)){ + doCast(SPELL_BERSERK); + DoScriptText(-1631244,m_creature); + } + } +}; + +CreatureAI* GetAI_boss_proffesor_putricide(Creature* pCreature) +{ + return new boss_proffesor_putricideAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_icc_gas_cloudAI : public BSWScriptedAI +{ + mob_icc_gas_cloudAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + Unit* pTarget; + bool expunded; + uint32 delay; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSpeedRate(MOVE_WALK, 0.5f); + m_creature->SetSpeedRate(MOVE_RUN, 0.2f); + pTarget = NULL; + expunded = false; + delay = 10000; + } + + void JustDied(Unit *killer) + { + if (!m_pInstance) return; + if (pTarget && pTarget->isAlive()) + doRemove(SPELL_GASEOUS_BLOAT, pTarget); + } + + void Aggro(Unit *who) + { + if (!m_pInstance || who->GetTypeId() != TYPEID_PLAYER) return; + + if (!pTarget || pTarget != who ) pTarget = who; + else return; + + delay = 10000; + + if (pTarget) + { + doAura(SPELL_GASEOUS_BLOAT, pTarget); + } + DoStartMovement(who); + } + + void JustReachedHome() + { + if (!m_pInstance) return; + m_creature->ForcedDespawn(); + } + + void UpdateAI(const uint32 uiDiff) + { + + if (!m_pInstance ) return; + + if(m_pInstance->GetData(TYPE_PUTRICIDE) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (expunded) m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (!pTarget) Aggro(m_creature->getVictim()); + + if (timedQuery(SPELL_SOUL_FEAST, uiDiff)) + { + doCast(SPELL_SOUL_FEAST); + } + + if (delay <= uiDiff) + { + if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, 3.0f)) + { + doCast(SPELL_EXPUNGED_GAS, pTarget); + doRemove(SPELL_GASEOUS_BLOAT, pTarget); + expunded = true; + }; + } else delay -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_icc_gas_cloud(Creature* pCreature) +{ + return new mob_icc_gas_cloudAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_icc_volatile_oozeAI : public BSWScriptedAI +{ + mob_icc_volatile_oozeAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + Unit* pTarget; + bool finita; + uint32 delay; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSpeedRate(MOVE_WALK, 0.5f); + m_creature->SetSpeedRate(MOVE_RUN, 0.2f); + pTarget = NULL; + finita = false; + delay = 10000; + } + + void JustDied(Unit *killer) + { + if (!m_pInstance) return; + if (pTarget && pTarget->isAlive()) + doRemove(SPELL_OOZE_ADHESIVE, pTarget); + } + + void Aggro(Unit *who) + { + if (!m_pInstance || !who || who->GetTypeId() != TYPEID_PLAYER) return; + + if (!pTarget || pTarget != who ) pTarget = who; + else return; + + delay = 10000; + + if (pTarget) + { + doAura(SPELL_OOZE_ADHESIVE, pTarget); + } + DoStartMovement(pTarget); + } + + void JustReachedHome() + { + if (!m_pInstance) return; + m_creature->ForcedDespawn(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance ) return; + + if ((m_pInstance->GetData(TYPE_PUTRICIDE) != IN_PROGRESS) || finita) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (!pTarget) Aggro(m_creature->getVictim()); + + if (timedQuery(SPELL_SOUL_FEAST, uiDiff)) + { + doCast(SPELL_SOUL_FEAST); + } + + if (delay <= uiDiff) + { + if (pTarget && pTarget->isAlive() && pTarget->IsWithinDistInMap(m_creature, 3.0f)) + { + doCast(SPELL_OOZE_ERUPTION); + doRemove(SPELL_OOZE_ADHESIVE, pTarget); + finita = true; + }; + } else delay -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_icc_volatile_ooze(Creature* pCreature) +{ + return new mob_icc_volatile_oozeAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_choking_gas_bombAI : public ScriptedAI +{ + mob_choking_gas_bombAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool finita; + uint32 copy_timer; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetInCombatWithZone(); + m_creature->SetDisplayId(11686); + SetCombatMovement(false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->CastSpell(m_creature, SPELL_ORANGE_RADIATION, false); + finita = false; + copy_timer = 8000; + } + + void AttackStart(Unit *pWho) + { + return; + } + + void JustReachedHome() + { + return; + } + + void JustDied(Unit *killer) + { + if (finita) return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + + if (m_pInstance->GetData(TYPE_PUTRICIDE) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->HasAura(SPELL_CHOKING_GAS)) + m_creature->CastSpell(m_creature, SPELL_CHOKING_GAS, false); + + if (!finita && m_creature->HasAura(SPELL_CHOKING_GAS_EXPLODE_TRIGGER)) + { +// m_creature->CastSpell(m_creature,SPELL_CHOKING_GAS_EXPLODE,false); + finita = true; + } + + if (!finita) + { + if (copy_timer <= uiDiff) + { + float fPosX, fPosY, fPosZ; + m_creature->GetPosition(fPosX, fPosY, fPosZ); + if (Creature* pCopy = m_creature->SummonCreature(m_creature->GetEntry(), fPosX, fPosY, fPosZ, 0, TEMPSUMMON_TIMED_DESPAWN, 11200)) + pCopy->CastSpell(pCopy, SPELL_CHOKING_GAS_EXPLODE_TRIGGER, false); + copy_timer = 3600000; + } else copy_timer -= uiDiff; + } + + } + +}; + +CreatureAI* GetAI_mob_choking_gas_bomb(Creature* pCreature) +{ + return new mob_choking_gas_bombAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_ooze_puddleAI : public ScriptedAI +{ + mob_ooze_puddleAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *m_pInstance; + float m_Size; + float m_Size0; + uint32 grow_timer; + + void Reset() + { + if(!m_pInstance) return; + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetDisplayId(11686); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetInCombatWithZone(); + SetCombatMovement(false); + m_Size0 = m_creature->GetObjectScale(); + if (m_Size0 > 1.0f) + { + m_creature->SetObjectScale(1.0f); + m_Size0 = 1.0f; + } + m_Size = m_Size0; + grow_timer = 500; + } + + void AttackStart(Unit *who) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance) return; + + if (m_pInstance->GetData(TYPE_PUTRICIDE) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->HasAura(SPELL_SLIME_PUDDLE)) + m_creature->CastSpell(m_creature, SPELL_SLIME_PUDDLE, false); + + // Override especially for clean core + if (m_Size / m_Size0 >= 2.6f) m_creature->ForcedDespawn(); + + if (grow_timer <= uiDiff) + { + m_Size = m_Size*1.01; + m_creature->SetObjectScale(m_Size); + grow_timer = 500; + } else grow_timer -= uiDiff; + } + +}; + +CreatureAI* GetAI_mob_ooze_puddle(Creature* pCreature) +{ + return new mob_ooze_puddleAI(pCreature); +} + +void AddSC_boss_proffesor_putricide() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_proffesor_putricide"; + newscript->GetAI = &GetAI_boss_proffesor_putricide; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_icc_volatile_ooze"; + newscript->GetAI = &GetAI_mob_icc_volatile_ooze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_icc_gas_cloud"; + newscript->GetAI = &GetAI_mob_icc_gas_cloud; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_choking_gas_bomb"; + newscript->GetAI = &GetAI_mob_choking_gas_bomb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ooze_puddle"; + newscript->GetAI = &GetAI_mob_ooze_puddle; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_rotface.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_rotface.cpp index 12939b8..3082050 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_rotface.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_rotface.cpp @@ -16,9 +16,425 @@ /* ScriptData SDName: boss_rotface -SD%Complete: 0% -SDComment: +SD%Complete: 80% +SDComment: by /dev/rsa. Need correct timers && infection logic SDCategory: Icecrown Citadel EndScriptData */ - +// Need correct timers #include "precompiled.h" +#include "def_spire.h" + +enum BossSpells +{ + SPELL_OOZE_FLOOD = 69789, + SPELL_OOZE_FLOOD_0 = 69788, + SPELL_OOZE_FLOOD_1 = 69783, + SPELL_SLIME_SPRAY = 69508, + SPELL_MUTATED_INFECTION_AURA = 69674, + SPELL_MUTATED_INFECTION = 70003, + SPELL_BERSERK = 47008, + + SPELL_STICKY_OOZE = 69774, + SPELL_STICKY_AURA = 69776, + SPELL_MERGE_OOZE = 69889, + SPELL_RADIATING_OOZE = 69750, + SPELL_RADIATING_OOZE_1 = 69760, + SPELL_UNSTABLE_OOZE = 69644, + SPELL_UNSTABLE_OOZE_AURA = 69558, + SPELL_OOZE_EXPLODE = 69839, + SPELL_OOZE_EXPLODE_AURA = 69840, + + NPC_BIG_OOZE = 36899, + NPC_SMALL_OOZE = 36897, + NPC_STICKY_OOZE = 37006, + NPC_OOZE_SPRAY_STALKER = 37986, + NPC_OOZE_STALKER = 37013, + NPC_OOZE_EXPLODE_STALKER = 38107, +}; + +static Locations SpawnLoc[]= +{ + {4471.821289f, 3162.986084f, 360.38501f}, // 0 + {4471.821289f, 3110.452148f, 360.38501f}, // 1 + {4418.825684f, 3110.452148f, 360.38501f}, // 2 + {4418.825684f, 3162.986084f, 360.38501f}, // 3 +}; + + +struct MANGOS_DLL_DECL boss_rotfaceAI : public BSWScriptedAI +{ + boss_rotfaceAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 stage; + bool intro; + bool pet; + bool nexttick; + + void Reset() + { + if(!pInstance) return; + if (m_creature->isAlive()) pInstance->SetData(TYPE_ROTFACE, NOT_STARTED); + stage = 0; + intro = false; + pet = false; + nexttick = false; + resetTimers(); + } + + void MoveInLineOfSight(Unit* pWho) + { + ScriptedAI::MoveInLineOfSight(pWho); + if(!pInstance || intro) return; + if (pWho->GetTypeId() != TYPEID_PLAYER) return; + + pInstance->SetData(TYPE_EVENT, 600); + debug_log("EventMGR: creature %u send signal %u ",m_creature->GetEntry(),pInstance->GetData(TYPE_EVENT)); + intro = true; + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631222,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631223,m_creature,pVictim); + break; + } + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + pInstance->SetData(TYPE_ROTFACE, IN_PROGRESS); + DoScriptText(-1631221,m_creature,who); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return; + pInstance->SetData(TYPE_ROTFACE, DONE); + DoScriptText(-1631224,m_creature, killer); + } + + void UpdateAI(const uint32 diff) + { + + if(!pInstance) return; + + if (!pet) + { + if (Creature* pGuard = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_PRECIOUS))) + if (!pGuard->isAlive()) + { + pet = true; + if (pInstance->GetData(TYPE_PRECIOUS) == NOT_STARTED) + { + DoScriptText(-1631228,m_creature); + pInstance->SetData(TYPE_PRECIOUS,DONE); + } + } + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (nexttick) + { + doCast(SPELL_OOZE_FLOOD_1); + DoScriptText(-1631227,m_creature); + nexttick = false; + }; + + if (timedQuery(SPELL_OOZE_FLOOD_1, diff)) + { + uint8 i = urand(0,3); + if (Unit* pTemp = doSummon(NPC_OOZE_STALKER,SpawnLoc[i].x, SpawnLoc[i].y, SpawnLoc[i].z, TEMPSUMMON_TIMED_DESPAWN, 15000)) + { + doCast(SPELL_OOZE_FLOOD, pTemp); + nexttick = true; + } + }; + + if (timedQuery(SPELL_SLIME_SPRAY, diff)) + if (doSummon(NPC_OOZE_SPRAY_STALKER)) + doCast(SPELL_SLIME_SPRAY); + + if (timedQuery(SPELL_MUTATED_INFECTION, diff)) + { + for(uint8 i = 0; i < getSpellData(SPELL_MUTATED_INFECTION); ++i) + if (Unit* pTarget = doSelectRandomPlayer(SPELL_MUTATED_INFECTION_AURA, false, 60.0f)) + doCast(SPELL_MUTATED_INFECTION, pTarget); + DoScriptText(-1631226,m_creature); + } + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631225,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_boss_rotface(Creature* pCreature) +{ + return new boss_rotfaceAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_small_oozeAI : public BSWScriptedAI +{ + mob_small_oozeAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + resetTimers(); + m_creature->SetRespawnDelay(7*DAY); + doCast(SPELL_RADIATING_OOZE); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSpeedRate(MOVE_RUN, 0.5); + m_creature->SetSpeedRate(MOVE_WALK, 0.5); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_ROTFACE) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_STICKY_OOZE, uiDiff); + + if (Creature* pTemp = doSelectNearestCreature(m_creature->GetEntry(),7.0f)) + { + doCast(SPELL_MERGE_OOZE, pTemp); + doSummon(NPC_BIG_OOZE); + pTemp->ForcedDespawn(); + m_creature->ForcedDespawn(); + }; + } +}; + +CreatureAI* GetAI_mob_small_ooze(Creature* pCreature) +{ + return new mob_small_oozeAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_big_oozeAI : public BSWScriptedAI +{ + mob_big_oozeAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + bool exploded; + + void Reset() + { + resetTimers(); + m_creature->SetRespawnDelay(7*DAY); + doCast(SPELL_UNSTABLE_OOZE); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSpeedRate(MOVE_RUN, 0.5); + m_creature->SetSpeedRate(MOVE_WALK, 0.5); + exploded = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_ROTFACE) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_STICKY_OOZE, uiDiff); + + if (Creature* pSmall = doSelectNearestCreature(NPC_SMALL_OOZE,5.0f)) + { + pSmall->ForcedDespawn(); + doCast(SPELL_UNSTABLE_OOZE); + }; + + if (Creature* pBig = doSelectNearestCreature(NPC_BIG_OOZE, 8.0f)) + { + pBig->ForcedDespawn(); + doCast(SPELL_UNSTABLE_OOZE); + } + + if ( auraCount(SPELL_UNSTABLE_OOZE_AURA) > 4 && !exploded) + { + doCast(SPELL_OOZE_EXPLODE); + exploded = true; + } + + } +}; + +CreatureAI* GetAI_mob_big_ooze(Creature* pCreature) +{ + return new mob_big_oozeAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_sticky_oozeAI : public ScriptedAI +{ + mob_sticky_oozeAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + m_creature->SetDisplayId(11686); + m_creature->SetRespawnDelay(7*DAY); + m_creature->CastSpell(m_creature, SPELL_STICKY_AURA, true); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWithZone(); + SetCombatMovement(false); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_ROTFACE) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + } +}; + +CreatureAI* GetAI_mob_sticky_ooze(Creature* pCreature) +{ + return new mob_sticky_oozeAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_ooze_explode_stalkerAI : public BSWScriptedAI +{ + mob_ooze_explode_stalkerAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + Creature* creator; + + void Reset() + { + m_creature->SetDisplayId(11686); + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + m_creature->SetInCombatWithZone(); + doCast(SPELL_OOZE_EXPLODE_AURA); + creator = doSelectNearestCreature(NPC_BIG_OOZE, 20.0f); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_ROTFACE) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (creator && creator->isAlive()) + creator->ForcedDespawn(); + + if (timedQuery(SPELL_OOZE_EXPLODE_AURA, uiDiff)) + m_creature->ForcedDespawn(); + + } +}; + +CreatureAI* GetAI_mob_ooze_explode_stalker(Creature* pCreature) +{ + return new mob_ooze_explode_stalkerAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_ooze_spray_stalkerAI : public ScriptedAI +{ + mob_ooze_spray_stalkerAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + SetCombatMovement(false); + m_creature->SetDisplayId(11686); + } + + void AttackStart(Unit *pWho) + { + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_ROTFACE) != IN_PROGRESS) + m_creature->ForcedDespawn(); + } +}; + +CreatureAI* GetAI_mob_ooze_spray_stalker(Creature* pCreature) +{ + return new mob_ooze_spray_stalkerAI(pCreature); +} + +void AddSC_boss_rotface() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_rotface"; + newscript->GetAI = &GetAI_boss_rotface; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_small_ooze"; + newscript->GetAI = &GetAI_mob_small_ooze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_big_ooze"; + newscript->GetAI = &GetAI_mob_big_ooze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_sticky_ooze"; + newscript->GetAI = &GetAI_mob_sticky_ooze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ooze_explode_stalker"; + newscript->GetAI = &GetAI_mob_ooze_explode_stalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ooze_spray_stalker"; + newscript->GetAI = &GetAI_mob_ooze_spray_stalker; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_sindragosa.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_sindragosa.cpp index 9aa17a3..50129c9 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_sindragosa.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_sindragosa.cpp @@ -16,9 +16,651 @@ /* ScriptData SDName: boss_sindragosa -SD%Complete: 0% -SDComment: +SD%Complete: 80% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - +// Need correct timers and models #include "precompiled.h" +#include "def_spire.h" + +enum BossSpells +{ +// Sindragosa + SPELL_FROST_AURA_1 = 70084, + SPELL_CLEAVE_1 = 19983, + SPELL_TAIL_SMASH = 71077, + SPELL_FROST_BREATH_1 = 69649, + SPELL_PERMEATING_CHILL = 70107, + SPELL_UNCHAINED_MAGIC = 69762, + SPELL_INSTABILITY = 69766, + SPELL_ICY_GRIP = 70117, + SPELL_BLISTERING_COLD = 70123, + + SPELL_FROST_BEACON = 70126, + SPELL_ICY_TOMB = 70157, + SPELL_ASPHYXATION = 71665, + SPELL_FROST_BOMB = 71053, + SPELL_FROST_BOMB_TRIGGER = 69846, + SPELL_FROST_BOMB_VISUAL = 64624, + SPELL_FROST_BOMB_VISUAL2 = 69016, + SPELL_ICE_TOMB_TRIGGER = 69675, + SPELL_MYSTIC_BUFFET = 70128, + + NPC_ICE_TOMB = 36980, + NPC_FROST_BOMB = 37186, + + QUEST_24757 = 72289, + SPELL_BERSERK = 47008, + +// Rimefang + SPELL_FROST_AURA = 71387, + SPELL_FROST_BREATH = 71386, + SPELL_ICY_BLAST = 71376, +// Spinestalker + SPELL_BELLOWING_ROAR = 36922, + SPELL_CLEAVE = 40505, + SPELL_TAIL_SWEEP = 71369, +}; + +static Locations SpawnLoc[]= +{ + {4408.052734f, 2484.825439f, 203.374207f}, // 0 Sindragosa spawn + {4474.239746f, 2484.243896f, 231.0f}, // 1 Sindragosa fly o=3.11 + {4474.239746f, 2484.243896f, 203.380402f}, // 2 Sindragosa fly - ground point o=3.11 +}; + +struct MANGOS_DLL_DECL boss_sindragosaAI : public BSWScriptedAI +{ + boss_sindragosaAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 stage; + uint8 icecount; + bool MovementStarted; + Unit* marked[5]; + + void Reset() + { + if(!pInstance) return; + resetTimers(); + stage = 0; + memset(&marked, 0, sizeof(marked)); + + m_creature->SetRespawnDelay(7*DAY); + switch (currentDifficulty) { + case RAID_DIFFICULTY_10MAN_NORMAL: + icecount = 2; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + icecount = 2; + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + icecount = 5; + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + icecount = 5; + break; + default: + icecount = 2; + break; + } + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1631421,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631422,m_creature,pVictim); + break; + } + } + + void JustReachedHome() + { + if (!pInstance) + return; + pInstance->SetData(TYPE_SINDRAGOSA, FAIL); + doRemoveFromAll(SPELL_ICY_TOMB); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_RIMEFANG))) + pTemp->Respawn(); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_SPINESTALKER))) + pTemp->Respawn(); + DoScriptText(-1631422,m_creature); + m_creature->ForcedDespawn(); + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + DoScriptText(-1631420,m_creature,who); + doCast(SPELL_FROST_AURA_1); + } + + void JustDied(Unit *killer) + { + if (!pInstance) + return; + doRemoveFromAll(SPELL_ICY_TOMB); + pInstance->SetData(TYPE_SINDRAGOSA, DONE); + DoScriptText(-1631423,m_creature,killer); + doCast(QUEST_24757); + } + + void MovementInform(uint32 type, uint32 id) + { + if (!pInstance) + return; + + if (type != POINT_MOTION_TYPE || !MovementStarted) return; + + if (id == 1) { + m_creature->GetMotionMaster()->MovementExpired(); + MovementStarted = false; + } + } + + void doBlisteringCold() + { + doCast(SPELL_ICY_GRIP); + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &pList = pMap->GetPlayers(); + if (pList.isEmpty()) return; + + for (Map::PlayerList::const_iterator i = pList.begin(); i != pList.end(); ++i) + if (Player* player = i->getSource()) + if (player->isAlive() && player->IsWithinDistInMap(m_creature, 30.0f)) + { + float fPosX, fPosY, fPosZ; + m_creature->GetPosition(fPosX, fPosY, fPosZ); + m_creature->GetRandomPoint(fPosX, fPosY, fPosZ, 1.0f, fPosX, fPosY, fPosZ); + player->NearTeleportTo(fPosX, fPosY, fPosZ+1.0f, (float)(urand(0,6)), true); + } + doCast(SPELL_BLISTERING_COLD); + } + + void IceMark() + { + memset(&marked, 0, sizeof(marked)); + + for (uint8 i = 0; i < icecount; i++) + if (marked[i] = doSelectRandomPlayer(SPELL_FROST_BEACON, false, 200.0f)) + doCast(SPELL_FROST_BEACON, marked[i]); + } + + void IceBlock() + { + for (uint8 i = 0; i < icecount; i++) + if (marked[i] && marked[i]->isAlive()) + { + doCast(SPELL_ICY_TOMB, marked[i]); + marked[i]->RemoveAurasDueToSpell(SPELL_FROST_BEACON); + float fPosX, fPosY, fPosZ; + marked[i]->GetPosition(fPosX, fPosY, fPosZ); + if (Unit* pTemp1 = doSummon(NPC_ICE_TOMB,fPosX, fPosY, fPosZ)) + pTemp1->AddThreat(marked[i], 1000.0f); + }; + + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(stage) + { + case 0: + timedCast(SPELL_CLEAVE_1, diff); + timedCast(SPELL_TAIL_SMASH, diff); + timedCast(SPELL_FROST_BREATH_1, diff); + timedCast(SPELL_PERMEATING_CHILL, diff); + + timedCast(SPELL_UNCHAINED_MAGIC, diff); + + if (timedQuery(SPELL_ICY_GRIP, diff)) + { + DoScriptText(-1631426,m_creature); + doBlisteringCold(); + } + + if (timedQuery(SPELL_FROST_BEACON, diff) && m_creature->GetHealthPercent() < 85.0f) stage = 1; + + if (m_creature->GetHealthPercent() < 35.0f) + { + doCast(SPELL_MYSTIC_BUFFET); + stage = 9; + DoScriptText(-1631429,m_creature); + } + break; + case 1: + DoScriptText(-1631425,m_creature); + IceMark(); + stage = 2; + MovementStarted = true; + SetCombatMovement(false); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->GetMotionMaster()->MovePoint(1, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_FLY_SIT_GROUND_UP); + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + break; + case 2: + if (!MovementStarted) { + stage = 3; + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_FLY_FALL); + }; + break; + case 3: + stage = 4; + IceBlock(); + m_creature->SetOrientation(3.1f); + break; + case 4: + if (timedQuery(SPELL_FROST_BOMB, diff)) + if (Unit* pTemp = doSelectRandomPlayerAtRange(300.0f)) + doCast(SPELL_FROST_BOMB_TRIGGER, pTemp); + + timedCast(SPELL_FROST_BREATH_1, diff); + + if (timedQuery(SPELL_FROST_BEACON, diff)) { + stage = 5; + } + break; + case 5: + MovementStarted = true; + SetCombatMovement(false); + m_creature->GetMotionMaster()->MovePoint(1, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z); + stage = 6; + m_creature->HandleEmoteCommand(EMOTE_STATE_FLY_SIT_GROUND); + break; + case 6: + if (!MovementStarted) { + stage = 0; + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->RemoveSplineFlag(SPLINEFLAG_FLYING); + }; + break; + + case 9: + timedCast(SPELL_CLEAVE_1, diff); + timedCast(SPELL_TAIL_SMASH, diff); + timedCast(SPELL_FROST_BREATH_1, diff); + timedCast(SPELL_PERMEATING_CHILL, diff); + timedCast(SPELL_UNCHAINED_MAGIC, diff); + + if (timedQuery(SPELL_ICY_GRIP, diff)) + { + DoScriptText(-1631426,m_creature); + doBlisteringCold(); + } + + break; + default: break; + } + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631424,m_creature); + }; + + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_boss_sindragosa(Creature* pCreature) +{ + return new boss_sindragosaAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_ice_tombAI : public BSWScriptedAI +{ + mob_ice_tombAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint64 victimGUID; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + victimGUID = 0; + m_creature->SetRespawnDelay(7*DAY); + } + + void Aggro(Unit* pWho) + { + if (!victimGUID && pWho && pWho->GetTypeId() == TYPEID_PLAYER) + { + if (pWho->HasAura(SPELL_ICY_TOMB)) + { + victimGUID = pWho->GetGUID(); + m_creature->SetInCombatWith(pWho); + } + else if (Unit* pTarget = doSelectRandomPlayer(SPELL_ICY_TOMB,true,3.0f)) + { + victimGUID = pTarget->GetGUID(); + m_creature->SetInCombatWith(pTarget); + } + + } + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > m_creature->GetHealth()) + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGUID)) + doRemove(SPELL_ICY_TOMB, pVictim); + } + + void AttackStart(Unit *pWho) + { + } + + void KilledUnit(Unit* _Victim) + { + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGUID)) + doRemove(SPELL_ICY_TOMB,pVictim); + } + + void JustDied(Unit* Killer) + { + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGUID)) + doRemove(SPELL_ICY_TOMB,pVictim); + } + + void UpdateAI(const uint32 uiDiff) + { + if ((m_pInstance && m_pInstance->GetData(TYPE_SINDRAGOSA) != IN_PROGRESS) + || (victimGUID && !m_creature->GetMap()->GetPlayer(victimGUID)->HasAura(SPELL_ICY_TOMB))) + { + if (Player* pVictim = m_creature->GetMap()->GetPlayer(victimGUID)) + doRemove(SPELL_ICY_TOMB,pVictim); + m_creature->ForcedDespawn(); + } + } + +}; + +CreatureAI* GetAI_mob_ice_tomb(Creature* pCreature) +{ + return new mob_ice_tombAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_frost_bombAI : public ScriptedAI +{ + mob_frost_bombAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance *m_pInstance; + uint32 boom_timer; + uint32 visual_timer; + bool finita; + + void Reset() + { + SetCombatMovement(false); + m_creature->SetRespawnDelay(7*DAY); + visual_timer = 6000; + boom_timer = 9000; + finita = false; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackStart(Unit *pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_pInstance && m_pInstance->GetData(TYPE_SINDRAGOSA) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (finita) + { + m_creature->CastSpell(m_creature, SPELL_FROST_BOMB, true); + m_creature->ForcedDespawn(); + } + + if (visual_timer <= uiDiff) + { + m_creature->CastSpell(m_creature, SPELL_FROST_BOMB_VISUAL, true); + visual_timer= DAY; + } + else visual_timer -= uiDiff; + + if (boom_timer <= uiDiff) + { + m_creature->CastSpell(m_creature,SPELL_FROST_BOMB_VISUAL2,false); + finita = true; + } + else boom_timer -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_frost_bomb(Creature* pCreature) +{ + return new mob_frost_bombAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_rimefangAI : public BSWScriptedAI +{ + mob_rimefangAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + Creature* pBrother; + + void Reset() + { + if(!pInstance) return; + if (pInstance->GetData(TYPE_SINDRAGOSA) != DONE) + pInstance->SetData(TYPE_SINDRAGOSA, NOT_STARTED); + resetTimers(); + m_creature->SetRespawnDelay(30*MINUTE); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pInstance || !pWho) return; + + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + + if (!m_creature->isInCombat() && pWho->IsWithinDistInMap(m_creature, 60.0f)) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + m_creature->GetMotionMaster()->MovementExpired(); + AttackStart(pWho); + SetCombatMovement(true); + } + ScriptedAI::MoveInLineOfSight(pWho); + } + + void JustReachedHome() + { + if (pInstance) + if (pInstance->GetData(TYPE_SINDRAGOSA) != DONE) + pInstance->SetData(TYPE_SINDRAGOSA, FAIL); + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + if (pInstance->GetData(TYPE_SINDRAGOSA) != DONE) pInstance->SetData(TYPE_SINDRAGOSA, IN_PROGRESS); + pBrother = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_SPINESTALKER)); + if (pBrother && !pBrother->isAlive()) pBrother->Respawn(); + if (pBrother) pBrother->SetInCombatWithZone(); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return; + if (pInstance->GetData(TYPE_SINDRAGOSA) == DONE) return; + if (pBrother && !pBrother->isAlive()) + m_creature->SummonCreature(NPC_SINDRAGOSA, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 3.17f, TEMPSUMMON_MANUAL_DESPAWN, DESPAWN_TIME); + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance || !m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (pInstance->GetData(TYPE_SINDRAGOSA) == DONE) + { + m_creature->SetRespawnDelay(DAY); + m_creature->ForcedDespawn(); + return; + } + + doCastAll(diff); + DoMeleeAttackIfReady(); + } +}; + + +CreatureAI* GetAI_mob_rimefang(Creature* pCreature) +{ + return new mob_rimefangAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_spinestalkerAI : public BSWScriptedAI +{ + mob_spinestalkerAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + Creature* pBrother; + + void Reset() + { + if(!pInstance) return; + if (pInstance->GetData(TYPE_SINDRAGOSA) != DONE) + pInstance->SetData(TYPE_SINDRAGOSA, NOT_STARTED); + resetTimers(); + m_creature->SetRespawnDelay(30*MINUTE); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pInstance || !pWho) return; + + if (pWho->GetTypeId() != TYPEID_PLAYER) + return; + + if (!m_creature->isInCombat() && pWho->IsWithinDistInMap(m_creature, 60.0f)) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + m_creature->GetMotionMaster()->MovementExpired(); + AttackStart(pWho); + SetCombatMovement(true); + } + ScriptedAI::MoveInLineOfSight(pWho); + } + + void JustReachedHome() + { + if (pInstance) + if (pInstance->GetData(TYPE_SINDRAGOSA) != DONE) + pInstance->SetData(TYPE_SINDRAGOSA, FAIL); + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + if (pInstance->GetData(TYPE_SINDRAGOSA) != DONE) pInstance->SetData(TYPE_SINDRAGOSA, IN_PROGRESS); + pBrother = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_RIMEFANG)); + if (pBrother && !pBrother->isAlive()) pBrother->Respawn(); + if (pBrother) pBrother->SetInCombatWithZone(); + } + + void JustDied(Unit *killer) + { + if (!pInstance) return; + if (pInstance->GetData(TYPE_SINDRAGOSA) == DONE) return; + if (pBrother && !pBrother->isAlive()) + m_creature->SummonCreature(NPC_SINDRAGOSA, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 3.17f, TEMPSUMMON_MANUAL_DESPAWN, DESPAWN_TIME); + } + + void UpdateAI(const uint32 diff) + { + + if (!pInstance || !m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (pInstance->GetData(TYPE_SINDRAGOSA) == DONE) + { + m_creature->SetRespawnDelay(DAY); + m_creature->ForcedDespawn(); + return; + } + + doCastAll(diff); + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_spinestalker(Creature* pCreature) +{ + return new mob_spinestalkerAI(pCreature); +} + +void AddSC_boss_sindragosa() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_sindragosa"; + newscript->GetAI = &GetAI_boss_sindragosa; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_rimefang"; + newscript->GetAI = &GetAI_mob_rimefang; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_spinestalker"; + newscript->GetAI = &GetAI_mob_spinestalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ice_tomb"; + newscript->GetAI = &GetAI_mob_ice_tomb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_bomb"; + newscript->GetAI = &GetAI_mob_frost_bomb; + newscript->RegisterSelf(); + +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_the_lich_king.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_the_lich_king.cpp index d51e2e5..f61d9c1 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_the_lich_king.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_the_lich_king.cpp @@ -16,9 +16,1210 @@ /* ScriptData SDName: boss_the_lich_king -SD%Complete: 0% -SDComment: +SD%Complete: 70% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - +// Need implement "in sword" phase #include "precompiled.h" +#include "def_spire.h" + +enum BossSpells +{ + SPELL_INFEST = 70541, + SPELL_NECROTIC_PLAGUE = 70337, + SPELL_PLAGUE_SIPHON = 74074, + SPELL_SOUL_REAPER = 69409, + SPELL_SPAWN_DEFILE = 72762, + SPELL_HARVEST_SOUL = 68980, + SPELL_HARVEST_SOUL_TELEPORT = 71372, +// + SPELL_CHANNEL_KING = 71769, + SPELL_BROKEN_FROSTMOURNE = 72398, + SPELL_BOOM_VISUAL = 72726, + SPELL_ICEBLOCK_TRIGGER = 71614, + SPELL_TIRION_LIGHT = 71797, + SPELL_FROSTMOURNE_TRIGGER = 72405, + SPELL_SUMMON_BROKEN_FROSTMOURNE = 72406, + SPELL_SUMMON_BROKEN_FROSTMOURNE_2 = 73017, + SPELL_DISENGAGE = 61508, + SPELL_FURY_OF_FROSTMOURNE = 70063, + SPELL_REVIVE_VISUAL = 37755, //Override? + SPELL_REVIVE = 51918, + SPELL_CLONE_PLAYER = 57507, + SPELL_BERSERK = 47008, + +//Transition phase + SPELL_REMORSELESS_WINTER = 68981, + SPELL_PAIN_AND_SUFFERING = 72133, + SPELL_QUAKE = 72262, + +//Raging spirit +// SPELL_SUMMON_RAGING_SPIRIT = 69201, // triggered + SPELL_SUMMON_RAGING_SPIRIT = 69200, + SPELL_SOUL_SHRIEK = 69242, + +//Ice sphere + SPELL_SUMMON_ICE_SPHERE = 69103, + SPELL_ICE_PULSE = 69099, + SPELL_ICE_BURST = 69108, + SPELL_ICE_SPHERE_VISUAL = 69090, + +//Drudge ghouls + SPELL_SUMMON_DRUDGE_GHOULS = 70358, + +//Shambling horror + SPELL_SUMMON_SHAMBLING_HORROR = 70372, + SPELL_SHOCKWAVE = 72149, + SPELL_HORROR_ENRAGE = 72143, + +//Vile spirits + SPELL_SUMMON_VILE_SPIRITS = 70498, + SPELL_SPIRITS_BURST = 70503, + +//Valkyr + SPELL_SUMMON_VALKYR = 69037, + NPC_VALKYR = 36609, + SPELL_WINGS_OF_THE_DAMNED = 74352, + +//Defile + SPELL_DEFILE = 72743, + +// Menethil + SPELL_REVALL = 26687, +// + NPC_ICE_SPHERE = 36633, + NPC_DEFILER = 38757, + NPC_RAGING_SPIRIT = 36701, + NPC_VILE_SPIRIT = 37799, + NPC_STRANGULATE_VEHICLE = 36598, + +}; + +enum Common +{ + FINAL_ARTHAS_MOVIE = 16, +}; + +static Locations SpawnLoc[]= +{ + {459.93689f, -2124.638184f, 1040.860107f}, // 0 Lich King Intro + {503.15652f, -2124.516602f, 1040.860107f}, // 1 Lich king move end + {491.27118f, -2124.638184f, 1040.860107f}, // 2 Tirion 1 + {481.69797f, -2124.638184f, 1040.860107f}, // 3 Tirion 2 + {498.00448f, -2201.573486f, 1046.093872f}, // 4 Valkyrs? + {517.48291f, -2124.905762f, 1040.861328f}, // 5 Tirion? + {529.85302f, -2124.709961f, 1040.859985f}, // 6 Lich king final, o=3.1146 + {520.311f, -2124.709961f, 1040.859985f}, // 7 Frostmourne +}; + +struct MANGOS_DLL_DECL boss_the_lich_king_iccAI : public BSWScriptedAI +{ + boss_the_lich_king_iccAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (instance_icecrown_spire*)pCreature->GetInstanceData(); + oldflag = 0; + Reset(); + } + + instance_icecrown_spire* pInstance; + uint8 stage; + uint32 nextEvent; + uint32 nextPoint; + uint32 UpdateTimer; + uint32 oldflag; + bool movementstarted; + bool battlestarted; + bool finalphase; + Creature* pTirion; + Creature* pFrostmourne; + std::list mobsGUIDList; + + void Reset() + { + if(!pInstance) return; + resetTimers(); + mobsGUIDList.clear(); + stage = 0; + nextEvent = 0; + nextPoint = 0; + movementstarted = false; + battlestarted = false; + finalphase = false; + m_creature->SetOrientation(0.0f); + pInstance->CloseDoor(pInstance->GetData64(GO_ICESHARD_1)); + pInstance->CloseDoor(pInstance->GetData64(GO_ICESHARD_2)); + pInstance->CloseDoor(pInstance->GetData64(GO_ICESHARD_3)); + pInstance->CloseDoor(pInstance->GetData64(GO_ICESHARD_4)); + if (oldflag) + if (GameObject* pGoFloor = pInstance->instance->GetGameObject(pInstance->GetData64(GO_ARTHAS_PLATFORM))) + { + pGoFloor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); + pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1,oldflag); + } + pInstance->CloseDoor(pInstance->GetData64(GO_FROSTY_WIND)); + } + + void MoveInLineOfSight(Unit* pWho) + { + } + + void EnterEvadeMode() + { + if (!pInstance) return; + if (finalphase && pInstance->GetData(TYPE_LICH_KING) == IN_PROGRESS) return; + + DespawnMobs(); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + if (m_creature->isAlive()) + m_creature->GetMotionMaster()->MoveTargetedHome(); + + m_creature->SetLootRecipient(NULL); + + Reset(); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || !movementstarted) return; + if (id == nextPoint) + { + movementstarted = false; + pInstance->SetData(TYPE_EVENT,nextEvent); + m_creature->GetMotionMaster()->MovementExpired(); + } + } + + void KilledUnit(Unit* pVictim) + { + + if (!battlestarted) return; + + switch (urand(0,1)) { + case 0: + DoScriptText(-1631519,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631517,m_creature,pVictim); + break; + }; + } + + void JustReachedHome() + { + if (!pInstance) return; + pInstance->SetData(TYPE_LICH_KING, FAIL); + stage = 0; + battlestarted = false; + finalphase = false; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + + void StartMovement(uint32 id, uint32 _nextEvent) + { + nextPoint = id; + nextEvent = _nextEvent; + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(id, SpawnLoc[id].x, SpawnLoc[id].y, SpawnLoc[id].z); + pInstance->SetData(TYPE_EVENT,0); + movementstarted = true; + } + + void JustSummoned(Creature* summoned) + { + if(!pInstance || !summoned) return; + + if (Unit* pTarget = doSelectRandomPlayerAtRange(60.0f)) + { + summoned->SetInCombatWith(pTarget); + summoned->AddThreat(pTarget,100.0f); + } + mobsGUIDList.push_back(summoned->GetGUID()); + } + + void DespawnMobs() + { + if (mobsGUIDList.empty()) + return; + + for(std::list::iterator itr = mobsGUIDList.begin(); itr != mobsGUIDList.end(); ++itr) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + if (pTemp->isAlive()) + { + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + mobsGUIDList.clear(); + } + + + void Aggro(Unit *who) + { + if(!pInstance) return; + pInstance->SetData(TYPE_LICH_KING, IN_PROGRESS); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return; + pInstance->SetData(TYPE_LICH_KING, DONE); + DoScriptText(-1631528,m_creature,killer); + + pInstance->SetData(TYPE_EVENT,14010); + DespawnMobs(); + + } + + void UpdateAI(const uint32 diff) + { + + if(!pInstance) return; + + if (pInstance->GetData(TYPE_EVENT_NPC) == NPC_LICH_KING) + { + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + if (UpdateTimer <= diff) + { + debug_log("EventMGR: creature %u received signal %u ",m_creature->GetEntry(),pInstance->GetData(TYPE_EVENT)); + switch (pInstance->GetData(TYPE_EVENT)) + { + case 12000: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STAND); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + StartMovement(0,12020); + break; + case 12020: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + DoScriptText(-1631501, m_creature); + UpdateTimer = 12000; + pInstance->SetData(TYPE_EVENT,12030); + break; + case 12040: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); + DoScriptText(-1631503, m_creature); + UpdateTimer = 8000; + pInstance->SetData(TYPE_EVENT,12041); + break; + case 12041: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_LAUGH); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,12042); + break; + case 12042: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,EMOTE_ONESHOT_POINT_NOSHEATHE); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,12043); + break; + case 12043: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,EMOTE_ONESHOT_NONE); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,12050); + break; + case 12060: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_TALK); + DoScriptText(-1631505, m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,12080); + break; + case 12080: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,EMOTE_STATE_READY2H); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,12100); + break; + case 12100: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE,EMOTE_ONESHOT_NONE); + UpdateTimer = 6000; + pInstance->SetData(TYPE_EVENT,12120); + break; + case 12120: + m_creature->GetMotionMaster()->Clear(); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(true); + m_creature->SetInCombatWithZone(); + battlestarted = true; + pInstance->SetData(TYPE_EVENT,12200); + UpdateTimer = 10000; + break; + case 12200: + DoScriptText(-1631506, m_creature); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,12220); + break; + case 13000: + m_creature->SetOrientation(3.1146f); + DoScriptText(-1631507, m_creature); + UpdateTimer = 12000; + finalphase = true; + doCast(SPELL_FURY_OF_FROSTMOURNE); + pInstance->SetData(TYPE_EVENT,13020); + if (pTirion = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_TIRION))) { + m_creature->SetInCombatWith(pTirion); + pTirion->AddThreat(m_creature, 1000.0f); + } + m_creature->SetInCombatWithZone(); + break; + case 13020: + DoScriptText(-1631508, m_creature); + UpdateTimer = 12000; + pInstance->SetData(TYPE_EVENT,13060); + break; + case 13060: + DoScriptText(-1631509, m_creature); + UpdateTimer = 15000; + pInstance->SetData(TYPE_EVENT,13100); + break; + case 13100: + DoScriptText(-1631510, m_creature); + UpdateTimer = 15000; + pInstance->SetData(TYPE_EVENT,13110); + doCast(SPELL_CHANNEL_KING); + break; + case 13120: + DoScriptText(-1631511, m_creature); + UpdateTimer = 12000; + pInstance->SetData(TYPE_EVENT,13130); + break; + case 13140: + UpdateTimer = 6000; + doRemove(SPELL_CHANNEL_KING); + pInstance->SetData(TYPE_EVENT,13150); + m_creature->CastSpell(m_creature, SPELL_SUMMON_BROKEN_FROSTMOURNE, false); + break; + case 13160: + UpdateTimer = 6000; + pInstance->SetData(TYPE_EVENT,13170); + m_creature->CastSpell(m_creature, SPELL_SUMMON_BROKEN_FROSTMOURNE_2, false); + break; + case 13180: + UpdateTimer = 12000; + pInstance->SetData(TYPE_EVENT,13190); + if (pFrostmourne = m_creature->SummonCreature(NPC_FROSTMOURNE_HOLDER, SpawnLoc[7].x, SpawnLoc[7].y, SpawnLoc[7].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 5000)) + { + pFrostmourne->CastSpell(pFrostmourne, SPELL_BROKEN_FROSTMOURNE, false); + pFrostmourne->CastSpell(pFrostmourne, SPELL_FROSTMOURNE_TRIGGER, false); + pFrostmourne->GetMotionMaster()->MoveChase(m_creature); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED); + } + break; + case 13200: + DoScriptText(-1631512, m_creature); + m_creature->RemoveAurasDueToSpell(SPELL_SUMMON_BROKEN_FROSTMOURNE); + m_creature->RemoveAllAuras(); + pFrostmourne->RemoveAurasDueToSpell(SPELL_FROSTMOURNE_TRIGGER); + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,13210); + break; + case 13280: + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,13290); + stage = 13; + if (pFrostmourne) pFrostmourne->ForcedDespawn(); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_FROSTMOURNE_TRIGGER))) + pTemp->ForcedDespawn(); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_FROSTMOURNE_HOLDER))) + pTemp->ForcedDespawn(); + SetCombatMovement(true); + battlestarted = true; + break; + default: + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + } + + if (battlestarted && !m_creature->SelectHostileTarget() && !finalphase) + { + battlestarted = false; + pInstance->SetData(TYPE_LICH_KING, FAIL); + pInstance->SetData(TYPE_EVENT,0); + EnterEvadeMode(); + return; + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(stage) + { + case 0: // Phase 1 +// timedCast(SPELL_SHOCKWAVE, diff); + timedCast(SPELL_INFEST, diff); + timedCast(SPELL_SUMMON_DRUDGE_GHOULS, diff); + timedCast(SPELL_PLAGUE_SIPHON, diff); + timedCast(SPELL_SUMMON_SHAMBLING_HORROR, diff); + timedCast(SPELL_NECROTIC_PLAGUE, diff); + + DoMeleeAttackIfReady(); + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631518,m_creature); + }; + + if (m_creature->GetHealthPercent() < 70.0f) + { + stage = 1; + DoScriptText(-1631515,m_creature); + } + break; + case 1: // Go in transition phase + m_creature->AttackStop(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + StartMovement(1,0); + stage = 2; + break; + case 2: + if (movementstarted) return; + doCast(SPELL_REMORSELESS_WINTER); + stage = 3; + break; + case 3: + timedCast(SPELL_SUMMON_RAGING_SPIRIT, diff); + timedCast(SPELL_SUMMON_ICE_SPHERE, diff); + timedCast(SPELL_PAIN_AND_SUFFERING, diff); + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631518,m_creature); + }; + + if (timedQuery(SPELL_REMORSELESS_WINTER, diff)) + { + doCast(SPELL_QUAKE); + stage = 4; + DoScriptText(-1631524, m_creature); + pInstance->OpenDoor(pInstance->GetData64(GO_SNOW_EDGE)); + }; + break; + case 4: // Platform destruct + if (timedQuery(SPELL_QUAKE, diff)) + { + pInstance->OpenDoor(pInstance->GetData64(GO_ICESHARD_1)); + pInstance->OpenDoor(pInstance->GetData64(GO_ICESHARD_2)); + pInstance->OpenDoor(pInstance->GetData64(GO_ICESHARD_3)); + pInstance->OpenDoor(pInstance->GetData64(GO_ICESHARD_4)); + if (GameObject* pGoFloor = pInstance->instance->GetGameObject(pInstance->GetData64(GO_ARTHAS_PLATFORM))) + { + pGoFloor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); + oldflag = pGoFloor->GetUInt32Value(GAMEOBJECT_BYTES_1); + pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1,8449); + } + pInstance->CloseDoor(pInstance->GetData64(GO_FROSTY_WIND)); + pInstance->CloseDoor(pInstance->GetData64(GO_SNOW_EDGE)); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(true); + stage = 5; + } + break; + case 5: // Phase 2 + + if (timedQuery(SPELL_SPAWN_DEFILE, diff)) + { + doCast(SPELL_SPAWN_DEFILE); + DoScriptText(-1631531,m_creature); + } + if (timedQuery(SPELL_SUMMON_VALKYR, diff)) + { + doCast(SPELL_SUMMON_VALKYR); + DoScriptText(-1631527,m_creature); + } + + timedCast(SPELL_SOUL_REAPER, diff); + timedCast(SPELL_INFEST, diff); + + DoMeleeAttackIfReady(); + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631518,m_creature); + }; + + if (m_creature->GetHealthPercent() < 40.0f) + { + stage = 6; + DoScriptText(-1631523,m_creature); + } + break; + case 6: // Go in transition phase + m_creature->AttackStop(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + StartMovement(1,0); + stage = 7; + break; + case 7: // Platform restore + if (movementstarted) return; + if (GameObject* pGoFloor = pInstance->instance->GetGameObject(pInstance->GetData64(GO_ARTHAS_PLATFORM))) + { + pGoFloor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); + pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1,oldflag); + } + pInstance->OpenDoor(pInstance->GetData64(GO_FROSTY_WIND)); + doCast(SPELL_REMORSELESS_WINTER); + stage = 8; + break; + case 8: + timedCast(SPELL_SUMMON_RAGING_SPIRIT, diff); + timedCast(SPELL_SUMMON_ICE_SPHERE, diff); + timedCast(SPELL_PAIN_AND_SUFFERING, diff); + + if (timedQuery(SPELL_BERSERK, diff)) + { + doCast(SPELL_BERSERK); + DoScriptText(-1631518,m_creature); + }; + + if (timedQuery(SPELL_REMORSELESS_WINTER, diff)) + { + DoScriptText(-1631524, m_creature); + doCast(SPELL_SUMMON_VILE_SPIRITS); + for (uint8 i = 0; i < getSpellData(SPELL_SUMMON_VILE_SPIRITS); ++i) + doCast(NPC_VILE_SPIRIT); + doCast(SPELL_QUAKE); + stage = 9; + pInstance->OpenDoor(pInstance->GetData64(GO_SNOW_EDGE)); + }; + + break; + case 9: // Platform destruct + if (timedQuery(SPELL_QUAKE, diff)) + { + if (GameObject* pGoFloor = pInstance->instance->GetGameObject(pInstance->GetData64(GO_ARTHAS_PLATFORM))) + { + pGoFloor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_DAMAGED | GO_FLAG_NODESPAWN); + oldflag = pGoFloor->GetUInt32Value(GAMEOBJECT_BYTES_1); + pGoFloor->SetUInt32Value(GAMEOBJECT_BYTES_1,8449); + } + pInstance->CloseDoor(pInstance->GetData64(GO_SNOW_EDGE)); + pInstance->CloseDoor(pInstance->GetData64(GO_FROSTY_WIND)); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(true); + stage = 10; + } + break; + case 10: // Phase 3 + if (timedQuery(SPELL_SPAWN_DEFILE, diff)) + { + doCast(SPELL_SPAWN_DEFILE); +// DoScriptText(-1631527,m_creature); + } + timedCast(SPELL_SOUL_REAPER, diff); + + if (timedQuery(SPELL_HARVEST_SOUL, diff)) + { + doCast(SPELL_HARVEST_SOUL); + DoScriptText(-1631520,m_creature); + } + + timedCast(SPELL_SOUL_REAPER, diff); + timedCast(SPELL_INFEST, diff); + + DoMeleeAttackIfReady(); + + if (m_creature->GetHealthPercent() < 10.0f) + { + stage = 11; + DoScriptText(-1631513,m_creature); + } + break; + case 11: // Ending Phase start + m_creature->AttackStop(); + SetCombatMovement(false); + StartMovement(6,13000); + stage = 12; + battlestarted = false; + break; + case 12: + break; + case 13: + DoMeleeAttackIfReady(); + break; + } + } +}; + + +CreatureAI* GetAI_boss_the_lich_king_icc(Creature* pCreature) +{ + return new boss_the_lich_king_iccAI(pCreature); +}; + +struct MANGOS_DLL_DECL boss_tirion_iccAI : public ScriptedAI +{ + boss_tirion_iccAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint32 UpdateTimer; + uint32 nextEvent; + uint32 nextPoint; + bool movementstarted; + uint64 MenethilGUID; + + void EnterEvadeMode() + { + if (!pInstance) return; + if (pInstance->GetData(TYPE_LICH_KING) == IN_PROGRESS) return; + ScriptedAI::EnterEvadeMode(); + } + + void Reset() + { + if(!pInstance) return; + movementstarted = false; + m_creature->RemoveAurasDueToSpell(SPELL_ICEBLOCK_TRIGGER); + m_creature->SetOrientation(M_PI_F); + } + + void StartMovement(uint32 id, uint32 _nextEvent) + { + nextPoint = id; + nextEvent = _nextEvent; + m_creature->GetMotionMaster()->MovePoint(id, SpawnLoc[id].x, SpawnLoc[id].y, SpawnLoc[id].z); + pInstance->SetData(TYPE_EVENT,0); + movementstarted = true; + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || !movementstarted) return; + if (id == nextPoint) + { + movementstarted = false; + pInstance->SetData(TYPE_EVENT,nextEvent); + m_creature->GetMotionMaster()->MovementExpired(); + } + } + + void doSendCinematic() + { + Map::PlayerList const &pList = m_creature->GetMap()->GetPlayers(); + if (pList.isEmpty()) return; + for (Map::PlayerList::const_iterator i = pList.begin(); i != pList.end(); ++i) + if (Player* pPlayer = i->getSource()) + if (pPlayer && pPlayer->isAlive() && pPlayer->IsInMap(m_creature)) + pPlayer->SendMovieStart(FINAL_ARTHAS_MOVIE); + } + + void doRevivePlayers() + { + Creature* pMenethil = m_creature->GetMap()->GetCreature(MenethilGUID); + Map::PlayerList const &pList = pMenethil->GetMap()->GetPlayers(); + if (pList.isEmpty()) return; + for (Map::PlayerList::const_iterator i = pList.begin(); i != pList.end(); ++i) + { + if (Player* pPlayer = i->getSource()) + { + if (pPlayer && !pPlayer->isAlive() && pPlayer->IsInMap(pMenethil)) + { + pMenethil->CastSpell(pPlayer, SPELL_REVALL, true); + pPlayer->ResurrectPlayer(100, false); + } + } + }; + } + + void UpdateAI(const uint32 diff) + { + + if (pInstance->GetData(TYPE_LICH_KING) == FAIL && m_creature->HasAura(SPELL_ICEBLOCK_TRIGGER)) + { + m_creature->RemoveAurasDueToSpell(SPELL_ICEBLOCK_TRIGGER); + m_creature->GetMotionMaster()->MoveTargetedHome(); + Reset(); + } + + if (pInstance->GetData(TYPE_EVENT_NPC) == NPC_TIRION) + { + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + if (UpdateTimer <= diff) + { + debug_log("EventMGR: creature %u received signal %u ",m_creature->GetEntry(),pInstance->GetData(TYPE_EVENT)); + switch (pInstance->GetData(TYPE_EVENT)) + { + case 12030: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_TALK); + DoScriptText(-1631552, m_creature); + UpdateTimer = 9000; + pInstance->SetData(TYPE_EVENT,12040); + break; + case 12050: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_POINT_NOSHEATHE); + DoScriptText(-1631554, m_creature); + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,12051); + break; + case 12051: + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + UpdateTimer = 1000; + pInstance->SetData(TYPE_EVENT,12052); + break; + case 12052: + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + StartMovement(3,12053); + break; + case 12053: + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,12060); + m_creature->CastSpell(m_creature, SPELL_ICEBLOCK_TRIGGER, true); + break; + case 13110: + DoScriptText(-1631555, m_creature); + UpdateTimer = 6000; + m_creature->CastSpell(m_creature, SPELL_TIRION_LIGHT, false); + pInstance->SetData(TYPE_EVENT,13120); + break; + case 13130: + SetCombatMovement(false); + m_creature->RemoveAurasDueToSpell(SPELL_ICEBLOCK_TRIGGER); + UpdateTimer = 500; + m_creature->SetOrientation(0.0f); + pInstance->SetData(TYPE_EVENT,13131); + break; + case 13131: + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + StartMovement(2,13132); + break; + case 13132: + StartMovement(5,13140); + DoScriptText(-1631556, m_creature); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H); + break; + case 13150: + UpdateTimer = 1000; + pInstance->SetData(TYPE_EVENT,13160); + break; + case 13170: + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,13180); + break; + case 13190: + UpdateTimer = 500; + pInstance->SetData(TYPE_EVENT,13200); + break; + case 13210: + UpdateTimer = 3000; + pInstance->SetData(TYPE_EVENT,13230); + break; + case 13230: + UpdateTimer = 12000; + { + Creature* pMenethil = m_creature->SummonCreature(NPC_MENETHIL, m_creature->GetPositionX()+5, m_creature->GetPositionY()+5, m_creature->GetPositionZ(), 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + MenethilGUID = pMenethil->GetGUID(); + } + pInstance->SetData(TYPE_EVENT,13250); + DoScriptText(-1631560, m_creature->GetMap()->GetCreature(MenethilGUID)); + break; + case 13250: + UpdateTimer = 6000; + pInstance->SetData(TYPE_EVENT,13270); + { + Creature* pMenethil = m_creature->GetMap()->GetCreature(MenethilGUID); + DoScriptText(-1631561, pMenethil); + pMenethil->CastSpell(pMenethil, SPELL_REVIVE_VISUAL, false); + } + doRevivePlayers(); + break; + case 13270: + UpdateTimer = 6000; + pInstance->SetData(TYPE_EVENT,13280); + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_LICH_KING))) + { + m_creature->SetInCombatWith(pLichKing); + pLichKing->SetInCombatWith(m_creature); + pLichKing->AddThreat(m_creature, 1000.0f); + m_creature->AI()->AttackStart(pLichKing); + Creature* pMenethil = m_creature->GetMap()->GetCreature(MenethilGUID); + pMenethil->AI()->AttackStart(pLichKing); + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(pLichKing); + }; + break; + case 13290: + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,13310); + DoScriptText(-1631590,m_creature->GetMap()->GetCreature(MenethilGUID)); + break; + case 13310: + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,13330); + DoScriptText(-1631591, m_creature); + break; + case 13330: + UpdateTimer = 5000; + pInstance->SetData(TYPE_EVENT,13350); + DoScriptText(-1631592, m_creature->GetMap()->GetCreature(MenethilGUID)); + break; + case 13350: + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,13370); + DoScriptText(-1631593, m_creature); + break; + case 14010: + m_creature->AttackStop(); + SetCombatMovement(false); + UpdateTimer =90000; + pInstance->SetData(TYPE_EVENT,14030); + m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE); + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_LICH_KING))) + pLichKing->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + doSendCinematic(); + break; + case 14030: + UpdateTimer = 20000; + pInstance->SetData(TYPE_EVENT,14030); + DoScriptText(-1631594, m_creature); + { + if (Creature* pMenethil = m_creature->GetMap()->GetCreature(MenethilGUID)) + if (pMenethil->isAlive()) + pMenethil->ForcedDespawn(); + if (Creature* pLichKing = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_LICH_KING))) + pLichKing->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + pInstance->SetData(TYPE_EVENT,0); + EnterEvadeMode(); + break; + default: + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + DoMeleeAttackIfReady(); + } + + +}; + +bool GossipHello_boss_tirion_icc(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance; + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + + if (pInstance->GetData(TYPE_LICH_KING) != NOT_STARTED && + pInstance->GetData(TYPE_LICH_KING) != FAIL ) + { + pPlayer->PlayerTalkClass->SendGossipMenu(721002, pCreature->GetGUID()); + return true; + }; + + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, -3631608, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF); + pPlayer->PlayerTalkClass->SendGossipMenu(721001, pCreature->GetGUID()); + return true; +}; + +bool GossipSelect_boss_tirion_icc(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance* pInstance; + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + if (!pInstance) return false; + + if (uiAction == GOSSIP_ACTION_INFO_DEF) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pInstance->SetData(TYPE_LICH_KING, IN_PROGRESS); + pInstance->SetData(TYPE_EVENT,12000); + return true; + } else return false; +}; + +CreatureAI* GetAI_boss_tirion_icc(Creature* pCreature) +{ + return new boss_tirion_iccAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_ice_sphere_iccAI : public BSWScriptedAI +{ + mob_ice_sphere_iccAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + resetTimers(); + doCast(SPELL_ICE_SPHERE_VISUAL); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_LICH_KING) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!hasAura(SPELL_ICE_SPHERE_VISUAL)) + doCast(SPELL_ICE_SPHERE_VISUAL); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + { + if (Unit* pTarget = doSelectRandomPlayerAtRange(120.0f)) + { + m_creature->SetInCombatWith(pTarget); + m_creature->AddThreat(pTarget,100.0f); + } + return; + } + + if (m_creature->getVictim()->GetTypeId() != TYPEID_PLAYER) + return; + + timedCast(SPELL_ICE_PULSE, uiDiff); + + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 1.0f)) + timedCast(SPELL_ICE_BURST,uiDiff); + } +}; + +CreatureAI* GetAI_mob_ice_sphere_icc(Creature* pCreature) +{ + return new mob_ice_sphere_iccAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_defiler_iccAI : public BSWScriptedAI +{ + mob_defiler_iccAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance *m_pInstance; + uint32 life_timer; + float m_Size0; + float m_Size; + + void Reset() + { + SetCombatMovement(false); + life_timer = 30000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->CastSpell(m_creature, SPELL_DEFILE, true); + m_Size0 = m_creature->GetFloatValue(OBJECT_FIELD_SCALE_X); + m_Size = m_Size0; + } + + void AttackStart(Unit *pWho) + { + return; + } + + bool doSearchPlayers() + { + if(doSelectRandomPlayerAtRange(m_Size * 3.0f)) return true; + else return false; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_pInstance && m_pInstance->GetData(TYPE_LICH_KING) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (life_timer <= uiDiff) + m_creature->ForcedDespawn(); + else life_timer -= uiDiff; + + if (doSearchPlayers() && m_Size <= m_Size0 * 6.0f) { + m_Size = m_Size*1.01; + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_Size); + } + + } + +}; + +CreatureAI* GetAI_mob_defiler_icc(Creature* pCreature) +{ + return new mob_defiler_iccAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_strangulate_vehicleAI : public ScriptedAI +{ + mob_strangulate_vehicleAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance *m_pInstance; + + void Reset() + { + SetCombatMovement(false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void AttackStart(Unit *pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + m_creature->ForcedDespawn(); + } + +}; + +CreatureAI* GetAI_mob_strangulate_vehicle(Creature* pCreature) +{ + return new mob_strangulate_vehicleAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_vile_spiritAI : public BSWScriptedAI +{ + mob_vile_spiritAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + bool movementstarted; + + void Reset() + { + resetTimers(); + if (Unit* pTarget = doSelectRandomPlayerAtRange(120.0f)) + { + m_creature->SetInCombatWith(pTarget); + m_creature->AddThreat(pTarget,1000.0f); + } + SetCombatMovement(false); + movementstarted = false; + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + } + + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_LICH_KING) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (timedQuery(SPELL_SPIRITS_BURST, uiDiff) && !movementstarted) + { + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + movementstarted = true; + } + + if (m_creature->getVictim()->GetTypeId() != TYPEID_PLAYER) + return; + + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 1.0f)) + { + doCast(SPELL_SPIRITS_BURST); + m_creature->ForcedDespawn(); + }; + } +}; + +CreatureAI* GetAI_mob_vile_spirit(Creature* pCreature) +{ + return new mob_vile_spiritAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_raging_spiritAI : public BSWScriptedAI +{ + mob_raging_spiritAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + resetTimers(); + m_creature->SetDisplayId(10771); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_LICH_KING) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + timedCast(SPELL_SOUL_SHRIEK, uiDiff); + } +}; + +CreatureAI* GetAI_mob_raging_spirit(Creature* pCreature) +{ + return new mob_raging_spiritAI(pCreature); +} + +void AddSC_boss_lich_king_icc() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_the_lich_king_icc"; + newscript->GetAI = &GetAI_boss_the_lich_king_icc; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_tirion_icc"; + newscript->GetAI = &GetAI_boss_tirion_icc; + newscript->pGossipHello = &GossipHello_boss_tirion_icc; + newscript->pGossipSelect = &GossipSelect_boss_tirion_icc; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_ice_sphere_icc"; + newscript->GetAI = &GetAI_mob_ice_sphere_icc; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_defiler_icc"; + newscript->GetAI = &GetAI_mob_defiler_icc; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_strangulate_vehicle"; + newscript->GetAI = &GetAI_mob_strangulate_vehicle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vile_spirit"; + newscript->GetAI = &GetAI_mob_vile_spirit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_raging_spirit"; + newscript->GetAI = &GetAI_mob_raging_spirit; + newscript->RegisterSelf(); + +}; diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_valithria_dreamwalker.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_valithria_dreamwalker.cpp index 5adb40e..2d4fd7b 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_valithria_dreamwalker.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/boss_valithria_dreamwalker.cpp @@ -16,9 +16,513 @@ /* ScriptData SDName: boss_valithria -SD%Complete: 0% -SDComment: +SD%Complete: 70% +SDComment: by /dev/rsa SDCategory: Icecrown Citadel EndScriptData */ - +// Need move emerald dream to phase 32, correct timers and other #include "precompiled.h" +#include "def_spire.h" + +static Locations SpawnLoc[]= +{ + {4203.470215f, 2484.500000f, 364.872009f}, // 0 Valithria + {4166.216797f, 2564.197266f, 364.873047f}, // 1 Valithria Room 1 + {4240.688477f, 2405.794678f, 364.868591f}, // 2 Valithria Room 2 + {4165.112305f, 2405.872559f, 364.872925f}, // 3 Valithria Room 3 + {4239.579102f, 2566.753418f, 364.868439f}, // 4 Valithria Room 4 + {4228.589844f, 2469.110107f, 364.868988f}, // 5 Mob 1 + {4236.000000f, 2479.500000f, 364.869995f}, // 6 Mob 2 + {4235.410156f, 2489.300049f, 364.872009f}, // 7 Mob 3 + {4228.509766f, 2500.310059f, 364.876007f}, // 8 Mob 4 +}; + +enum BossSpells +{ +// SPELL_NIGHTMARE_PORTAL = 72481, // Not worked yet. Use 71977 (visual effect) instead? + SPELL_NIGHTMARE_PORTAL = 71977, + SPELL_EMERALD_VIGOR = 70873, + SPELL_DREAMWALKER_RAGE = 71189, + SPELL_IMMUNITY = 72724, + SPELL_CORRUPTION = 70904, + SPELL_DREAM_SLIP = 71196, + SPELL_ICE_SPIKE = 70702, + +// Summons + NPC_RISEN_ARCHMAGE = 37868, + NPC_SUPPRESSOR = 37863, + NPC_BLASING_SKELETON = 36791, + NPC_BLISTERING_ZOMBIE = 37934, + NPC_GLUTTONOUS_ABOMINATION = 37886, + NPC_NIGHTMARE_PORTAL = 38429, // Not realized yet + // Mana void + NPC_MANA_VOID = 38068, // Bugged, need override + SPELL_VOID_BUFF = 71085, +}; + +struct MANGOS_DLL_DECL boss_valithria_dreamwalkerAI : public BSWScriptedAI +{ + boss_valithria_dreamwalkerAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (instance_icecrown_spire*)pCreature->GetInstanceData(); + Reset(); + } + + instance_icecrown_spire* pInstance; + bool battlestarted; + bool intro; + uint8 currentDoor; + uint8 currentDoor2; + int8 portalscount; + std::list mobsGUIDList; + uint32 speedK; + Creature* dummyTarget; + + void Reset() + { + if(!pInstance) return; + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetHealth(m_creature->GetMaxHealth()/2.0f); + if (pInstance->GetData(TYPE_VALITHRIA) != DONE) + pInstance->SetData(TYPE_VALITHRIA, NOT_STARTED); + else m_creature->ForcedDespawn(); + resetTimers(); + SetCombatMovement(false); + setStage(0); + speedK = 0; + portalscount = 0; + battlestarted = false; + intro = false; + currentDoor = 0; + currentDoor2 = 0; + mobsGUIDList.clear(); + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_VALITHRIA_QUEST))) + if (pTemp->GetVisibility() == VISIBILITY_ON) + pTemp->SetVisibility(VISIBILITY_OFF); + doCast(SPELL_CORRUPTION); + } + + uint64 GetDoor(uint8 doornum) + { + switch (doornum) { + case 1: + return pInstance->GetData64(GO_VALITHRIA_DOOR_1); + break; + case 2: + return pInstance->GetData64(GO_VALITHRIA_DOOR_2); + break; + case 3: + return pInstance->GetData64(GO_VALITHRIA_DOOR_3); + break; + case 4: + return pInstance->GetData64(GO_VALITHRIA_DOOR_4); + break; + default: + return 0; + break; + }; + } + + void CallMobs(uint8 door) + { + if(!door) return; + uint8 mobs; + uint32 randommob; + + switch (currentDifficulty) { + case RAID_DIFFICULTY_10MAN_NORMAL: + mobs = urand(1,3); + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + mobs = urand(2,4); + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + mobs = urand(2,5); + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + mobs = urand(3,5); + break; + default: + mobs = urand(1,5); + break; + } + + for(uint8 i = 0; i <= mobs; ++i) + { + switch (urand(0,4)) { + case 0: randommob = NPC_RISEN_ARCHMAGE; break; + case 1: randommob = NPC_SUPPRESSOR; break; + case 2: randommob = NPC_BLASING_SKELETON; break; + case 3: randommob = NPC_BLISTERING_ZOMBIE; break; + case 4: randommob = NPC_GLUTTONOUS_ABOMINATION;break; + default: randommob = NPC_RISEN_ARCHMAGE; break; + } + if (Unit* pTemp = doSummon(randommob, SpawnLoc[door].x, SpawnLoc[door].y, SpawnLoc[door].z, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000)) + mobsGUIDList.push_back(pTemp->GetGUID()); + } + } + + void QueryEvadeMode() + { + + if ( m_creature->GetHealthPercent() > 1.0f ) { + Map* pMap = m_creature->GetMap(); + Map::PlayerList const &players = pMap->GetPlayers(); + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + { + if(Player* pPlayer = i->getSource()) + if(pPlayer->isAlive() && !pPlayer->isGameMaster() + && pPlayer->IsWithinDistInMap(m_creature, 90.0f)) return; + } + } + pInstance->SetData(TYPE_VALITHRIA, FAIL); + DoScriptText(-1631409,m_creature); + DespawnMobs(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->LoadCreatureAddon(); + if (m_creature->isAlive()) + m_creature->GetMotionMaster()->MoveTargetedHome(); + m_creature->SetLootRecipient(NULL); + pInstance->CloseDoor(GetDoor(currentDoor)); + pInstance->CloseDoor(GetDoor(currentDoor2)); + Reset(); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pInstance || ( intro && battlestarted)) return; + + if (pWho->GetTypeId() != TYPEID_PLAYER) return; + + if (!intro) + { + DoScriptText(-1631401,m_creature,pWho); + intro = true; + doCast(SPELL_IMMUNITY); + } + if (!battlestarted && pWho->isAlive() && pWho->IsWithinDistInMap(m_creature, 40.0f)) + { + DoScriptText(-1631401,m_creature,pWho); + battlestarted = true; + pInstance->SetData(TYPE_VALITHRIA, IN_PROGRESS); + m_creature->SetHealth(m_creature->GetMaxHealth()/2.0f); + dummyTarget = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_COMBAT_TRIGGER)); + if (!dummyTarget) + dummyTarget = m_creature->SummonCreature(NPC_COMBAT_TRIGGER, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 1000); + if (!dummyTarget->isAlive()) + dummyTarget->Respawn(); + if (dummyTarget) + { + dummyTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + dummyTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + dummyTarget->GetMotionMaster()->MoveIdle(); + dummyTarget->StopMoving(); + } + m_creature->SetInCombatWith(dummyTarget); + m_creature->SetHealth(m_creature->GetMaxHealth()/2.0f); + } + } + + void KilledUnit(Unit* pVictim) + { + if(!pInstance) return; + + switch (urand(0,1)) { + case 0: + DoScriptText(-1631403,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631404,m_creature,pVictim); + break; + }; + } + + void JustSummoned(Creature* summoned) + { + if(!pInstance || !summoned || !battlestarted) return; + + if ( summoned->GetEntry() != NPC_NIGHTMARE_PORTAL ) { + m_creature->SetInCombatWithZone(); + m_creature->SetInCombatWith(summoned); + summoned->SetInCombatWith(m_creature); + summoned->AddThreat(m_creature, 100.0f); + summoned->GetMotionMaster()->MoveChase(m_creature); + } + + } + + void DespawnMobs() + { + if (mobsGUIDList.empty()) + return; + + for(std::list::iterator itr = mobsGUIDList.begin(); itr != mobsGUIDList.end(); ++itr) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + if (pTemp->isAlive()) + { + pTemp->DeleteThreatList(); + pTemp->CombatStop(true); + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + mobsGUIDList.clear(); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return + pInstance->SetData(TYPE_VALITHRIA, FAIL); + DoScriptText(-1631409,m_creature); + DespawnMobs(); + m_creature->Respawn(); + Reset(); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!m_creature || !m_creature->isAlive()) + return; + + if (uiDamage >= m_creature->GetHealth()) uiDamage = 0; + } + + void AttackStart(Unit *who) + { + } + + void UpdateAI(const uint32 diff) + { + + if (!hasAura(SPELL_CORRUPTION,m_creature) && getStage() == 0) + doCast(SPELL_CORRUPTION); + + if (!battlestarted) return; + + QueryEvadeMode(); + + switch(getStage()) + { + case 0: + if ( m_creature->GetHealthPercent() > 90.0f ) setStage(2); + if ( m_creature->GetHealthPercent() < 10.0f ) setStage(3); + break; + case 1: + if ( m_creature->GetHealthPercent() < 90.0f && m_creature->GetHealthPercent() > 10.0f ) setStage(0); + if ( m_creature->GetHealthPercent() > 99.9f ) setStage(5); + break; + case 2: + DoScriptText(-1631407,m_creature); + setStage(1); + break; + case 3: + DoScriptText(-1631406,m_creature); + setStage(1); + break; + case 4: + break; + case 5: + DoScriptText(-1631408,m_creature); + if (hasAura(SPELL_CORRUPTION,m_creature)) doRemove(SPELL_CORRUPTION); + setStage(6); + return; + break; + case 6: + if (timedQuery(SPELL_CORRUPTION, diff)) setStage(7); + return; + break; + case 7: + doCast(SPELL_DREAMWALKER_RAGE); + setStage(8); + return; + break; + case 8: + if (timedQuery(SPELL_CORRUPTION, diff)) + { + setStage(9); + DespawnMobs(); + } + return; + break; + case 9: + if (Creature* pTemp = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_VALITHRIA_QUEST))) + { + pTemp->SetPhaseMask(65535,true); + if (pTemp->HasAura(SPELL_CORRUPTION)) + pTemp->RemoveAurasDueToSpell(SPELL_CORRUPTION); + if (pTemp->GetVisibility() == VISIBILITY_OFF) + pTemp->SetVisibility(VISIBILITY_ON); + } + pInstance->SetData(TYPE_VALITHRIA, DONE); + setStage(10); + m_creature->ForcedDespawn(); + break; + default: + break; + } + + + if (timedQuery(NPC_RISEN_ARCHMAGE, (uint32)(diff + diff*(speedK/100)))) { + if (urand(0,1) == 1) DoScriptText(-1631402,m_creature); + speedK = speedK+10; + if (currentDifficulty == RAID_DIFFICULTY_25MAN_NORMAL + || currentDifficulty == RAID_DIFFICULTY_25MAN_HEROIC) { + pInstance->CloseDoor(GetDoor(currentDoor2)); + currentDoor2 = urand(1,2); + pInstance->OpenDoor(GetDoor(currentDoor2)); + CallMobs(currentDoor2); + + pInstance->CloseDoor(GetDoor(currentDoor)); + currentDoor = urand(3,4); + pInstance->OpenDoor(GetDoor(currentDoor)); + CallMobs(currentDoor); + } else { + pInstance->CloseDoor(GetDoor(currentDoor)); + currentDoor = urand(1,4); + pInstance->OpenDoor(GetDoor(currentDoor)); + CallMobs(currentDoor); + } + }; + + if (timedQuery(SPELL_NIGHTMARE_PORTAL, diff) || portalscount > 0) + { + if (!portalscount) { + portalscount = 3; + DoScriptText(-1631405,m_creature); + }; + doCast(SPELL_NIGHTMARE_PORTAL); + --portalscount; + }; + + timedCast(SPELL_ICE_SPIKE, diff); + + return; + } +}; + +CreatureAI* GetAI_boss_valithria_dreamwalker(Creature* pCreature) +{ + return new boss_valithria_dreamwalkerAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_nightmare_portalAI : public BSWScriptedAI +{ + mob_nightmare_portalAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool portalcasted; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + m_creature->GetMotionMaster()->MoveRandom(); + m_creature->SetDisplayId(29352); + portalcasted = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_pInstance || portalcasted) return; + + if (pWho->isAlive() && pWho->GetTypeId() == TYPEID_PLAYER && pWho->IsWithinDistInMap(m_creature, 2.0f)) + { + doCast(SPELL_EMERALD_VIGOR); + portalcasted = true; + } + } + + void AttackStart(Unit *pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_VALITHRIA) != IN_PROGRESS || portalcasted) + if (timedQuery(SPELL_EMERALD_VIGOR, uiDiff)) + m_creature->ForcedDespawn(); + + } + +}; + +CreatureAI* GetAI_mob_nightmare_portal(Creature *pCreature) +{ + return new mob_nightmare_portalAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_mana_voidAI : public ScriptedAI +{ + mob_mana_voidAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_ui_Timer; + + void Reset() + { +// m_creature->SetDisplayId(29308); + SetCombatMovement(false); +// m_creature->GetMotionMaster()->MoveRandom(); + m_creature->CastSpell(m_creature, SPELL_VOID_BUFF, false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_ui_Timer = 30000; + } + + void AttackStart(Unit *pWho) + { + return; + } + + void JustDied(Unit *killer) + { + m_creature->RemoveCorpse(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_pInstance || m_pInstance->GetData(TYPE_VALITHRIA) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_ui_Timer < uiDiff) + m_creature->ForcedDespawn(); + else m_ui_Timer -= uiDiff; + } + +}; + +CreatureAI* GetAI_mob_mana_void(Creature *pCreature) +{ + return new mob_mana_voidAI(pCreature); +}; + +void AddSC_boss_valithria_dreamwalker() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_valithria_dreamwalker"; + newscript->GetAI = &GetAI_boss_valithria_dreamwalker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_nightmare_portal"; + newscript->GetAI = &GetAI_mob_nightmare_portal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_mana_void"; + newscript->GetAI = &GetAI_mob_mana_void; + newscript->RegisterSelf(); + +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/def_spire.h b/scripts/northrend/icecrown_citadel/icecrown_citadel/def_spire.h new file mode 100644 index 0000000..bd9c469 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/def_spire.h @@ -0,0 +1,273 @@ +/* Copyright (C) 2010 by /dev/rsa for ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_ICECROWN_SPIRE_H +#define DEF_ICECROWN_SPIRE_H +#include "BSW_ai.h" + +enum +{ + + TYPE_TELEPORT = 0, + TYPE_MARROWGAR = 1, + TYPE_DEATHWHISPER = 2, + TYPE_FLIGHT_WAR = 3, + TYPE_SAURFANG = 4, + TYPE_FESTERGUT = 5, + TYPE_ROTFACE = 6, + TYPE_PUTRICIDE = 7, + TYPE_BLOOD_COUNCIL = 8, + TYPE_LANATHEL = 9, + TYPE_VALITHRIA = 10, + TYPE_SINDRAGOSA = 11, + TYPE_KINGS_OF_ICC = 12, + TYPE_LICH_KING = 13, + TYPE_ICECROWN_QUESTS = 14, + TYPE_COUNT = 15, + MAX_ENCOUNTERS, + + TYPE_STINKY, + TYPE_PRECIOUS, + + NPC_LORD_MARROWGAR = 36612, + NPC_LADY_DEATHWHISPER = 36855, + NPC_DEATHBRINGER_SAURFANG = 37813, + NPC_FESTERGUT = 36626, + NPC_ROTFACE = 36627, + NPC_PROFESSOR_PUTRICIDE = 36678, + NPC_TALDARAM = 37973, + NPC_VALANAR = 37970, + NPC_KELESETH = 37972, + NPC_LANATHEL = 37955, + NPC_VALITHRIA = 36789, + NPC_VALITHRIA_QUEST = 38589, + NPC_SINDRAGOSA = 36853, + NPC_LICH_KING = 36597, + + NPC_LANATHEL_INTRO = 38004, + NPC_BLOOD_ORB_CONTROL = 38008, + + NPC_MURADIN = 36948, + + NPC_TIRION = 38995, + NPC_MENETHIL = 38579, + NPC_SPIRIT_WARDEN = 38579, + + NPC_FROSTMOURNE_TRIGGER = 38584, + NPC_FROSTMOURNE_HOLDER = 27880, + + NPC_STINKY = 37025, + NPC_PRECIOUS = 37217, + + NPC_RIMEFANG = 37533, + NPC_SPINESTALKER = 37534, + + NPC_COMBAT_TRIGGER = 38752, + + GO_TELEPORT_GOSSIP_MESSAGE = 99323, + TELEPORT_GOSSIP_MESSAGE = 99322, + + GO_ICEWALL_1 = 201911, + GO_ICEWALL_2 = 201910, + + GO_ORATORY_DOOR = 201563, + GO_DEATHWHISPER_ELEVATOR = 202220, //5653 + + GO_SAURFANG_DOOR = 201825, + + GO_GAS_RELEASE_VALVE = 201616, //72479 + + GO_ORANGE_PLAGUE = 201371, //72536 + GO_GREEN_PLAGUE = 201370, //72537 + + GO_SCIENTIST_DOOR_GREEN = 201614, //72530 + GO_SCIENTIST_DOOR_ORANGE = 201613, //72531 + GO_SCIENTIST_DOOR_COLLISION = 201612, + GO_SCIENTIST_DOOR = 201372, //72541 + + GO_BLOODWING_DOOR = 201920, //72532 + GO_CRIMSON_HALL_DOOR = 201376, //72532 + GO_COUNCIL_DOOR_1 = 201377, //72533 + GO_COUNCIL_DOOR_2 = 201378, //72534 + + GO_FROSTWING_DOOR = 201919, + GO_GREEN_DRAGON_DOOR_1 = 201375, //1202 + GO_GREEN_DRAGON_DOOR_2 = 201374, //1200 + GO_VALITHRIA_DOOR_1 = 201380, //1618 + GO_VALITHRIA_DOOR_2 = 201382, //1482 + GO_VALITHRIA_DOOR_3 = 201383, //1335 + GO_VALITHRIA_DOOR_4 = 201381, //1558 + + GO_SINDRAGOSA_DOOR_1 = 201369, //1619 + GO_SINDRAGOSA_DOOR_2 = 201379, + + GO_FROZENTRONE_TR = 202223, //72061 + + GO_SAURFANG_CACHE_10 = 202239, + GO_SAURFANG_CACHE_25 = 202240, + GO_SAURFANG_CACHE_10_H = 202238, + GO_SAURFANG_CACHE_25_H = 202241, + + GO_GUNSHIP_ARMORY_A_10 = 201872, // + GO_GUNSHIP_ARMORY_A_25 = 201873, // + GO_GUNSHIP_ARMORY_A_10H = 201874, // + GO_GUNSHIP_ARMORY_A_25H = 201875, // + + GO_GUNSHIP_ARMORY_H_10 = 202177, // + GO_GUNSHIP_ARMORY_H_25 = 202178, // + GO_GUNSHIP_ARMORY_H_10H = 202179, // + GO_GUNSHIP_ARMORY_H_25H = 202180, // + + GO_DREAMWALKER_CACHE_10 = 201959, // + GO_DREAMWALKER_CACHE_25 = 202339, // + GO_DREAMWALKER_CACHE_10_H = 202338, // + GO_DREAMWALKER_CACHE_25_H = 202340, // + + GO_PLAGUE_SIGIL = 202182, + GO_FROSTWING_SIGIL = 202181, + GO_BLOODWING_SIGIL = 202183, + + GO_ICESHARD_1 = 202142, //8304 + GO_ICESHARD_2 = 202141, //8364 + GO_ICESHARD_3 = 202143, //8310 + GO_ICESHARD_4 = 202144, //9007 + + GO_FROSTY_WIND = 202188, // + GO_FROSTY_EDGE = 202189, // + GO_SNOW_EDGE = 202190, // + GO_ARTHAS_PLATFORM = 202161, // + GO_ARTHAS_PRECIPICE = 202078, // + + TYPE_EVENT_TIMER = 99, + TYPE_EVENT = 100, + TYPE_EVENT_NPC = 101, + MAP_NUM = 631, + DATA_DIRECTION = 1001, + DATA_BLOOD_COUNCIL_HEALTH = 1002, + DATA_BLOOD_INVOCATION = 1003, + DESPAWN_TIME = 300000, + +}; + +class MANGOS_DLL_DECL instance_icecrown_spire : public ScriptedInstance +{ +public: + instance_icecrown_spire(Map* pMap); + ~instance_icecrown_spire() {} + + void Initialize(); + + void OnObjectCreate(GameObject* pGo); + void OnCreatureCreate(Creature* pCreature); + + void OpenDoor(uint64 guid); + void CloseDoor(uint64 guid); + void OpenAllDoors(); + void OnPlayerEnter(Player* pPlayer); + bool IsEncounterInProgress() const; + + void SetData(uint32 uiType, uint32 uiData); + uint32 GetData(uint32 uiType); + uint64 GetData64(uint32 uiType); + + const char* Save() { return strSaveData.c_str(); } + void Load(const char* chrIn); + +private: + + uint8 Difficulty; + bool needSave; + std::string strSaveData; + + //Creatures GUID + uint32 m_auiEncounter[MAX_ENCOUNTERS+1]; + uint64 m_uiMarrogwarGUID; + uint64 m_uiDeathWhisperGUID; + uint64 m_uiSaurfangGUID; + uint64 m_uiRotfaceGUID; + uint64 m_uiFestergutGUID; + uint64 m_uiPutricideGUID; + uint64 m_uiTaldaramGUID; + uint64 m_uiValanarGUID; + uint64 m_uiKelesethGUID; + uint64 m_uiLanathelGUID; + uint64 m_uiLanathelintroGUID; + uint64 m_uiValithriaGUID; + uint64 m_uiValithriaQuestGUID; + uint64 m_uiSindragosaGUID; + uint64 m_uiLichKingGUID; + uint64 m_uiGasReleaseValveGUID; + uint64 m_uiBloodOrbCtrlGUID; + + uint64 m_uiRimefangGUID; + uint64 m_uiSpinestalkerGUID; + + uint64 m_uiStinkyGUID; + uint64 m_uiPreciousGUID; + + uint64 m_uidummyTargetGUID; + + uint64 m_uiIcewall1GUID; + uint64 m_uiIcewall2GUID; + uint64 m_uiSaurfangDoorGUID; + uint64 m_uiOratoryDoorGUID; + uint64 m_uiDeathWhisperElevatorGUID; + uint64 m_uiOrangePlagueGUID; + uint64 m_uiGreenPlagueGUID; + uint64 m_uiSDoorGreenGUID; + uint64 m_uiSDoorOrangeGUID; + uint64 m_uiSDoorCollisionGUID; + uint64 m_uiScientistDoorGUID; + uint64 m_uiCrimsonDoorGUID; + uint64 m_uiBloodwingDoorGUID; + uint64 m_uiCounsilDoor1GUID; + uint64 m_uiCounsilDoor2GUID; + uint64 m_uiGreenDragonDoor1GUID; + uint64 m_uiGreenDragonDoor2GUID; + uint64 m_uiFrostwingDoorGUID; + + uint64 m_uiValithriaDoor1GUID; + uint64 m_uiValithriaDoor2GUID; + uint64 m_uiValithriaDoor3GUID; + uint64 m_uiValithriaDoor4GUID; + + uint64 m_uiSindragosaDoor1GUID; + uint64 m_uiSindragosaDoor2GUID; + + uint64 m_uiIceShard1GUID; + uint64 m_uiIceShard2GUID; + uint64 m_uiIceShard3GUID; + uint64 m_uiIceShard4GUID; + + uint64 m_uiFrostyWindGUID; + uint64 m_uiFrostyEdgeGUID; + uint64 m_uiSnowEdgeGUID; + uint64 m_uiArthasPlatformGUID; + uint64 m_uiArthasPrecipiceGUID; + + uint64 m_uiFrostmourneGUID; + uint64 m_uiFrostmourneTriggerGUID; + uint64 m_uiFrostmourneHolderGUID; + + uint64 m_uiSaurfangCacheGUID; + uint64 m_uiGunshipArmoryAGUID; + uint64 m_uiGunshipArmoryHGUID; + uint64 m_uiValitriaCacheGUID; + + uint64 m_uiGunshipArmoryH_ID; + uint64 m_uiGunshipArmoryA_ID; + + uint32 m_uiDataCouncilHealth; + uint32 m_uiCouncilInvocation; + + uint32 m_auiEvent; + uint32 m_auiEventTimer; + uint32 m_uiDirection; + + uint32 m_uiStinkystate; + uint32 m_uiPreciousstate; + +}; + +#endif diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/gunship_battle.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/gunship_battle.cpp index 39d9f43..905c401 100644 --- a/scripts/northrend/icecrown_citadel/icecrown_citadel/gunship_battle.cpp +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/gunship_battle.cpp @@ -22,3 +22,7 @@ SDCategory: Icecrown Citadel EndScriptData */ #include "precompiled.h" + +void AddSC_gunship_battle() +{ +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_citadel.h b/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_citadel.h new file mode 100644 index 0000000..e592de1 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_citadel.h @@ -0,0 +1,3 @@ +/* Copyright (C) 2006 - 2010 ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_spire.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_spire.cpp new file mode 100644 index 0000000..c4bd4a4 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_spire.cpp @@ -0,0 +1,174 @@ +/* Copyright (C) 2006 - 2010 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: icecrown_spire +SD%Complete: 100% +SDComment: by /dev/rsa +SDCategory: Icecrown Citadel - mobs +EndScriptData */ + +#include "precompiled.h" +#include "def_spire.h" +enum +{ + SPELL_BERSERK = 47008, + SPELL_FROST_BREATH = 70116, + SPELL_BLIZZARD = 70362, + SPELL_SOUL_FEAST = 71203, + SPELL_CLEAVE = 70361, + + SPELL_STOMP = 64652, + SPELL_DEATH_PLAGUE = 72865, +}; + +struct MANGOS_DLL_DECL mob_spire_frostwyrmAI : public BSWScriptedAI +{ + mob_spire_frostwyrmAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 stage; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + stage = 0; + resetTimers(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(stage) + { + case 0: { + timedCast(SPELL_SOUL_FEAST, diff); + break;} + case 1: { + doCast(SPELL_BERSERK); + stage = 2; + break;} + case 2: { + break;} + } + + timedCast(SPELL_CLEAVE, diff); + timedCast(SPELL_BLIZZARD, diff); + timedCast(SPELL_FROST_BREATH, diff); + + if (m_creature->GetHealthPercent() < 10.0f && stage == 0) stage = 1; + + timedCast(SPELL_BERSERK, diff); + + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_mob_spire_frostwyrm(Creature* pCreature) +{ + return new mob_spire_frostwyrmAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_frost_giantAI : public BSWScriptedAI +{ + mob_frost_giantAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 stage; + + void Aggro(Unit *who) + { + if(pInstance) pInstance->SetData(TYPE_FLIGHT_WAR, IN_PROGRESS); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return; + if (killer->GetTypeId() == TYPEID_PLAYER) + pInstance->SetData(TYPE_FLIGHT_WAR, DONE); + } + + void JustReachedHome() + { + if (pInstance) pInstance->SetData(TYPE_FLIGHT_WAR, FAIL); + } + + void Reset() + { + m_creature->SetRespawnDelay(7*DAY); + stage = 0; + resetTimers(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(stage) + { + case 0: { + timedCast(SPELL_SOUL_FEAST, diff); + break;} + case 1: { + doCast(SPELL_BERSERK); + stage = 2; + break;} + case 2: { + break;} + } + timedCast(SPELL_STOMP, diff); + timedCast(SPELL_DEATH_PLAGUE, diff); + + if (m_creature->GetHealthPercent() < 2.0f && stage == 0) stage = 1; + + timedCast(SPELL_BERSERK, diff); + + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_mob_frost_giant(Creature* pCreature) +{ + return new mob_frost_giantAI(pCreature); +} + +void AddSC_icecrown_spire() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_spire_frostwyrm"; + newscript->GetAI = &GetAI_mob_spire_frostwyrm; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_giant"; + newscript->GetAI = &GetAI_mob_frost_giant; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_teleport.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_teleport.cpp new file mode 100644 index 0000000..f4b1ce8 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/icecrown_teleport.cpp @@ -0,0 +1,146 @@ +/* Copyright (C) 2006 - 2010 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: icecrown_teleport +SD%Complete: 100% +SDComment: by /dev/rsa +SDCategory: Icecrown Citadel +EndScriptData */ +#include "precompiled.h" +#include "def_spire.h" + +enum +{ +PORTALS_COUNT = 7 +}; + +struct t_Locations +{ + int textNum; + uint32 map_num; + float x, y, z, o; + uint32 spellID; + bool state; + bool active; + uint32 encounter; +}; + +static t_Locations PortalLoc[]= +{ +{-3631600,MAP_NUM,-17.1928f, 2211.44f, 30.1158f,3.14f,70856,true,true,TYPE_TELEPORT}, // +{-3631601,MAP_NUM,-503.62f, 2211.47f, 62.8235f,3.14f,70856,false,true,TYPE_MARROWGAR}, // +{-3631602,MAP_NUM,-615.145f, 2211.47f, 199.972f,0,70857,false,true,TYPE_DEATHWHISPER}, // +{-3631603,MAP_NUM,-549.131f, 2211.29f, 539.291f,0,70858,false,true,TYPE_FLIGHT_WAR}, // +{-3631604,MAP_NUM,4198.42f, 2769.22f, 351.065f,0,70859,false,true,TYPE_SAURFANG}, // +{-3631606,MAP_NUM,4356.580078f, 2565.75f, 220.401993f,4.90f,70861,false,true,TYPE_VALITHRIA}, // +{-3631607,MAP_NUM,528.767273f, -2124.845947f, 1043.1f,3.14f, 70860,false,true,TYPE_KINGS_OF_ICC}, // +}; + + +bool GOGossipSelect_go_icecrown_teleporter(Player *pPlayer, GameObject* pGo, uint32 sender, uint32 action) +{ + if(sender != GOSSIP_SENDER_MAIN) return false; + + if(!pPlayer->getAttackers().empty()) return false; + + if(action >= 0 && action < PORTALS_COUNT) + pPlayer->TeleportTo(PortalLoc[action].map_num, PortalLoc[action].x, PortalLoc[action].y, PortalLoc[action].z, PortalLoc[action].o); + if (PortalLoc[action].spellID != 0 ) + pPlayer->_AddAura(PortalLoc[action].spellID, 2000); + + pPlayer->CLOSE_GOSSIP_MENU(); + return true; +} + +bool GOGossipHello_go_icecrown_teleporter(Player *pPlayer, GameObject* pGo) +{ + ScriptedInstance *pInstance = (ScriptedInstance *) pGo->GetInstanceData(); + + if (!pInstance || !pPlayer) return false; + if (pPlayer->isInCombat()) return true; + + for(uint8 i = 0; i < PORTALS_COUNT; i++) { + if (PortalLoc[i].active == true && (PortalLoc[i].state == true || pInstance->GetData(PortalLoc[i].encounter) == DONE || pPlayer->isGameMaster())) + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_TAXI, PortalLoc[i].textNum, GOSSIP_SENDER_MAIN, i); + }; + pPlayer->SEND_GOSSIP_MENU(TELEPORT_GOSSIP_MESSAGE, pGo->GetGUID()); + return true; +} + +bool GOHello_go_plague_sigil(Player *player, GameObject* pGo) +{ + instance_icecrown_spire* pInstance = (instance_icecrown_spire*)pGo->GetInstanceData(); + if(!pInstance) return false; + + if (pInstance->GetData(TYPE_FESTERGUT) == DONE + && pInstance->GetData(TYPE_ROTFACE) == DONE) + { + pInstance->OpenDoor(pInstance->GetData64(GO_SCIENTIST_DOOR_ORANGE)); + pInstance->OpenDoor(pInstance->GetData64(GO_SCIENTIST_DOOR_GREEN)); + pInstance->OpenDoor(pInstance->GetData64(GO_SCIENTIST_DOOR_COLLISION)); + }; + return true; +} + +bool GOHello_go_bloodwing_sigil(Player *player, GameObject* pGo) +{ + instance_icecrown_spire* pInstance = (instance_icecrown_spire*)pGo->GetInstanceData(); + if(!pInstance) return false; + + if (pInstance->GetData(TYPE_SAURFANG) == DONE) + pInstance->OpenDoor(pInstance->GetData64(GO_BLOODWING_DOOR)); + + return true; +} + +bool GOHello_go_frostwing_sigil(Player *player, GameObject* pGo) +{ + instance_icecrown_spire* pInstance = (instance_icecrown_spire*)pGo->GetInstanceData(); + if(!pInstance) return false; + + if (pInstance->GetData(TYPE_SAURFANG) == DONE) + pInstance->OpenDoor(pInstance->GetData64(GO_FROSTWING_DOOR)); + + return true; +} + + +void AddSC_icecrown_teleporter() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_icecrown_teleporter"; + newscript->pGOGossipHello = &GOGossipHello_go_icecrown_teleporter; + newscript->pGOGossipSelect = &GOGossipSelect_go_icecrown_teleporter; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_plague_sigil"; + newscript->pGOHello = &GOHello_go_plague_sigil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_bloodwing_sigil"; + newscript->pGOHello = &GOHello_go_bloodwing_sigil; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_frostwing_sigil"; + newscript->pGOHello = &GOHello_go_frostwing_sigil; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_citadel.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_citadel.cpp new file mode 100644 index 0000000..d2346d4 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_citadel.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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_icecrown_citadel +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Icecrown Citadel +EndScriptData */ + +#include "precompiled.h" + +void AddSC_instance_icecrown_citadel() +{ +} diff --git a/scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_spire.cpp b/scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_spire.cpp new file mode 100644 index 0000000..be74c68 --- /dev/null +++ b/scripts/northrend/icecrown_citadel/icecrown_citadel/instance_icecrown_spire.cpp @@ -0,0 +1,828 @@ +/* Copyright (C) 2006 - 2010 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_icecrown_spire +SD%Complete: 90% +SDComment: by /dev/rsa +SDCategory: Icecrown Citadel +EndScriptData */ + +#include "precompiled.h" +#include "def_spire.h" +#include "World.h" + +static Locations SpawnLoc[]= +{ + {-446.788971f, 2003.362915f, 191.233948f}, // 0 Horde ship enter + {-428.140503f, 2421.336914f, 191.233078f}, // 1 Alliance ship enter +}; + + instance_icecrown_spire::instance_icecrown_spire(Map* pMap) : ScriptedInstance(pMap) + { + Difficulty = pMap->GetDifficulty(); + Initialize(); + } + + void instance_icecrown_spire::OpenDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + } + + void instance_icecrown_spire::CloseDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_READY); + } + + void instance_icecrown_spire::OpenAllDoors() + { + if (m_auiEncounter[1] == DONE) { + OpenDoor(m_uiIcewall1GUID); + OpenDoor(m_uiIcewall2GUID); + OpenDoor( m_uiOratoryDoorGUID); + }; + if (m_auiEncounter[2] == DONE) { + if (GameObject* pGO = instance->GetGameObject(m_uiDeathWhisperElevatorGUID)) + { + pGO->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGO->SetGoState(GO_STATE_READY); + } + }; + if (m_auiEncounter[4] == DONE) { + OpenDoor(m_uiSaurfangDoorGUID); + OpenDoor(m_uiBloodwingDoorGUID); + OpenDoor(m_uiFrostwingDoorGUID); + }; + if (m_auiEncounter[5] == DONE) OpenDoor(m_uiSDoorOrangeGUID); + if (m_auiEncounter[6] == DONE) OpenDoor(m_uiSDoorGreenGUID); + if (m_auiEncounter[6] == DONE && m_auiEncounter[5] == DONE) OpenDoor(m_uiSDoorCollisionGUID); + if (m_auiEncounter[8] == DONE) { + OpenDoor(m_uiCounsilDoor1GUID); + OpenDoor(m_uiCounsilDoor2GUID); + }; + if (m_auiEncounter[10] == DONE) + { + OpenDoor(m_uiValithriaDoor2GUID); + OpenDoor(m_uiSindragosaDoor2GUID); + OpenDoor(m_uiSindragosaDoor1GUID); + }; + + } + + void instance_icecrown_spire::Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + m_auiEncounter[i] = NOT_STARTED; + + m_auiEncounter[0] = 0; + + m_uiMarrogwarGUID = 0; + m_uiDeathWhisperGUID = 0; + m_uiSaurfangGUID = 0; + m_uiSaurfangCacheGUID = 0; + m_uiGunshipArmoryAGUID = 0; + m_uiGunshipArmoryHGUID = 0; + m_uiIcewall1GUID = 0; + m_uiIcewall2GUID = 0; + m_uiSDoorOrangeGUID = 0; + m_uiSDoorGreenGUID = 0; + m_uiBloodwingDoorGUID = 0; + m_uiSDoorCollisionGUID = 0; + m_auiEvent = 0; + m_auiEventTimer = 1000; + m_uiCouncilInvocation = 0; + m_uiDirection = 0; + m_uiStinkystate = NOT_STARTED; + m_uiPreciousstate = NOT_STARTED; + + switch (Difficulty) { + case RAID_DIFFICULTY_10MAN_NORMAL: + m_uiGunshipArmoryH_ID = GO_GUNSHIP_ARMORY_H_10; + m_uiGunshipArmoryA_ID = GO_GUNSHIP_ARMORY_A_10; + break; + case RAID_DIFFICULTY_10MAN_HEROIC: + m_uiGunshipArmoryH_ID = GO_GUNSHIP_ARMORY_H_10H; + m_uiGunshipArmoryA_ID = GO_GUNSHIP_ARMORY_A_10H; + break; + case RAID_DIFFICULTY_25MAN_NORMAL: + m_uiGunshipArmoryH_ID = GO_GUNSHIP_ARMORY_H_25; + m_uiGunshipArmoryA_ID = GO_GUNSHIP_ARMORY_A_25; + break; + case RAID_DIFFICULTY_25MAN_HEROIC: + m_uiGunshipArmoryH_ID = GO_GUNSHIP_ARMORY_H_25H; + m_uiGunshipArmoryA_ID = GO_GUNSHIP_ARMORY_A_25H; + break; + default: + m_uiGunshipArmoryH_ID = 0; + m_uiGunshipArmoryA_ID = 0; + break; + }; + } + + bool instance_icecrown_spire::IsEncounterInProgress() const + { + for(uint8 i = 1; i < MAX_ENCOUNTERS-2 ; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) return true; + + return false; + } + + void instance_icecrown_spire::OnPlayerEnter(Player *pPlayer) + { + OpenAllDoors(); + + enum PhaseControl + { + HORDE_CONTROL_PHASE_SHIFT_1 = 55773, + HORDE_CONTROL_PHASE_SHIFT_2 = 60028, + ALLIANCE_CONTROL_PHASE_SHIFT_1 = 55774, + ALLIANCE_CONTROL_PHASE_SHIFT_2 = 60027, + }; +/* + + if (!sWorld.getConfig(CONFIG_BOOL_ALLOW_TWO_SIDE_INTERACTION_GROUP)) return; + + switch (pPlayer->GetTeam()) + { + case ALLIANCE: + if (pPlayer && pPlayer->IsInWorld() && pPlayer->HasAura(HORDE_CONTROL_PHASE_SHIFT_1)) + pPlayer->RemoveAurasDueToSpell(HORDE_CONTROL_PHASE_SHIFT_1); + pPlayer->CastSpell(pPlayer, HORDE_CONTROL_PHASE_SHIFT_2, false); + break; + case HORDE: + if (pPlayer && pPlayer->IsInWorld() && pPlayer->HasAura(ALLIANCE_CONTROL_PHASE_SHIFT_1)) + pPlayer->RemoveAurasDueToSpell(ALLIANCE_CONTROL_PHASE_SHIFT_1); + pPlayer->CastSpell(pPlayer, ALLIANCE_CONTROL_PHASE_SHIFT_2, false); + break; + }; +*/ + }; + + void instance_icecrown_spire::OnCreatureCreate(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case NPC_LORD_MARROWGAR: + m_uiMarrogwarGUID = pCreature->GetGUID(); + break; + case NPC_LADY_DEATHWHISPER: + m_uiDeathWhisperGUID = pCreature->GetGUID(); + break; + case NPC_DEATHBRINGER_SAURFANG: + m_uiSaurfangGUID = pCreature->GetGUID(); + break; + case NPC_FESTERGUT: + m_uiFestergutGUID = pCreature->GetGUID(); + break; + case NPC_ROTFACE: + m_uiRotfaceGUID = pCreature->GetGUID(); + break; + case NPC_PROFESSOR_PUTRICIDE: + m_uiPutricideGUID = pCreature->GetGUID(); + break; + case NPC_TALDARAM: + m_uiTaldaramGUID = pCreature->GetGUID(); + break; + case NPC_VALANAR: + m_uiValanarGUID = pCreature->GetGUID(); + break; + case NPC_KELESETH: + m_uiKelesethGUID = pCreature->GetGUID(); + break; + case NPC_LANATHEL: + m_uiLanathelGUID = pCreature->GetGUID(); + break; + case NPC_LANATHEL_INTRO: + m_uiLanathelintroGUID = pCreature->GetGUID(); + break; + case NPC_VALITHRIA: + m_uiValithriaGUID = pCreature->GetGUID(); + break; + case NPC_VALITHRIA_QUEST: + m_uiValithriaQuestGUID = pCreature->GetGUID(); + break; + case NPC_SINDRAGOSA: + m_uiSindragosaGUID = pCreature->GetGUID(); + break; + case NPC_LICH_KING: + m_uiLichKingGUID = pCreature->GetGUID(); + break; + case NPC_RIMEFANG: + m_uiRimefangGUID = pCreature->GetGUID(); + break; + case NPC_SPINESTALKER: + m_uiSpinestalkerGUID = pCreature->GetGUID(); + break; + case NPC_STINKY: + m_uiStinkyGUID = pCreature->GetGUID(); + break; + case NPC_PRECIOUS: + m_uiPreciousGUID = pCreature->GetGUID(); + break; + case NPC_COMBAT_TRIGGER: + m_uidummyTargetGUID = pCreature->GetGUID(); + break; + case NPC_FROSTMOURNE_TRIGGER: + m_uiFrostmourneTriggerGUID = pCreature->GetGUID(); break; + case NPC_FROSTMOURNE_HOLDER: + m_uiFrostmourneHolderGUID = pCreature->GetGUID(); break; + } + } + + void instance_icecrown_spire::OnObjectCreate(GameObject* pGo) + { + switch(pGo->GetEntry()) + { + case GO_ICEWALL_1: + m_uiIcewall1GUID = pGo->GetGUID(); + break; + case GO_ICEWALL_2: + m_uiIcewall2GUID = pGo->GetGUID(); + break; + case GO_ORATORY_DOOR: + m_uiOratoryDoorGUID = pGo->GetGUID(); + break; + case GO_DEATHWHISPER_ELEVATOR: + m_uiDeathWhisperElevatorGUID = pGo->GetGUID(); + break; + case GO_SAURFANG_DOOR: + m_uiSaurfangDoorGUID = pGo->GetGUID(); + break; + case GO_ORANGE_PLAGUE: + m_uiOrangePlagueGUID = pGo->GetGUID(); + break; + case GO_GREEN_PLAGUE: + m_uiGreenPlagueGUID = pGo->GetGUID(); + break; + case GO_SCIENTIST_DOOR_GREEN: + m_uiSDoorGreenGUID = pGo->GetGUID(); + break; + case GO_SCIENTIST_DOOR_ORANGE: + m_uiSDoorOrangeGUID = pGo->GetGUID(); + break; + case GO_SCIENTIST_DOOR_COLLISION: + m_uiSDoorCollisionGUID = pGo->GetGUID(); + break; + case GO_SCIENTIST_DOOR: + m_uiScientistDoorGUID = pGo->GetGUID(); + break; + case GO_CRIMSON_HALL_DOOR: + m_uiCrimsonDoorGUID = pGo->GetGUID(); + break; + case GO_BLOODWING_DOOR: + m_uiBloodwingDoorGUID = pGo->GetGUID(); + break; + case GO_COUNCIL_DOOR_1: + m_uiCounsilDoor1GUID = pGo->GetGUID(); + break; + case GO_COUNCIL_DOOR_2: + m_uiCounsilDoor2GUID = pGo->GetGUID(); + break; + case GO_FROSTWING_DOOR: + m_uiFrostwingDoorGUID = pGo->GetGUID(); + break; + case GO_GREEN_DRAGON_DOOR_1: + m_uiGreenDragonDoor1GUID = pGo->GetGUID(); + break; + case GO_GREEN_DRAGON_DOOR_2: + m_uiGreenDragonDoor2GUID = pGo->GetGUID(); + break; + case GO_VALITHRIA_DOOR_1: + m_uiValithriaDoor1GUID = pGo->GetGUID(); + break; + case GO_VALITHRIA_DOOR_2: + m_uiValithriaDoor2GUID = pGo->GetGUID(); + break; + case GO_VALITHRIA_DOOR_3: + m_uiValithriaDoor3GUID = pGo->GetGUID(); + break; + case GO_VALITHRIA_DOOR_4: + m_uiValithriaDoor4GUID = pGo->GetGUID(); + break; + case GO_SINDRAGOSA_DOOR_1: + m_uiSindragosaDoor1GUID = pGo->GetGUID(); + break; + case GO_SINDRAGOSA_DOOR_2: + m_uiSindragosaDoor2GUID = pGo->GetGUID(); + break; + case GO_SAURFANG_CACHE_10: + if(Difficulty == RAID_DIFFICULTY_10MAN_NORMAL) + m_uiSaurfangCacheGUID = pGo->GetGUID(); + break; + case GO_SAURFANG_CACHE_25: + if(Difficulty == RAID_DIFFICULTY_25MAN_NORMAL) + m_uiSaurfangCacheGUID = pGo->GetGUID(); + break; + case GO_SAURFANG_CACHE_10_H: + if(Difficulty == RAID_DIFFICULTY_10MAN_HEROIC) + m_uiSaurfangCacheGUID = pGo->GetGUID(); + break; + case GO_SAURFANG_CACHE_25_H: + if(Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) + m_uiSaurfangCacheGUID = pGo->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_A_10: + if(Difficulty == RAID_DIFFICULTY_10MAN_NORMAL) + m_uiGunshipArmoryAGUID = pGo->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_A_25: + if(Difficulty == RAID_DIFFICULTY_25MAN_NORMAL) + m_uiGunshipArmoryAGUID = pGo->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_A_10H: + if(Difficulty == RAID_DIFFICULTY_10MAN_HEROIC) + m_uiGunshipArmoryAGUID = pGo->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_A_25H: + if(Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) + m_uiGunshipArmoryAGUID = pGo->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_H_10: + if(Difficulty == RAID_DIFFICULTY_10MAN_NORMAL) + m_uiGunshipArmoryHGUID = pGo->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_H_25: + if(Difficulty == RAID_DIFFICULTY_25MAN_NORMAL) + m_uiGunshipArmoryHGUID = pGo->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_H_10H: + if(Difficulty == RAID_DIFFICULTY_10MAN_HEROIC) + m_uiGunshipArmoryHGUID = pGo->GetGUID(); + break; + case GO_GUNSHIP_ARMORY_H_25H: + if(Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) + m_uiGunshipArmoryHGUID = pGo->GetGUID(); + break; + case GO_DREAMWALKER_CACHE_10: + if(Difficulty == RAID_DIFFICULTY_10MAN_NORMAL) + m_uiValitriaCacheGUID = pGo->GetGUID(); + break; + case GO_DREAMWALKER_CACHE_25: + if(Difficulty == RAID_DIFFICULTY_25MAN_NORMAL) + m_uiValitriaCacheGUID = pGo->GetGUID(); + break; + case GO_DREAMWALKER_CACHE_10_H: + if(Difficulty == RAID_DIFFICULTY_10MAN_HEROIC) + m_uiValitriaCacheGUID = pGo->GetGUID(); + break; + case GO_DREAMWALKER_CACHE_25_H: + if(Difficulty == RAID_DIFFICULTY_25MAN_HEROIC) + m_uiValitriaCacheGUID = pGo->GetGUID(); + break; + case GO_ICESHARD_1: + m_uiIceShard1GUID = pGo->GetGUID(); + break; + case GO_ICESHARD_2: + m_uiIceShard2GUID = pGo->GetGUID(); + break; + case GO_ICESHARD_3: + m_uiIceShard3GUID = pGo->GetGUID(); + break; + case GO_ICESHARD_4: + m_uiIceShard4GUID = pGo->GetGUID(); + break; + case GO_FROSTY_WIND: + m_uiFrostyWindGUID = pGo->GetGUID(); + break; + case GO_FROSTY_EDGE: + m_uiFrostyEdgeGUID = pGo->GetGUID(); + break; + case GO_SNOW_EDGE: + m_uiSnowEdgeGUID = pGo->GetGUID(); + break; + case GO_ARTHAS_PLATFORM: + m_uiArthasPlatformGUID = pGo->GetGUID(); + break; + case GO_ARTHAS_PRECIPICE: + m_uiArthasPrecipiceGUID = pGo->GetGUID(); + break; + case GO_GAS_RELEASE_VALVE: + m_uiGasReleaseValveGUID = pGo->GetGUID(); + break; + case NPC_BLOOD_ORB_CONTROL: + m_uiBloodOrbCtrlGUID = pGo->GetGUID(); + break; + } + OpenAllDoors(); + } + + void instance_icecrown_spire::SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_TELEPORT: + break; + case TYPE_MARROWGAR: + m_auiEncounter[TYPE_MARROWGAR] = uiData; + if (uiData == DONE) + { + OpenDoor(m_uiIcewall1GUID); + OpenDoor(m_uiIcewall2GUID); + OpenDoor( m_uiOratoryDoorGUID); + } + break; + case TYPE_DEATHWHISPER: + m_auiEncounter[TYPE_DEATHWHISPER] = uiData; + if (uiData == DONE) { + if (GameObject* pGO = instance->GetGameObject(m_uiDeathWhisperElevatorGUID)) + { + pGO->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGO->SetGoState(GO_STATE_READY); + } + } + break; + case TYPE_FLIGHT_WAR: + if (uiData == DONE && m_auiEncounter[TYPE_FLIGHT_WAR] != DONE ) { + if (GameObject* pChest = instance->GetGameObject(m_uiGunshipArmoryAGUID)) + if (pChest && !pChest->isSpawned()) { + pChest->SetRespawnTime(7*DAY); + }; + + if (GameObject* pChest = instance->GetGameObject(m_uiGunshipArmoryHGUID)) + if (pChest && !pChest->isSpawned()) { + pChest->SetRespawnTime(7*DAY); + }; + }; + m_auiEncounter[3] = uiData; + break; + case TYPE_SAURFANG: + m_auiEncounter[TYPE_SAURFANG] = uiData; + if (uiData == DONE) + { + OpenDoor(m_uiSaurfangDoorGUID); + OpenDoor(m_uiBloodwingDoorGUID); + OpenDoor(m_uiFrostwingDoorGUID); + + if (GameObject* pChest = instance->GetGameObject(m_uiSaurfangCacheGUID)) + if (pChest && !pChest->isSpawned()) + { + pChest->SetRespawnTime(7*DAY); + }; + }; + break; + case TYPE_FESTERGUT: + m_auiEncounter[TYPE_FESTERGUT] = uiData; + if (uiData == IN_PROGRESS) CloseDoor(m_uiOrangePlagueGUID); + else OpenDoor(m_uiOrangePlagueGUID); + if (uiData == DONE) { + OpenDoor(m_uiSDoorOrangeGUID); + if (m_auiEncounter[TYPE_ROTFACE] == DONE) + { + OpenDoor(m_uiSDoorCollisionGUID); + OpenDoor(m_uiGreenPlagueGUID); + } + } + break; + case TYPE_ROTFACE: + m_auiEncounter[TYPE_ROTFACE] = uiData; + if (uiData == IN_PROGRESS) + CloseDoor(m_uiGreenPlagueGUID); + else + OpenDoor(m_uiGreenPlagueGUID); + if (uiData == DONE) + { + OpenDoor(m_uiSDoorGreenGUID); + if (m_auiEncounter[TYPE_FESTERGUT] == DONE) + { + OpenDoor(m_uiSDoorOrangeGUID); + OpenDoor(m_uiSDoorCollisionGUID); + } + } + break; + case TYPE_PUTRICIDE: + m_auiEncounter[TYPE_PUTRICIDE] = uiData; + if (uiData == IN_PROGRESS) + CloseDoor(m_uiScientistDoorGUID); + else + OpenDoor(m_uiScientistDoorGUID); + if (uiData == DONE) + { + if (m_auiEncounter[TYPE_SINDRAGOSA] == DONE + && m_auiEncounter[TYPE_LANATHEL] == DONE) + m_auiEncounter[TYPE_KINGS_OF_ICC] = DONE; + } + break; + case TYPE_BLOOD_COUNCIL: + m_auiEncounter[TYPE_BLOOD_COUNCIL] = uiData; + + if (uiData == IN_PROGRESS) + CloseDoor(m_uiCrimsonDoorGUID); + else + OpenDoor(m_uiCrimsonDoorGUID); + + if (uiData == DONE) + { + OpenDoor(m_uiCounsilDoor1GUID); + OpenDoor(m_uiCounsilDoor2GUID); + } + break; + case TYPE_LANATHEL: + m_auiEncounter[TYPE_LANATHEL] = uiData; + if (uiData == DONE) + { + if (m_auiEncounter[TYPE_PUTRICIDE] == DONE + && m_auiEncounter[TYPE_SINDRAGOSA] == DONE) + m_auiEncounter[TYPE_KINGS_OF_ICC] = DONE; + } + break; + case TYPE_VALITHRIA: + m_auiEncounter[TYPE_VALITHRIA] = uiData; + + if (uiData == IN_PROGRESS) + CloseDoor(m_uiGreenDragonDoor1GUID); + else + OpenDoor(m_uiGreenDragonDoor1GUID); + + if (uiData == DONE) + { + OpenDoor(m_uiGreenDragonDoor2GUID); + OpenDoor(m_uiSindragosaDoor1GUID); + OpenDoor(m_uiSindragosaDoor2GUID); + if (GameObject* pChest = instance->GetGameObject(m_uiValitriaCacheGUID)) + if (pChest && !pChest->isSpawned()) + { + pChest->SetRespawnTime(7*DAY); + }; + }; + break; + case TYPE_SINDRAGOSA: + m_auiEncounter[TYPE_SINDRAGOSA] = uiData; + if (uiData == DONE) + { + if (m_auiEncounter[TYPE_PUTRICIDE] == DONE + && m_auiEncounter[TYPE_LANATHEL] == DONE) + m_auiEncounter[TYPE_KINGS_OF_ICC] = DONE; + } + break; + case TYPE_LICH_KING: + m_auiEncounter[TYPE_LICH_KING] = uiData; + break; + case TYPE_ICECROWN_QUESTS: + m_auiEncounter[TYPE_ICECROWN_QUESTS] = uiData; + break; + case TYPE_COUNT: + m_auiEncounter[TYPE_COUNT] = uiData; + uiData = NOT_STARTED; + break; + case DATA_BLOOD_COUNCIL_HEALTH: m_uiDataCouncilHealth = uiData; + uiData = NOT_STARTED; + break; + case DATA_BLOOD_INVOCATION: m_uiCouncilInvocation = uiData; + uiData = NOT_STARTED; + break; + case DATA_DIRECTION: m_uiDirection = uiData; + uiData = NOT_STARTED; + break; + case TYPE_EVENT: m_auiEvent = uiData; uiData = NOT_STARTED; break; + case TYPE_EVENT_TIMER: m_auiEventTimer = uiData; uiData = NOT_STARTED; break; + case TYPE_STINKY: m_uiStinkystate = uiData; uiData = NOT_STARTED; break; + case TYPE_PRECIOUS: m_uiPreciousstate = uiData; uiData = NOT_STARTED; break; + } + + if (uiData == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + saveStream << m_auiEncounter[i] << " "; + + strSaveData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 instance_icecrown_spire::GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_TELEPORT: + case TYPE_MARROWGAR: + case TYPE_DEATHWHISPER: + case TYPE_FLIGHT_WAR: + case TYPE_SAURFANG: + case TYPE_FESTERGUT: + case TYPE_ROTFACE: + case TYPE_PUTRICIDE: + case TYPE_BLOOD_COUNCIL: + case TYPE_LANATHEL: + case TYPE_VALITHRIA: + case TYPE_SINDRAGOSA: + case TYPE_KINGS_OF_ICC: + case TYPE_LICH_KING: + case TYPE_ICECROWN_QUESTS: + case TYPE_COUNT: + return m_auiEncounter[uiType]; + + case DATA_DIRECTION: return m_uiDirection; + case DATA_BLOOD_COUNCIL_HEALTH: return m_uiDataCouncilHealth; + case DATA_BLOOD_INVOCATION: return m_uiCouncilInvocation; + case TYPE_STINKY: return m_uiStinkystate; + case TYPE_PRECIOUS: return m_uiPreciousstate; + case TYPE_EVENT: return m_auiEvent; + case TYPE_EVENT_TIMER: return m_auiEventTimer; + case TYPE_EVENT_NPC: switch (m_auiEvent) + { + case 12030: + case 12050: + case 12051: + case 12052: + case 12053: + case 12070: + case 12090: + case 12110: + case 12130: + case 12150: + case 12170: + case 13110: + case 13130: + case 13131: + case 13132: + case 13150: + case 13170: + case 13190: + case 13210: + case 13230: + case 13250: + case 13270: + case 13290: + case 13310: + case 13330: + case 13350: + case 13370: + case 14010: + case 14030: + case 14050: + case 14070: + return NPC_TIRION; + break; + + case 12000: + case 12020: + case 12040: + case 12041: + case 12042: + case 12043: + case 12060: + case 12080: + case 12100: + case 12120: + case 12200: + case 13000: + case 13020: + case 13040: + case 13060: + case 13080: + case 13100: + case 13120: + case 13140: + case 13160: + case 13180: + case 13200: + case 13220: + case 13240: + case 13260: + case 13280: + case 13300: + case 14000: + return NPC_LICH_KING; + break; + case 500: + case 510: + case 550: + case 560: + case 570: + case 580: + case 590: + case 600: + case 610: + case 620: + case 630: + case 640: + case 650: + case 660: + return NPC_PROFESSOR_PUTRICIDE; + break; + + case 800: + case 810: + case 820: + return NPC_LANATHEL_INTRO; + break; + + default: + break; + }; + + } + return 0; + } + + uint64 instance_icecrown_spire::GetData64(uint32 uiData) + { + switch(uiData) + { + case NPC_LORD_MARROWGAR: return m_uiMarrogwarGUID; + case NPC_LADY_DEATHWHISPER: return m_uiDeathWhisperGUID; + case NPC_DEATHBRINGER_SAURFANG: return m_uiSaurfangGUID; + case NPC_FESTERGUT: return m_uiFestergutGUID; + case NPC_ROTFACE: return m_uiRotfaceGUID; + case NPC_PROFESSOR_PUTRICIDE: return m_uiPutricideGUID; + case NPC_TALDARAM: return m_uiTaldaramGUID; + case NPC_VALANAR: return m_uiValanarGUID; + case NPC_KELESETH: return m_uiKelesethGUID; + case NPC_LANATHEL: return m_uiLanathelGUID; + case NPC_LANATHEL_INTRO: return m_uiLanathelintroGUID; + case NPC_VALITHRIA: return m_uiValithriaGUID; + case NPC_VALITHRIA_QUEST: return m_uiValithriaQuestGUID; + case NPC_SINDRAGOSA: return m_uiSindragosaGUID; + case NPC_LICH_KING: return m_uiLichKingGUID; + case NPC_RIMEFANG: return m_uiRimefangGUID; + case NPC_SPINESTALKER: return m_uiSpinestalkerGUID; + case NPC_STINKY: return m_uiStinkyGUID; + case NPC_PRECIOUS: return m_uiPreciousGUID; + case GO_SCIENTIST_DOOR_ORANGE: return m_uiSDoorOrangeGUID; + case GO_SCIENTIST_DOOR_GREEN: return m_uiSDoorGreenGUID; + case GO_SCIENTIST_DOOR_COLLISION: return m_uiSDoorCollisionGUID; + case GO_BLOODWING_DOOR: return m_uiBloodwingDoorGUID; + case GO_FROSTWING_DOOR: return m_uiFrostwingDoorGUID; + case GO_VALITHRIA_DOOR_1: return m_uiValithriaDoor1GUID; + case GO_VALITHRIA_DOOR_2: return m_uiValithriaDoor2GUID; + case GO_VALITHRIA_DOOR_3: return m_uiValithriaDoor3GUID; + case GO_VALITHRIA_DOOR_4: return m_uiValithriaDoor4GUID; + case GO_ICESHARD_1: return m_uiIceShard1GUID; + case GO_ICESHARD_2: return m_uiIceShard2GUID; + case GO_ICESHARD_3: return m_uiIceShard3GUID; + case GO_ICESHARD_4: return m_uiIceShard4GUID; + case GO_FROSTY_WIND: return m_uiFrostyWindGUID; + case GO_FROSTY_EDGE: return m_uiFrostyEdgeGUID; + case GO_SNOW_EDGE: return m_uiSnowEdgeGUID; + case GO_ARTHAS_PLATFORM: return m_uiArthasPlatformGUID; + case GO_ARTHAS_PRECIPICE: return m_uiArthasPrecipiceGUID; + case NPC_FROSTMOURNE_TRIGGER: return m_uiFrostmourneTriggerGUID; + case NPC_FROSTMOURNE_HOLDER: return m_uiFrostmourneHolderGUID; + case NPC_COMBAT_TRIGGER: return m_uidummyTargetGUID; + case GO_GAS_RELEASE_VALVE: return m_uiGasReleaseValveGUID; + case NPC_BLOOD_ORB_CONTROL: return m_uiBloodOrbCtrlGUID; + } + return 0; + } + + void instance_icecrown_spire::Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + { + loadStream >> m_auiEncounter[i]; + + if (m_auiEncounter[i] == IN_PROGRESS && i >= 1) + m_auiEncounter[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + OpenAllDoors(); + } + +InstanceData* GetInstanceData_instance_icecrown_spire(Map* pMap) +{ + return new instance_icecrown_spire(pMap); +} + + +void AddSC_instance_icecrown_spire() +{ + Script* pNewScript; + pNewScript = new Script; + pNewScript->Name = "instance_icecrown_spire"; + pNewScript->GetInstanceData = &GetInstanceData_instance_icecrown_spire; + pNewScript->RegisterSelf(); +} diff --git a/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp b/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp new file mode 100644 index 0000000..215ca48 --- /dev/null +++ b/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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_malygos +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Eye of Eternity +EndScriptData */ + +#include "precompiled.h" + +void AddSC_boss_malygos() +{ +} diff --git a/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h b/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h new file mode 100644 index 0000000..dc0d78d --- /dev/null +++ b/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h @@ -0,0 +1,13 @@ +#ifndef DEF_EYE_OF_ETERNITY_H +#define DEF_EYE_OF_ETERNITY_H + +enum eTypes +{ + MAX_ENCOUNTER = 1, + + TYPE_MALYGOS = 0, + DATA_MALIGOS = 10, + NPC_MALYGOS = 28859 +}; + +#endif diff --git a/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp b/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp new file mode 100644 index 0000000..d3a1d8b --- /dev/null +++ b/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp @@ -0,0 +1,109 @@ +#include "precompiled.h" +#include "eye_of_eternity.h" + +enum eGameObjects +{ + GO_Malygos_CHEST_HERO = 193967, + GO_Malygos_CHEST = 193905 +}; + +struct MANGOS_DLL_DECL instance_eye_of_eternity : public ScriptedInstance +{ + instance_eye_of_eternity(Map* pMap) : ScriptedInstance(pMap), MalygosChest(NULL) { Initialize(); }; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + + uint64 m_uiMalygosGUID; + + uint64 MalygosChest; + + void Initialize() + { + m_uiMalygosGUID = 0; + MalygosChest = 0; + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + } + + void OnCreatureCreate(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case NPC_MALYGOS: + m_uiMalygosGUID = pCreature->GetGUID(); + break; + } + + } + + void OnObjectCreate(GameObject* pGo) + { + switch(pGo->GetEntry()) + { + case GO_Malygos_CHEST_HERO: + MalygosChest = pGo->GetGUID(); + if (m_auiEncounter[TYPE_MALYGOS] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + case GO_Malygos_CHEST: + MalygosChest = pGo->GetGUID(); + if (m_auiEncounter[TYPE_MALYGOS] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_MALYGOS: + m_auiEncounter[TYPE_MALYGOS] = data; + if (data == DONE && MalygosChest) + DoRespawnGameObject(MalygosChest, 30*MINUTE); + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint64 GetData64(uint32 data) + { + switch(data) + { + case TYPE_MALYGOS: + return m_uiMalygosGUID; + } + + return 0; + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_MALYGOS: + return m_auiEncounter[type]; + } + + return 0; + } +}; + +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/scripts/northrend/nexus/nexus/boss_keristrasza.cpp b/scripts/northrend/nexus/nexus/boss_keristrasza.cpp index ed956c6..2121fc9 100644 --- a/scripts/northrend/nexus/nexus/boss_keristrasza.cpp +++ b/scripts/northrend/nexus/nexus/boss_keristrasza.cpp @@ -78,7 +78,6 @@ struct MANGOS_DLL_DECL boss_keristraszaAI : public ScriptedAI m_bIsEnraged = false; - if (!m_pInstance) return; diff --git a/scripts/northrend/nexus/oculus/boss_drakos.cpp b/scripts/northrend/nexus/oculus/boss_drakos.cpp new file mode 100644 index 0000000..71c809e --- /dev/null +++ b/scripts/northrend/nexus/oculus/boss_drakos.cpp @@ -0,0 +1,227 @@ +/* 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: Boss_Drakos +SD%Complete: 80% +SDComment: +SDAuthor: originally from TC, reworked by MaxXx2021 Aka Mioka, corrected by /dev/rsa +SDCategory: Oculus +EndScriptData */ + +#include "precompiled.h" +#include "oculus.h" + +enum +{ + 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, + + SPELL_MAGIC_PULL = 51336, + SPELL_MAGIC_PULL_EFFECT = 50770, + SPELL_THUNDERING_STOMP_N = 50774, + SPELL_THUNDERING_STOMP_H = 59370, + SPELL_UNSTABLE_SPHERE_PASSIVE = 50756, + SPELL_UNSTABLE_SPHERE_PULSE = 50757, + SPELL_UNSTABLE_SPHERE_TIMER = 50758, + SPELL_UNSTABLE_SPHERE_EXPLODE = 50759, + + NPC_UNSTABLE_SPHERE = 28166 +}; + +#define CENTER_X 960.120f +#define CENTER_Y 1049.413f + +struct MANGOS_DLL_DECL boss_drakosAI : public ScriptedAI +{ + boss_drakosAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiMagicPullTimer ; + uint32 m_uiStompTimer ; + uint32 m_uiBombSummonTimer ; + + void Reset() + { + m_uiMagicPullTimer = urand(12000, 15000); + m_uiStompTimer = urand(3000, 6000); + m_uiBombSummonTimer = 7000; + if (m_pInstance && m_creature->isAlive()) + m_pInstance->SetData(TYPE_DRAKOS, NOT_STARTED); + } + + void Aggro(Unit* who) + { + DoScriptText(SAY_AGGRO, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_DRAKOS, IN_PROGRESS); + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_DRAKOS, DONE); + } + + void KilledUnit(Unit *victim) + { + switch (urand(0, 2)) + { + case 0: DoScriptText(SAY_KILL_1, m_creature); break; + case 1: DoScriptText(SAY_KILL_2, m_creature); break; + case 2: DoScriptText(SAY_KILL_3, m_creature); break; + } + } + + void SpellHitTarget(Unit *target, const SpellEntry *spell) + { + if (spell->Id == SPELL_MAGIC_PULL) + if (target->GetTypeId() == TYPEID_PLAYER) + DoCast(target, SPELL_MAGIC_PULL_EFFECT, true); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiBombSummonTimer < diff) + { + m_creature->SummonCreature(NPC_UNSTABLE_SPHERE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000); + m_creature->SummonCreature(NPC_UNSTABLE_SPHERE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 1000); + m_uiBombSummonTimer = 3000; + } + else + m_uiBombSummonTimer -= diff; + + if (m_uiMagicPullTimer < diff) + { + DoCast(m_creature, SPELL_MAGIC_PULL); + m_uiMagicPullTimer = urand(15000, 25000); + switch (urand(0, 3)) + { + case 0: DoScriptText(SAY_PULL_1, m_creature); break; + case 1: DoScriptText(SAY_PULL_2, m_creature); break; + case 2: DoScriptText(SAY_PULL_3, m_creature); break; + case 3: DoScriptText(SAY_PULL_4, m_creature); break; + } + } + else + m_uiMagicPullTimer -= diff; + + if (m_uiStompTimer < diff) + { + DoCast(m_creature, SPELL_THUNDERING_STOMP_N); + m_uiStompTimer = urand(11000, 18000); + switch (urand(0, 2)) + { + case 0: DoScriptText(SAY_STOMP_1, m_creature); break; + case 1: DoScriptText(SAY_STOMP_2, m_creature); break; + case 2: DoScriptText(SAY_STOMP_3, m_creature); break; + } + } + else + m_uiStompTimer -= diff ; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_drakos(Creature* pCreature) +{ + return new boss_drakosAI (pCreature); +} + +struct MANGOS_DLL_DECL npc_unstable_sphereAI : public ScriptedAI +{ + npc_unstable_sphereAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_uiPulseTimer; + + void Reset() + { + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + m_creature->GetMotionMaster()->MovePoint(0, (CENTER_X-35)+rand()%70, (CENTER_Y-35)+rand()%70, m_creature->GetPositionZ()); + m_creature->SetSpeedRate(MOVE_RUN, 2, true); + m_creature->setFaction(14); + DoCast(m_creature, SPELL_UNSTABLE_SPHERE_PASSIVE, true); + DoCast(m_creature, SPELL_UNSTABLE_SPHERE_TIMER, true); + m_uiPulseTimer = 3000; + m_creature->ForcedDespawn(19000); + } + + void AttackStart(Unit* pWho) + { + } + + void UpdateAI(const uint32 diff) + { + + if (m_pInstance && m_pInstance->GetData(TYPE_DRAKOS) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_uiPulseTimer < diff) + { + DoCast(m_creature, SPELL_UNSTABLE_SPHERE_PULSE, true); + m_uiPulseTimer = 3000; + } + else + m_uiPulseTimer -= diff; + } +}; + +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/scripts/northrend/nexus/oculus/boss_eregos.cpp b/scripts/northrend/nexus/oculus/boss_eregos.cpp new file mode 100644 index 0000000..f830b1b --- /dev/null +++ b/scripts/northrend/nexus/oculus/boss_eregos.cpp @@ -0,0 +1,320 @@ +/* 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: Boss_Eregos +SD%Complete: 60% +SDComment: +SDAuthor: originally from TC, reworked by MaxXx2021 Aka Mioka, corrected by /dev/rsa +SDCategory: Oculus +EndScriptData */ + +#include "precompiled.h" +#include "oculus.h" + +enum Spells +{ + SAY_AGGRO = -1578030, + SAY_KILL_1 = -1578031, + SAY_KILL_2 = -1578032, + SAY_KILL_3 = -1578033, + SAY_DEATH = -1578034, + SAY_ARCANE_SHIELD = -1578035, + SAY_FIRE_SHIELD = -1578036, + SAY_NATURE_SHIELD = -1578037, + SAY_FRENZY = -1578038, + SAY_SPAWN = -1578039, + + SPELL_ARCANE_BARRAGE_N = 50804, + SPELL_ARCANE_BARRAGE_H = 59381, + SPELL_ARCANE_VOLLEY_N = 51153, + SPELL_ARCANE_VOLLEY_H = 59382, + SPELL_ENRAGED_ASSAULT = 51170, + SPELL_SUMMON_DRAKE = 51175, + SPELL_PLANAR_ANOMALIES = 57959, + SPELL_PLANAR_ANOMALIES_SUMMON = 57963, //need spell script on m_creature 27656 + SPELL_PLANAR_ANOMALIES_VISUAL = 57971, + SPELL_PLANAR_SHIFT = 51162, + SPELL_PLANAR_ANOMALIES_DMG = 57976, + + NPC_PLANAR_ANOMALY = 30879, + NPC_DRAGON = 28276 +}; + +struct MANGOS_DLL_DECL boss_eregosAI : public ScriptedAI +{ + boss_eregosAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 uiArcaneBarrageTimer; + uint32 uiArcaneVolleyTimer; + uint32 uiEnragedAssaultTimer; + uint32 uiSummonTimer; + + uint8 m_uiSummonCount; + + bool m_bIsMove; + + void Reset() + { + m_creature->SetVisibility(VISIBILITY_ON); + if (m_pInstance) + { + m_pInstance->SetData(TYPE_EREGOS, NOT_STARTED); + if(m_pInstance->GetData(TYPE_UROM) == DONE) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + uiArcaneBarrageTimer = 12000; + uiArcaneVolleyTimer = 17000; + uiEnragedAssaultTimer = 24000; + uiSummonTimer = 15000; + m_uiSummonCount = 0; + m_bIsMove = true; + } + + void MoveInLineOfSight(Unit* pWho) + { + if(pWho->GetTypeId() == TYPEID_PLAYER + && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) + && !((Player*)pWho)->isGameMaster() + && m_creature->IsWithinDistInMap(pWho, 100.0f) + && pWho->GetVehicle() + && m_pInstance->GetData(TYPE_UROM) == DONE) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + ScriptedAI::MoveInLineOfSight(pWho); + } + + void Aggro(Unit* who) + { + DoScriptText(SAY_AGGRO, m_creature); + if (m_pInstance) + m_pInstance->SetData(TYPE_EREGOS, IN_PROGRESS); + } + + void KilledUnit(Unit *victim) + { + uint8 uiText = urand(0, 2); + switch (uiText) + { + case 0: DoScriptText(SAY_KILL_1, m_creature); break; + case 1: DoScriptText(SAY_KILL_2, m_creature); break; + case 2: DoScriptText(SAY_KILL_3, m_creature); break; + } + } + + void JustDied(Unit* killer) + { + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()-100.0f, 0); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()-100.0f, SPLINETYPE_NORMAL , m_creature->GetSplineFlags(), 6000); + DoScriptText(SAY_DEATH, m_creature); + if (m_pInstance) + m_pInstance->SetData(TYPE_EREGOS, DONE); + } + + void DamageTaken(Unit *done_by, uint32 &damage) + { + if(m_creature->HasAura(SPELL_PLANAR_SHIFT)) + damage = 0; + } + + void JustSummoned(Creature* pSummoned) + { + if(pSummoned->GetEntry() == NPC_PLANAR_ANOMALY) + { + pSummoned->SetDisplayId(11686); + pSummoned->SetInCombatWithZone(); + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + } + + if(pSummoned->GetEntry() == NPC_DRAGON) + { + pSummoned->SetInCombatWithZone(); + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + } + } + + void AttackStart(Unit* who) + { + if (!who) + return; + + if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) + return; + + ScriptedAI::AttackStart(who); + } + + void SummonAnomalies() + { + std::list t_list = m_creature->getThreatManager().getThreatList(); + if (t_list.size()) + { + for (std::list::iterator itr = t_list.begin(); itr != t_list.end(); ++itr) + { + Unit *pTarget = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); + if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER) + DoCast(m_creature, SPELL_PLANAR_ANOMALIES_SUMMON, true); + } + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_creature->GetHealthPercent() < 50.0f && m_uiSummonCount == 0) + { + SummonAnomalies(); + m_uiSummonCount = 1; + m_creature->CastSpell(m_creature, SPELL_PLANAR_SHIFT,true); + } + + if(m_creature->GetHealthPercent() < 25.0f && m_uiSummonCount == 1) + { + SummonAnomalies(); + m_uiSummonCount = 2; + m_creature->CastSpell(m_creature, SPELL_PLANAR_SHIFT,true); + } + + if(m_creature->GetDistance2d(m_creature->getVictim()) > 35.0f && !m_bIsMove) + { + m_bIsMove = true; + SetCombatMovement(m_bIsMove); + if(Unit* pTarget = m_creature->getVictim()) + m_creature->GetMotionMaster()->MoveChase(pTarget); + } + + if(m_creature->GetDistance2d(m_creature->getVictim()) < 20.0f && m_bIsMove) + { + m_bIsMove = false; + SetCombatMovement(m_bIsMove); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->StopMoving(); + } + + if(uiArcaneBarrageTimer <= diff) + { + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_ARCANE_BARRAGE_N : SPELL_ARCANE_BARRAGE_H); + uiArcaneBarrageTimer = 3000; + } else uiArcaneBarrageTimer -= diff; + + if(uiSummonTimer <= diff) + { + for(uint8 i = 1; i < 3; i++) + DoCast(m_creature, SPELL_SUMMON_DRAKE, true); + uiSummonTimer = 15000; + } else uiSummonTimer -= diff; + + if(uiArcaneVolleyTimer <= diff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ARCANE_VOLLEY_N : SPELL_ARCANE_VOLLEY_H); + uiArcaneVolleyTimer = 17000; + } else uiArcaneVolleyTimer -= diff; + + if(uiEnragedAssaultTimer <= diff) + { + DoCast(m_creature, SPELL_ENRAGED_ASSAULT, true); + uiEnragedAssaultTimer = 44000; + } else uiEnragedAssaultTimer -= diff; + } +}; + +struct MANGOS_DLL_DECL npc_planar_anomalyAI : public ScriptedAI +{ + npc_planar_anomalyAI(Creature *pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 uiPulseTimer; + uint32 uiDeathTimer; + + void Reset() + { + m_creature->SetDisplayId(11686); + m_creature->SetObjectScale(2.0f); + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + m_creature->SetSpeedRate(MOVE_RUN, 1.5, true); + m_creature->setFaction(14); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, SPELL_PLANAR_ANOMALIES_VISUAL, true); + uiDeathTimer = 20500; + uiPulseTimer = 19000; + } + + void UpdateAI(const uint32 diff) + { + if (uiPulseTimer < diff) + { + m_creature->RemoveAurasDueToSpell(SPELL_PLANAR_ANOMALIES_VISUAL); + m_creature->CastSpell(m_creature, SPELL_PLANAR_ANOMALIES_DMG, true); + uiPulseTimer = 6000; + } else uiPulseTimer -= diff; + + if (uiDeathTimer < diff) + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else uiDeathTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_eregos(Creature* pCreature) +{ + return new boss_eregosAI (pCreature); +} + +CreatureAI* GetAI_npc_planar_anomaly(Creature* pCreature) +{ + return new npc_planar_anomalyAI (pCreature); +} + +void AddSC_boss_eregos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_eregos"; + newscript->GetAI = &GetAI_boss_eregos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_planar_anomaly"; + newscript->GetAI = &GetAI_npc_planar_anomaly; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/nexus/oculus/boss_urom.cpp b/scripts/northrend/nexus/oculus/boss_urom.cpp new file mode 100644 index 0000000..e8623cc --- /dev/null +++ b/scripts/northrend/nexus/oculus/boss_urom.cpp @@ -0,0 +1,378 @@ +/* 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: Boss_Urom +SD%Complete: 70% +SDComment: +SDAuthor: originally from TC, reworked by MaxXx2021 Aka Mioka, corrected by /dev/rsa +SDCategory: Oculus +EndScriptData */ + +#include "precompiled.h" +#include "oculus.h" + +enum +{ + SAY_AGGRO = -1578012, + SAY_KILL_1 = -1578013, + SAY_KILL_2 = -1578014, + SAY_KILL_3 = -1578015, + SAY_DEATH = -1578016, + SAY_EXPLOSION_1 = -1578017, + SAY_EXPLOSION_2 = -1578018, + SAY_SUMMON_1 = -1578019, + SAY_SUMMON_2 = -1578020, + SAY_SUMMON_3 = -1578021, + + SPELL_ARCANE_BARRIER = 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, + + //NPCs + NPC_PHANTASMAL_MAMMOTH = 27642, + NPC_PHANTASMAL_WOLF = 27644, + NPC_PHANTASMAL_CLOUDSCRAPER = 27645, + NPC_PHANTASMAL_OGRE = 27647, + NPC_PHANTASMAL_NAGA = 27648, + NPC_PHANTASMAL_MURLOC = 27649, + NPC_PHANTASMAL_AIR = 27650, + NPC_PHANTASMAL_FIRE = 27651, + NPC_PHANTASMAL_WATER = 27653 +}; +/* +struct Locations +{ + float x, y, z, o; + uint32 id; +}; +*/ +struct Locations Teleport[]= +{ + {1177.469f, 937.721f, 527.405f, 2.21f}, //first platform + {968.5880f, 1042.58f, 527.321f, 0.13f}, //second platform + {1163.671f, 1171.02f, 527.321f, 4.19f}, //third platform + {1116.765f, 1075.93f, 508.361f, 4.26f}, //middle platform + {1103.659f, 1049.88f, 518.148f, 5.80f} //oculus center +}; + +struct MANGOS_DLL_DECL boss_uromAI : public BSWScriptedAI +{ + boss_uromAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiFrostBombTimer; + uint32 m_uiLiveBombTimer; + uint32 m_uiTeleportTimer; + uint32 m_uiArcaneExplodeTimer; + uint32 m_uiRelocateTimer; + uint32 m_uiBackTimer; + uint32 m_uiCheckTimer; + + bool m_bIsTeleported; + bool m_bIsTalk; + + void Reset() + { + m_uiFrostBombTimer = 9000; + m_uiLiveBombTimer = 14000; + m_uiTeleportTimer = 30000; + m_uiRelocateTimer = 31500; + m_uiBackTimer = 9000; + m_uiCheckTimer = 2000; + m_uiArcaneExplodeTimer = 1000; + + m_bIsTeleported = false; + m_bIsTalk = false; + + if (m_pInstance && m_pInstance->GetData(TYPE_UROM) != IN_PROGRESS) + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_pInstance->SetData(TYPE_UROM, NOT_STARTED); + if(m_pInstance->GetData(TYPE_VAROS) == DONE) + { + m_creature->RemoveAurasDueToSpell(SPELL_ARCANE_BARRIER); + m_creature->InterruptNonMeleeSpells(false); +// m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + DoCast(m_creature, SPELL_ARCANE_BARRIER); + } + } + } + + void DoSummon(uint32 Entry01, uint32 Entry02, uint32 Entry03, uint32 Entry04, uint32 Entry05 = 0) + { + m_creature->SummonCreature(Entry01, m_creature->GetPositionX() - (10.0f) * cos(M_PI / 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI / 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + m_creature->SummonCreature(Entry02, m_creature->GetPositionX() - (10.0f) * cos(M_PI * 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI * 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + m_creature->SummonCreature(Entry03, m_creature->GetPositionX() - (10.0f) * cos(M_PI + M_PI / 2), m_creature->GetPositionY() - (10.0f) * sin(M_PI + M_PI / 2), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + m_creature->SummonCreature(Entry04, m_creature->GetPositionX() - (10.0f) * cos(M_PI), m_creature->GetPositionY() - (10.0f) * sin(M_PI), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + if(Entry05 != 0) + m_creature->SummonCreature(Entry05, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 15000); + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if(pSpell->Id == SPELL_SUMMON_MENAGERIE) //|| pSpell->Id == SPELL_SUMMON_MENAGERIE_2 || pSpell->Id == SPELL_SUMMON_MENAGERIE_3) + m_bIsTalk = false; + if(pSpell->Id == SPELL_SUMMON_MENAGERIE_2) + m_bIsTalk = false; + if(pSpell->Id == SPELL_SUMMON_MENAGERIE_3) + m_bIsTalk = false; + } + + void TeleportBoss(float X, float Y, float Z, float O) + { + m_creature->GetMap()->CreatureRelocation(m_creature, X, Y, Z, O); + m_creature->SendMonsterMove(X, Y, Z, SPLINETYPE_NORMAL, SPLINEFLAG_DONE, 0); + m_creature->Relocate(X, Y, Z, O); + } + + void AttackStart(Unit* pWho) + { + if (!m_pInstance) + return; + + if(m_pInstance->GetData(TYPE_UROM_PHASE) < 3) + return; + + if (m_bIsTeleported) + return; + + ScriptedAI::AttackStart(pWho); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_pInstance) + return; + + if(pWho->GetTypeId() == TYPEID_PLAYER + && !((Player*)pWho)->isGameMaster() + && m_creature->IsWithinDistInMap(pWho, 30.0f) + && !pWho->GetVehicle() + && m_pInstance->GetData(TYPE_VAROS) == DONE + && !m_bIsTalk) + { + switch(m_pInstance->GetData(TYPE_UROM_PHASE)) + { + case 0: + m_bIsTalk = true; + SetCombatMovement(false); + m_pInstance->SetData(TYPE_UROM, IN_PROGRESS); + m_creature->InterruptNonMeleeSpells(false); + m_creature->RemoveAurasDueToSpell(53813); + DoScriptText(SAY_SUMMON_1, m_creature); + DoSummon(NPC_PHANTASMAL_FIRE, NPC_PHANTASMAL_FIRE, NPC_PHANTASMAL_AIR, NPC_PHANTASMAL_WATER); + DoCast(m_creature, SPELL_SUMMON_MENAGERIE); + m_pInstance->SetData(TYPE_UROM_PHASE, 1); + break; + case 1: + m_bIsTalk = true; + DoScriptText(SAY_SUMMON_2, m_creature); + DoSummon(NPC_PHANTASMAL_OGRE, NPC_PHANTASMAL_OGRE, NPC_PHANTASMAL_NAGA, NPC_PHANTASMAL_MURLOC); + DoCast(m_creature, SPELL_SUMMON_MENAGERIE_2); + m_pInstance->SetData(TYPE_UROM_PHASE, 2); + break; + case 2: + m_bIsTalk = true; + DoScriptText(SAY_SUMMON_3, m_creature); + DoSummon(NPC_PHANTASMAL_MAMMOTH, NPC_PHANTASMAL_WOLF, NPC_PHANTASMAL_WOLF, NPC_PHANTASMAL_CLOUDSCRAPER, NPC_PHANTASMAL_CLOUDSCRAPER); + DoCast(m_creature, SPELL_SUMMON_MENAGERIE_3); + m_pInstance->SetData(TYPE_UROM_PHASE, 3); + break; + case 3: + m_bIsTalk = true; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(true); + AttackStart(pWho); + break; + default: + break; + } + } + + ScriptedAI::MoveInLineOfSight(pWho); + } + + void Aggro(Unit* pWho) + { + if(pWho->GetTypeId() != TYPEID_PLAYER) + EnterEvadeMode(); + else DoScriptText(SAY_AGGRO, m_creature); + } + + void JustSummoned(Creature* summoned) + { + if(!m_pInstance || !summoned) return; + + if (Unit* pTarget = doSelectRandomPlayerAtRange(100.0f)) + { + summoned->SetInCombatWith(pTarget); + summoned->AddThreat(pTarget,100.0f); + } + } + + void EnterEvadeMode() + { + + if (!m_pInstance) + return; + + if( m_pInstance->GetData(TYPE_UROM_PHASE) < 3) + { + Map::PlayerList const &pList = m_creature->GetMap()->GetPlayers(); + if (!pList.isEmpty()) + return; + } + m_pInstance->SetData(TYPE_UROM, FAIL); + m_pInstance->SetData(TYPE_UROM_PHASE, 1); + ScriptedAI::EnterEvadeMode(); + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_UROM, DONE); + } + + void KilledUnit(Unit *victim) + { + uint8 uiText = urand(0, 2); + switch (uiText) + { + case 0: DoScriptText(SAY_KILL_1, m_creature); break; + case 1: DoScriptText(SAY_KILL_2, m_creature); break; + case 2: DoScriptText(SAY_KILL_3, m_creature); break; + } + } + + void CheckVehicle() + { + Map *map = m_creature->GetMap(); + if(map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if(PlayerList.isEmpty()) + return; + + for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if(i->getSource()->isAlive() && i->getSource()->GetVehicle()) + EnterEvadeMode(); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(!m_bIsTeleported) + { + if(m_uiFrostBombTimer < uiDiff) + { + m_creature->CastSpell(m_creature->getVictim(), SPELL_FROSTBOMB, false); + m_uiFrostBombTimer = urand(5000, 7000); + } else m_uiFrostBombTimer -= uiDiff; + + if(m_uiLiveBombTimer < uiDiff) + { + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_TIME_BOMB : SPELL_TIME_BOMB_2); + m_uiLiveBombTimer = urand(15000, 25000); + } else m_uiLiveBombTimer -= uiDiff; + + if(m_uiTeleportTimer < uiDiff) + { + DoCast(m_creature, SPELL_TELEPORT); + m_uiTeleportTimer = 31500; + } else m_uiTeleportTimer -= uiDiff; + + if(m_uiCheckTimer < uiDiff) + { + CheckVehicle(); + m_uiCheckTimer = 2000; + } else m_uiCheckTimer -= uiDiff; + + if(m_uiRelocateTimer < uiDiff) + { + m_bIsTeleported = true; + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->StopMoving(); + TeleportBoss(Teleport[4].x,Teleport[4].y,Teleport[4].z,Teleport[4].o); + m_uiRelocateTimer = 31500; + } else m_uiRelocateTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + else + { + if(m_uiArcaneExplodeTimer < uiDiff) + { + DoScriptText(urand(0,1) ? SAY_EXPLOSION_1 : SAY_EXPLOSION_2, m_creature); + DoCast(m_creature, SPELL_EMPOWERED_ARCANE_EXPLOSION); + m_uiArcaneExplodeTimer = 32000; + } else m_uiArcaneExplodeTimer -= uiDiff; + + if(m_uiBackTimer < uiDiff) + { + TeleportBoss((m_creature->getVictim())->GetPositionX(),(m_creature->getVictim())->GetPositionY(),(m_creature->getVictim())->GetPositionZ(),(m_creature->getVictim())->GetOrientation()); + m_creature->RemoveSplineFlag(SPLINEFLAG_FLYING); + if(m_creature->getVictim()) + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_uiBackTimer = 9000; + m_bIsTeleported = false; + m_uiArcaneExplodeTimer = 1000; + } else m_uiBackTimer -= uiDiff; + } + } +}; + +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/scripts/northrend/nexus/oculus/boss_varos.cpp b/scripts/northrend/nexus/oculus/boss_varos.cpp new file mode 100644 index 0000000..e430478 --- /dev/null +++ b/scripts/northrend/nexus/oculus/boss_varos.cpp @@ -0,0 +1,470 @@ +/* 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: Boss_Varos +SD%Complete: 70% +SDComment: +SDAuthor: originally from TC, reworked by MaxXx2021 Aka Mioka, corrected by /dev/rsa +SDCategory: Oculus +EndScriptData */ + +#include "precompiled.h" +#include "oculus.h" + +enum +{ + 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, + + SPELL_ARCANE_SHIELD = 50053, + 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, + + NPC_AZURE_CAPTAIN = 28236, + NPC_BEAM = 28239, + NPC_VAROS_CORE = 28183, + + SPELL_CORE_VISUAL = 50798, + SPELL_CORE_MISSILE = 61407, //need core fix max target 4, and spell script on 28183 + SPELL_BEAM = 51024, //need spell scrip on 28239 + SPELL_BEAM_DMG_AURA = 51019, + SPELL_BEAM_VISUAL_SOUND = 51022, //need script target 28239 + SPELL_SUMMON_BEAM = 51017 +}; + +struct dLocations +{ + float x1, y1, x2, y2; + uint32 id; +}; + +struct dLocations Regions[]= +{ + {0, 0, 0}, + {1323.0f, 1056.0f, 1333.0f, 1066.0f}, //first orb 1 + {1319.3f, 1084.0f, 1329.5f, 1094.0f}, //second orb 2 + {1288.3f, 1108.8f, 1298.3f, 1118.8f}, //third orb 3 + {1260.3f, 1104.2f, 1270.3f, 1114.2f}, //four orb 4 + {1237.7f, 1074.5f, 1247.7f, 1084.5f}, //fifth orb 5 + {1241.8f, 1046.1f, 1251.8f, 1056.1f}, // 6 + {1272.0f, 1022.1f, 1282.0f, 1032.1f}, // 7 + {1300.5f, 1026.2f, 1310.5f, 1036.2f} // 8 +}; + +struct MANGOS_DLL_DECL boss_varosAI : public ScriptedAI +{ + boss_varosAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint8 MinOrb; + uint8 MaxOrb; + + uint32 m_uiCoreTimer; + uint32 m_uiOrbCast; + uint32 m_uiDragonAttackTimer; + uint32 m_uiDragonMoveTimer; + uint32 m_uiCheckTimer; + + uint64 m_uiAzureDrakeGUID; + + bool m_bIsCastChain; + + float angle01; + float angle02; + + void Reset() + { + MinOrb = 1; + MaxOrb = 4; + angle01 = 0; + angle02 = 0; + m_uiOrbCast = 7000; + m_uiCheckTimer = 2000; + m_uiDragonAttackTimer = 10000; + m_uiCoreTimer = urand(7000, 15000); + m_uiDragonMoveTimer = 16000; + m_bIsCastChain = false; + if(m_pInstance) + { + m_pInstance->SetData(TYPE_VAROS, NOT_STARTED); + if(m_pInstance->GetData(TYPE_ROBOTS) == 0) + { + m_creature->RemoveAurasDueToSpell(SPELL_ARCANE_SHIELD); + m_creature->InterruptNonMeleeSpells(false); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + else + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, SPELL_ARCANE_SHIELD); + } + if(Creature* Dragon = m_pInstance->instance->GetCreature(m_uiAzureDrakeGUID)) + Dragon->DealDamage(Dragon, Dragon->GetMaxHealth(),NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + m_uiAzureDrakeGUID = 0; + } + + void CheckVehicle() + { + Map* map = m_creature->GetMap(); + if(map && map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if(PlayerList.isEmpty()) + return; + + for(Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if(i->getSource()->isAlive() && i->getSource()->GetVehicle()) + EnterEvadeMode(); + } + } + } + + void Aggro(Unit* who) + { + DoScriptText(SAY_AGGRO, m_creature); + + if(m_pInstance) + m_pInstance->SetData(TYPE_VAROS, IN_PROGRESS); + + if(Creature* Dragon = m_creature->SummonCreature(NPC_AZURE_CAPTAIN, (m_creature->GetPositionX()-45)+rand()%90, (m_creature->GetPositionY()-45)+rand()%90, m_creature->GetPositionZ() + 30.0f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 100)) + { + Dragon->AddSplineFlag(SPLINEFLAG_FLYING); + Dragon->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiAzureDrakeGUID = Dragon->GetGUID(); + } + } + + void AttackStart(Unit* pWho) + { + if(m_pInstance) + if(m_pInstance->GetData(TYPE_ROBOTS) != 0) + return; + + ScriptedAI::AttackStart(pWho); + + } + + void JustDied(Unit* killer) + { + DoScriptText(SAY_DEATH, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_VAROS, DONE); + } + + void KilledUnit(Unit *victim) + { + DoScriptText(urand(0,1) ? SAY_KILL_1 : SAY_KILL_2, m_creature); + } + + void JustSummoned(Creature* pSummoned) + { + if(pSummoned->GetEntry() == NPC_BEAM) + { + pSummoned->setFaction(14); + pSummoned->SetDisplayId(11686); + pSummoned->CastSpell(pSummoned, SPELL_BEAM_VISUAL_SOUND, false); + pSummoned->CastSpell(pSummoned, SPELL_BEAM_DMG_AURA, false); + pSummoned->SetInCombatWithZone(); + if(Unit* pTarget = pSummoned->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pSummoned->AI()->AttackStart(pTarget); + if(m_pInstance) + if(Creature* Dragon = m_pInstance->instance->GetCreature(m_uiAzureDrakeGUID)) + { + Dragon->GetMotionMaster()->MovementExpired(false); + Dragon->GetMotionMaster()->Clear(false); + Dragon->CastSpell(pSummoned, SPELL_BEAM, true); + } + } + } + + void SelectFourOrb() //huck work perfecly + { + MinOrb = MinOrb+2; + MaxOrb = MaxOrb+2; + if(MinOrb > 8) + MinOrb = 1; + if(MaxOrb > 8) + MaxOrb = 2; + + std::list m_pSpheres; + GetCreatureListWithEntryInGrid(m_pSpheres, m_creature, NPC_VAROS_CORE, DEFAULT_VISIBILITY_INSTANCE); + + if(!m_pSpheres.empty()) + for(std::list::iterator iter = m_pSpheres.begin(); iter != m_pSpheres.end(); ++iter) + { + for(uint8 i = 1; i < 9; i++) + if((i <= MaxOrb && i >= MinOrb) || (MinOrb == 7 && (i <= MaxOrb || i >= MinOrb))) + if((*iter)->GetPositionX() > Regions[i].x1 && (*iter)->GetPositionX() < Regions[i].x2) + if((*iter)->GetPositionY() > Regions[i].y1 && (*iter)->GetPositionY() < Regions[i].y2) + if(SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_CORE_MISSILE)) + { + pTempSpell->EffectImplicitTargetA[0] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[0] = 0; + pTempSpell->EffectImplicitTargetA[1] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[1] = 0; + pTempSpell->EffectImplicitTargetA[2] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[2] = 0; + (*iter)->CastSpell(m_creature, pTempSpell, true); + } + } + } + + void CastEnergy() + { + std::list m_pSpheres; + GetCreatureListWithEntryInGrid(m_pSpheres, m_creature, NPC_VAROS_CORE, DEFAULT_VISIBILITY_INSTANCE); + + if(!m_pSpheres.empty()) + for(std::list::iterator iter = m_pSpheres.begin(); iter != m_pSpheres.end(); ++iter) + { + for(uint8 i = 1; i < 9; i++) + if((i <= MaxOrb && i >= MinOrb) || (MinOrb == 7 && (i <= MaxOrb || i >= MinOrb))) + if((*iter)->GetPositionX() > Regions[i].x1 && (*iter)->GetPositionX() < Regions[i].x2) + if((*iter)->GetPositionY() > Regions[i].y1 && (*iter)->GetPositionY() < Regions[i].y2) + { + if(SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_ENERGIZE_CORES_TRIGGER_1)) + { + pTempSpell->EffectImplicitTargetA[0] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[0] = 0; + pTempSpell->EffectImplicitTargetA[1] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[1] = 0; + pTempSpell->EffectImplicitTargetA[2] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[2] = 0; + (*iter)->CastSpell(m_creature, pTempSpell, true); + } + + if(i == MinOrb) + angle01 = m_creature->GetAngle((*iter)); + if(i == MaxOrb) + angle02 = m_creature->GetAngle((*iter)); + + Map *map = m_creature->GetMap(); + if(map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if(PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive()) + { + float pAngle = m_creature->GetAngle(i->getSource()); + if(angle01 < angle02) + if(pAngle < angle02 && pAngle > angle01) + DoEnergy(i->getSource()); + if(angle01 > angle02) + if(pAngle < angle02 || pAngle > angle01) + DoEnergy(i->getSource()); + } + } + } + } + } + } + + void DoEnergy(Unit* pTarget) + { + if(SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(m_bIsRegularMode ? SPELL_ENERGIZE_CORES : SPELL_ENERGIZE_CORES_2)) + { + pTempSpell->EffectImplicitTargetA[0] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[0] = 0; + pTempSpell->EffectImplicitTargetA[1] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[1] = 0; + pTempSpell->EffectImplicitTargetA[2] = TARGET_EFFECT_SELECT; + pTempSpell->EffectImplicitTargetB[2] = 0; + m_creature->CastSpell(pTarget, pTempSpell, true); + } + + } + + /*void SpellHitTarget(Unit *target, const SpellEntry *spell) + { + if(spell->Id == (m_bIsRegularMode ? SPELL_ENERGIZE_CORES : SPELL_ENERGIZE_CORES_2) && target->GetTypeId() == TYPEID_PLAYER) + { + int32 uiDmg = m_bIsRegularMode ? urand(5938, 6562) : urand(9025, 9975); + m_creature->DealDamage(target, uiDmg,NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, NULL, false); + } + }*/ + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiCheckTimer < uiDiff) + { + CheckVehicle(); + m_uiCheckTimer = 2000; + } else m_uiCheckTimer -= uiDiff; + + if(m_uiDragonAttackTimer <= uiDiff) + { + DoCast(m_creature, SPELL_SUMMON_BEAM, true); + m_uiDragonAttackTimer = 25000; + m_uiDragonMoveTimer = 16000; + uint8 uiText = urand(0, 2); + switch (uiText) + { + case 0: DoScriptText(SAY_STRIKE_1, m_creature); break; + case 1: DoScriptText(SAY_STRIKE_2, m_creature); break; + case 2: DoScriptText(SAY_STRIKE_3, m_creature); break; + } + } else m_uiDragonAttackTimer -= uiDiff; + + if(m_uiDragonMoveTimer <= uiDiff) + { + if(m_pInstance) + if(Creature* Dragon = m_pInstance->instance->GetCreature(m_uiAzureDrakeGUID)) + { + Dragon->GetMotionMaster()->MovementExpired(false); + Dragon->GetMotionMaster()->Clear(false); + Dragon->GetMotionMaster()->MovePoint(0, (m_creature->GetPositionX()-45)+rand()%90, (m_creature->GetPositionY()-45)+rand()%90, m_creature->GetPositionZ() + 30.0f); + } + m_uiDragonMoveTimer = 25000; + } else m_uiDragonMoveTimer -= uiDiff; + + if(!m_bIsCastChain) + { + if(m_uiOrbCast <= uiDiff) + { + m_uiOrbCast = 1000; + m_bIsCastChain = true; + SelectFourOrb(); + m_uiCoreTimer = 5000; + } else m_uiOrbCast -= uiDiff; + } + else + { + if(m_uiCoreTimer <= uiDiff) + { + m_uiCoreTimer = 5000; + m_bIsCastChain = false; + CastEnergy(); + m_uiOrbCast = 1000; + } else m_uiCoreTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL npc_varos_orbAI : public ScriptedAI +{ + npc_varos_orbAI(Creature *pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->setFaction(14); + DoCast(m_creature, SPELL_CORE_VISUAL, true); + } + + void AttackStart(Unit* pWho) + { + } + + void UpdateAI(const uint32 diff) + { + } +}; + +struct MANGOS_DLL_DECL npc_varos_beam_targetAI : public ScriptedAI +{ + npc_varos_beam_targetAI(Creature *pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + uint32 uiDeathTimer; + + void Reset() + { + m_creature->SetSpeedRate(MOVE_RUN, 0.5f, true); + uiDeathTimer = 15000; + } + + void UpdateAI(const uint32 diff) + { + if (uiDeathTimer < diff) + m_creature->ForcedDespawn(); + else uiDeathTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_varos(Creature* pCreature) +{ + return new boss_varosAI (pCreature); +} + +CreatureAI* GetAI_npc_varos_orb(Creature* pCreature) +{ + return new npc_varos_orbAI (pCreature); +} + +CreatureAI* GetAI_npc_varos_beam_target(Creature* pCreature) +{ + return new npc_varos_beam_targetAI (pCreature); +} + +void AddSC_boss_varos() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_varos"; + newscript->GetAI = &GetAI_boss_varos; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_varos_orb"; + newscript->GetAI = &GetAI_npc_varos_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_varos_beam_target"; + newscript->GetAI = &GetAI_npc_varos_beam_target; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/nexus/oculus/instance_oculus.cpp b/scripts/northrend/nexus/oculus/instance_oculus.cpp new file mode 100644 index 0000000..95219b7 --- /dev/null +++ b/scripts/northrend/nexus/oculus/instance_oculus.cpp @@ -0,0 +1,240 @@ +/* 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: instance_oculus +SD%Complete: 70% +SDComment: +SDAuthor: originally from TC, reworked by MaxXx2021 Aka Mioka, corrected by /dev/rsa +SDCategory: Oculus +EndScriptData */ + +#include "precompiled.h" +#include "oculus.h" + +/* The Occulus encounters: +0 - Drakos the Interrogator +1 - Varos Cloudstrider +2 - Mage-Lord Urom +3 - Ley-Guardian Eregos */ + +enum +{ + SAY_VAROS_SPAWN = -1578029, +}; + +struct MANGOS_DLL_DECL instance_oculus : public ScriptedInstance +{ + instance_oculus(Map* pMap) : ScriptedInstance(pMap) + { + m_bIsRegularMode = pMap->IsRegularDifficulty(); + Initialize(); + }; + + uint64 uiDrakos; + uint64 m_uiVarosGUID; + uint64 m_uiUromGUID; + uint64 m_uiEregosGUID; + uint64 uiProect; + uint64 uiCacheEregosGUID; + uint64 uiCacheEregosHGUID; + uint64 m_uiSpotLightGUID; + + uint32 m_auiEncounter[MAX_ENCOUNTERS+1]; + + std::string strSaveData; + bool m_bIsRegularMode; + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTERS+1; ++i) + m_auiEncounter[i] = NOT_STARTED; + + uiCacheEregosGUID = 0; + m_uiSpotLightGUID = 0; + uiProect = 0; + m_uiVarosGUID = 0; + m_uiUromGUID = 0; + m_uiEregosGUID = 0; + m_auiEncounter[TYPE_ROBOTS] = 10; + m_auiEncounter[TYPE_UROM_PHASE] = 0; + } + + void OnObjectCreate(GameObject* pGO) + { + switch(pGO->GetEntry()) + { + case GO_EREGOS_CACHE: + uiCacheEregosGUID = pGO->GetGUID(); + break; + case GO_EREGOS_CACHE_H: + uiCacheEregosHGUID = pGO->GetGUID(); + break; + case GO_SPOTLIGHT: + m_uiSpotLightGUID = pGO->GetGUID(); + break; + } + } + + void OnCreatureCreate(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case NPC_DRAKOS: + uiDrakos = pCreature->GetGUID(); + break; + case NPC_VAROS: + m_uiVarosGUID = pCreature->GetGUID(); + break; + case NPC_UROM: + m_uiUromGUID = pCreature->GetGUID(); + break; + case NPC_EREGOS: + m_uiEregosGUID = pCreature->GetGUID(); + break; + case NPC_BALGAR_IMAGE: + uiProect = pCreature->GetGUID(); + break; + } + } + + void SetData(uint32 type, uint32 data) + { + switch(type) + { + case TYPE_DRAKOS: + case TYPE_VAROS: + case TYPE_UROM: + m_auiEncounter[type] = data; + break; + case TYPE_EREGOS: + m_auiEncounter[type] = data; + if (data == DONE) + { + DoRespawnGameObject((m_bIsRegularMode ? uiCacheEregosGUID : uiCacheEregosHGUID), HOUR); + DoRespawnGameObject(m_uiSpotLightGUID, HOUR); + } + break; + case TYPE_ROBOTS: + m_auiEncounter[type] = m_auiEncounter[type] - data; + if(m_auiEncounter[type] == 0) + { + if(Creature* pVaros = instance->GetCreature(m_uiVarosGUID)) + { + DoScriptText(SAY_VAROS_SPAWN, pVaros); + pVaros->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pVaros->InterruptNonMeleeSpells(false); + pVaros->RemoveAurasDueToSpell(50053); + } + } + data = NOT_STARTED; + break; + case TYPE_UROM_PHASE: + m_auiEncounter[type] = data; + data = NOT_STARTED; + break; + } + + if (data == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + saveStream << m_auiEncounter[i] << " "; + + strSaveData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + uint32 GetData(uint32 type) + { + switch(type) + { + case TYPE_DRAKOS: + case TYPE_VAROS: + case TYPE_UROM: + case TYPE_EREGOS: + case TYPE_ROBOTS: + case TYPE_UROM_PHASE: + return m_auiEncounter[type]; + default: + return 0; + } + return 0; + } + + uint64 GetData64(uint32 identifier) + { + switch(identifier) + { + case DATA_DRAKOS: return uiDrakos; + case NPC_VAROS: return m_uiVarosGUID; + case NPC_UROM: return m_uiUromGUID; + case NPC_EREGOS: return m_uiEregosGUID; + } + return 0; + } + + const char* Save() + { + return strSaveData.c_str(); + } + + void Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + { + loadStream >> m_auiEncounter[i]; + + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + m_auiEncounter[TYPE_ROBOTS] = 10; + m_auiEncounter[TYPE_UROM_PHASE] = 0; + + 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/scripts/northrend/nexus/oculus/oculus.cpp b/scripts/northrend/nexus/oculus/oculus.cpp new file mode 100644 index 0000000..9a37579 --- /dev/null +++ b/scripts/northrend/nexus/oculus/oculus.cpp @@ -0,0 +1,232 @@ +/* Copyright (C) 2006 - 2010 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: oculus +SD%Complete: ?% +SDComment: by /dev/rsa +SDCategory: Oculus - mobs and special +EndScriptData */ + +#include "precompiled.h" +#include "oculus.h" +enum Spells +{ + SPELL_GREEN_SEAT = 49346, + SPELL_YELLOW_SEAT = 49460, + SPELL_RED_SEAT = 49464, +}; + +enum NPC +{ + NPC_GREEN_DRAGON = 27692, + NPC_YELLOW_DRAGON = 27755, + NPC_RED_DRAGON = 27756, +}; + +struct MANGOS_DLL_DECL mob_oculus_dragonAI : public ScriptedAI +{ + mob_oculus_dragonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + bool Active; + ObjectGuid ownerGUID; + uint32 seatSpell; + uint32 StartTimer; + + void Reset() + { + Active = false; + ownerGUID = 0; + StartTimer = 2000; + switch (m_creature->GetEntry()) + { + case NPC_GREEN_DRAGON: + seatSpell = SPELL_GREEN_SEAT; + break; + case NPC_RED_DRAGON: + seatSpell = SPELL_RED_SEAT; + break; + case NPC_YELLOW_DRAGON: + seatSpell = SPELL_YELLOW_SEAT; + break; + default: + seatSpell = 0; + break; + } + ownerGUID = m_creature->GetCreatorGuid(); + + if (Unit* owner = m_creature->GetMap()->GetUnit(ownerGUID)) + owner->RemoveAurasDueToSpell(53797); + } + + void AttackStart(Unit *) {} + void MoveInLineOfSight(Unit*) {} + + void JustSummoned() + { + } + + void JustDied(Unit* killer) + { + if (!m_creature || m_creature->GetTypeId() != TYPEID_UNIT) + return; + + if (ownerGUID.IsEmpty()) + ownerGUID = m_creature->GetCreatorGuid(); + + Unit* owner = m_creature->GetMap()->GetUnit(ownerGUID); + + if (!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + owner->RemoveAurasDueToSpell(seatSpell); + owner->RemoveAurasDueToSpell(53797); + m_creature->SetCreatorGuid(ObjectGuid()); + } + + void MovementInform(uint32 uiType, uint32 uiPointId) + { + if (uiType != POINT_MOTION_TYPE && uiPointId == 0) + return; + + if (Unit* owner = m_creature->GetMap()->GetUnit(ownerGUID)) + { + m_creature->setFaction(owner->getFaction()); + owner->CastSpell(m_creature, seatSpell, true); + owner->CastSpell(owner, 53797, true); + } + } + + void UpdateAI(const uint32 uiDiff) + { + + if (ownerGUID.IsEmpty()) + ownerGUID = m_creature->GetCreatorGuid(); + + if (!ownerGUID.IsEmpty()) + { + if (StartTimer < uiDiff && !Active) + { + if (Unit* owner = m_creature->GetMap()->GetUnit(ownerGUID)) + { + float x, y, z; + owner->GetClosePoint(x, y, z, owner->GetObjectBoundingRadius(), 1.0f, owner->GetAngle(m_creature)); + m_creature->GetMotionMaster()->MovePoint(0, x, y, z); + Active = true; + } + } + else + StartTimer -= uiDiff; + } + else + if (StartTimer < uiDiff) + m_creature->ForcedDespawn(); + } +}; + +CreatureAI* GetAI_mob_oculus_dragon(Creature* pCreature) +{ + return new mob_oculus_dragonAI(pCreature); +} + +/*##### +# npc_robot +#####*/ + +struct MANGOS_DLL_DECL npc_oculus_robotAI : public ScriptedAI +{ + npc_oculus_robotAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + } + + void JustDied(Unit* pKiller) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_ROBOTS, 1); + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_oculus_robot(Creature* pCreature) +{ + return new npc_oculus_robotAI (pCreature); +} + +struct MANGOS_DLL_DECL npc_belgar_imageAI : public ScriptedAI +{ + npc_belgar_imageAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + } + + void UpdateAI(const uint32 diff) + { + if(!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + } +}; + +CreatureAI* GetAI_npc_belgar_image(Creature* pCreature) +{ + return new npc_belgar_imageAI (pCreature); +} + +void AddSC_oculus() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_oculus_dragon"; + newscript->GetAI = &GetAI_mob_oculus_dragon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_oculus_robot"; + newscript->GetAI = &GetAI_npc_oculus_robot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_belgar_image"; + newscript->GetAI = &GetAI_npc_belgar_image; + newscript->RegisterSelf(); + +} diff --git a/scripts/northrend/nexus/oculus/oculus.h b/scripts/northrend/nexus/oculus/oculus.h new file mode 100644 index 0000000..4affa6b --- /dev/null +++ b/scripts/northrend/nexus/oculus/oculus.h @@ -0,0 +1,43 @@ +/* Copyright (C) 2010 by /dev/rsa for ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_OCULUS_H +#define DEF_OCULUS_H +#include "BSW_ai.h" +#include "BSW_instance.h" + +enum +{ + TYPE_DRAKOS, + TYPE_VAROS, + TYPE_UROM, + TYPE_EREGOS, + TYPE_ROBOTS, + TYPE_UROM_PHASE, + MAX_ENCOUNTERS, + + DATA_DRAKOS, + DATA_VAROS, + DATA_UROM, + DATA_EREGOS, + + NPC_ROBOT = 27641, + NPC_BALGAR_IMAGE = 28012, + NPC_DRAKOS = 27654, + NPC_VAROS = 27447, + NPC_UROM = 27655, + NPC_EREGOS = 27656, +// + GO_DRAGON_CAGE_DOOR = 193995, + GO_EREGOS_CACHE = 191349, + GO_EREGOS_CACHE_H = 193603, + GO_SPOTLIGHT = 191351, + + BELGAR_TEXT_0 = 13267, + BELGAR_TEXT_1 = 13268, + BELGAR_TEXT_2 = 13269, + +}; + +#endif diff --git a/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp b/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp index 023781c..ebf6318 100644 --- a/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp +++ b/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp @@ -16,8 +16,8 @@ /* ScriptData SDName: Boss Sartharion -SD%Complete: 70% -SDComment: Flame wave, achievement and portal events need to be implemented +SD%Complete: 100% +SDComment: It's alive! ;) Now this is script is alive realy! (c) MaxXx2021 and PSZ SDCategory: Obsidian Sanctum EndScriptData */ @@ -58,12 +58,14 @@ enum SPELL_TAIL_LASH_H = 58957, // A sweeping tail strike hits all enemies behind the caster, inflicting 4375 to 5625 damage and stunning them for 2 sec. SPELL_WILL_OF_SARTHARION = 61254, // Sartharion's presence bolsters the resolve of the Twilight Drakes, increasing their total health by 25%. This effect also increases Sartharion's health by 25%. SPELL_LAVA_STRIKE = 57571, // (Real spell casted should be 57578) 57571 then trigger visual missile, then summon Lava Blaze on impact(spell 57572) + SPELL_CYCLONE_AURA_2 = 57598, SPELL_TWILIGHT_REVENGE = 60639, SPELL_PYROBUFFET = 56916, // currently used for hard enrage after 15 minutes SPELL_PYROBUFFET_RANGE = 58907, // possibly used when player get too far away from dummy creatures (2x creature entry 30494) SPELL_TWILIGHT_SHIFT_ENTER = 57620, // enter phase. Player get this when click GO + SPELL_TWILIGHT_SHIFT_DMG = 57874, // damage during being in twilight realm SPELL_TWILIGHT_SHIFT_REMOVAL = 61187, // leave phase SPELL_TWILIGHT_SHIFT_REMOVAL_ALL = 61190, // leave phase (probably version to make all leave) @@ -103,6 +105,8 @@ enum SPELL_HATCH_EGGS_EFFECT_H = 59190, SPELL_HATCH_EGGS_EFFECT = 58685, + NPC_TWILIGHT_EGG = 30882, + //Whelps NPC_TWILIGHT_WHELP = 30890, NPC_SHARTHARION_TWILIGHT_WHELP = 31214, @@ -112,9 +116,12 @@ enum SPELL_FLAME_TSUNAMI = 57494, // the visual dummy SPELL_FLAME_TSUNAMI_LEAP = 60241, // SPELL_EFFECT_138 some leap effect, causing caster to move in direction SPELL_FLAME_TSUNAMI_DMG_AURA = 57492, // periodic damage, npc has this aura + SPELL_FLAME_TSUNAMI_DMG = 57491, // damage players + SPELL_FLAME_TSUNAMI_BUFF = 60430, // buff Lava Blazes NPC_FLAME_TSUNAMI = 30616, // for the flame waves NPC_LAVA_BLAZE = 30643, // adds spawning from flame strike + NPC_FIRE_CYCLONE = 30648, //using these custom points for dragons start and end POINT_ID_INIT = 100, @@ -156,6 +163,21 @@ Waypoint m_aDragonCommon[]= {3209.969f, 566.523f, 98.652f} }; +float m_afTsunamiStartLoc[5][4]= +{ + //left to right + {3201.0f, 487.75f, 58.6f, 6.23f}, + {3201.0f, 533.54f, 58.6f, 6.23f}, + {3201.0f, 579.14f, 58.6f, 6.23f}, + //right to left + {3287.5f, 552.53f, 58.6f, 3.19f}, + {3287.5f, 511.10f, 58.6f, 3.19f}, +}; + +uint64 m_uiAcolyteShadronGUID; +uint64 m_uiAcolyteVesperonGUID; +std::list m_lEggsGUIDList; + /*###### ## Boss Sartharion ######*/ @@ -166,6 +188,9 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI { m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + m_bTenebronHelpedInFight = false; + m_bShadronHelpedInFight = false; + m_bVesperonHelpedInFight = false; Reset(); } @@ -186,11 +211,25 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI uint32 m_uiFlameBreathTimer; uint32 m_uiTailSweepTimer; uint32 m_uiCleaveTimer; - uint32 m_uiLavaStrikeTimer; + uint32 m_uiCycloneAuraTimer; bool m_bHasCalledTenebron; bool m_bHasCalledShadron; bool m_bHasCalledVesperon; + bool m_bTenebronHelpedInFight; + bool m_bShadronHelpedInFight; + bool m_bVesperonHelpedInFight; + + bool bCanUseWill; + bool bFirstWill; + uint32 m_uiSarthHealth; + uint32 m_uiTeneHealth; + uint32 m_uiShadHealth; + uint32 m_uiVespHealth; + + uint32 m_uiCheckTwilightTimer; + + std::list m_lFireCyclones; void Reset() { @@ -206,16 +245,59 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI m_uiFlameTsunamiTimer = 30000; m_uiFlameBreathTimer = 20000; - m_uiTailSweepTimer = 20000; + m_uiTailSweepTimer = 5000; m_uiCleaveTimer = 7000; - m_uiLavaStrikeTimer = 5000; + m_uiCycloneAuraTimer = 10000; m_bHasCalledTenebron = false; m_bHasCalledShadron = false; m_bHasCalledVesperon = false; - if (m_creature->HasAura(SPELL_TWILIGHT_REVENGE)) - m_creature->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE); + bCanUseWill = false; + bFirstWill = true; + + m_uiCheckTwilightTimer = 2000; + + if (m_pInstance) + { + Creature* pTene = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_TENEBRON)); + Creature* pShad = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_SHADRON)); + Creature* pVesp = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_VESPERON)); + + if (m_bTenebronHelpedInFight && pTene) + { + if (pTene->isDead()) + pTene->Respawn(); + else + pTene->AI()->EnterEvadeMode(); + } + + if (m_bShadronHelpedInFight && pShad) + { + if (pShad->isDead()) + pShad->Respawn(); + else + pShad->AI()->EnterEvadeMode(); + } + + if (m_bVesperonHelpedInFight && pVesp) + { + if (pVesp->isDead()) + pVesp->Respawn(); + else + pVesp->AI()->EnterEvadeMode(); + } + } + + m_lFireCyclones.clear(); + GetCreatureListWithEntryInGrid(m_lFireCyclones, m_creature, NPC_FIRE_CYCLONE, 100.0f); + + m_bTenebronHelpedInFight = false; + m_bShadronHelpedInFight = false; + m_bVesperonHelpedInFight = false; + + m_creature->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SAR); + m_creature->RemoveAurasDueToSpell(SPELL_TWILIGHT_REVENGE); } void JustReachedHome() @@ -237,9 +319,26 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI } } + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > m_creature->GetHealth()) + { + uint8 uiHardMode = 0; + if (m_bTenebronHelpedInFight) + ++uiHardMode; + if (m_bShadronHelpedInFight) + ++uiHardMode; + if (m_bVesperonHelpedInFight) + ++uiHardMode; + + if (uiHardMode) + m_creature->UpdateEntry(m_creature->GetEntry()*10+uiHardMode); + } + } + void JustDied(Unit* pKiller) { - DoScriptText(SAY_SARTHARION_DEATH,m_creature); + DoScriptText(SAY_SARTHARION_DEATH, m_creature); if (m_pInstance) m_pInstance->SetData(TYPE_SARTHARION_EVENT, DONE); @@ -247,7 +346,7 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI void KilledUnit(Unit* pVictim) { - switch(urand(0, 2)) + switch (urand(0, 2)) { case 0: DoScriptText(SAY_SARTHARION_SLAY_1, m_creature); break; case 1: DoScriptText(SAY_SARTHARION_SLAY_2, m_creature); break; @@ -262,11 +361,12 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI Creature* pVesp = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_VESPERON)); //if at least one of the dragons are alive and are being called - bool bCanUseWill = false; - if (pTene && pTene->isAlive() && !pTene->getVictim()) { bCanUseWill = true; + pTene->CastSpell(pTene, SPELL_POWER_OF_TENEBRON, false); + pTene->AddSplineFlag(SPLINEFLAG_FLYING); + pTene->RemoveSplineFlag(SPLINEFLAG_WALKMODE); pTene->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aTene[0].m_fX, m_aTene[0].m_fY, m_aTene[0].m_fZ); if (!pTene->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) @@ -276,6 +376,9 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (pShad && pShad->isAlive() && !pShad->getVictim()) { bCanUseWill = true; + pShad->CastSpell(pShad, SPELL_POWER_OF_SHADRON, false); + pShad->AddSplineFlag(SPLINEFLAG_FLYING); + pShad->RemoveSplineFlag(SPLINEFLAG_WALKMODE); pShad->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aShad[0].m_fX, m_aShad[0].m_fY, m_aShad[0].m_fZ); if (!pShad->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) @@ -285,6 +388,9 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (pVesp && pVesp->isAlive() && !pVesp->getVictim()) { bCanUseWill = true; + pVesp->CastSpell(pVesp, SPELL_POWER_OF_VESPERON, false); + pVesp->AddSplineFlag(SPLINEFLAG_FLYING); + pVesp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); pVesp->GetMotionMaster()->MovePoint(POINT_ID_INIT, m_aVesp[0].m_fX, m_aVesp[0].m_fY, m_aVesp[0].m_fZ); if (!pVesp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) @@ -292,7 +398,7 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI } if (bCanUseWill) - DoCastSpellIfCan(m_creature, SPELL_WILL_OF_SARTHARION); + DoCast(m_creature, SPELL_WILL_OF_SARTHARION); } void CallDragon(uint32 uiDataId) @@ -303,27 +409,41 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (pTemp && pTemp->isAlive() && !pTemp->getVictim()) { - if (pTemp->HasSplineFlag(SPLINEFLAG_WALKMODE)) - pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - if (pTemp->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiSarthHealth = m_creature->GetHealth(); + DoCast(m_creature, SPELL_WILL_OF_SARTHARION, false); + bCanUseWill = true; int32 iTextId = 0; - switch(pTemp->GetEntry()) + Creature* pAdd = NULL; + pAdd = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_TENEBRON)); + if (pAdd) + m_uiTeneHealth = pAdd->GetHealth(); + pAdd = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_SHADRON)); + if (pAdd) + m_uiShadHealth = pAdd->GetHealth(); + pAdd = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_VESPERON)); + if (pAdd) + m_uiVespHealth = pAdd->GetHealth(); + + switch (pTemp->GetEntry()) { case NPC_TENEBRON: iTextId = SAY_SARTHARION_CALL_TENEBRON; pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aTene[1].m_fX, m_aTene[1].m_fY, m_aTene[1].m_fZ); + m_bTenebronHelpedInFight = true; break; case NPC_SHADRON: iTextId = SAY_SARTHARION_CALL_SHADRON; pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aShad[1].m_fX, m_aShad[1].m_fY, m_aShad[1].m_fZ); + m_bShadronHelpedInFight = true; break; case NPC_VESPERON: iTextId = SAY_SARTHARION_CALL_VESPERON; pTemp->GetMotionMaster()->MovePoint(POINT_ID_LAND, m_aVesp[1].m_fX, m_aVesp[1].m_fY, m_aVesp[1].m_fZ); + m_bVesperonHelpedInFight = true; break; } @@ -345,10 +465,19 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) { if (i->getSource()->isAlive()) - DoScriptText(WHISPER_LAVA_CHURN, m_creature,i->getSource()); + DoScriptText(WHISPER_LAVA_CHURN, m_creature, i->getSource()); } } } + + uint8 uiTsunamiDirection = urand(0, 1); + uint8 uiTsunamiWavesAmount = 3; + if (uiTsunamiDirection) + uiTsunamiWavesAmount = 2; + for (uint8 i = uiTsunamiDirection*3; i < uiTsunamiDirection*3+uiTsunamiWavesAmount; ++i) + { + m_creature->SummonCreature(NPC_FLAME_TSUNAMI, m_afTsunamiStartLoc[i][0], m_afTsunamiStartLoc[i][1], m_afTsunamiStartLoc[i][2], m_afTsunamiStartLoc[i][3], TEMPSUMMON_TIMED_DESPAWN, 18000); + } } void UpdateAI(const uint32 uiDiff) @@ -357,18 +486,57 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if (bCanUseWill) + { + if (bFirstWill) + { + m_creature->SetHealth(m_creature->GetHealth()*1.25); + } + else + { + m_creature->SetHealth(m_uiSarthHealth); + Creature* pTemp = NULL; + pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_TENEBRON)); + if (pTemp && pTemp->isAlive()) + pTemp->SetHealth(m_uiTeneHealth); + pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_SHADRON)); + if (pTemp && pTemp->isAlive()) + pTemp->SetHealth(m_uiShadHealth); + pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_VESPERON)); + if (pTemp && pTemp->isAlive()) + pTemp->SetHealth(m_uiVespHealth); + } + bCanUseWill = false; + bFirstWill = false; + } + //spell will target dragons, if they are still alive at 35% - if (!m_bIsBerserk && m_creature->GetHealthPercent() < 35.0f) + if (!m_bIsBerserk && m_creature->GetHealthPercent() <= 35.0f) { DoScriptText(SAY_SARTHARION_BERSERK, m_creature); - DoCastSpellIfCan(m_creature, SPELL_BERSERK); + //DoCast(m_creature, SPELL_BERSERK); + Creature* pTemp = NULL; + pTemp = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_TENEBRON)); + if (pTemp && pTemp->isAlive()) + pTemp->CastSpell(pTemp, 27680, true); + pTemp = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_SHADRON)); + if (pTemp && pTemp->isAlive()) + pTemp->CastSpell(pTemp, 27680, true); + pTemp = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_VESPERON)); + if (pTemp && pTemp->isAlive()) + pTemp->CastSpell(pTemp, 27680, true); + m_bIsBerserk = true; } //soft enrage if (!m_bIsSoftEnraged && m_creature->GetHealthPercent() <= 10.0f) { - // TODO + if (!m_lFireCyclones.empty()) + for (std::list::iterator iter = m_lFireCyclones.begin(); iter != m_lFireCyclones.end(); ++iter) + if (*iter) + (*iter)->CastSpell(*iter, SPELL_CYCLONE_AURA_2, true); + m_bIsSoftEnraged = true; } @@ -377,7 +545,7 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI { if (m_uiEnrageTimer < uiDiff) { - DoCastSpellIfCan(m_creature, SPELL_PYROBUFFET, CAST_TRIGGERED); + DoCast(m_creature, SPELL_PYROBUFFET, true); m_bIsHardEnraged = true; } else @@ -388,6 +556,14 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (m_uiFlameTsunamiTimer < uiDiff) { SendFlameTsunami(); + switch(urand(0, 3)) + { + case 0: DoScriptText(SAY_SARTHARION_SPECIAL_1, m_creature); break; + case 1: DoScriptText(SAY_SARTHARION_SPECIAL_2, m_creature); break; + case 2: DoScriptText(SAY_SARTHARION_SPECIAL_3, m_creature); break; + case 3: DoScriptText(SAY_SARTHARION_SPECIAL_4, m_creature); break; + } + m_uiFlameTsunamiTimer = 30000; } else @@ -397,7 +573,7 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI if (m_uiFlameBreathTimer < uiDiff) { DoScriptText(SAY_SARTHARION_BREATH, m_creature); - DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H); m_uiFlameBreathTimer = urand(25000, 35000); } else @@ -406,8 +582,8 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI // Tail Sweep if (m_uiTailSweepTimer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_TAIL_LASH : SPELL_TAIL_LASH_H); - m_uiTailSweepTimer = urand(15000, 20000); + DoCast(m_creature, m_bIsRegularMode ? SPELL_TAIL_LASH : SPELL_TAIL_LASH_H); + m_uiTailSweepTimer = urand(5000, 7000); } else m_uiTailSweepTimer -= uiDiff; @@ -415,30 +591,38 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI // Cleave if (m_uiCleaveTimer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE); + DoCast(m_creature->getVictim(), SPELL_CLEAVE); m_uiCleaveTimer = urand(7000, 10000); } else m_uiCleaveTimer -= uiDiff; // Lavas Strike - if (m_uiLavaStrikeTimer < uiDiff) + if (m_uiCycloneAuraTimer < uiDiff) { - if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (!m_lFireCyclones.empty()) { - DoCastSpellIfCan(pTarget, SPELL_LAVA_STRIKE); - - switch(urand(0, 15)) + std::list::iterator iter = m_lFireCyclones.begin(); + advance(iter, urand(0, m_lFireCyclones.size()-1)); + if (*iter) { - case 0: DoScriptText(SAY_SARTHARION_SPECIAL_1, m_creature); break; - case 1: DoScriptText(SAY_SARTHARION_SPECIAL_2, m_creature); break; - case 2: DoScriptText(SAY_SARTHARION_SPECIAL_3, m_creature); break; + (*iter)->CastSpell(*iter, SPELL_CYCLONE_AURA_2, true); + + switch(urand(0, 15)) + { + case 0: DoScriptText(SAY_SARTHARION_SPECIAL_1, m_creature); break; + case 1: DoScriptText(SAY_SARTHARION_SPECIAL_2, m_creature); break; + case 2: DoScriptText(SAY_SARTHARION_SPECIAL_3, m_creature); break; + } } } - m_uiLavaStrikeTimer = urand(5000, 20000); + if (m_bIsSoftEnraged) + m_uiCycloneAuraTimer = 10000; + else + m_uiCycloneAuraTimer = urand(20000, 25000); } else - m_uiLavaStrikeTimer -= uiDiff; + m_uiCycloneAuraTimer -= uiDiff; // call tenebron if (!m_bHasCalledTenebron && m_uiTenebronTimer < uiDiff) @@ -467,6 +651,61 @@ struct MANGOS_DLL_DECL boss_sartharionAI : public ScriptedAI else m_uiVesperonTimer -= uiDiff; + if (m_uiCheckTwilightTimer < uiDiff) + { + bool bNoAliveTwilightRealm = true; + if (m_pInstance) + { + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID)) + { + if (pAcolyte->isAlive()) + { + bNoAliveTwilightRealm = false; + } + } + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID)) + { + if (pAcolyte->isAlive()) + { + bNoAliveTwilightRealm = false; + } + } + if (!m_lEggsGUIDList.empty()) + { + for (std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + { + if (pTemp->isAlive()) + { + bNoAliveTwilightRealm = false; + break; + } + } + } + } + if (bNoAliveTwilightRealm) + { + Map* pMap = m_creature->GetMap(); + + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive()) + i->getSource()->CastSpell(i->getSource(), SPELL_TWILIGHT_SHIFT_REMOVAL, true); + } + } + } + } + m_uiCheckTwilightTimer = 2000; + } + else + m_uiCheckTwilightTimer -= uiDiff; + DoMeleeAttackIfReady(); EnterEvadeIfOutOfCombatArea(uiDiff); @@ -529,20 +768,38 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI uint32 m_uiWaypointId; uint32 m_uiMoveNextTimer; - int32 m_iPortalRespawnTime; bool m_bCanMoveFree; void Reset() { - if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE)) - m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); m_uiWaypointId = 0; m_uiMoveNextTimer = 500; - m_iPortalRespawnTime = 30000; m_bCanMoveFree = false; } + void AttackStart(Unit* pWho) + { + if (!pWho || m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + + if (IsCombatMovement()) + m_creature->GetMotionMaster()->MoveChase(pWho); + } + } + + void JustReachedHome() + { + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + } + void MovementInform(uint32 uiType, uint32 uiPointId) { if (!m_pInstance || uiType != POINT_MOTION_TYPE) @@ -562,6 +819,7 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI { m_creature->GetMotionMaster()->Clear(); m_bCanMoveFree = false; + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); m_creature->SetInCombatWithZone(); return; } @@ -601,98 +859,206 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI } } + //Removes debuff from players + void RemoveDebuff(uint32 uiSpellId) + { + Map* pMap = m_creature->GetMap(); + + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + i->getSource()->RemoveAurasDueToSpell(uiSpellId); + if (uiSpellId == SPELL_TWILIGHT_SHIFT_ENTER) + i->getSource()->RemoveAurasDueToSpell(SPELL_TWILIGHT_SHIFT_DMG); + } + } + } + //"opens" the portal and does the "opening" whisper void OpenPortal() { int32 iTextId = 0; + int32 iPortalRespawnTime = 0; //there are 4 portal spawn locations, each are expected to be spawned with negative spawntimesecs in database //using a grid search here seem to be more efficient than caching all four guids //in instance script and calculate range to each. - GameObject* pPortal = GetClosestGameObjectWithEntry(m_creature,GO_TWILIGHT_PORTAL,50.0f); - - switch(m_creature->GetEntry()) + if (GameObject* pPortal = GetClosestGameObjectWithEntry(m_creature, GO_TWILIGHT_PORTAL, 100.0f)) { - case NPC_TENEBRON: - iTextId = WHISPER_HATCH_EGGS; - break; - case NPC_SHADRON: - case NPC_VESPERON: - iTextId = WHISPER_OPEN_PORTAL; - break; - } + Creature* pAcolyte = NULL; + switch(m_creature->GetEntry()) + { + case NPC_TENEBRON: + iTextId = WHISPER_HATCH_EGGS; + m_lEggsGUIDList.clear(); + for (uint8 i=0; i<6; ++i) + { + if (Creature* pEgg = m_creature->SummonCreature(NPC_TWILIGHT_EGG, pPortal->GetPositionX()-10+urand(0, 20), pPortal->GetPositionY()-10+urand(0, 20), pPortal->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000)) + { + pEgg->SetPhaseMask(16, true); + m_lEggsGUIDList.push_back(pEgg->GetGUID()); + } + } + iPortalRespawnTime = 20; + break; + case NPC_SHADRON: + iTextId = WHISPER_OPEN_PORTAL; + if (m_pInstance) + { + pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID); + if (!pAcolyte || (pAcolyte && pAcolyte->isDead())) + { + pAcolyte = NULL; + if (pAcolyte = m_creature->SummonCreature(NPC_ACOLYTE_OF_SHADRON, pPortal->GetPositionX()-10+urand(0, 20), pPortal->GetPositionY()-10+urand(0, 20), pPortal->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000)) + { + m_uiAcolyteShadronGUID = pAcolyte->GetGUID(); + pAcolyte->SetPhaseMask(16, true); + } + } + if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + { + if (Creature* pSarth = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_SARTHARION))) + pSarth->CastSpell(pSarth, SPELL_GIFT_OF_TWILIGTH_SAR, true); + } + else + { + if (Creature* pShad = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_SHADRON))) + pShad->CastSpell(pShad, SPELL_GIFT_OF_TWILIGTH_SHA, true); + } + } + iPortalRespawnTime = 60; + break; + case NPC_VESPERON: + iTextId = WHISPER_OPEN_PORTAL; + if (m_pInstance) + { + uint32 uiTempSpell; + if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) + uiTempSpell = 58835; + else + uiTempSpell = 57935; + + SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(uiTempSpell); + if (pTempSpell) + { + pTempSpell->StackAmount = 1; + pTempSpell->procCharges = 0; + m_creature->CastSpell(m_creature, pTempSpell, true); + } + + pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID); + if (!pAcolyte || (pAcolyte && pAcolyte->isDead())) + { + pAcolyte = NULL; + if (pAcolyte = m_creature->SummonCreature(NPC_ACOLYTE_OF_VESPERON, pPortal->GetPositionX()-10+urand(0, 20), pPortal->GetPositionY()-10+urand(0, 20), pPortal->GetPositionZ()+1.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000)) + { + m_uiAcolyteVesperonGUID = pAcolyte->GetGUID(); + pAcolyte->SetPhaseMask(16, true); + } + } + } + iPortalRespawnTime = 60; + break; + } - DoRaidWhisper(iTextId); + DoRaidWhisper(iTextId); - //By using SetRespawnTime() we will actually "spawn" the object with our defined time. - //Once time is up, portal will disappear again. - if (pPortal && !pPortal->isSpawned()) - { - pPortal->SetRespawnTime(m_iPortalRespawnTime); - pPortal->Refresh(); - } + //By using SetRespawnTime() we will actually "spawn" the object with our defined time. + //Once time is up, portal will disappear again. + + pPortal->SetRespawnTime(iPortalRespawnTime); + pPortal->UpdateObjectVisibility(); - //Unclear what are expected to happen if one drake has a portal open already - //Refresh respawnTime so time again are set to 30secs? + //Unclear what are expected to happen if one drake has a portal open already + //Refresh respawnTime so time again are set to 30secs? + } } - //Removes each drakes unique debuff from players - void RemoveDebuff(uint32 uiSpellId) - { - Map* pMap = m_creature->GetMap(); - if (pMap && pMap->IsDungeon()) + void CheckTwilightRealm() + { + bool bNoAliveTwilightRealm = true; + if (m_pInstance) { - 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()->isAlive() && i->getSource()->HasAura(uiSpellId)) - i->getSource()->RemoveAurasDueToSpell(uiSpellId); - } + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID)) + if (pAcolyte->isAlive()) + bNoAliveTwilightRealm = false; + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID)) + if (pAcolyte->isAlive()) + bNoAliveTwilightRealm = false; + if (!m_lEggsGUIDList.empty()) + for (std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( *itr)) + if (pTemp->isAlive()) + { + bNoAliveTwilightRealm = false; + break; + } + if (bNoAliveTwilightRealm) + RemoveDebuff(SPELL_TWILIGHT_SHIFT_ENTER); } } void JustDied(Unit* pKiller) { int32 iTextId = 0; - uint32 uiSpellId = 0; switch(m_creature->GetEntry()) { case NPC_TENEBRON: + { iTextId = SAY_TENEBRON_DEATH; - uiSpellId = SPELL_POWER_OF_TENEBRON; + + if (!m_lEggsGUIDList.empty()) + for (std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr) + if (Creature* pEgg = m_creature->GetMap()->GetCreature( *itr)) + pEgg->ForcedDespawn(); break; + } case NPC_SHADRON: + { iTextId = SAY_SHADRON_DEATH; - uiSpellId = SPELL_POWER_OF_SHADRON; + + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteShadronGUID)) + pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + break; + } case NPC_VESPERON: + { iTextId = SAY_VESPERON_DEATH; - uiSpellId = SPELL_POWER_OF_VESPERON; + + if (Creature* pAcolyte = m_pInstance->instance->GetCreature(m_uiAcolyteVesperonGUID)) + pAcolyte->DealDamage(pAcolyte, pAcolyte->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + break; + } } DoScriptText(iTextId, m_creature); - RemoveDebuff(uiSpellId); - if (m_pInstance) { // not if solo mini-boss fight if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + { + RemoveDebuff(SPELL_TWILIGHT_SHIFT_ENTER); return; + } // Twilight Revenge to main boss if (Creature* pSartharion = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_SARTHARION))) { if (pSartharion->isAlive()) - m_creature->CastSpell(pSartharion,SPELL_TWILIGHT_REVENGE,true); + m_creature->CastSpell(pSartharion, SPELL_TWILIGHT_REVENGE, true); + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } } } @@ -721,23 +1087,30 @@ struct MANGOS_DLL_DECL dummy_dragonAI : public ScriptedAI struct MANGOS_DLL_DECL mob_tenebronAI : public dummy_dragonAI { - mob_tenebronAI(Creature* pCreature) : dummy_dragonAI(pCreature) { Reset(); } + mob_tenebronAI(Creature* pCreature) : dummy_dragonAI(pCreature) + { + Reset(); + } uint32 m_uiShadowBreathTimer; uint32 m_uiShadowFissureTimer; uint32 m_uiHatchEggTimer; + uint32 m_uiCheckTimer; + uint32 m_uiTailSweepTimer; void Reset() { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiHatchEggTimer = 30000; + m_uiShadowBreathTimer = 10000; + m_uiShadowFissureTimer = 8000; + m_uiHatchEggTimer = 15000; + m_uiCheckTimer = 2000; + m_uiTailSweepTimer = 5000; + m_lEggsGUIDList.clear(); } void Aggro(Unit* pWho) { DoScriptText(SAY_TENEBRON_AGGRO, m_creature); - DoCastSpellIfCan(m_creature, SPELL_POWER_OF_TENEBRON); } void KilledUnit(Unit* pVictim) @@ -758,9 +1131,9 @@ struct MANGOS_DLL_DECL mob_tenebronAI : public dummy_dragonAI if (m_uiShadowFissureTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOW_FISSURE : SPELL_SHADOW_FISSURE_H); + DoCast(pTarget, m_bIsRegularMode ? SPELL_SHADOW_FISSURE : SPELL_SHADOW_FISSURE_H); - m_uiShadowFissureTimer = urand(15000, 20000); + m_uiShadowFissureTimer = urand(8000, 10000); } else m_uiShadowFissureTimer -= uiDiff; @@ -769,12 +1142,36 @@ struct MANGOS_DLL_DECL mob_tenebronAI : public dummy_dragonAI if (m_uiShadowBreathTimer < uiDiff) { DoScriptText(SAY_TENEBRON_BREATH, m_creature); - DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_BREATH : SPELL_SHADOW_BREATH_H); - m_uiShadowBreathTimer = urand(20000, 25000); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_BREATH : SPELL_SHADOW_BREATH_H); + m_uiShadowBreathTimer = urand(10000, 30000); } else m_uiShadowBreathTimer -= uiDiff; + if (m_uiTailSweepTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_TAIL_LASH : SPELL_TAIL_LASH_H); + m_uiTailSweepTimer = urand(5000, 7000); + } + else + m_uiTailSweepTimer -= uiDiff; + + if (m_uiHatchEggTimer < uiDiff) + { + OpenPortal(); + m_uiHatchEggTimer = 45000; + } + else + m_uiHatchEggTimer -= uiDiff; + + if (m_uiCheckTimer < uiDiff && m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + { + CheckTwilightRealm(); + m_uiCheckTimer = 2000; + } + else + m_uiCheckTimer -= uiDiff; + DoMeleeAttackIfReady(); } }; @@ -790,29 +1187,30 @@ CreatureAI* GetAI_mob_tenebron(Creature* pCreature) struct MANGOS_DLL_DECL mob_shadronAI : public dummy_dragonAI { - mob_shadronAI(Creature* pCreature) : dummy_dragonAI(pCreature) { Reset(); } + mob_shadronAI(Creature* pCreature) : dummy_dragonAI(pCreature) + { + Reset(); + } uint32 m_uiShadowBreathTimer; uint32 m_uiShadowFissureTimer; uint32 m_uiAcolyteShadronTimer; + uint32 m_uiCheckTimer; + uint32 m_uiTailSweepTimer; void Reset() { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiAcolyteShadronTimer = 60000; - - if (m_creature->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) - m_creature->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); - - if (m_creature->HasAura(SPELL_GIFT_OF_TWILIGTH_SHA)) - m_creature->RemoveAurasDueToSpell(SPELL_GIFT_OF_TWILIGTH_SHA); + m_uiShadowBreathTimer = 10000; + m_uiShadowFissureTimer = 8000; + m_uiAcolyteShadronTimer = 15000; + m_uiCheckTimer = 2000; + m_uiTailSweepTimer = 5000; + m_uiAcolyteShadronGUID = 0; } void Aggro(Unit* pWho) { DoScriptText(SAY_SHADRON_AGGRO,m_creature); - DoCastSpellIfCan(m_creature, SPELL_POWER_OF_SHADRON); } void KilledUnit(Unit* pVictim) @@ -833,9 +1231,9 @@ struct MANGOS_DLL_DECL mob_shadronAI : public dummy_dragonAI if (m_uiShadowFissureTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOW_FISSURE : SPELL_SHADOW_FISSURE_H); + DoCast(pTarget, m_bIsRegularMode ? SPELL_SHADOW_FISSURE : SPELL_SHADOW_FISSURE_H); - m_uiShadowFissureTimer = urand(15000, 20000); + m_uiShadowFissureTimer = urand(8000, 10000); } else m_uiShadowFissureTimer -= uiDiff; @@ -844,12 +1242,36 @@ struct MANGOS_DLL_DECL mob_shadronAI : public dummy_dragonAI if (m_uiShadowBreathTimer < uiDiff) { DoScriptText(SAY_SHADRON_BREATH, m_creature); - DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_BREATH : SPELL_SHADOW_BREATH_H); - m_uiShadowBreathTimer = urand(20000, 25000); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_BREATH : SPELL_SHADOW_BREATH_H); + m_uiShadowBreathTimer = urand(10000, 30000); } else m_uiShadowBreathTimer -= uiDiff; + if (m_uiTailSweepTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_TAIL_LASH : SPELL_TAIL_LASH_H); + m_uiTailSweepTimer = urand(5000, 7000); + } + else + m_uiTailSweepTimer -= uiDiff; + + if (m_uiAcolyteShadronTimer < uiDiff) + { + OpenPortal(); + m_uiAcolyteShadronTimer = 60000; + } + else + m_uiAcolyteShadronTimer -= uiDiff; + + if (m_uiCheckTimer < uiDiff && m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + { + CheckTwilightRealm(); + m_uiCheckTimer = 2000; + } + else + m_uiCheckTimer -= uiDiff; + DoMeleeAttackIfReady(); } }; @@ -865,23 +1287,30 @@ CreatureAI* GetAI_mob_shadron(Creature* pCreature) struct MANGOS_DLL_DECL mob_vesperonAI : public dummy_dragonAI { - mob_vesperonAI(Creature* pCreature) : dummy_dragonAI(pCreature) { Reset(); } + mob_vesperonAI(Creature* pCreature) : dummy_dragonAI(pCreature) + { + Reset(); + } uint32 m_uiShadowBreathTimer; uint32 m_uiShadowFissureTimer; uint32 m_uiAcolyteVesperonTimer; + uint32 m_uiCheckTimer; + uint32 m_uiTailSweepTimer; void Reset() { - m_uiShadowBreathTimer = 20000; - m_uiShadowFissureTimer = 5000; - m_uiAcolyteVesperonTimer = 60000; + m_uiShadowBreathTimer = 10000; + m_uiShadowFissureTimer = 8000; + m_uiAcolyteVesperonTimer = 15000; + m_uiCheckTimer = 2000; + m_uiTailSweepTimer = 5000; + m_uiAcolyteVesperonGUID = 0; } void Aggro(Unit* pWho) { DoScriptText(SAY_VESPERON_AGGRO,m_creature); - DoCastSpellIfCan(m_creature, SPELL_POWER_OF_VESPERON); } void KilledUnit(Unit* pVictim) @@ -902,9 +1331,9 @@ struct MANGOS_DLL_DECL mob_vesperonAI : public dummy_dragonAI if (m_uiShadowFissureTimer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SHADOW_FISSURE : SPELL_SHADOW_FISSURE_H); + DoCast(pTarget, m_bIsRegularMode ? SPELL_SHADOW_FISSURE : SPELL_SHADOW_FISSURE_H); - m_uiShadowFissureTimer = urand(15000, 20000); + m_uiShadowFissureTimer = urand(8000, 10000); } else m_uiShadowFissureTimer -= uiDiff; @@ -913,12 +1342,36 @@ struct MANGOS_DLL_DECL mob_vesperonAI : public dummy_dragonAI if (m_uiShadowBreathTimer < uiDiff) { DoScriptText(SAY_VESPERON_BREATH, m_creature); - DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_BREATH : SPELL_SHADOW_BREATH_H); - m_uiShadowBreathTimer = urand(20000, 25000); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHADOW_BREATH : SPELL_SHADOW_BREATH_H); + m_uiShadowBreathTimer = urand(10000, 30000); } else m_uiShadowBreathTimer -= uiDiff; + if (m_uiTailSweepTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_TAIL_LASH : SPELL_TAIL_LASH_H); + m_uiTailSweepTimer = urand(5000, 7000); + } + else + m_uiTailSweepTimer -= uiDiff; + + if (m_uiAcolyteVesperonTimer < uiDiff) + { + OpenPortal(); + m_uiAcolyteVesperonTimer = 60000; + } + else + m_uiAcolyteVesperonTimer -= uiDiff; + + if (m_uiCheckTimer < uiDiff && m_pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + { + CheckTwilightRealm(); + m_uiCheckTimer = 2000; + } + else + m_uiCheckTimer -= uiDiff; + DoMeleeAttackIfReady(); } }; @@ -944,14 +1397,6 @@ struct MANGOS_DLL_DECL mob_acolyte_of_shadronAI : public ScriptedAI void Reset() { - if (m_pInstance) - { - //if not solo figth, buff main boss, else place debuff on mini-boss. both spells TARGET_SCRIPT - if (m_pInstance->GetData(TYPE_SARTHARION_EVENT) == IN_PROGRESS) - DoCastSpellIfCan(m_creature, SPELL_GIFT_OF_TWILIGTH_SAR); - else - DoCastSpellIfCan(m_creature, SPELL_GIFT_OF_TWILIGTH_SHA); - } } void JustDied(Unit* killer) @@ -1009,18 +1454,25 @@ struct MANGOS_DLL_DECL mob_acolyte_of_vesperonAI : public ScriptedAI void Reset() { - DoCastSpellIfCan(m_creature, SPELL_TWILIGHT_TORMENT_VESP_ACO); } void JustDied(Unit* pKiller) { - // remove twilight torment on Vesperon - if (m_pInstance) + // remove twilight torment + Map* pMap = m_creature->GetMap(); + + if (pMap && pMap->IsDungeon()) { - Creature* pVesperon = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_VESPERON)); + Map::PlayerList const &PlayerList = pMap->GetPlayers(); - if (pVesperon && pVesperon->isAlive() && pVesperon->HasAura(SPELL_TWILIGHT_TORMENT_VESP)) - pVesperon->RemoveAurasDueToSpell(SPELL_TWILIGHT_TORMENT_VESP); + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + i->getSource()->RemoveAurasDueToSpell(57935); + i->getSource()->RemoveAurasDueToSpell(58835); + } } } @@ -1046,12 +1498,36 @@ struct MANGOS_DLL_DECL mob_twilight_eggsAI : public ScriptedAI { mob_twilight_eggsAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); } + uint32 m_uiSummonWhelpTimer; + void Reset() + { + m_uiSummonWhelpTimer = 20000; + } + + void AttackStart(Unit* pWho) + { + } + + void MoveInLineOfSight(Unit* pWho) { } - void AttackStart(Unit* pWho) { } - void MoveInLineOfSight(Unit* pWho) { } + void UpdateAI(const uint32 uiDiff) + { + if (m_uiSummonWhelpTimer < uiDiff) + { + if (Creature* pWhelp = DoSpawnCreature(NPC_TWILIGHT_WHELP, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pWhelp->SetPhaseMask(1, true); + pWhelp->SetInCombatWithZone(); + } + m_uiSummonWhelpTimer = 20000; + m_creature->ForcedDespawn(); + } + else + m_uiSummonWhelpTimer -= uiDiff; + } }; CreatureAI* GetAI_mob_twilight_eggs(Creature* pCreature) @@ -1083,7 +1559,7 @@ struct MANGOS_DLL_DECL mob_twilight_whelpAI : public ScriptedAI // twilight torment if (m_uiFadeArmorTimer < uiDiff) { - DoCastSpellIfCan(m_creature->getVictim(), SPELL_FADE_ARMOR); + DoCast(m_creature->getVictim(), SPELL_FADE_ARMOR); m_uiFadeArmorTimer = urand(5000, 10000); } else @@ -1098,6 +1574,221 @@ CreatureAI* GetAI_mob_twilight_whelp(Creature* pCreature) return new mob_twilight_whelpAI(pCreature); } +/*###### +## Mob Fire Cyclone +######*/ + +struct MANGOS_DLL_DECL mob_fire_cycloneAI : public ScriptedAI +{ + mob_fire_cycloneAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiLavaStrikeTimer; + uint8 m_uiLavaStrikesCount; + bool m_bLavaStrikeAllowed; + + + void Reset() + { + m_bLavaStrikeAllowed = false; + } + + void AttackStart(Unit* pWho) + { + } + + void MoveInLineOfSight(Unit* pWho) + { + } + + void SpellHit(Unit* pCaster, const SpellEntry* pSpell) + { + if (pSpell->Id == SPELL_CYCLONE_AURA_2) + { + DoCast(m_creature, 57560, true); + m_bLavaStrikeAllowed = true; + m_uiLavaStrikeTimer = 0; + m_uiLavaStrikesCount = 0; + } + } + + void JustSummoned(Creature* pSummoned) + { + if (pSummoned->GetEntry() == NPC_LAVA_BLAZE) + if (urand(0, 3)) //25% to stay + pSummoned->ForcedDespawn(); + else + pSummoned->SetInCombatWithZone(); + } + + void UpdateAI(const uint32 uiDiff) + { + + if (m_bLavaStrikeAllowed) + { + if (m_uiLavaStrikeTimer < uiDiff) + { + m_creature->CastSpell(urand(3220, 3275), urand(486, 575), 58.8f, SPELL_LAVA_STRIKE, true); + m_uiLavaStrikeTimer = 1000; + ++m_uiLavaStrikesCount; + if (m_uiLavaStrikesCount>=5) + m_bLavaStrikeAllowed = false; + } + else + m_uiLavaStrikeTimer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_mob_fire_cyclone(Creature* pCreature) +{ + return new mob_fire_cycloneAI(pCreature); +} + +/*###### +## Mob Flame Tsunami +######*/ + +struct MANGOS_DLL_DECL mob_flame_tsunamiAI : public ScriptedAI +{ + mob_flame_tsunamiAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiTickTimer; + uint32 m_uiMovementStartTimer; + uint64 m_uiDummyDamagerGUID; + + void Reset() + { + m_creature->SetDisplayId(11686); + DoCast(m_creature, SPELL_FLAME_TSUNAMI, true); + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_uiMovementStartTimer = 4000; + m_uiTickTimer = 1000; + m_uiDummyDamagerGUID = 0; + if (Creature* pDummyDamager = DoSpawnCreature(31103, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 18000)) + { + pDummyDamager->SetDisplayId(11686); + pDummyDamager->setFaction(14); + pDummyDamager->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + pDummyDamager->SetSpeedRate(MOVE_RUN, m_creature->GetSpeedRate(MOVE_RUN)); + m_uiDummyDamagerGUID = pDummyDamager->GetGUID(); + } + } + + void AttackStart(Unit* pWho) + { + } + + void MoveInLineOfSight(Unit* pWho) + { + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiMovementStartTimer < uiDiff) + { + int8 uiDirection = 1; + if (m_creature->GetPositionX() > 3240.0f) + uiDirection = -1; + m_creature->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX()+uiDirection*86.5f, m_creature->GetPositionY(), m_creature->GetPositionZ()); + if (m_pInstance) + if (Creature* pDummyDamager = m_pInstance->instance->GetCreature(m_uiDummyDamagerGUID)) + pDummyDamager->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX()+uiDirection*86.5f, m_creature->GetPositionY(), m_creature->GetPositionZ()); + m_uiMovementStartTimer = 30000; + } + else + m_uiMovementStartTimer -= uiDiff; + + if (m_uiTickTimer < uiDiff) + { + if (m_pInstance) + if (Creature* pDummyDamager = m_pInstance->instance->GetCreature(m_uiDummyDamagerGUID)) + pDummyDamager->CastSpell(pDummyDamager, SPELL_FLAME_TSUNAMI_DMG, false); + + std::list lLavaBlazes; + GetCreatureListWithEntryInGrid(lLavaBlazes, m_creature, NPC_LAVA_BLAZE, 6.0f); + if (!lLavaBlazes.empty()) + { + SpellEntry* pTempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_FLAME_TSUNAMI_BUFF); + if (pTempSpell) + { + pTempSpell->EffectImplicitTargetA[0] = TARGET_SELF; + pTempSpell->EffectImplicitTargetB[0] = 0; + pTempSpell->EffectImplicitTargetA[1] = TARGET_SELF; + pTempSpell->EffectImplicitTargetB[1] = 0; + pTempSpell->EffectImplicitTargetA[2] = TARGET_SELF; + pTempSpell->EffectImplicitTargetB[2] = 0; + for (std::list::iterator iter = lLavaBlazes.begin(); iter != lLavaBlazes.end(); ++iter) + { + (*iter)->CastSpell(*iter, pTempSpell, false); + (*iter)->SetHealth((*iter)->GetHealth()*4); + } + } + } + + Map* pMap = m_creature->GetMap(); + if (pMap && pMap->IsDungeon()) + { + Map::PlayerList const &PlayerList = pMap->GetPlayers(); + + if (!PlayerList.isEmpty()) + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + if (i->getSource()->isAlive() && m_creature->GetDistance2d(i->getSource()) <= 5.0f) + { + i->getSource()->SetOrientation(m_creature->GetOrientation()); + i->getSource()->CastSpell(i->getSource(), SPELL_FLAME_TSUNAMI_LEAP, true); + } + } + + m_uiTickTimer = 1000; + } + else + m_uiTickTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_flame_tsunami(Creature* pCreature) +{ + return new mob_flame_tsunamiAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_lava_blazeAI : public ScriptedAI +{ + mob_lava_blazeAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_SARTHARION_EVENT) != IN_PROGRESS) + m_creature->ForcedDespawn(); + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_lava_blaze(Creature* pCreature) +{ + return new mob_lava_blazeAI(pCreature); +}; + void AddSC_boss_sartharion() { Script *newscript; @@ -1141,4 +1832,19 @@ void AddSC_boss_sartharion() newscript->Name = "mob_twilight_whelp"; newscript->GetAI = &GetAI_mob_twilight_whelp; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fire_cyclone"; + newscript->GetAI = &GetAI_mob_fire_cyclone; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flame_tsunami"; + newscript->GetAI = &GetAI_mob_flame_tsunami; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_lava_blaze"; + newscript->GetAI = &GetAI_mob_lava_blaze; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ruby_sanctum/boss_baltharus.cpp b/scripts/northrend/ruby_sanctum/boss_baltharus.cpp index 8574ab9..44d3452 100644 --- a/scripts/northrend/ruby_sanctum/boss_baltharus.cpp +++ b/scripts/northrend/ruby_sanctum/boss_baltharus.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* Copyright (C) 2010 /dev/rsa for 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 @@ -16,9 +16,338 @@ /* ScriptData SDName: boss_baltharus -SD%Complete: -SDComment: placeholder -SDCategory: Ruby Sanctum +SD%Complete: 90% +SDComment: by notagain and /dev/rsa +SDCategory: ruby_sanctum EndScriptData */ +// Not fully offlike clone work, but Blizz idea is intact. +// Need correct timers #include "precompiled.h" +#include "ruby_sanctum.h" + +static Locations SpawnLoc[]= +{ + {3152.329834f, 359.41757f, 85.301605f}, // Baltharus target point + {3153.06f, 389.486f, 86.2596f}, // Baltharus initial point +}; + +enum Equipment +{ + EQUIP_MAIN = 49888, + EQUIP_OFFHAND = EQUIP_NO_CHANGE, + EQUIP_RANGED = EQUIP_NO_CHANGE, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; + +enum BossSpells +{ + SPELL_BLADE_TEMPEST = 75125, // every 22 secs + SPELL_ENERVATING_BRAND = 74502, // friendlys in 12yards = 74505 + SPELL_REPELLING_WAVE = 74509, // once if call clone + SPELL_SABER_LASH = 40504, // every 10-15 secs + SPELL_SUMMON_CLONE = 74511, // summons npc 39899 (Clone) + SPELL_CHANNEL_SPELL = 76221, // Channeling dummy spell +}; + +/*###### +## boss_baltharus +######*/ + +struct MANGOS_DLL_DECL boss_baltharusAI : public BSWScriptedAI +{ + boss_baltharusAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + Creature* pDummyTarget; + Creature* pClone; + bool inCombat; + bool intro; + + void Reset() + { + if(!pInstance) + return; + + if (m_creature->isAlive()) pInstance->SetData(TYPE_BALTHARUS, NOT_STARTED); + m_creature->SetRespawnDelay(7*DAY); + resetTimers(); + setStage(0); + pClone = NULL; + inCombat = false; + intro = false; + if (pDummyTarget = m_creature->GetMap()->GetCreature( pInstance->GetData64(NPC_BALTHARUS_TARGET))) + { + if (!pDummyTarget->isAlive()) pDummyTarget->Respawn(); + + pDummyTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pDummyTarget->GetMotionMaster()->MoveIdle(); + } + else if (pDummyTarget = m_creature->SummonCreature(NPC_BALTHARUS_TARGET, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 0.0f, TEMPSUMMON_MANUAL_DESPAWN, 1000)) + { + pDummyTarget->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pDummyTarget->GetMotionMaster()->MoveIdle(); + } + + if(Creature* pTarget = m_creature->GetMap()->GetCreature( pInstance->GetData64(NPC_XERESTRASZA))) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pTarget->GetGUID()); + } + + void JustReachedHome() + { + if (!pInstance) return; + + pInstance->SetData(TYPE_BALTHARUS, FAIL); + } + + void MoveInLineOfSight(Unit* pWho) + { + ScriptedAI::MoveInLineOfSight(pWho); + if(!pInstance || intro || + pWho->GetTypeId() != TYPEID_PLAYER || + !pWho->IsWithinDistInMap(m_creature, 60.0f)) return; + + pInstance->SetData(TYPE_EVENT, 10); + DoScriptText(-1666305,m_creature); + intro = true; + } + + void JustDied(Unit* pKiller) + { + if (!pInstance) return; + + if (pDummyTarget) pDummyTarget->ForcedDespawn(); + DoScriptText(-1666303,m_creature); + pInstance->SetData(TYPE_BALTHARUS, DONE); + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1666301,m_creature,pVictim); + break; + case 1: + DoScriptText(-1666302,m_creature,pVictim); + break; + }; + } + + void JustSummoned(Creature* summoned) + { + if(!pInstance || !summoned) return; + + if ( summoned->GetEntry() != NPC_BALTHARUS_TARGET ) + { + if (!pClone) pClone = summoned; + else if (!pClone->isAlive()) pClone = summoned; + pClone->SetInCombatWithZone(); + } + } + + void SummonedCreatureJustDied(Creature* summoned) + { + if (!pInstance || !summoned) return; + + if (summoned == pClone) pClone = NULL; + } + + void Aggro(Unit* pWho) + { + if (!pInstance) return; + if (pWho->GetTypeId() != TYPEID_PLAYER) return; + + if (pDummyTarget) pDummyTarget->ForcedDespawn(); + + SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); + + inCombat = true; + m_creature->InterruptNonMeleeSpells(true); + SetCombatMovement(true); + pInstance->SetData(TYPE_BALTHARUS, IN_PROGRESS); + DoScriptText(-1666300,m_creature); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (!pInstance) return; + + if (!m_creature || !m_creature->isAlive()) + return; + + if(pDoneBy->GetGUID() == m_creature->GetGUID()) + return; + + if (pClone && pClone->isAlive()) + { + pDoneBy->DealDamage(pClone, uiDamage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + uiDamage = 0; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance) return; + + if (!inCombat && !m_creature->IsNonMeleeSpellCasted(false)) + timedCast(SPELL_CHANNEL_SPELL, uiDiff, pDummyTarget); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch (getStage()) + { + case 0: + if ( m_creature->GetHealthPercent() <= 66.0f) setStage(1); + break; + + case 1: + m_creature->InterruptNonMeleeSpells(true); + if (is25()) + doCast(SPELL_SUMMON_CLONE); + setStage(2); + break; + + case 2: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + doCast(SPELL_REPELLING_WAVE); + setStage(3); + + case 3: + if ( m_creature->GetHealthPercent() <= 50.0f) setStage(4); + break; + + case 4: + m_creature->InterruptNonMeleeSpells(true); + if (!is25()) + doCast(SPELL_SUMMON_CLONE); + setStage(5); + break; + + case 5: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + doCast(SPELL_REPELLING_WAVE); + setStage(6); + + case 6: + if ( m_creature->GetHealthPercent() <= 33.0f) setStage(7); + break; + + case 7: + m_creature->InterruptNonMeleeSpells(true); + if (is25()) + doCast(SPELL_SUMMON_CLONE); + setStage(8); + break; + + case 8: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + doCast(SPELL_REPELLING_WAVE); + setStage(9); + + case 9: + default: + break; + } + +// timedCast(SPELL_BLADE_TEMPEST, uiDiff); + timedCast(SPELL_ENERVATING_BRAND, uiDiff); + timedCast(SPELL_SABER_LASH, uiDiff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_baltharus(Creature* pCreature) +{ + return new boss_baltharusAI(pCreature); +} + +/*###### +## mob_baltharus_clone +######*/ + +struct MANGOS_DLL_DECL mob_baltharus_cloneAI : public BSWScriptedAI +{ + mob_baltharus_cloneAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if(!pInstance) return; + resetTimers(); + m_creature->SetRespawnDelay(7*DAY); + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1666301,m_creature,pVictim); + break; + case 1: + DoScriptText(-1666302,m_creature,pVictim); + break; + }; + } + + void JustDied(Unit* pKiller) + { + if (!pInstance) return; + } + + void Aggro(Unit* pWho) + { + if (!pInstance) return; + + SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); + + m_creature->SetInCombatWithZone(); + } + + void UpdateAI(const uint32 uiDiff) + { + + if (!pInstance) return; + + if (pInstance->GetData(TYPE_BALTHARUS) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + doCastAll(uiDiff); + + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_mob_baltharus_clone(Creature* pCreature) +{ + return new mob_baltharus_cloneAI(pCreature); +} + + +void AddSC_boss_baltharus() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_baltharus"; + newscript->GetAI = &GetAI_boss_baltharus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_baltharus_clone"; + newscript->GetAI = &GetAI_mob_baltharus_clone; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/ruby_sanctum/boss_halion.cpp b/scripts/northrend/ruby_sanctum/boss_halion.cpp index 04969e6..d2af455 100644 --- a/scripts/northrend/ruby_sanctum/boss_halion.cpp +++ b/scripts/northrend/ruby_sanctum/boss_halion.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* Copyright (C) 2010 /dev/rsa for 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 @@ -16,9 +16,1238 @@ /* ScriptData SDName: boss_halion -SD%Complete: -SDComment: placeholder -SDCategory: Ruby Sanctum +SD%Complete: 80% +SDComment: by notagain, corrected by /dev/rsa +SDCategory: ruby_sanctum EndScriptData */ +// TODO: correct timers, Add twilight interorbs connection, sql spells, TESTING +// Attention please! This script required some core modification. + #include "precompiled.h" +#include "ruby_sanctum.h" + +enum +{ + //SPELLS + //All + SPELL_TWILIGHT_PRECISION = 78243, // Increases Halion's chance to hit by 5% and decreases all players' chance to dodge by 20% + SPELL_BERSERK = 26663, // Increases the caster's attack and movement speeds by 150% and all damage it deals by 500% for 5 min. Also grants immunity to Taunt effects. + SPELL_START_PHASE2 = 74808, // Phases the caster into the Twilight realm, leaving behind a large rift. + SPELL_TWILIGHT_ENTER = 74807, // Phases the caster into the Twilight realm - phase 32 + SPELL_TWILIGHT_ENTER2 = 74812, // + SPELL_SUMMON_TWILIGHT_PORTAL = 74809, // + + //NEED SCRIPT + SPELL_TAIL_LASH = 74531, // A sweeping tail strike hits all enemies behind the caster, inflicting 3063 to 3937 damage and stunning them for 2 sec. + SPELL_TWILIGHT_DIVISION = 75063, // Phases the caster, allowing him to exist and act simultaneously in both the material and Twilight realms. + SPELL_TWILIGHT_CUTTER = 77844, // Inflicts 13,875 to 16,125 Shadow damage every second to players touched by the shadow beam + //CORPOREALITY + SPELL_CORPOREALITY_EVEN = 74826, // Deals & receives normal damage + SPELL_CORPOREALITY_20I = 74827, // Damage dealt increased by 10% & Damage taken increased by 15% + SPELL_CORPOREALITY_40I = 74828, // Damage dealt increased by 30% & Damage taken increased by 50% + SPELL_CORPOREALITY_60I = 74829, // Damage dealt increased by 60% & Damage taken increased by 100% + SPELL_CORPOREALITY_80I = 74830, // Damage dealt increased by 100% & Damage taken increased by 200% + SPELL_CORPOREALITY_100I = 74831, // Damage dealt increased by 200% & Damage taken increased by 400% + SPELL_CORPOREALITY_20D = 74832, // Damage dealt reduced by 10% & Damage taken reduced by 15% + SPELL_CORPOREALITY_40D = 74833, // Damage dealt reduced by 30% & Damage taken reduced by 50% + SPELL_CORPOREALITY_60D = 74834, // Damage dealt reduced by 60% & Damage taken reduced by 100% + SPELL_CORPOREALITY_80D = 74835, // Damage dealt reduced by 100% & Damage taken reduced by 200% + SPELL_CORPOREALITY_100D = 74836, // Damage dealt reduced by 200% & Damage taken reduced by 400% + //METEOR STRIKE + SPELL_METEOR = 74637, // Script Start (summon NPC_METEOR_STRIKE) + SPELL_METEOR_IMPACT = 74641, // IMPACT ZONE FOR METEOR + SPELL_METEOR_STRIKE = 74648, // Inflicts 18,750 to 21,250 Fire damage to enemies within 12 yards of the targeted area. Takes about 5 seconds to land. + SPELL_METEOR_FLAME = 74718, // FLAME FROM METEOR + //N10 + SPELL_FLAME_BREATH = 74525, // Inflicts 17,500 to 22,500 Fire damage to players in front of Halion + SPELL_DARK_BREATH = 74806, // Inflicts 17,500 to 22,500 Shadow damage to players in front of Halion + SPELL_DUSK_SHROUD = 75484, // Inflicts 3,000 Shadow damage every 2 seconds to everyone in the Twilight Realm + //Combustion + NPC_COMBUSTION = 40001, + SPELL_MARK_OF_COMBUSTION = 74567, // Dummy effect only + SPELL_FIERY_COMBUSTION = 74562, // Inflicts 4,000 Fire damage every 2 seconds for 30 seconds to a random raider. Every time Fiery Combustion does damage, it applies a stackable Mark of Combustion. + SPELL_COMBUSTION_EXPLODE = 74607, + SPELL_COMBUSTION_AURA = 74629, + //Consumption + NPC_CONSUMPTION = 40135, + SPELL_MARK_OF_CONSUMPTION = 74795, // Dummy effect only + SPELL_SOUL_CONSUMPTION = 74792, // Inflicts 4,000 Shadow damage every 2 seconds for 30 seconds to a random raider. Every time Soul Consumption does damage, it applies a stackable Mark of Consumption. + SPELL_CONSUMPTION_EXPLODE = 74799, + SPELL_CONSUMPTION_AURA = 74803, + //Summons + NPC_METEOR_STRIKE = 40029, //casts "impact zone" then meteor + NPC_METEOR_STRIKE_1 = 40041, + NPC_METEOR_STRIKE_2 = 40042, + + FR_RADIUS = 45, + + //SAYS + SAY_HALION_SPAWN = -1666100, //17499 Meddlesome insects, you're too late! The Ruby Sanctum is lost. + SAY_HALION_AGGRO = -1666101, //17500 Your world teeters on the brink of annihilation. You will all bear witness to the coming of a new age of destruction! + SAY_HALION_SLAY_1 = -1666102, //17501 Another hero falls. + SAY_HALION_SLAY_2 = -1666103, //17502 Ha Ha Ha! + SAY_HALION_DEATH = -1666104, //17503 Relish this victory mortals, for it will be your last. This world will burn with the Master's return! + SAY_HALION_BERSERK = -1666105, //17504 Not good enough! + SAY_HALION_SPECIAL_1 = -1666106, //17505 The heavens burn! + SAY_HALION_SPECIAL_2 = -1666107, //17506 Beware the shadow! + SAY_HALION_PHASE_2 = -1666108, //17507 You will find only suffering within the realm of Twilight. Enter if you dare. + SAY_HALION_PHASE_3 = -1666109, //17508 I am the light AND the darkness! Cower mortals before the Herald of Deathwing! + EMOTE_WARNING = -1666110, //orbs charge warning + EMOTE_REAL = -1666111, // To real world message + EMOTE_TWILIGHT = -1666112, // To twilight world message + EMOTE_NEITRAL = -1666113, // Halion reveal HP message +}; + +static Locations SpawnLoc[]= +{ + {3154.99f, 535.637f, 72.8887f}, // 0 - Halion spawn point (center) +}; + +/*###### +## boss_halion_real (Physical version) +######*/ +struct MANGOS_DLL_DECL boss_halion_realAI : public BSWScriptedAI +{ + boss_halion_realAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + bool intro; + uint8 nextPoint; + bool MovementStarted; + + void Reset() + { + if(!pInstance) + return; + m_creature->SetRespawnDelay(7*DAY); + + if (m_creature->isAlive()) + { + pInstance->SetData(TYPE_HALION, NOT_STARTED); + pInstance->SetData(TYPE_HALION_EVENT, FAIL); + } + + resetTimers(); + setStage(0); + nextPoint = 0; + intro = false; + SetCombatMovement(true); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (GameObject* pGoPortal = pInstance->instance->GetGameObject(pInstance->GetData64(GO_HALION_PORTAL_1))) + pGoPortal->Delete(); + if (GameObject* pGoPortal = pInstance->instance->GetGameObject(pInstance->GetData64(GO_HALION_PORTAL_2))) + pGoPortal->Delete(); + if (GameObject* pGoPortal = pInstance->instance->GetGameObject(pInstance->GetData64(GO_HALION_PORTAL_3))) + pGoPortal->Delete(); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pInstance) return; + + if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER) return; + + if (!intro && pWho->IsWithinDistInMap(m_creature, 60.0f)) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + DoScriptText(-1666100,m_creature); + intro = true; + m_creature->SetActiveObjectState(true); + } + + if (intro && !m_creature->isInCombat() && pWho->IsWithinDistInMap(m_creature, 20.0f)) + AttackStart(pWho); + + ScriptedAI::MoveInLineOfSight(pWho); + } + + void JustReachedHome() + { + if (!pInstance) return; + + if (pInstance->GetData(TYPE_HALION_EVENT) != FAIL) return + + ScriptedAI::JustReachedHome(); + +// pInstance->SetData(TYPE_HALION, FAIL); + + m_creature->SetActiveObjectState(false); + } + + void EnterEvadeMode() + { + + if (!pInstance) return; + + if (pInstance->GetData(TYPE_HALION_EVENT) != FAIL) return; + + ScriptedAI::EnterEvadeMode(); + + m_creature->SetActiveObjectState(false); + } + + void JustDied(Unit* pKiller) + { + if (!pInstance) + return; + m_creature->SetActiveObjectState(false); + + DoScriptText(-1666104,m_creature); + + if (Creature* pclone = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_TWILIGHT))) + { + if (!pclone->isAlive()) + { + pInstance->SetData(TYPE_HALION, DONE); + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pInstance->SetData(TYPE_COUNTER, 0); + } + else + { + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) + { + case 0: + DoScriptText(-1631006,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631007,m_creature,pVictim); + break; + }; + } + + void Aggro(Unit* pWho) + { + if (!pInstance) + return; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + doCast(SPELL_TWILIGHT_PRECISION); + m_creature->SetInCombatWithZone(); + pInstance->SetData(TYPE_HALION, IN_PROGRESS); + DoScriptText(-1666101,m_creature); + } + + void MovementInform(uint32 type, uint32 id) + { + if (!pInstance) return; + + if (type != POINT_MOTION_TYPE || !MovementStarted) return; + + if (id == nextPoint) { + m_creature->GetMotionMaster()->MovementExpired(); + MovementStarted = false; + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + } + } + + void StartMovement(uint32 id) + { + nextPoint = id; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(id, SpawnLoc[id].x, SpawnLoc[id].y, SpawnLoc[id].z); + MovementStarted = true; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance) + return; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch (getStage()) + { + case 0: //PHASE 1 PHYSICAL REALM + timedCast(SPELL_FLAME_BREATH, uiDiff); + timedCast(SPELL_FIERY_COMBUSTION, uiDiff); + timedCast(SPELL_METEOR, uiDiff); + if (m_creature->GetHealthPercent() < 75.0f) setStage(1); + break; + + case 1: // Switch to phase 2 + m_creature->AttackStop(); + m_creature->InterruptNonMeleeSpells(true); + DoScriptText(-1666108,m_creature); + pInstance->SetData(TYPE_HALION_EVENT, NOT_STARTED); + SetCombatMovement(false); + StartMovement(0); + { + Creature* pControl = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_CONTROL)); + if (!pControl) + pControl = m_creature->SummonCreature(NPC_HALION_CONTROL, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 1000); + else if (!pControl->isAlive()) + pControl->Respawn(); + pControl->SetActiveObjectState(true); + pControl->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWith(pControl); + pControl->SetInCombatWith(m_creature); + } + setStage(2); + break; + + case 2: + if (MovementStarted) return; + doCast(SPELL_SUMMON_TWILIGHT_PORTAL); + setStage(3); + if (GameObject* pGoPortal = pInstance->instance->GetGameObject(pInstance->GetData64(GO_HALION_PORTAL_1))) + pGoPortal->SetPhaseMask(31,true); + if (GameObject* pGoRing = pInstance->instance->GetGameObject(pInstance->GetData64(GO_FLAME_RING))) + pGoRing->SetPhaseMask(65535,true); + break; + + case 3: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + m_creature->SetActiveObjectState(true); + doCast(SPELL_START_PHASE2); + setStage(4); + break; + + case 4: + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + if (Creature* pControl = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_CONTROL))) + { + m_creature->SetInCombatWith(pControl); + pControl->SetInCombatWith(m_creature); + } + Creature* pTwilight = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_TWILIGHT)); + if (!pTwilight) + pTwilight = m_creature->SummonCreature(NPC_HALION_TWILIGHT, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 1000); + else if (!pTwilight->isAlive()) + pTwilight->Respawn(); + pTwilight->SetCreatorGuid(ObjectGuid()); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + setStage(5); + } + break; + + case 5: // HALION awaiting end battle in TWILIGHT REALM + if (pInstance->GetData(TYPE_HALION_EVENT) == IN_PROGRESS) + { +// pInstance->SetData(TYPE_HALION_EVENT, SPECIAL); + doRemove(SPELL_START_PHASE2); + if (Creature* pControl = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_CONTROL))) + { + m_creature->SetInCombatWith(pControl); + pControl->SetInCombatWith(m_creature); + } + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetHealth(m_creature->GetMaxHealth()/2); + m_creature->SetInCombatWithZone(); + setStage(6); + } + return; + + case 6: // Switch to phase 3 +// doCast(SPELL_TWILIGHT_DIVISION); + DoScriptText(-1666109,m_creature); + pInstance->SetData(TYPE_HALION_EVENT, SPECIAL); + setStage(7); + break; + + case 7: + if (m_creature->IsNonMeleeSpellCasted(false)) return; + if (m_creature->getVictim()->GetTypeId() != TYPEID_PLAYER) return; + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + setStage(8); + break; + + case 8: //PHASE 3 BOTH REALMS + timedCast(SPELL_FLAME_BREATH, uiDiff); + timedCast(SPELL_FIERY_COMBUSTION, uiDiff); + timedCast(SPELL_METEOR, uiDiff); + break; + + default: + break; + } + + timedCast(SPELL_BERSERK, uiDiff); + + DoMeleeAttackIfReady(); + + } +}; + +CreatureAI* GetAI_boss_halion_real(Creature* pCreature) +{ + return new boss_halion_realAI(pCreature); +} + +/*###### +## boss_halion_twilight (Twilight version) +######*/ + +struct MANGOS_DLL_DECL boss_halion_twilightAI : public BSWScriptedAI +{ + boss_halion_twilightAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + uint8 stage; + bool intro; + + void Reset() + { + if(!pInstance) + return; + m_creature->SetRespawnDelay(7*DAY); + setStage(0); + intro = false; + resetTimers(); + m_creature->SetInCombatWithZone(); + if (Creature* pControl = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_CONTROL))) + { + m_creature->SetInCombatWith(pControl); + pControl->SetInCombatWith(m_creature); + } + Creature* pFocus = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_ORB_ROTATION_FOCUS)); + if (!pFocus ) + pFocus = m_creature->SummonCreature(NPC_ORB_ROTATION_FOCUS, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 1000); + else if (!pFocus->isAlive()) + pFocus->Respawn(); + + if (Creature* pReal = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_REAL))) + if (pReal->isAlive()) + m_creature->SetHealth(pReal->GetHealth()); + if (!hasAura(SPELL_TWILIGHT_ENTER)) + doCast(SPELL_TWILIGHT_ENTER); + } + + void JustReachedHome() + { + if (!pInstance) return; + + if (pInstance->GetData(TYPE_HALION_EVENT) != FAIL || getStage() == 0) + return; + + ScriptedAI::JustReachedHome(); + } + + void EnterEvadeMode() + { + + if (!pInstance) return; + + if (pInstance->GetData(TYPE_HALION_EVENT) != FAIL || getStage() == 0) + return; + + ScriptedAI::EnterEvadeMode(); + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pInstance) return; + + if (!pWho || pWho->GetTypeId() != TYPEID_PLAYER) return; + + if (!intro && pWho->IsWithinDistInMap(m_creature, 20.0f)) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE); + intro = true; + AttackStart(pWho); + setStage(1); + doCast(SPELL_TWILIGHT_PRECISION); + if (Creature* pReal = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_REAL))) + if (pReal->isAlive()) + m_creature->SetHealth(pReal->GetHealth()); + + + } + + ScriptedAI::MoveInLineOfSight(pWho); + } + + void JustDied(Unit* pKiller) + { + if (!pInstance) + return; + DoScriptText(-1666104,m_creature); + doRemoveFromAll(SPELL_TWILIGHT_ENTER); + if (Creature* pReal = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_REAL))) + if (!pReal->isAlive()) + { + pInstance->SetData(TYPE_HALION, DONE); + pReal->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + pInstance->SetData(TYPE_COUNTER, 0); + } + m_creature->ForcedDespawn(); + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) + { + case 0: + DoScriptText(-1631006,m_creature,pVictim); + break; + case 1: + DoScriptText(-1631007,m_creature,pVictim); + break; + }; + } + + void Aggro(Unit* pWho) + { + if (!pInstance) + return; + } + + void UpdateAI(const uint32 uiDiff) + { + + if (!hasAura(SPELL_TWILIGHT_ENTER)) + doCast(SPELL_TWILIGHT_ENTER); + + if (!pInstance || pInstance->GetData(TYPE_HALION) != IN_PROGRESS || pInstance->GetData(TYPE_HALION_EVENT) == FAIL) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + + switch (getStage()) + { + case 1: //SPAWNED - Twilight realm +// doCast(SPELL_TWILIGHT_DIVISION); + timedCast(SPELL_DUSK_SHROUD, uiDiff); + timedCast(SPELL_DARK_BREATH, uiDiff); + timedCast(SPELL_SOUL_CONSUMPTION, uiDiff); + if (m_creature->GetHealthPercent() < 50.0f) setStage(2); + break; + + case 2: //To two realms + pInstance->SetData(TYPE_HALION_EVENT, IN_PROGRESS); + DoScriptText(-1666109,m_creature); + m_creature->SummonGameobject(GO_HALION_PORTAL_3, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 0, 0); + if (GameObject* pGoPortal = pInstance->instance->GetGameObject(pInstance->GetData64(GO_HALION_PORTAL_3))) + pGoPortal->SetPhaseMask(32,true); + doCast(SPELL_TWILIGHT_DIVISION); + setStage(3); + break; + + case 3: //PHASE 3 BOTH REALMS + timedCast(SPELL_DUSK_SHROUD, uiDiff); + timedCast(SPELL_DARK_BREATH, uiDiff); + timedCast(SPELL_SOUL_CONSUMPTION, uiDiff); + break; + + default: + break; + } + + timedCast(SPELL_BERSERK, uiDiff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_halion_twilight(Creature* pCreature) +{ + return new boss_halion_twilightAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_halion_meteorAI : public BSWScriptedAI +{ + mob_halion_meteorAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + Reset(); + } + + float direction; + + void Reset() + { + m_creature->SetDisplayId(11686); + m_creature->SetRespawnDelay(7*DAY); + SetCombatMovement(false); + setStage(0); + m_creature->SetInCombatWithZone(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void UpdateAI(const uint32 diff) + { + switch (getStage()) + { + case 0: + if (timedCast(SPELL_METEOR_IMPACT, diff) == CAST_OK) setStage(1); + break; + + case 1: + if (timedCast(SPELL_METEOR_STRIKE, diff) == CAST_OK) setStage(2); + break; + + case 2: + // Place summon flames there + { + direction = 2.0f*M_PI_F*((float)urand(0,15)/16.0f); + float x, y, radius; + radius = 0.0f; + for(uint8 i = 0; i < getSpellData(SPELL_METEOR_STRIKE); ++i) + { + radius = radius + 5.0f; + m_creature->GetNearPoint2D(x, y, radius, direction); + doSummon(NPC_METEOR_STRIKE_1, x, y, m_creature->GetPositionZ(), TEMPSUMMON_TIMED_DESPAWN, 20000); + m_creature->GetNearPoint2D(x, y, radius, direction+M_PI_F); + doSummon(NPC_METEOR_STRIKE_1, x, y, m_creature->GetPositionZ(), TEMPSUMMON_TIMED_DESPAWN, 20000); + } + }; + { + direction = direction + M_PI_F/4; + float x, y, radius; + radius = 0.0f; + for(uint8 i = 0; i < getSpellData(SPELL_METEOR_STRIKE); ++i) + { + radius = radius + 5.0f; + m_creature->GetNearPoint2D(x, y, radius, direction); + doSummon(NPC_METEOR_STRIKE_1, x, y, m_creature->GetPositionZ(), TEMPSUMMON_TIMED_DESPAWN, 20000); + m_creature->GetNearPoint2D(x, y, radius, direction+M_PI_F); + doSummon(NPC_METEOR_STRIKE_1, x, y, m_creature->GetPositionZ(), TEMPSUMMON_TIMED_DESPAWN, 20000); + } + + }; + setStage(3); + break; + + case 3: + if (timedQuery(SPELL_METEOR_IMPACT, diff)) m_creature->ForcedDespawn(); + break; + + default: + break; + } + + } +}; + +CreatureAI* GetAI_mob_halion_meteor(Creature* pCreature) +{ + return new mob_halion_meteorAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_halion_flameAI : public BSWScriptedAI +{ + mob_halion_flameAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + Reset(); + } + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetDisplayId(11686); + m_creature->SetRespawnDelay(7*DAY); + SetCombatMovement(false); + m_creature->SetInCombatWithZone(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!hasAura(SPELL_METEOR_FLAME)) + doCast(SPELL_METEOR_FLAME); + + } + +}; + +CreatureAI* GetAI_mob_halion_flame(Creature* pCreature) +{ + return new mob_halion_flameAI(pCreature); +}; + +struct HalionBuffLine +{ + float diff; // Health diff in percent + uint32 real, twilight; // Buff pair +}; + +static HalionBuffLine Buff[]= +{ + {-10.0f,SPELL_CORPOREALITY_100I, SPELL_CORPOREALITY_100D}, + {-8.0f,SPELL_CORPOREALITY_80I, SPELL_CORPOREALITY_80D}, + {-6.0f,SPELL_CORPOREALITY_60I, SPELL_CORPOREALITY_60D}, + {-4.0f,SPELL_CORPOREALITY_40I, SPELL_CORPOREALITY_40D}, + {-2.0f,SPELL_CORPOREALITY_20I, SPELL_CORPOREALITY_20D}, + {-1.0f,SPELL_CORPOREALITY_EVEN, SPELL_CORPOREALITY_EVEN}, + {1.0f,SPELL_CORPOREALITY_EVEN, SPELL_CORPOREALITY_EVEN}, + {2.0f,SPELL_CORPOREALITY_20D, SPELL_CORPOREALITY_20I}, + {4.0f,SPELL_CORPOREALITY_40D, SPELL_CORPOREALITY_40I}, + {6.0f,SPELL_CORPOREALITY_60D, SPELL_CORPOREALITY_60I}, + {8.0f,SPELL_CORPOREALITY_80D, SPELL_CORPOREALITY_80I}, + {10.0f,SPELL_CORPOREALITY_100D, SPELL_CORPOREALITY_100I}, +}; + +struct MANGOS_DLL_DECL mob_halion_controlAI : public BSWScriptedAI +{ + mob_halion_controlAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + Creature* pHalionReal; + Creature* pHalionTwilight; + uint32 m_lastBuffReal, m_lastBuffTwilight; + bool m_detectplayers; + + void Reset() + { + if (!pInstance) return; + resetTimers(); + m_detectplayers = true; + m_creature->SetDisplayId(11686); + m_creature->SetPhaseMask(65535, true); +// m_creature->SetDisplayId(10045); + m_creature->SetRespawnDelay(7*DAY); + SetCombatMovement(false); + m_lastBuffReal = 0; + m_lastBuffTwilight = 0; + m_creature->SetActiveObjectState(true); + pInstance->SetData(TYPE_COUNTER, 0); + pInstance->SetData(TYPE_HALION_EVENT, NOT_STARTED); + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void UpdateAI(const uint32 diff) + { + if (!pInstance || pInstance->GetData(TYPE_HALION) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!pInstance) return; + + if (timedQuery(SPELL_CORPOREALITY_EVEN, diff)) + { + if (!doSelectRandomPlayerAtRange(80.0f)) + { + debug_log("ruby_sanctum: cannot detect players in range! "); + if (!m_detectplayers) + { + pInstance->SetData(TYPE_HALION_EVENT, FAIL); + pInstance->SetData(TYPE_HALION, FAIL); + m_creature->ForcedDespawn(); + } else m_detectplayers = false; + } else m_detectplayers = true; + + if (pInstance->GetData(TYPE_HALION_EVENT) != SPECIAL) return; + + pHalionReal = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_REAL)); + pHalionTwilight = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_TWILIGHT)); + + float p_RealHP = (pHalionReal && pHalionReal->isAlive()) ? pHalionReal->GetHealthPercent() : 0.0f; + float p_TwilightHP = (pHalionTwilight && pHalionTwilight->isAlive()) ? pHalionTwilight->GetHealthPercent() : 0.0f; + + float m_diff = (p_RealHP - p_TwilightHP); + + uint8 buffnum; + if (m_diff <= Buff[0].diff) buffnum = 0; + else for (uint8 i = 0; i < 11; i++) + if (m_diff >= Buff[i].diff) + buffnum = i+1; + else break; + + if (!m_lastBuffReal || m_lastBuffReal != Buff[buffnum].real) + { + if (m_lastBuffReal) doRemove(m_lastBuffReal, pHalionReal); + doCast(Buff[buffnum].real, pHalionReal); + m_lastBuffReal = Buff[buffnum].real; + } + + if (!m_lastBuffTwilight || m_lastBuffTwilight != Buff[buffnum].twilight) + { + if (m_lastBuffTwilight) doRemove(m_lastBuffTwilight, pHalionReal); + doCast(Buff[buffnum].twilight, pHalionTwilight); + m_lastBuffTwilight = Buff[buffnum].twilight; + } + + debug_log("ruby_sanctum: Buff num = %u, m_diff = %d ", buffnum, m_diff); + + pInstance->SetData(TYPE_COUNTER, 50 + (int)Buff[buffnum].diff); + + } + + } + +}; + +CreatureAI* GetAI_mob_halion_control(Creature* pCreature) +{ + return new mob_halion_controlAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_orb_rotation_focusAI : public ScriptedAI +{ + mob_orb_rotation_focusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + uint32 m_timer; + float m_direction, m_nextdirection; + bool m_warning; + + void Reset() + { + m_creature->SetDisplayId(11686); +// m_creature->SetDisplayId(10045); + m_creature->SetRespawnDelay(7*DAY); + m_creature->SetPhaseMask(65535, true); + SetCombatMovement(false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_direction = 0.0f; + m_nextdirection = 0.0f; + m_timer = 30000; + m_warning = false; + + Creature* pPulsar1 = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_SHADOW_PULSAR_N)); + if (!pPulsar1 ) + { + float x,y; + m_creature->GetNearPoint2D(x, y, FR_RADIUS, m_direction); + pPulsar1 = m_creature->SummonCreature(NPC_SHADOW_PULSAR_N, x, y, m_creature->GetPositionZ(), 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + } else if (!pPulsar1->isAlive()) + pPulsar1->Respawn(); + + Creature* pPulsar2 = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_SHADOW_PULSAR_S)); + if (!pPulsar2) + { + float x,y; + m_creature->GetNearPoint2D(x, y, FR_RADIUS, m_direction + M_PI_F); + pPulsar2 = m_creature->SummonCreature(NPC_SHADOW_PULSAR_S, x, y, m_creature->GetPositionZ(), 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + } else if (!pPulsar2->isAlive()) + pPulsar2->Respawn(); + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_HALION) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (pInstance->GetData(DATA_ORB_S) == DONE && pInstance->GetData(DATA_ORB_N) == DONE) + { + m_direction = m_nextdirection; + m_nextdirection = (m_direction - M_PI_F/64.0f); + if (m_nextdirection < 0.0f ) m_nextdirection = m_nextdirection + 2.0f*M_PI_F; + pInstance->SetData(DATA_ORB_DIRECTION, (uint32)(m_nextdirection*1000)); + pInstance->SetData(DATA_ORB_N, SPECIAL); + pInstance->SetData(DATA_ORB_S, SPECIAL); + debug_log("EventMGR: creature %u send direction %u ",m_creature->GetEntry(),pInstance->GetData(DATA_ORB_DIRECTION)); + } + + if (m_timer - 6000 <= uiDiff && !m_warning) + { + DoScriptText(-1666110,m_creature); + m_warning = true; + } + + if (m_timer <= uiDiff) + { + float x,y; + m_creature->GetNearPoint2D(x, y, FR_RADIUS, m_nextdirection); + m_creature->SummonCreature(NPC_ORB_CARRIER, x, y, m_creature->GetPositionZ(), 0, TEMPSUMMON_MANUAL_DESPAWN, 5000); + m_timer = 30000; + m_warning = false; + } else m_timer -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_orb_rotation_focus(Creature* pCreature) +{ + return new mob_orb_rotation_focusAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_halion_orbAI : public BSWScriptedAI +{ + mob_halion_orbAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + float m_direction,m_delta; + uint32 m_flag; + uint32 m_flag1; + bool MovementStarted; + Creature* focus; + uint32 nextPoint; + + void Reset() + { + if (!pInstance) return; + m_creature->SetRespawnDelay(7*DAY); + SetCombatMovement(false); + m_creature->SetPhaseMask(32, true); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (m_creature->GetEntry() == NPC_SHADOW_PULSAR_N) + { + m_flag = DATA_ORB_N; + m_delta = 0.0f; + } else if (m_creature->GetEntry() == NPC_SHADOW_PULSAR_S) + { + m_flag = DATA_ORB_S; + m_delta = M_PI_F; + }; + m_direction = 0.0f; + nextPoint = 0; + MovementStarted = false; + pInstance->SetData(m_flag, DONE); + debug_log("EventMGR: creature %u assume m_flag %u ",m_creature->GetEntry(),m_flag); + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void MovementInform(uint32 type, uint32 id) + { + if (!pInstance) return; + + if (type != POINT_MOTION_TYPE || !MovementStarted) return; + + if (id == nextPoint) { + m_creature->GetMotionMaster()->MovementExpired(); + MovementStarted = false; + pInstance->SetData(m_flag, DONE); + } + } + + void StartMovement(uint32 id) + { + if (!pInstance) return; + nextPoint = id; + float x,y; + pInstance->SetData(m_flag, IN_PROGRESS); + MovementStarted = true; + m_direction = ((float)pInstance->GetData(DATA_ORB_DIRECTION)/1000 + m_delta); + if (m_direction > 2.0f*M_PI_F) m_direction = m_direction - 2.0f*M_PI_F; + if (focus = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_ORB_ROTATION_FOCUS))) + focus->GetNearPoint2D(x, y, FR_RADIUS, m_direction); + else m_creature->ForcedDespawn(); +// debug_log("EventMGR: creature %u go to move point %u ",m_creature->GetEntry(),id); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(id, x, y, m_creature->GetPositionZ()); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_HALION) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (Unit* pTarget = doSelectRandomPlayerAtRange(2.0f)) + doCast(SPELL_TWILIGHT_CUTTER, pTarget); + + if (!MovementStarted && pInstance->GetData(m_flag) == SPECIAL) + { +// debug_log("EventMGR: creature %u get direction %u ",m_creature->GetEntry(),pInstance->GetData(DATA_ORB_DIRECTION)); + StartMovement(1); + } + + } +}; + +CreatureAI* GetAI_mob_halion_orb(Creature* pCreature) +{ + return new mob_halion_orbAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_orb_carrierAI : public BSWScriptedAI +{ + mob_orb_carrierAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance* pInstance; + bool MovementStarted; + + void Reset() + { +// m_creature->SetDisplayId(10045); + m_creature->SetRespawnDelay(7*DAY); + SetCombatMovement(false); + m_creature->SetPhaseMask(32, true); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + MovementStarted = false; + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSpeedRate(MOVE_RUN, 6.0f); + } + + void AttackStart(Unit *pWho) + { + return; + } + + void MovementInform(uint32 type, uint32 id) + { + if (!pInstance) return; + + if (type != POINT_MOTION_TYPE || !MovementStarted) return; + + if (id == 1) { + m_creature->GetMotionMaster()->MovementExpired(); + MovementStarted = false; + m_creature->ForcedDespawn(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!pInstance || pInstance->GetData(TYPE_HALION) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (Unit* pTarget = doSelectRandomPlayerAtRange(2.0f)) + doCast(SPELL_TWILIGHT_CUTTER, pTarget); + + if (!MovementStarted) + { + float x,y; + float m_direction = ((float)pInstance->GetData(DATA_ORB_DIRECTION)/1000.0f + M_PI_F - M_PI_F/32.0f); + if (m_direction > 2.0f*M_PI_F) m_direction = m_direction - 2.0f*M_PI_F; + if (Creature* focus = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_ORB_ROTATION_FOCUS))) + focus->GetNearPoint2D(x, y, FR_RADIUS, m_direction); + else m_creature->ForcedDespawn(); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(1, x, y, m_creature->GetPositionZ()); + MovementStarted = true; + } + + } + +}; + +CreatureAI* GetAI_mob_orb_carrier(Creature* pCreature) +{ + return new mob_orb_carrierAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_soul_consumptionAI : public BSWScriptedAI +{ + mob_soul_consumptionAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance* m_pInstance; + float m_Size0; + float m_Size; + + void Reset() + { + if (!isHeroic()) m_creature->SetPhaseMask(32,true); + else m_creature->SetPhaseMask(65535,true); + SetCombatMovement(false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + doCast(SPELL_CONSUMPTION_AURA); + m_Size0 = m_creature->GetObjectScale(); + m_Size = m_Size0; + } + + void AttackStart(Unit *pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_pInstance && m_pInstance->GetData(TYPE_HALION) != IN_PROGRESS) + m_creature->ForcedDespawn(); + +// if (!hasAura(SPELL_TWILIGHT_ENTER)) +// doCast(SPELL_TWILIGHT_ENTER); + + if (timedQuery(SPELL_CONSUMPTION_AURA, uiDiff)) + m_creature->ForcedDespawn(); + + if (doSelectRandomPlayerAtRange(m_Size * 3.0f) && m_Size <= m_Size0 * 3.0f) { + m_Size = m_Size*1.01; + m_creature->SetObjectScale(m_Size); + } + } +}; + +CreatureAI* GetAI_mob_soul_consumption(Creature* pCreature) +{ + return new mob_soul_consumptionAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_fiery_combustionAI : public BSWScriptedAI +{ + mob_fiery_combustionAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + m_pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance* m_pInstance; + float m_Size0; + float m_Size; + + void Reset() + { + if (!isHeroic()) m_creature->SetPhaseMask(31,true); + else m_creature->SetPhaseMask(65535,true); + SetCombatMovement(false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + doCast(SPELL_COMBUSTION_AURA); + m_Size0 = m_creature->GetObjectScale(); + m_Size = m_Size0; + } + + void AttackStart(Unit *pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_pInstance && m_pInstance->GetData(TYPE_HALION) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (timedQuery(SPELL_COMBUSTION_AURA, uiDiff)) + m_creature->ForcedDespawn(); + + if (doSelectRandomPlayerAtRange(m_Size * 3.0f) && m_Size <= m_Size0 * 3.0f) { + m_Size = m_Size*1.01; + m_creature->SetObjectScale(m_Size); + } + } + +}; + +CreatureAI* GetAI_mob_fiery_combustion(Creature* pCreature) +{ + return new mob_fiery_combustionAI(pCreature); +}; + + +bool GOHello_go_halion_portal_twilight(Player *player, GameObject* pGo) +{ + ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData(); + if(!pInstance) return false; + player->CastSpell(player,SPELL_TWILIGHT_ENTER,false); + return true; +} + +bool GOHello_go_halion_portal_real(Player *player, GameObject* pGo) +{ + ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData(); + if(!pInstance) return false; + player->RemoveAurasDueToSpell(SPELL_TWILIGHT_ENTER); + return true; +} + +void AddSC_boss_halion() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_halion_real"; + newscript->GetAI = &GetAI_boss_halion_real; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_halion_twilight"; + newscript->GetAI = &GetAI_boss_halion_twilight; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_halion_meteor"; + newscript->GetAI = &GetAI_mob_halion_meteor; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_halion_flame"; + newscript->GetAI = &GetAI_mob_halion_flame; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_halion_orb"; + newscript->GetAI = &GetAI_mob_halion_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_halion_control"; + newscript->GetAI = &GetAI_mob_halion_control; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_orb_rotation_focus"; + newscript->GetAI = &GetAI_mob_orb_rotation_focus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_orb_carrier"; + newscript->GetAI = &GetAI_mob_orb_carrier; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_soul_consumption"; + newscript->GetAI = &GetAI_mob_soul_consumption; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_fiery_combustion"; + newscript->GetAI = &GetAI_mob_fiery_combustion; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_halion_portal_twilight"; + newscript->pGOHello = &GOHello_go_halion_portal_twilight; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_halion_portal_real"; + newscript->pGOHello = &GOHello_go_halion_portal_real; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/ruby_sanctum/boss_saviana.cpp b/scripts/northrend/ruby_sanctum/boss_saviana.cpp index abef372..03580fe 100644 --- a/scripts/northrend/ruby_sanctum/boss_saviana.cpp +++ b/scripts/northrend/ruby_sanctum/boss_saviana.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* Copyright (C) 2010 /dev/rsa for 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 @@ -15,10 +15,308 @@ */ /* ScriptData -SDName: boss_saviana -SD%Complete: -SDComment: placeholder -SDCategory: Ruby Sanctum +SDName: boss_ragefire +SD%Complete: 90% +SDComment: by notagain && /dev/rsa +SDCategory: ruby_sanctum EndScriptData */ #include "precompiled.h" +#include "ruby_sanctum.h" + +enum BossSpells +{ + SPELL_ENRAGE = 78722, //soft enrage + fire nova + SPELL_FLAME_BREATH = 74404, + SPELL_BEACON = 74453, //mark for conflag, in enter to fly phase, 2 in 10, 5 in 25 + SPELL_CONFLAGATION = 74452, // after fly up + SPELL_CONFLAGATION_1 = 74455, // Triggered? + SPELL_CONFLAGATION_2 = 74456, // Aura + + MAX_BEACON_TARGETS = 5, +}; + +static Locations SpawnLoc[]= +{ + {3151.3898f, 636.8519f, 78.7396f}, // 0 Saviana start point + {3149.635f, 668.9644f, 90.507f}, // 1 Saviana fly phase, o=4,69 +}; + +struct MANGOS_DLL_DECL boss_ragefireAI : public BSWScriptedAI +{ + boss_ragefireAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + uint8 nextPoint; + Unit* marked[MAX_BEACON_TARGETS]; + bool MovementStarted; + bool conflagated; + + void Reset() + { + if(!pInstance) + return; + m_creature->SetRespawnDelay(7*DAY); + if (m_creature->isAlive()) pInstance->SetData(TYPE_RAGEFIRE, NOT_STARTED); + resetTimers(); + setStage(0); + nextPoint = 0; + conflagated = false; + for (uint8 i = 0; i < MAX_BEACON_TARGETS; ++i) + marked[i] = NULL; + } + + void MovementInform(uint32 type, uint32 id) + { + if (!pInstance) return; + + if (type != POINT_MOTION_TYPE || !MovementStarted) return; + + if (id == nextPoint) { + m_creature->GetMotionMaster()->MovementExpired(); + MovementStarted = false; + } + } + + void SetFly(bool command = false) + { + if (command) + { + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->HandleEmoteCommand(EMOTE_ONESHOT_FLY_SIT_GROUND_UP); + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + } + else + { + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->RemoveSplineFlag(SPLINEFLAG_FLYING); + } + } + + void StartMovement(uint32 id) + { + nextPoint = id; + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(id, SpawnLoc[id].x, SpawnLoc[id].y, SpawnLoc[id].z); + MovementStarted = true; + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1666401,m_creature,pVictim); + break; + case 1: + DoScriptText(-1666402,m_creature,pVictim); + break; + }; + } + + void JustReachedHome() + { + if (pInstance) + pInstance->SetData(TYPE_RAGEFIRE, FAIL); + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + + pInstance->SetData(TYPE_RAGEFIRE, IN_PROGRESS); + m_creature->SetInCombatWithZone(); + DoScriptText(-1666400,m_creature); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return; + + pInstance->SetData(TYPE_RAGEFIRE, DONE); + DoScriptText(-1666403,m_creature); + } + + void doBeacon(bool command = false) + { + if (command) + { + for(uint8 i = 0; i < getSpellData(SPELL_BEACON); ++i) + { + if (Unit* pTarget = doSelectRandomPlayer(SPELL_BEACON, false, 100.0f)) + { + if (doCast(SPELL_BEACON, pTarget) == CAST_OK) + marked[i] = pTarget; + else marked[i] = NULL; + } + } + conflagated = true; + } + else + { + m_creature->InterruptNonMeleeSpells(true); + for(uint8 i = 0; i < getSpellData(SPELL_BEACON); ++i) + { + if (marked[i]) + doCast(SPELL_CONFLAGATION_2, marked[i]); + marked[i] = NULL; + } + doCast(SPELL_CONFLAGATION_1); + conflagated = false; + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch (getStage()) + { + case 0: //GROUND + timedCast(SPELL_FLAME_BREATH, diff); + timedCast(SPELL_ENRAGE, diff); + if ( m_creature->GetHealthPercent() <= 80.0f) setStage(1); + break; + + case 1: //Air phase start + SetCombatMovement(false); + m_creature->InterruptNonMeleeSpells(true); + SetFly(true); + doBeacon(true); + StartMovement(1); + setStage(2); + break; + + case 2: // Wait for movement + if (MovementStarted) return; + doCast(SPELL_CONFLAGATION); + DoScriptText(-1666404,m_creature); + setStage(3); + break; + + case 3: // Wait for cast finish + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + doBeacon(false); + setStage(4); + }; + break; + + case 4: // Air phase + timedCast(SPELL_FLAME_BREATH, diff); + if (timedQuery(SPELL_BEACON, diff)) + { + doBeacon(true); + doCast(SPELL_CONFLAGATION); + }; + if (conflagated && timedQuery(SPELL_CONFLAGATION_1, diff)) + { + doBeacon(false); + }; + if ( m_creature->GetHealthPercent() <= 60.0f) setStage(5); + break; + + case 5: //Air phase end + StartMovement(0); + setStage(6); + break; + + case 6: // Wait for movement + if (MovementStarted) return; + SetFly(false); + SetCombatMovement(true); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + setStage(7); + break; + + case 7: //GROUND + timedCast(SPELL_FLAME_BREATH, diff); + timedCast(SPELL_ENRAGE, diff); + if ( m_creature->GetHealthPercent() <= 40.0f) setStage(8); + break; + + case 8: //Air phase start + SetCombatMovement(false); + m_creature->InterruptNonMeleeSpells(true); + SetFly(true); + doBeacon(true); + StartMovement(1); + setStage(9); + break; + + case 9: // Wait for movement + if (MovementStarted) return; + doCast(SPELL_CONFLAGATION); + DoScriptText(-1666404,m_creature); + setStage(10); + break; + + case 10: // Wait for cast finish + if (!m_creature->IsNonMeleeSpellCasted(false)) + { + doBeacon(false); + setStage(11); + }; + break; + + case 11: // Air phase + timedCast(SPELL_FLAME_BREATH, diff); + if (timedQuery(SPELL_BEACON, diff)) + { + doBeacon(true); + doCast(SPELL_CONFLAGATION); + }; + if (conflagated && timedQuery(SPELL_CONFLAGATION_1, diff)) + { + doBeacon(false); + }; + if ( m_creature->GetHealthPercent() <= 20.0f) setStage(12); + break; + + case 12: //Air phase end + StartMovement(0); + setStage(13); + break; + + case 13: // Wait for movement + if (MovementStarted) return; + SetFly(false); + SetCombatMovement(true); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + setStage(14); + break; + + case 14: //GROUND + timedCast(SPELL_FLAME_BREATH, diff); + timedCast(SPELL_ENRAGE, diff*2); + break; + + default: + break; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ragefire(Creature* pCreature) +{ + return new boss_ragefireAI(pCreature); +} + +void AddSC_boss_ragefire() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_ragefire"; + newscript->GetAI = &GetAI_boss_ragefire; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/ruby_sanctum/boss_zarithrian.cpp b/scripts/northrend/ruby_sanctum/boss_zarithrian.cpp new file mode 100644 index 0000000..880bc7b --- /dev/null +++ b/scripts/northrend/ruby_sanctum/boss_zarithrian.cpp @@ -0,0 +1,219 @@ +/* Copyright (C) 2010 /dev/rsa for 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_zarithian +SD%Complete: 90% +SDComment: by /dev/rsa && notagain +SDCategory: ruby_sanctum +EndScriptData */ + +// Need correct timers + +#include "precompiled.h" +#include "ruby_sanctum.h" + +enum BossSpells +{ + SPELL_CALL_FLAMECALLER = 74398, + SPELL_CLEAVE_ARMOR = 74367, + SPELL_IMTIMIDATING_ROAR = 74384, + SPELL_LAVA_GOUT = 74394, + SPELL_BLAST_NOVA = 74392, + + NPC_FLAMECALLER = 39814, +}; + +enum Equipment +{ + EQUIP_MAIN = 47156, + EQUIP_OFFHAND = 51812, + EQUIP_RANGED = EQUIP_NO_CHANGE, + EQUIP_DONE = EQUIP_NO_CHANGE, +}; + +static Locations SpawnLoc[]= +{ + {3008.552734f, 530.471680f, 89.195290f}, // 0 - Zarithian start point, o = 6,16 + {3014.313477f, 486.453735f, 89.255096f}, // 1 - Mob spawn 1 + {3025.324951f, 580.588501f, 88.593185f}, // 2 - Mob spawn 2 +}; + +struct MANGOS_DLL_DECL boss_zarithianAI : public BSWScriptedAI +{ + boss_zarithianAI(Creature* pCreature) : BSWScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if(!pInstance) + return; + + if (m_creature->isAlive()) + { + pInstance->SetData(TYPE_ZARITHIAN, NOT_STARTED); + resetTimers(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + setStage(0); + } + } + + void MoveInLineOfSight(Unit* pWho) + { + if (getStage()) + ScriptedAI::MoveInLineOfSight(pWho); + + if (!getStage() && + pInstance->GetData(TYPE_XERESTRASZA) == DONE && + pInstance->GetData(TYPE_BALTHARUS) == DONE && + pInstance->GetData(TYPE_RAGEFIRE) == DONE) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + setStage(1); + }; + } + + void KilledUnit(Unit* pVictim) + { + switch (urand(0,1)) { + case 0: + DoScriptText(-1666201,m_creature,pVictim); + break; + case 1: + DoScriptText(-1666202,m_creature,pVictim); + break; + }; + } + + void JustReachedHome() + { + if (!pInstance) return; + pInstance->SetData(TYPE_ZARITHIAN, FAIL); + } + + void JustSummoned(Creature* summoned) + { + if(!pInstance || !summoned) return; + + summoned->SetInCombatWithZone(); + if (Unit* pTarget = doSelectRandomPlayerAtRange(60.0f)) + { + summoned->AddThreat(pTarget, 100.0f); + summoned->GetMotionMaster()->MoveChase(pTarget); + } + + } + + void Aggro(Unit *who) + { + if(!pInstance) return; + + SetEquipmentSlots(false, EQUIP_MAIN, EQUIP_OFFHAND, EQUIP_RANGED); + pInstance->SetData(TYPE_ZARITHIAN, IN_PROGRESS); + DoScriptText(-1666200,m_creature); + } + + void JustDied(Unit *killer) + { + if(!pInstance) return; + + pInstance->SetData(TYPE_ZARITHIAN, DONE); + DoScriptText(-1666203,m_creature); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (timedQuery(SPELL_CALL_FLAMECALLER, diff)) + { + doSummon(NPC_FLAMECALLER, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z); + doSummon(NPC_FLAMECALLER, SpawnLoc[2].x, SpawnLoc[2].y, SpawnLoc[2].z); + +// if (currentDifficulty == RAID_DIFFICULTY_25MAN_NORMAL +// || currentDifficulty == RAID_DIFFICULTY_25MAN_HEROIC) +// doCast(SPELL_CALL_FLAMECALLER); + + DoScriptText(-1666204,m_creature); + } + + timedCast(SPELL_CLEAVE_ARMOR, diff); + timedCast(SPELL_IMTIMIDATING_ROAR, diff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_zarithian(Creature* pCreature) +{ + return new boss_zarithianAI(pCreature); +}; + +struct MANGOS_DLL_DECL mob_flamecaller_rubyAI : public BSWScriptedAI +{ + mob_flamecaller_rubyAI(Creature *pCreature) : BSWScriptedAI(pCreature) + { + pInstance = ((ScriptedInstance*)pCreature->GetInstanceData()); + Reset(); + } + + ScriptedInstance *pInstance; + + void Reset() + { + if(!pInstance) return; + resetTimers(); + m_creature->SetRespawnDelay(7*DAY); + } + + void UpdateAI(const uint32 diff) + { + + if (pInstance && pInstance->GetData(TYPE_ZARITHIAN) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + doCastAll(diff); + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_flamecaller_ruby(Creature* pCreature) +{ + return new mob_flamecaller_rubyAI(pCreature); +}; + +void AddSC_boss_zarithrian() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_zarithian"; + newscript->GetAI = &GetAI_boss_zarithian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flamecaller_ruby"; + newscript->GetAI = &GetAI_mob_flamecaller_ruby; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/ruby_sanctum/instance_ruby_sanctum.cpp b/scripts/northrend/ruby_sanctum/instance_ruby_sanctum.cpp new file mode 100644 index 0000000..deb17c2 --- /dev/null +++ b/scripts/northrend/ruby_sanctum/instance_ruby_sanctum.cpp @@ -0,0 +1,404 @@ +/* Copyright (C) 2006 - 2010 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_ruby_sanctum +SD%Complete: 50% +SDComment: by notagain, corrected by /dev/rsa +SDCategory: ruby_sanctum +EndScriptData */ + +//TODO: Trash mobs, spawn and removal of fire ring/walls, spawn of halion + +#include "precompiled.h" +#include "ruby_sanctum.h" + +struct MANGOS_DLL_DECL instance_ruby_sanctum : public ScriptedInstance +{ + instance_ruby_sanctum(Map* pMap) : ScriptedInstance(pMap) + { + Initialize(); + } + + bool needSave; + std::string strSaveData; + + //Creatures GUID + uint32 m_auiEncounter[MAX_ENCOUNTERS+1]; + + uint32 m_auiEventTimer; + uint32 m_auiHalionEvent; + + uint32 m_auiOrbDirection; + uint32 m_auiOrbNState; + uint32 m_auiOrbSState; + + uint64 m_uiHalion_pGUID; + uint64 m_uiHalion_tGUID; + uint64 m_uiHalionControlGUID; + uint64 m_uiRagefireGUID; + uint64 m_uiZarithianGUID; + uint64 m_uiBaltharusGUID; + uint64 m_uiCloneGUID; + uint64 m_uiXerestraszaGUID; + + uint64 m_uiOrbNGUID; + uint64 m_uiOrbSGUID; + uint64 m_uiOrbFocusGUID; + uint64 m_uiOrbCarrierGUID; + + //object GUID + uint64 m_uiHalionPortal1GUID; + uint64 m_uiHalionPortal2GUID; + uint64 m_uiHalionPortal3GUID; + uint64 m_uiHalionFireWallSGUID; + uint64 m_uiHalionFireWallMGUID; + uint64 m_uiHalionFireWallLGUID; + uint64 m_uiBaltharusTargetGUID; + + uint64 m_uiFireFieldGUID; + uint64 m_uiFlameWallsGUID; + uint64 m_uiFlameRingGUID; + + void OpenDoor(uint64 guid) + { + if(!guid) + return; + + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) + pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + } + + void CloseDoor(uint64 guid) + { + if(!guid) + return; + + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) + pGo->SetGoState(GO_STATE_READY); + } + + void Initialize() + { + for (uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + m_auiEncounter[i] = NOT_STARTED; + + m_auiEventTimer = 1000; + + m_uiHalion_pGUID = 0; + m_uiHalion_tGUID = 0; + m_uiRagefireGUID = 0; + m_uiZarithianGUID = 0; + m_uiBaltharusGUID = 0; + m_uiCloneGUID = 0; + m_uiHalionPortal1GUID = 0; + m_uiHalionPortal2GUID = 0; + m_uiHalionPortal3GUID = 0; + m_uiXerestraszaGUID = 0; + m_uiHalionFireWallSGUID = 0; + m_uiHalionFireWallMGUID = 0; + m_uiHalionFireWallLGUID = 0; + m_uiBaltharusTargetGUID = 0; + m_auiOrbDirection = 0; + m_uiOrbNGUID = 0; + m_uiOrbSGUID = 0; + m_uiOrbFocusGUID = 0; + m_auiOrbNState = NOT_STARTED; + m_auiOrbSState = NOT_STARTED; + + } + + bool IsEncounterInProgress() const + { + for(uint8 i = 1; i < MAX_ENCOUNTERS ; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + + return false; + } + + void UpdateWorldState(bool command, uint32 value) + { + Map::PlayerList const &players = instance->GetPlayers(); + + if (command) + { + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + if(Player* pPlayer = i->getSource()) + if(pPlayer->isAlive()) + { + pPlayer->SendUpdateWorldState(UPDATE_STATE_UI_SHOW,0); + if (pPlayer->HasAura(74807)) + pPlayer->SendUpdateWorldState(UPDATE_STATE_UI_COUNT_T, 100 - value); + else pPlayer->SendUpdateWorldState(UPDATE_STATE_UI_COUNT_R, value); + pPlayer->SendUpdateWorldState(UPDATE_STATE_UI_SHOW,1); + } + } + else + { + for (Map::PlayerList::const_iterator i = players.begin(); i != players.end(); ++i) + if(Player* pPlayer = i->getSource()) + if(pPlayer->isAlive()) + pPlayer->SendUpdateWorldState(UPDATE_STATE_UI_SHOW,0); + } + } + + void OpenAllDoors() + { + if (m_auiEncounter[TYPE_RAGEFIRE] == DONE && + m_auiEncounter[TYPE_BALTHARUS] == DONE && + m_auiEncounter[TYPE_XERESTRASZA] == DONE) + OpenDoor(m_uiFlameWallsGUID); + else CloseDoor(m_uiFlameWallsGUID); + } + + void OnCreatureCreate(Creature* pCreature) + { + switch(pCreature->GetEntry()) + { + case NPC_HALION_REAL: m_uiHalion_pGUID = pCreature->GetGUID(); break; + case NPC_HALION_TWILIGHT: m_uiHalion_tGUID = pCreature->GetGUID(); break; + case NPC_HALION_CONTROL: m_uiHalionControlGUID = pCreature->GetGUID(); break; + case NPC_RAGEFIRE: m_uiRagefireGUID = pCreature->GetGUID(); break; + case NPC_ZARITHIAN: m_uiZarithianGUID = pCreature->GetGUID(); break; + case NPC_BALTHARUS: m_uiBaltharusGUID = pCreature->GetGUID(); break; + case NPC_BALTHARUS_TARGET: m_uiBaltharusTargetGUID = pCreature->GetGUID(); break; + case NPC_CLONE: m_uiCloneGUID = pCreature->GetGUID(); break; + case NPC_XERESTRASZA: m_uiXerestraszaGUID = pCreature->GetGUID(); break; + case NPC_SHADOW_PULSAR_N: m_uiOrbNGUID = pCreature->GetGUID(); break; + case NPC_SHADOW_PULSAR_S: m_uiOrbSGUID = pCreature->GetGUID(); break; + case NPC_ORB_ROTATION_FOCUS: m_uiOrbFocusGUID = pCreature->GetGUID(); break; + case NPC_ORB_CARRIER: m_uiOrbCarrierGUID = pCreature->GetGUID(); break; + } + } + + void OnObjectCreate(GameObject* pGo) + { + switch(pGo->GetEntry()) + { + case GO_HALION_PORTAL_1: m_uiHalionPortal1GUID = pGo->GetGUID(); break; + case GO_HALION_PORTAL_2: m_uiHalionPortal2GUID = pGo->GetGUID(); break; + case GO_HALION_PORTAL_3: m_uiHalionPortal3GUID = pGo->GetGUID(); break; + case GO_FLAME_WALLS: m_uiFlameWallsGUID = pGo->GetGUID(); break; + case GO_FLAME_RING: m_uiFlameRingGUID = pGo->GetGUID(); break; + case GO_FIRE_FIELD: m_uiFireFieldGUID = pGo->GetGUID(); break; + } + OpenAllDoors(); + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch(uiType) + { + case TYPE_EVENT: m_auiEncounter[uiType] = uiData; uiData = NOT_STARTED; break; + case TYPE_RAGEFIRE: m_auiEncounter[uiType] = uiData; + OpenAllDoors(); + break; + case TYPE_BALTHARUS: m_auiEncounter[uiType] = uiData; + OpenAllDoors(); + break; + case TYPE_XERESTRASZA: m_auiEncounter[uiType] = uiData; + if (uiData == IN_PROGRESS) + OpenDoor(m_uiFireFieldGUID); + else if (uiData == NOT_STARTED) + { + CloseDoor(m_uiFireFieldGUID); + OpenAllDoors(); + } + else if (uiData == DONE) + { + OpenAllDoors(); + if (m_auiEncounter[TYPE_ZARITHIAN] == DONE) + { + m_auiEncounter[TYPE_EVENT] = 200; + m_auiEventTimer = 30000; + }; + } + break; + case TYPE_ZARITHIAN: m_auiEncounter[uiType] = uiData; + if (uiData == DONE) + { + OpenDoor(m_uiFlameWallsGUID); + m_auiEncounter[TYPE_EVENT] = 200; + m_auiEventTimer = 30000; + } + else if (uiData == IN_PROGRESS) + CloseDoor(m_uiFlameWallsGUID); + else if (uiData == FAIL) + OpenDoor(m_uiFlameWallsGUID); + break; + case TYPE_HALION: m_auiEncounter[uiType] = uiData; + if (uiData == IN_PROGRESS) + { + CloseDoor(m_uiFlameRingGUID); + } + else + { + OpenDoor(m_uiFlameRingGUID); + } + break; + case TYPE_HALION_EVENT: m_auiHalionEvent = uiData; uiData = NOT_STARTED; break; + case TYPE_EVENT_TIMER: m_auiEventTimer = uiData; uiData = NOT_STARTED; break; + + case DATA_ORB_DIRECTION: m_auiOrbDirection = uiData; uiData = NOT_STARTED; break; + case DATA_ORB_N: m_auiOrbNState = uiData; uiData = NOT_STARTED; break; + case DATA_ORB_S: m_auiOrbSState = uiData; uiData = NOT_STARTED; break; + case TYPE_COUNTER: + if (uiData == 0) + UpdateWorldState(false,0); + else UpdateWorldState(true,uiData); + uiData = NOT_STARTED; + break; + } + + if (uiData == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + saveStream << m_auiEncounter[i] << " "; + + strSaveData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } + + const char* Save() + { + return strSaveData.c_str(); + } + + uint32 GetData(uint32 uiType) + { + switch(uiType) + { + case TYPE_RAGEFIRE: return m_auiEncounter[uiType]; + case TYPE_BALTHARUS: return m_auiEncounter[uiType]; + case TYPE_XERESTRASZA: return m_auiEncounter[uiType]; + case TYPE_ZARITHIAN: return m_auiEncounter[uiType]; + case TYPE_HALION: return m_auiEncounter[uiType]; + + case TYPE_EVENT: return m_auiEncounter[uiType]; + + case TYPE_HALION_EVENT: return m_auiHalionEvent; + + case TYPE_EVENT_TIMER: return m_auiEventTimer; + case TYPE_EVENT_NPC: switch (m_auiEncounter[TYPE_EVENT]) + { + case 10: + case 20: + case 30: + case 40: + case 50: + case 60: + case 70: + case 80: + case 90: + case 100: + case 110: + case 200: + case 210: + return NPC_XERESTRASZA; + break; + default: + break; + }; + return 0; + + case DATA_ORB_DIRECTION: return m_auiOrbDirection; + case DATA_ORB_N: return m_auiOrbNState; + case DATA_ORB_S: return m_auiOrbSState; + + } + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch(uiData) + { + case NPC_BALTHARUS: return m_uiBaltharusGUID; + case NPC_CLONE: return m_uiCloneGUID; + case NPC_ZARITHIAN: return m_uiZarithianGUID; + case NPC_RAGEFIRE: return m_uiRagefireGUID; + case NPC_HALION_REAL: return m_uiHalion_pGUID; + case NPC_HALION_TWILIGHT: return m_uiHalion_tGUID; + case NPC_HALION_CONTROL: return m_uiHalionControlGUID; + case NPC_XERESTRASZA: return m_uiXerestraszaGUID; + case NPC_BALTHARUS_TARGET: return m_uiBaltharusTargetGUID; + + case GO_FLAME_WALLS: return m_uiFlameWallsGUID; + case GO_FLAME_RING: return m_uiFlameRingGUID; + case GO_FIRE_FIELD: return m_uiFireFieldGUID; + + case GO_HALION_PORTAL_1: return m_uiHalionPortal1GUID; + case GO_HALION_PORTAL_2: return m_uiHalionPortal2GUID; + case GO_HALION_PORTAL_3: return m_uiHalionPortal3GUID; + + case NPC_SHADOW_PULSAR_N: return m_uiOrbNGUID; + case NPC_SHADOW_PULSAR_S: return m_uiOrbSGUID; + case NPC_ORB_ROTATION_FOCUS: return m_uiOrbFocusGUID; + case NPC_ORB_CARRIER: return m_uiOrbCarrierGUID; + } + return 0; + } + + void Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + + for(uint8 i = 0; i < MAX_ENCOUNTERS; ++i) + { + loadStream >> m_auiEncounter[i]; + + if (m_auiEncounter[i] == IN_PROGRESS + || m_auiEncounter[i] == FAIL) + m_auiEncounter[i] = NOT_STARTED; + } + + m_auiEncounter[TYPE_XERESTRASZA] = NOT_STARTED; + + OUT_LOAD_INST_DATA_COMPLETE; + OpenAllDoors(); + } +}; + +InstanceData* GetInstanceData_instance_ruby_sanctum(Map* pMap) +{ + return new instance_ruby_sanctum(pMap); +} + +void AddSC_instance_ruby_sanctum() +{ + Script* pNewScript; + pNewScript = new Script; + pNewScript->Name = "instance_ruby_sanctum"; + pNewScript->GetInstanceData = &GetInstanceData_instance_ruby_sanctum; + pNewScript->RegisterSelf(); +} diff --git a/scripts/northrend/ruby_sanctum/ruby_sanctum.cpp b/scripts/northrend/ruby_sanctum/ruby_sanctum.cpp new file mode 100644 index 0000000..0e314d9 --- /dev/null +++ b/scripts/northrend/ruby_sanctum/ruby_sanctum.cpp @@ -0,0 +1,226 @@ +/* Copyright (C) 2010 /dev/rsa for 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: ruby_sanctum mobs +SD%Complete: 10% +SDComment: by notagain, corrected by /dev/rsa +SDCategory: ruby_sanctum +EndScriptData */ + +#include "precompiled.h" +#include "ruby_sanctum.h" + +static Locations SpawnLoc[]= +{ + {3155.540039f, 342.391998f, 84.596802f}, // 0 - start point + {3152.329834f, 359.41757f, 85.301605f}, // 1 - second say + {3152.078369f, 383.939178f, 86.337875f}, // 2 - other says and staying + {3154.99f, 535.637f, 72.8887f}, // 3 - Halion spawn point +}; + +struct MANGOS_DLL_DECL mob_xerestraszaAI : public ScriptedAI +{ + mob_xerestraszaAI(Creature *pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* pInstance; + uint32 nextEvent; + uint32 nextPoint; + uint32 UpdateTimer; + bool movementstarted; + bool onSessionEvent; + + void Reset() + { + if(!pInstance) return; + nextEvent = 0; + nextPoint = 0; + movementstarted = false; + UpdateTimer = 2000; + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + pInstance->SetData(TYPE_XERESTRASZA, NOT_STARTED); + m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSpeedRate(MOVE_WALK, 0.8f); + m_creature->SetRespawnDelay(7*DAY); + } + + void MovementInform(uint32 type, uint32 id) + { + if (type != POINT_MOTION_TYPE || !movementstarted) return; + if (id == nextPoint) + { + movementstarted = false; + pInstance->SetData(TYPE_EVENT,nextEvent); + m_creature->GetMotionMaster()->MovementExpired(); + } + } + + void StartMovement(uint32 id, uint32 _nextEvent) + { + nextPoint = id; + nextEvent = _nextEvent; + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MovePoint(id, SpawnLoc[id].x, SpawnLoc[id].y, SpawnLoc[id].z); + pInstance->SetData(TYPE_EVENT,0); + movementstarted = true; + } + + void AttackStart(Unit *who) + { + //ignore all attackstart commands + return; + } + + void MoveInLineOfSight(Unit *who) + { + if(!pInstance || !who || who->GetTypeId() != TYPEID_PLAYER) + return; + + if (pInstance->GetData(TYPE_BALTHARUS) != DONE + || pInstance->GetData(TYPE_XERESTRASZA) != NOT_STARTED) return; + + if(!who->IsWithinDistInMap(m_creature, 60.0f)) return; + + pInstance->SetData(TYPE_XERESTRASZA, IN_PROGRESS); + pInstance->SetData(TYPE_EVENT, 30); + onSessionEvent = true; + } + + void UpdateAI(const uint32 diff) + { + if(!pInstance) return; + + if (pInstance->GetData(TYPE_EVENT_NPC) == NPC_XERESTRASZA) + { + UpdateTimer = pInstance->GetData(TYPE_EVENT_TIMER); + if (UpdateTimer <= diff) + { + debug_log("EventMGR: creature %u received signal %u ",m_creature->GetEntry(),pInstance->GetData(TYPE_EVENT)); + switch (pInstance->GetData(TYPE_EVENT)) + { +// Xerestrasza intro + case 10: + UpdateTimer = 7000; + pInstance->SetData(TYPE_EVENT, 20); + break; + case 20: + DoScriptText(-1666000,m_creature); + pInstance->SetData(TYPE_EVENT,0); + break; +// Xerestrasza event + case 30: + m_creature->SetActiveObjectState(true); + DoScriptText(-1666001,m_creature); + StartMovement(1,40); + break; + case 40: + DoScriptText(-1666002,m_creature); + StartMovement(2,50); + break; + case 50: + DoScriptText(-1666003,m_creature); + UpdateTimer = 12000; + pInstance->SetData(TYPE_EVENT,60); + break; + case 60: + DoScriptText(-1666004,m_creature); + UpdateTimer = 12000; + pInstance->SetData(TYPE_EVENT,70); + break; + case 70: + DoScriptText(-1666005,m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,80); + break; + case 80: + DoScriptText(-1666006,m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,90); + break; + case 90: + DoScriptText(-1666007,m_creature); + UpdateTimer = 10000; + pInstance->SetData(TYPE_EVENT,100); + break; + case 100: + DoScriptText(-1666008,m_creature); + UpdateTimer = 4000; + pInstance->SetData(TYPE_EVENT,110); + break; + case 110: + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,0); + pInstance->SetData(TYPE_XERESTRASZA, DONE); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_creature->SetActiveObjectState(false); + break; +// Halion spawn + case 200: + m_creature->SetActiveObjectState(true); + { + Creature* pHalion = m_creature->GetMap()->GetCreature(pInstance->GetData64(NPC_HALION_REAL)); + if (pInstance->GetData(TYPE_BALTHARUS) == DONE && + pInstance->GetData(TYPE_RAGEFIRE) == DONE && + pInstance->GetData(TYPE_XERESTRASZA) == DONE && + pInstance->GetData(TYPE_ZARITHIAN) == DONE && + pInstance->GetData(TYPE_HALION) != DONE) + { + if (!pHalion) + pHalion = m_creature->SummonCreature(NPC_HALION_REAL, SpawnLoc[3].x, SpawnLoc[3].y, SpawnLoc[3].z, 6.23f, TEMPSUMMON_MANUAL_DESPAWN, HOUR*IN_MILLISECONDS); + if (pHalion && !pHalion->isAlive()) + pHalion->Respawn(); + if (pHalion) + pHalion->SetCreatorGuid(ObjectGuid()); + } + } + UpdateTimer = 4000; + pInstance->SetData(TYPE_EVENT,210); + break; + case 210: + m_creature->SetActiveObjectState(false); + UpdateTimer = 2000; + pInstance->SetData(TYPE_EVENT,0); + break; + + default: + break; + } + } else UpdateTimer -= diff; + pInstance->SetData(TYPE_EVENT_TIMER, UpdateTimer); + } + + } +}; + +CreatureAI* GetAI_mob_xerestrasza(Creature* pCreature) +{ + return new mob_xerestraszaAI(pCreature); +} + +void AddSC_ruby_sanctum() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "mob_xerestrasza"; + newscript->GetAI = &GetAI_mob_xerestrasza; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/ruby_sanctum/ruby_sanctum.h b/scripts/northrend/ruby_sanctum/ruby_sanctum.h new file mode 100644 index 0000000..fc96765 --- /dev/null +++ b/scripts/northrend/ruby_sanctum/ruby_sanctum.h @@ -0,0 +1,71 @@ +/* Copyright (C) 2010 by /dev/rsa for ScriptDev2 + * This program is free software licensed under GPL version 2 + * Please see the included DOCS/LICENSE.TXT for more information */ + +#ifndef DEF_RUBY_SANCTUM_H +#define DEF_RUBY_SANCTUM_H +#include "BSW_ai.h" + +enum +{ + MAX_ENCOUNTERS = 6, + + TYPE_EVENT = 0, + TYPE_RAGEFIRE = 1, + TYPE_BALTHARUS = 2, + TYPE_XERESTRASZA = 3, + TYPE_ZARITHIAN = 4, + TYPE_HALION = 5, + + TYPE_COUNTER = 6, // for WorldUpdateState + TYPE_HALION_EVENT = 7, + + TYPE_EVENT_TIMER = 50, + TYPE_EVENT_NPC = 51, + + NPC_HALION_REAL = 39863, // Halion Physical Realm NPC + NPC_HALION_TWILIGHT = 40142, // Halion Twilight Realm NPC + NPC_HALION_CONTROL = 40146, + + NPC_BALTHARUS = 39751, + NPC_CLONE = 39899, + NPC_ZARITHIAN = 39746, + NPC_RAGEFIRE = 39747, + + NPC_XERESTRASZA = 40429, + + NPC_BALTHARUS_TARGET = 39900, + NPC_ZARITHIAN_SPAWN_STALKER = 39794, + + // Orb rotation + NPC_SHADOW_PULSAR_N = 40083, //spinning orb N spawn + NPC_SHADOW_PULSAR_S = 40100, //spinning orb S spawn + NPC_ORB_CARRIER = 40081, + NPC_ORB_ROTATION_FOCUS = 40091, + + + GO_HALION_PORTAL_1 = 202794, //1327 ENTRY + GO_HALION_PORTAL_2 = 202795, //1327 ENTRY + GO_HALION_PORTAL_3 = 202796, //1327 EXIT + + GO_FIRE_FIELD = 203005, + GO_FLAME_WALLS = 203006, + GO_FLAME_RING = 203007, + + DATA_EVENT_TIMER = 101, + DATA_EVENT = 102, + + DATA_ORB_DIRECTION = 110, + DATA_ORB_S = 111, + DATA_ORB_N = 112, + +}; + +enum uiWorldStates +{ + UPDATE_STATE_UI_COUNT_R = 5049, + UPDATE_STATE_UI_COUNT_T = 5050, + UPDATE_STATE_UI_SHOW = 5051, +}; + +#endif diff --git a/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp b/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp index b4d6aa1..bf9203e 100644 --- a/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp +++ b/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp @@ -188,6 +188,8 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI if (pSpark->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) pSpark->GetMotionMaster()->MovementExpired(); + pSpark->SetSpeedRate(MOVE_RUN,2); + pSpark->GetMotionMaster()->MovePoint(POINT_CALLBACK, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); } } @@ -236,7 +238,7 @@ struct MANGOS_DLL_DECL boss_ionarAI : public ScriptedAI m_bIsSplitPhase = false; } // Lightning effect and restore Ionar - else if (m_uiSparkAtHomeCount == MAX_SPARKS) + else { m_creature->SetVisibility(VISIBILITY_ON); m_creature->CastSpell(m_creature, SPELL_SPARK_DESPAWN, false); diff --git a/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp b/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp index 9e88b3b..5d56820 100644 --- a/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp +++ b/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp @@ -24,6 +24,7 @@ EndScriptData */ #include "precompiled.h" #include "halls_of_lightning.h" + enum { SAY_AGGRO = -1602018, @@ -125,7 +126,7 @@ struct MANGOS_DLL_DECL boss_lokenAI : public ScriptedAI if (m_bIsAura) { // workaround for PULSING_SHOCKWAVE - /*if (m_uiPulsingShockwave_Timer < uiDiff) + if (m_uiPulsingShockwave_Timer < uiDiff) { Map *map = m_creature->GetMap(); if (map->IsDungeon()) @@ -144,13 +145,13 @@ struct MANGOS_DLL_DECL boss_lokenAI : public ScriptedAI if (m_fDist <= 1.0f) // Less than 1 yard dmg = (m_bIsRegularMode ? 800 : 850); // need to correct damage else // Further from 1 yard - dmg = round((m_bIsRegularMode ? 200 : 250) * m_fDist) + (m_bIsRegularMode ? 800 : 850); // need to correct damage + dmg = int32((m_bIsRegularMode ? 200 : 250) * m_fDist) + (m_bIsRegularMode ? 800 : 850); // need to correct damage m_creature->CastCustomSpell(i->getSource(), (m_bIsRegularMode ? 52942 : 59837), &dmg, 0, 0, false); } } m_uiPulsingShockwave_Timer = 2000; - }else m_uiPulsingShockwave_Timer -= uiDiff;*/ + }else m_uiPulsingShockwave_Timer -= uiDiff; } else { diff --git a/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp b/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp index e4f1444..9aaf055 100644 --- a/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp +++ b/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp @@ -329,8 +329,7 @@ bool EffectDummyCreature_npc_volkhan_anvil(Unit* pCaster, uint32 uiSpellId, Spel if (pCaster->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE) pCaster->GetMotionMaster()->MovementExpired(); - ((Creature*)pCaster)->GetMap()->CreatureRelocation((Creature*)pCaster, fX, fY, fZ, pCreatureTarget->GetOrientation()); - ((Creature*)pCaster)->SendMonsterMove(fX, fY, fZ, SPLINETYPE_NORMAL, ((Creature*)pCaster)->GetSplineFlags(), 1); + ((Creature*)pCaster)->MonsterMove(fX, fY, fZ, 1); pCreatureTarget->CastSpell(pCaster, SPELL_TEMPER_DUMMY, false); diff --git a/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp b/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp new file mode 100644 index 0000000..7546133 --- /dev/null +++ b/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp @@ -0,0 +1,175 @@ +/* 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 Krystallus +SDAuthor: ckegg +SD%Complete: 0% +SDComment: +SDCategory: Halls of Stone +EndScriptData */ + +#include "precompiled.h" +#include "def_halls_of_stone.h" + +enum +{ + SAY_AGGRO = -1599000, + SAY_KILL = -1599001, + SAY_DEATH = -1599002, + SAY_SHATTER = -1599003, + + SPELL_BOULDER_TOSS = 50843, + SPELL_BOULDER_TOSS_H = 59742, + SPELL_GROUND_SPIKE = 59750, + SPELL_GROUND_SLAM = 50827, + SPELL_SHATTER = 50810, + SPELL_SHATTER_H = 61546, + SPELL_STOMP = 50868, + SPELL_STOMP_H = 59744, + +}; + +/*###### +## boss_krystallus +######*/ + +struct MANGOS_DLL_DECL boss_krystallusAI : public ScriptedAI +{ + boss_krystallusAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + bool m_bIsRegularMode; + bool m_bIsSlam; + + uint32 m_uiToss_Timer; + uint32 m_uiSpike_Timer; + uint32 m_uiSlam_Timer; + uint32 m_uiShatter_Timer; + uint32 m_uiStomp_Timer; + + void Reset() + { + m_bIsSlam = false; + m_uiToss_Timer = 3000 + rand()%6000; + m_uiSpike_Timer = 9000 + rand()%5000; + m_uiSlam_Timer = 15000 + rand()%3000; + m_uiStomp_Timer = 20000 + rand()%9000; + m_uiShatter_Timer = 0; + + if(m_pInstance) + m_pInstance->SetData(TYPE_KRYSTALLUS, NOT_STARTED); + } + + void EnterCombat(Unit* pWho) + { + DoScriptText(SAY_AGGRO,m_creature); + + if(m_pInstance) + m_pInstance->SetData(TYPE_KRYSTALLUS, IN_PROGRESS); + } + + void KilledUnit(Unit* pVictim) + { + DoScriptText(SAY_KILL, m_creature); + } + + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_DEATH, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_KRYSTALLUS, DONE); + } + + void UpdateAI(const uint32 uiDiff) + { + //Return since we have no target + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiToss_Timer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_BOULDER_TOSS_H : SPELL_BOULDER_TOSS); + m_uiToss_Timer = 9000 + rand()%6000; + } + else + m_uiToss_Timer -= uiDiff; + + if (m_uiSpike_Timer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_GROUND_SPIKE); + m_uiSpike_Timer = 12000 + rand()%5000; + } + else + m_uiSpike_Timer -= uiDiff; + + if (m_uiStomp_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_STOMP_H : SPELL_STOMP); + m_uiStomp_Timer = 20000 + rand()%9000; + } + else + m_uiStomp_Timer -= uiDiff; + + if (m_uiSlam_Timer < uiDiff) + { + DoCast(m_creature, SPELL_GROUND_SLAM); + m_bIsSlam = true; + m_uiShatter_Timer = 10000; + m_uiSlam_Timer = 15000 + rand()%3000; + } + else + m_uiSlam_Timer -= uiDiff; + + if (m_bIsSlam) + { + if (m_uiShatter_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHATTER_H : SPELL_SHATTER); + m_bIsSlam = false; + m_uiShatter_Timer = 0; + } + else + m_uiShatter_Timer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +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/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp b/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp index 0b28902..ef8072c 100644 --- a/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp +++ b/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* 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 @@ -16,13 +16,13 @@ /* ScriptData SDName: Boss_Maiden_of_Grief -SD%Complete: 60% +SD%Complete: 20% SDComment: SDCategory: Halls of Stone EndScriptData */ #include "precompiled.h" -#include "halls_of_stone.h" +#include "def_halls_of_stone.h" enum { @@ -34,16 +34,13 @@ enum SAY_STUN = -1599010, SAY_DEATH = -1599011, - SPELL_STORM_OF_GRIEF = 50752, - SPELL_STORM_OF_GRIEF_H = 59772, - - SPELL_SHOCK_OF_SORROW = 50760, - SPELL_SHOCK_OF_SORROW_H = 59726, - + SPELL_PARTING_SORROW = 59723, SPELL_PILLAR_OF_WOE = 50761, SPELL_PILLAR_OF_WOE_H = 59727, - - SPELL_PARTING_SORROW = 59723 + SPELL_SHOCK_OF_SORROW = 50760, + SPELL_SHOCK_OF_SORROW_H = 59726, + SPELL_STORM_OF_GRIEF = 50752, + SPELL_STORM_OF_GRIEF_H = 59772, }; /*###### @@ -62,25 +59,33 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; - uint32 m_uiStormTimer; - uint32 m_uiShockTimer; - uint32 m_uiPillarTimer; + uint32 m_uiPartingSorrow_Timer; + uint32 m_uiPillarWoe_Timer; + uint32 m_uiShockSorrow_Timer; + uint32 m_uiStorm_Timer; void Reset() { - m_uiStormTimer = 5000; - m_uiShockTimer = 10000; - m_uiPillarTimer = 15000; + m_uiPartingSorrow_Timer = 9000 + rand()%5000; + m_uiPillarWoe_Timer = 3000 + rand()%4000; + m_uiStorm_Timer = 10000 + rand()%5000; + m_uiShockSorrow_Timer = 20000 + rand()%5000; + + if(m_pInstance) + m_pInstance->SetData(TYPE_GRIEF, NOT_STARTED); } void Aggro(Unit* pWho) { DoScriptText(SAY_AGGRO, m_creature); + + if(m_pInstance) + m_pInstance->SetData(TYPE_GRIEF, IN_PROGRESS); } void KilledUnit(Unit* pVictim) { - switch(urand(0, 3)) + switch(rand()%4) { case 0: DoScriptText(SAY_SLAY_1, m_creature); break; case 1: DoScriptText(SAY_SLAY_2, m_creature); break; @@ -94,7 +99,7 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI DoScriptText(SAY_DEATH, m_creature); if (m_pInstance) - m_pInstance->SetData(TYPE_MAIDEN, DONE); + m_pInstance->SetData(TYPE_GRIEF, DONE); } void UpdateAI(const uint32 uiDiff) @@ -102,35 +107,40 @@ struct MANGOS_DLL_DECL boss_maiden_of_griefAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; - if (m_uiStormTimer < uiDiff) + if (m_uiPartingSorrow_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_STORM_OF_GRIEF : SPELL_STORM_OF_GRIEF_H) == CAST_OK) - m_uiStormTimer = 20000; + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_PARTING_SORROW); + m_uiPartingSorrow_Timer = 12000 + rand()%5000; } else - m_uiStormTimer -= uiDiff; + m_uiPartingSorrow_Timer -= uiDiff; - if (m_uiPillarTimer < uiDiff) + if (m_uiPillarWoe_Timer < uiDiff) { if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) - { - if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_PILLAR_OF_WOE : SPELL_PILLAR_OF_WOE_H) == CAST_OK) - m_uiPillarTimer = 10000; - } + DoCast(pTarget, m_bIsRegularMode ? SPELL_PILLAR_OF_WOE_H : SPELL_PILLAR_OF_WOE); + m_uiPillarWoe_Timer = 9000 + rand()%4000; + } + else + m_uiPillarWoe_Timer -= uiDiff; + + if (m_uiStorm_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_STORM_OF_GRIEF_H : SPELL_STORM_OF_GRIEF); + m_uiStorm_Timer = 20000 + rand()%5000; } else - m_uiPillarTimer -= uiDiff; + m_uiStorm_Timer -= uiDiff; - if (m_uiShockTimer < uiDiff) + if (m_uiShockSorrow_Timer < uiDiff) { - if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHOCK_OF_SORROW : SPELL_SHOCK_OF_SORROW_H) == CAST_OK) - { - DoScriptText(SAY_STUN, m_creature); - m_uiShockTimer = 35000; - } + DoScriptText(SAY_STUN, m_creature); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHOCK_OF_SORROW_H : SPELL_SHOCK_OF_SORROW); + m_uiShockSorrow_Timer = 20000 + rand()%5000; } else - m_uiShockTimer -= uiDiff; + m_uiShockSorrow_Timer -= uiDiff; DoMeleeAttackIfReady(); } diff --git a/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp b/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp index b9f30e9..21a50f2 100644 --- a/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp +++ b/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* 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 @@ -22,47 +22,45 @@ SDCategory: Halls of Stone EndScriptData */ #include "precompiled.h" -#include "halls_of_stone.h" +#include "def_halls_of_stone.h" enum { - SAY_AGGRO = -1599000, - SAY_SLAY_1 = -1599001, - SAY_SLAY_2 = -1599002, - SAY_SLAY_3 = -1599003, - SAY_DEATH = -1599004, - EMOTE_GENERIC_FRENZY = -1000002, - - SPELL_FRENZY = 28747, - - SPELL_CHAIN_LIGHTNING = 50830, - SPELL_CHAIN_LIGHTNING_H = 59844, - - SPELL_STATIC_CHARGE = 50834, - SPELL_STATIC_CHARGE_H = 59846, - - SPELL_LIGHTNING_SHIELD = 50831, - SPELL_LIGHTNING_SHIELD_H = 59845, - - SPELL_LIGHTNING_RING = 50840, - SPELL_LIGHTNING_RING_H = 59848, - - SPELL_SUMMON_IRON_DWARF = 50789, // periodic dummy aura, tick each 30sec or each 20sec in heroic - SPELL_SUMMON_IRON_DWARF_H = 59860, // left/right 50790,50791 - - SPELL_SUMMON_IRON_TROGG = 50792, // periodic dummy aura, tick each 10sec or each 7sec in heroic - SPELL_SUMMON_IRON_TROGG_H = 59859, // left/right 50793,50794 - - SPELL_SUMMON_MALFORMED_OOZE = 50801, // periodic dummy aura, tick each 5sec or each 3sec in heroic - SPELL_SUMMON_MALFORMED_OOZE_H = 59858, // left/right 50802,50803 + SAY_AGGRO = -1599000, + SAY_SLAY_1 = -1599001, + SAY_SLAY_2 = -1599002, + SAY_SLAY_3 = -1599003, + SAY_DEATH = -1599004, + EMOTE_GENERIC_FRENZY = -1000002, + + SPELL_CHAIN_LIGHTING = 50830, + SPELL_CHAIN_LIGHTING_H = 59844, + SPELL_FRENZY = 28747, + SPELL_LIGHTING_SHIELD = 50831, + SPELL_LIGHTING_SHIELD_H = 59845, + SPELL_STATIC_CHARGE = 50834, //Periodic Trigger 2s interval, spell =50835 + SPELL_STATIC_CHARGE_H = 59846, //Periodic Trigger 2s interval, spell =50847 + + SPELL_LIGHTING_RING = 51849, + SPELL_LIGHTING_RING_H = 59861, + SPELL_LIGHTING_RING1 = 50840, + SPELL_LIGHTING_RING1_H = 59848, + + NPC_FORGED_IRON_TROGG = 27979, + NPC_MALFORMED_OOZE = 27981, + NPC_FORGED_IRON_DWARF = 27982, +}; - SPELL_SUMMON_IRON_SLUDGE = 50747, // instakill TARGET_SCRIPT - SPELL_IRON_SLUDGE_SPAWN_VISUAL = 50777, +struct Locations +{ + float x, y, z; + uint32 id; +}; - NPC_IRON_TROGG = 27979, - NPC_IRON_DWARF = 27982, - NPC_MALFORMED_OOZE = 27981, - NPC_IRON_SLUDGE = 28165 +static Locations PipeLoc[]= +{ + {1295.44f, 734.07f, 200.3f}, // left + {1297.7f, 595.6f, 199.9f}, // right }; /*###### @@ -80,37 +78,46 @@ struct MANGOS_DLL_DECL boss_sjonnirAI : public ScriptedAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; + bool m_bIsFrenzy; + + std::list m_lDwarfGUIDList; + uint32 m_uiChainLightning_Timer; + uint32 m_uiLightningShield_Timer; + uint32 m_uiStaticCharge_Timer; + uint32 m_uiLightningRing_Timer; + uint32 m_uiSummon_Timer; + uint32 m_uiFrenzy_Timer; void Reset() { - if (m_creature->isAlive()) - m_creature->CastSpell(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_SHIELD : SPELL_LIGHTNING_SHIELD_H, false); - } + m_bIsFrenzy = false; - void Aggro(Unit* pWho) - { - DoScriptText(SAY_AGGRO, m_creature); + m_uiChainLightning_Timer = 3000 + rand()%5000; + m_uiLightningShield_Timer = 20000 + rand()%5000; + m_uiStaticCharge_Timer = 20000 + rand()%5000; + m_uiLightningRing_Timer = 30000 + rand()%5000; + m_uiSummon_Timer = 5000; + m_uiFrenzy_Timer = 300000; - m_creature->CastSpell(m_creature, m_bIsRegularMode ? SPELL_SUMMON_IRON_DWARF : SPELL_SUMMON_IRON_DWARF_H, true); - m_creature->CastSpell(m_creature, m_bIsRegularMode ? SPELL_SUMMON_IRON_TROGG : SPELL_SUMMON_IRON_TROGG_H, true); - } + DespawnDwarf(); + if(m_pInstance) + m_pInstance->SetData(TYPE_GRIEF, NOT_STARTED); + } - void JustSummoned(Creature* pSummoned) + void Aggro(Unit* pWho) { - if (pSummoned->GetEntry() == NPC_IRON_TROGG || pSummoned->GetEntry() == NPC_IRON_DWARF || pSummoned->GetEntry() == NPC_MALFORMED_OOZE) - { - float fX, fY, fZ; - pSummoned->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 10.0f, fX, fY, fZ); + DoScriptText(SAY_AGGRO, m_creature); - pSummoned->RemoveSplineFlag(SPLINEFLAG_WALKMODE); - pSummoned->GetMotionMaster()->MovePoint(0, fX, fY, fZ); - } + if(m_pInstance) + m_pInstance->SetData(TYPE_GRIEF, IN_PROGRESS); +// pSummoned->RemoveSplineFlag(SPLINEFLAG_WALKMODE); +// pSummoned->GetMotionMaster()->MovePoint(0, fX, fY, fZ); } void KilledUnit(Unit* pVictim) { - switch(urand(0, 2)) + switch(rand()%3) { case 0: DoScriptText(SAY_SLAY_1, m_creature); break; case 1: DoScriptText(SAY_SLAY_2, m_creature); break; @@ -121,6 +128,37 @@ struct MANGOS_DLL_DECL boss_sjonnirAI : public ScriptedAI void JustDied(Unit* pKiller) { DoScriptText(SAY_DEATH, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_GRIEF, DONE); + } + + void DespawnDwarf() + { + if (m_lDwarfGUIDList.empty()) + return; + + for(std::list::iterator itr = m_lDwarfGUIDList.begin(); itr != m_lDwarfGUIDList.end(); ++itr) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + } + + m_lDwarfGUIDList.clear(); + } + + void JustSummoned(Creature* pSummoned) + { + m_lDwarfGUIDList.push_back(pSummoned->GetGUID()); + + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pSummoned->AddThreat(pTarget, 0.0f); + pSummoned->AI()->AttackStart(pTarget); + } } void UpdateAI(const uint32 uiDiff) @@ -128,6 +166,66 @@ struct MANGOS_DLL_DECL boss_sjonnirAI : public ScriptedAI if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) return; + if (m_uiChainLightning_Timer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_CHAIN_LIGHTING_H : SPELL_CHAIN_LIGHTING); + m_uiChainLightning_Timer = 10000 + rand()%5000; + } + else + m_uiChainLightning_Timer -= uiDiff; + + if (m_uiLightningShield_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_LIGHTING_SHIELD_H : SPELL_LIGHTING_SHIELD); + m_uiLightningShield_Timer = 20000 + rand()%5000; + } + else + m_uiLightningShield_Timer -= uiDiff; + + if (m_uiStaticCharge_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_STATIC_CHARGE_H : SPELL_STATIC_CHARGE); + m_uiStaticCharge_Timer = 20000 + rand()%5000; + } + else + m_uiStaticCharge_Timer -= uiDiff; + + if (m_uiLightningRing_Timer < uiDiff) + { + if (m_creature->IsNonMeleeSpellCasted(false)) + m_creature->InterruptNonMeleeSpells(false); + DoCast(m_creature, m_bIsRegularMode ? SPELL_LIGHTING_RING_H : SPELL_LIGHTING_RING); + m_uiLightningRing_Timer = 30000 + rand()%5000; + } + else + m_uiLightningRing_Timer -= uiDiff; + + if (m_uiSummon_Timer < uiDiff) + { + uint32 SummonPipe = rand()%2; + uint32 SummonEntry = 0; + switch(rand()%3) + { + case 0: SummonEntry = NPC_FORGED_IRON_TROGG; break; + case 1: SummonEntry = NPC_MALFORMED_OOZE; break; + case 2: SummonEntry = NPC_FORGED_IRON_DWARF; break; + } + m_creature->SummonCreature(SummonEntry, PipeLoc[SummonPipe].x, PipeLoc[SummonPipe].y, PipeLoc[SummonPipe].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + m_uiSummon_Timer = 20000; + } + else + m_uiSummon_Timer -= uiDiff; + + if (!m_bIsFrenzy && m_uiFrenzy_Timer < uiDiff) + { + DoCast(m_creature, SPELL_FRENZY); + m_bIsFrenzy = true; + m_uiFrenzy_Timer = 0; + } + else + m_uiFrenzy_Timer -= uiDiff; + DoMeleeAttackIfReady(); } }; diff --git a/scripts/northrend/ulduar/halls_of_stone/def_halls_of_stone.h b/scripts/northrend/ulduar/halls_of_stone/def_halls_of_stone.h new file mode 100644 index 0000000..1b06148 --- /dev/null +++ b/scripts/northrend/ulduar/halls_of_stone/def_halls_of_stone.h @@ -0,0 +1,55 @@ +/* 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_STONE_H +#define DEF_HALLS_OF_STONE_H + +enum +{ + MAX_ENCOUNTER = 4, + + DATA_KRYSTALLUS = 1, + DATA_GRIEF = 2, + DATA_BRANN = 3, + DATA_SJONNIR = 4, + + DATA_KADDRAK = 5, + DATA_ABEDNEUM = 6, + DATA_MARNAK = 7, + + DATA_GO_TRIBUNAL_CONSOLE = 8, + DATA_GO_SKY_FLOOR = 9, + DATA_GO_KADDRAK = 10, + DATA_GO_ABEDNEUM = 11, + DATA_GO_MARNAK = 12, + + TYPE_KRYSTALLUS = 20, + TYPE_GRIEF = 21, + TYPE_BRANN = 22, + TYPE_SJONNIR = 23, + + NPC_KRYSTALLUS = 27977, + NPC_GRIEF = 27975, + NPC_BRANN = 28070, + NPC_SJONNIR = 27978, + + NPC_KADDRAK = 30898, // left + NPC_ABEDNEUM = 30899, // middle + NPC_MARNAK = 30897, // right + + GO_GRIEF_DOOR = 191292, + GO_BRANN_DOOR = 191293, + GO_SJONNIR_DOOR = 191296, + + GO_KADDRAK = 191671, // left + GO_ABEDNEUM = 191669, // middle + GO_MARNAK = 191670, // right + + GO_TRIBUNAL_CONSOLE = 193907, + GO_TRIBUNAL_CHEST = 190586, + GO_TRIBUNAL_CHEST_H = 193996, + GO_TRIBUNAL_SKY_FLOOR = 191527, +}; + +#endif diff --git a/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp b/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp index 8731713..0f733c9 100644 --- a/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp +++ b/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* 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 @@ -22,8 +22,8 @@ SDCategory: Halls of Stone EndScriptData */ #include "precompiled.h" -#include "halls_of_stone.h" #include "escort_ai.h" +#include "def_halls_of_stone.h" enum { @@ -91,12 +91,180 @@ enum SAY_ENTRANCE_MEET = -1599064, TEXT_ID_START = 13100, - TEXT_ID_PROGRESS = 13101 + TEXT_ID_PROGRESS = 13101, + + NPC_TRIBUNAL_OF_THE_AGES = 28234, + NPC_BRANN_BRONZEBEARD = 28070, + SPELL_STEALTH = 58506, + + // KADDRAK + SPELL_GLARE_OF_THE_TRIBUNAL = 50988, + SPELL_GLARE_OF_THE_TRIBUNAL_H = 59870, + + // MARNAK + SPELL_DARK_MATTER = 51012, + SPELL_DARK_MATTER_H = 59868, + NPC_DARK_MATTER_TARGET = 28237, + + // ABEDNEUM + SPELL_SEARING_GAZE = 51136, + SPELL_SEARING_GAZE_H = 59867, + NPC_SEARING_GAZE_TARGET = 28265, + + NPC_DARK_RUNE_PROTECTOR = 27983, + NPC_DARK_RUNE_STORMCALLER = 27984, + NPC_IRON_GOLEM_CUSTODIAN = 27985, + + QUEST_HALLS_OF_STONE = 13207, }; #define GOSSIP_ITEM_START "Brann, it would be our honor!" #define GOSSIP_ITEM_PROGRESS "Let's move Brann, enough of the history lessons!" +struct Locations +{ + float x, y, z; + uint32 id; +}; + +static Locations SpawnLoc[]= +{ + {946.992f, 397.016f, 208.374f}, + {960.748f, 382.944f, 208.374f}, +}; + + +/*###### +## mob_tribuna_controller +######*/ + +struct MANGOS_DLL_DECL mob_tribuna_controllerAI : public ScriptedAI +{ + mob_tribuna_controllerAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + std::list m_lKaddrakGUIDList; + //std::list m_lMarnakGUIDList; + //std::list m_lAbedneumGUIDList; + + bool m_bIsActivateKaddrak; + bool m_bIsActivateMarnak; + bool m_bIsActivateAbedneum; + + uint32 m_uiKaddrak_Encounter_timer; + uint32 m_uiMarnak_Encounter_timer; + uint32 m_uiAbedneum_Encounter_timer; + + void Reset() + { + m_bIsActivateKaddrak = false; + m_bIsActivateMarnak = false; + m_bIsActivateAbedneum = false; + + m_uiKaddrak_Encounter_timer = 1500; + m_uiMarnak_Encounter_timer = 10000; + m_uiAbedneum_Encounter_timer = 10000; + + m_lKaddrakGUIDList.clear(); + //m_lMarnakGUIDList.clear(); + //m_lAbedneumGUIDList.clear(); + } + + void UpdateFacesList() + { + GetCreatureListWithEntryInGrid(m_lKaddrakGUIDList, m_creature, NPC_KADDRAK, 50.0f); + if (!m_lKaddrakGUIDList.empty()) + { + uint32 uiPositionCounter = 0; + for(std::list::iterator itr = m_lKaddrakGUIDList.begin(); itr != m_lKaddrakGUIDList.end(); ++itr) + { + if (!(*itr)) continue; + + if (Creature* c = (Creature *)(*itr)) + { + if (c->isAlive()) + { + if (uiPositionCounter == 0) + { + c->GetMap()->CreatureRelocation((*itr), 927.265f, 333.200f, 218.780f, (*itr)->GetOrientation()); + c->MonsterMove(927.265f, 333.200f, 218.780f, 1); + } + else + { + c->GetMap()->CreatureRelocation((*itr), 921.745f, 328.076f, 218.780f, (*itr)->GetOrientation()); + c->MonsterMove(921.745f, 328.076f, 218.780f, 1); + } + } + ++uiPositionCounter; + } + } + } + //GetCreatureListWithEntryInGrid(m_lMarnakGUIDList, m_creature, NPC_MARNAK, 50.0f); + //GetCreatureListWithEntryInGrid(m_lAbedneumGUIDList, m_creature, NPC_ABEDNEUM, 50.0f); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_bIsActivateKaddrak) + { + if (m_uiKaddrak_Encounter_timer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (!m_lKaddrakGUIDList.empty()) + for(std::list::iterator itr = m_lKaddrakGUIDList.begin(); itr != m_lKaddrakGUIDList.end(); ++itr) + if ((*itr)->isAlive()) + (*itr)->CastSpell(pTarget, m_bIsRegularMode ? SPELL_GLARE_OF_THE_TRIBUNAL_H : SPELL_GLARE_OF_THE_TRIBUNAL, true); + + m_uiKaddrak_Encounter_timer = 1500; + } + else + m_uiKaddrak_Encounter_timer -= uiDiff; + } + if (m_bIsActivateMarnak) + { + if (m_uiMarnak_Encounter_timer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (Creature* pTemp = m_creature->SummonCreature(NPC_DARK_MATTER_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1000)) + { + pTemp->SetDisplayId(11686); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->CastSpell(pTarget, m_bIsRegularMode ? SPELL_DARK_MATTER_H : SPELL_DARK_MATTER, true); + } + + m_uiMarnak_Encounter_timer = 30000 + rand()%1000; + } + else + m_uiMarnak_Encounter_timer -= uiDiff; + } + if (m_bIsActivateAbedneum) + { + if (m_uiAbedneum_Encounter_timer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + if (Creature* pTemp = m_creature->SummonCreature(NPC_SEARING_GAZE_TARGET, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN, 10000)) + { + pTemp->SetDisplayId(11686); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->CastSpell(pTemp, m_bIsRegularMode ? SPELL_SEARING_GAZE_H : SPELL_SEARING_GAZE, true); + } + + m_uiAbedneum_Encounter_timer = 30000 + rand()%1000; + } + else + m_uiAbedneum_Encounter_timer -= uiDiff; + } + } +}; + /*###### ## npc_brann_hos ######*/ @@ -112,18 +280,87 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI ScriptedInstance* m_pInstance; bool m_bIsRegularMode; + bool m_bIsBattle; + bool m_bIsLowHP; + + uint32 m_uiStep; + uint32 m_uiPhase_timer; + + uint64 m_uiControllerGUID; + std::list m_lDwarfGUIDList; void Reset() { + if (!HasEscortState(STATE_ESCORT_ESCORTING)) + { + m_bIsLowHP = false; + m_bIsBattle = false; + + m_uiStep = 0; + m_uiPhase_timer = 0; + + m_uiControllerGUID = 0; + + DespawnDwarf(); + + if(m_pInstance) + m_pInstance->SetData(TYPE_BRANN, NOT_STARTED); + } + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (!m_bIsBattle) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho, 0.0f); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho); + } } void WaypointReached(uint32 uiPointId) { + switch(uiPointId) + { + case 7: + if (Creature* pCreature = GetClosestCreatureWithEntry(m_creature, NPC_TRIBUNAL_OF_THE_AGES, 100.0f)) + { + if (!pCreature->isAlive()) + pCreature->Respawn(); + ((mob_tribuna_controllerAI*)pCreature->AI())->UpdateFacesList(); + m_uiControllerGUID = pCreature->GetGUID(); + } + break; + case 13: + DoScriptText(SAY_EVENT_INTRO_1, m_creature); + SetEscortPaused(true); + SetRun(true); + JumpToNextStep(20000); + break; + case 17: + DoScriptText(SAY_EVENT_INTRO_2, m_creature); + if (m_pInstance) + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_TRIBUNAL_CONSOLE)); + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + SetEscortPaused(true); + JumpToNextStep(8500); + break; + case 18: + SetEscortPaused(true); + break; + } } void KilledUnit(Unit* pVictim) { - switch(urand(0, 2)) + switch(rand()%3) { case 0: DoScriptText(SAY_KILL_1, m_creature); break; case 1: DoScriptText(SAY_KILL_2, m_creature); break; @@ -136,23 +373,367 @@ struct MANGOS_DLL_DECL npc_brann_hosAI : public npc_escortAI DoScriptText(SAY_DEATH, m_creature); } - void UpdateEscortAI(const uint32 uiDiff) + void DespawnDwarf() { - if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + if (m_lDwarfGUIDList.empty()) return; - DoMeleeAttackIfReady(); + for(std::list::iterator itr = m_lDwarfGUIDList.begin(); itr != m_lDwarfGUIDList.end(); ++itr) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + } + + m_lDwarfGUIDList.clear(); + } + + void SpawnDwarf(uint32 uiType) + { + switch(uiType) + { + case 1: + { + uint32 uiSpawnNumber = (m_bIsRegularMode ? 3 : 2); + for (uint8 i = 0; i < uiSpawnNumber; ++i) + m_creature->SummonCreature(NPC_DARK_RUNE_PROTECTOR, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + m_creature->SummonCreature(NPC_DARK_RUNE_STORMCALLER, SpawnLoc[0].x, SpawnLoc[0].y, SpawnLoc[0].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + } + case 2: + for (uint8 i = 0; i < 2; ++i) + m_creature->SummonCreature(NPC_DARK_RUNE_STORMCALLER, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + case 3: + m_creature->SummonCreature(NPC_IRON_GOLEM_CUSTODIAN, SpawnLoc[1].x, SpawnLoc[1].y, SpawnLoc[1].z, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000); + break; + } + } + + void JustSummoned(Creature* pSummoned) + { + m_lDwarfGUIDList.push_back(pSummoned->GetGUID()); + pSummoned->AddThreat(m_creature, 0.0f); + pSummoned->AI()->AttackStart(m_creature); + } + + void JumpToNextStep(uint32 uiTimer) + { + m_uiPhase_timer = uiTimer; + m_uiStep++; + } + + void UpdateEscortAI(const uint32 uiDiff) + { + if (m_uiPhase_timer < uiDiff) + { + switch(m_uiStep) + { + case 0: // unused + break; + case 1: + if (m_pInstance) + { + if (m_pInstance->GetData(TYPE_BRANN) != NOT_STARTED) + return; + + m_pInstance->SetData(TYPE_BRANN, IN_PROGRESS); + } + m_bIsBattle = false; + DoScriptText(SAY_ESCORT_START, m_creature); + JumpToNextStep(0); + break; + case 3: + SetEscortPaused(false); + JumpToNextStep(0); + break; + case 5: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_INTRO_3_ABED, pTemp); + JumpToNextStep(8500); + break; + case 6: + DoScriptText(SAY_EVENT_A_1, m_creature); + JumpToNextStep(6500); + break; + case 7: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_A_2_KADD, pTemp); + JumpToNextStep(12500); + break; + case 8: + DoScriptText(SAY_EVENT_A_3, m_creature); + if (m_pInstance) + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_KADDRAK)); + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_uiControllerGUID)) + ((mob_tribuna_controllerAI*)pTemp->AI())->m_bIsActivateKaddrak = true; + JumpToNextStep(5000); + break; + case 9: + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 10: + DoScriptText(SAY_EVENT_B_1, m_creature); + JumpToNextStep(6000); + break; + case 11: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_B_2_MARN, pTemp); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 12: + DoScriptText(SAY_EVENT_B_3, m_creature); + if (m_pInstance) + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_MARNAK)); + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_uiControllerGUID)) + ((mob_tribuna_controllerAI*)pTemp->AI())->m_bIsActivateMarnak = 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, m_creature); + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 16: + SpawnDwarf(2); + JumpToNextStep(20000); + break; + case 17: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_C_2_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(20000); + break; + case 18: + DoScriptText(SAY_EVENT_C_3, m_creature); + if (m_pInstance) + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_ABEDNEUM)); + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_uiControllerGUID)) + ((mob_tribuna_controllerAI*)pTemp->AI())->m_bIsActivateAbedneum = 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, m_creature); + SpawnDwarf(3); + JumpToNextStep(20000); + break; + case 22: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_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, m_creature); + SpawnDwarf(3); + JumpToNextStep(5000); + break; + case 25: + SpawnDwarf(1); + JumpToNextStep(5000); + break; + case 26: + SpawnDwarf(2); + JumpToNextStep(10000); + break; + case 27: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_D_4_ABED, pTemp); + SpawnDwarf(1); + JumpToNextStep(10000); + break; + case 28: + DoScriptText(SAY_EVENT_END_01, m_creature); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + if (m_pInstance) + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_SKY_FLOOR)); + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_uiControllerGUID)) + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_bIsBattle = true; + SetEscortPaused(false); + JumpToNextStep(3500); + break; + case 29: + DoScriptText(SAY_EVENT_END_02, m_creature); + JumpToNextStep(3500); + break; + case 30: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_03_ABED, pTemp); + JumpToNextStep(4500); + break; + case 31: + DoScriptText(SAY_EVENT_END_04, m_creature); + JumpToNextStep(6500); + break; + case 32: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_05_ABED, pTemp); + JumpToNextStep(6500); + break; + case 33: + DoScriptText(SAY_EVENT_END_06, m_creature); + JumpToNextStep(2500); + break; + case 34: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_07_ABED, pTemp); + JumpToNextStep(10500); + break; + case 35: + DoScriptText(SAY_EVENT_END_08, m_creature); + JumpToNextStep(4500); + break; + case 36: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_09_KADD, pTemp); + JumpToNextStep(7500); + break; + case 37: + DoScriptText(SAY_EVENT_END_10, m_creature); + JumpToNextStep(2500); + break; + case 38: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_11_KADD, pTemp); + JumpToNextStep(10500); + break; + case 39: + DoScriptText(SAY_EVENT_END_12, m_creature); + JumpToNextStep(2500); + break; + case 40: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_KADDRAK))) + DoScriptText(SAY_EVENT_END_13_KADD, pTemp); + JumpToNextStep(9500); + break; + case 41: + DoScriptText(SAY_EVENT_END_14, m_creature); + JumpToNextStep(5500); + break; + case 42: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_15_MARN, pTemp); + JumpToNextStep(3500); + break; + case 43: + DoScriptText(SAY_EVENT_END_16, m_creature); + JumpToNextStep(3500); + break; + case 44: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_17_MARN, pTemp); + JumpToNextStep(11500); + break; + case 45: + DoScriptText(SAY_EVENT_END_18, m_creature); + JumpToNextStep(10500); + break; + case 46: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_MARNAK))) + DoScriptText(SAY_EVENT_END_19_MARN, pTemp); + JumpToNextStep(2500); + break; + case 47: + DoScriptText(SAY_EVENT_END_20, m_creature); + JumpToNextStep(4500); + break; + case 48: + if (m_pInstance) + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_ABEDNEUM))) + DoScriptText(SAY_EVENT_END_21_ABED, pTemp); + JumpToNextStep(3500); + break; + case 49: + { + if (m_pInstance) + { + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_KADDRAK)); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_MARNAK)); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_ABEDNEUM)); + m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_SKY_FLOOR)); + m_pInstance->SetData(TYPE_BRANN, DONE); + } + + Player* pPlayer = GetPlayerForEscort(); + if (pPlayer) + pPlayer->GroupEventHappens(QUEST_HALLS_OF_STONE, m_creature); + + m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); + + JumpToNextStep(180000); + break; + } + case 50: + SetEscortPaused(false); + break; + } + } + else m_uiPhase_timer -= uiDiff; + + if (!m_bIsLowHP && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) <= 30) + { + DoScriptText(SAY_LOW_HEALTH, m_creature); + m_bIsLowHP = true; + } + else if (m_bIsLowHP && (m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) > 30) + m_bIsLowHP = false; } }; bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) { + ScriptedInstance* m_pInstance; + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + if (pCreature->isQuestGiver()) pPlayer->PrepareQuestMenu(pCreature->GetGUID()); - pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID()); +if (m_pInstance->GetData(TYPE_BRANN) != DONE) 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()); + //pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_PROGRESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); //pPlayer->SEND_GOSSIP_MENU(TEXT_ID_PROGRESS, pCreature->GetGUID()); return true; @@ -161,7 +742,11 @@ bool GossipHello_npc_brann_hos(Player* pPlayer, Creature* pCreature) 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(); + ((npc_brann_hosAI*)pCreature->AI())->m_uiStep = 1; + ((npc_brann_hosAI*)pCreature->AI())->Start(false, pPlayer->GetGUID()); + } return true; } @@ -171,14 +756,24 @@ CreatureAI* GetAI_npc_brann_hos(Creature* pCreature) return new npc_brann_hosAI(pCreature); } +CreatureAI* GetAI_mob_tribuna_controller(Creature* pCreature) +{ + return new mob_tribuna_controllerAI (pCreature); +} + void AddSC_halls_of_stone() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "npc_brann_hos"; - pNewScript->GetAI = &GetAI_npc_brann_hos; - pNewScript->pGossipHello = &GossipHello_npc_brann_hos; - pNewScript->pGossipSelect = &GossipSelect_npc_brann_hos; - pNewScript->RegisterSelf(); + 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/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp b/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp index 27ba40f..31ee069 100644 --- a/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp +++ b/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* 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 @@ -16,62 +16,108 @@ /* ScriptData SDName: Instance_Halls_of_Stone -SD%Complete: 10% +SD%Complete: 0% SDComment: SDCategory: Halls of Stone EndScriptData */ #include "precompiled.h" -#include "halls_of_stone.h" +#include "def_halls_of_stone.h" + +/* Halls of Lightning encounters: +0 - Krystallus +1 - Maiden of Grief +2 - Brann Bronzebeard +3 - Sjonnir The Ironshaper +*/ struct MANGOS_DLL_DECL instance_halls_of_stone : public ScriptedInstance { - instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + instance_halls_of_stone(Map* pMap) : ScriptedInstance(pMap) { + Regular = pMap->IsRegularDifficulty(); + Initialize(); + }; uint32 m_auiEncounter[MAX_ENCOUNTER]; + bool Regular; + std::string strSaveData; + uint64 m_uiKrystallusGUID; + uint64 m_uiGriefGUID; uint64 m_uiBrannGUID; + uint64 m_uiSjonnirGUID; + uint64 m_uiKaddrakGUID; uint64 m_uiAbedneumGUID; uint64 m_uiMarnakGUID; + uint64 m_uiGriefDoorGUID; + uint64 m_uiBrannDoorGUID; uint64 m_uiSjonnirDoorGUID; - uint64 m_uiTribunalDoorGUID; - uint64 m_uiTribunalChestGUID; - uint64 m_uiTribunalHeadRightGUID; - uint64 m_uiTribunalHeadCenterGUID; - uint64 m_uiTribunalHeadLeftGUID; - uint64 m_uiTribunalConsoleGUID; - uint64 m_uiTribunalFloorGUID; - uint64 m_uiSjonnirConsoleGUID; + + uint64 m_uiGoTribunalConsoleGUID; + uint64 m_uiGoTribunalChestGUID; + uint64 m_uiGoTribunalSkyFloorGUID; + uint64 m_uiGoKaddrakGUID; + uint64 m_uiGoAbedneumGUID; + uint64 m_uiGoMarnakGUID; + + void OpenDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_ACTIVE); + } + + void CloseDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_READY); + } void Initialize() { - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - - m_uiBrannGUID = 0; - m_uiKaddrakGUID = 0; - m_uiAbedneumGUID = 0; - m_uiMarnakGUID = 0; - - m_uiSjonnirDoorGUID = 0; - m_uiTribunalDoorGUID = 0; - m_uiTribunalChestGUID = 0; - m_uiTribunalHeadRightGUID = 0; - m_uiTribunalHeadCenterGUID = 0; - m_uiTribunalHeadLeftGUID = 0; - m_uiTribunalConsoleGUID = 0; - m_uiTribunalFloorGUID = 0; - m_uiSjonnirConsoleGUID = 0; + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + m_auiEncounter[i]=NOT_STARTED; + + m_uiKrystallusGUID = 0; + m_uiGriefGUID = 0; + m_uiBrannGUID = 0; + m_uiSjonnirGUID = 0; + + m_uiKaddrakGUID = 0; + m_uiAbedneumGUID = 0; + m_uiMarnakGUID = 0; + + m_uiGriefDoorGUID = 0; + m_uiBrannDoorGUID = 0; + m_uiSjonnirDoorGUID = 0; + + m_uiGoTribunalConsoleGUID = 0; + m_uiGoTribunalChestGUID = 0; + m_uiGoTribunalSkyFloorGUID = 0; + m_uiGoKaddrakGUID = 0; + m_uiGoAbedneumGUID = 0; + m_uiGoMarnakGUID = 0; } void OnCreatureCreate(Creature* pCreature) { switch(pCreature->GetEntry()) { + case NPC_KRYSTALLUS: + m_uiKrystallusGUID = pCreature->GetGUID(); + break; + case NPC_GRIEF: + m_uiGriefGUID = pCreature->GetGUID(); + break; case NPC_BRANN: m_uiBrannGUID = pCreature->GetGUID(); break; + case NPC_SJONNIR: + m_uiSjonnirGUID = pCreature->GetGUID(); + break; case NPC_KADDRAK: m_uiKaddrakGUID = pCreature->GetGUID(); break; @@ -88,67 +134,114 @@ struct MANGOS_DLL_DECL instance_halls_of_stone : public ScriptedInstance { switch(pGo->GetEntry()) { - case GO_DOOR_SJONNIR: + case GO_GRIEF_DOOR: + m_uiGriefDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[0] != DONE) + CloseDoor(m_uiGriefDoorGUID); + else OpenDoor(m_uiGriefDoorGUID); + break; + case GO_BRANN_DOOR: + m_uiBrannDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[1] != DONE) + CloseDoor(m_uiBrannDoorGUID); + else OpenDoor(m_uiBrannDoorGUID); + break; + case GO_SJONNIR_DOOR: m_uiSjonnirDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[2] != DONE) + CloseDoor(m_uiSjonnirDoorGUID); + else OpenDoor(m_uiSjonnirDoorGUID); break; - case GO_DOOR_TRIBUNAL: - m_uiTribunalDoorGUID = pGo->GetGUID(); + case GO_TRIBUNAL_CONSOLE: + m_uiGoTribunalConsoleGUID = pGo->GetGUID(); break; case GO_TRIBUNAL_CHEST: - case GO_TRIBUNAL_CHEST_H: - m_uiTribunalChestGUID = pGo->GetGUID(); - break; - case GO_TRIBUNAL_HEAD_RIGHT: - m_uiTribunalHeadRightGUID = pGo->GetGUID(); + if (Regular) m_uiGoTribunalChestGUID = pGo->GetGUID(); break; - case GO_TRIBUNAL_HEAD_CENTER: - m_uiTribunalHeadCenterGUID = pGo->GetGUID(); + case GO_TRIBUNAL_CHEST_H: + if (!Regular) m_uiGoTribunalChestGUID = pGo->GetGUID(); break; - case GO_TRIBUNAL_HEAD_LEFT: - m_uiTribunalHeadLeftGUID = pGo->GetGUID(); + case GO_TRIBUNAL_SKY_FLOOR: + m_uiGoTribunalSkyFloorGUID = pGo->GetGUID(); break; - case GO_TRIBUNAL_CONSOLE: - m_uiTribunalConsoleGUID = pGo->GetGUID(); + case GO_KADDRAK: + m_uiGoKaddrakGUID = pGo->GetGUID(); break; - case GO_TRIBUNAL_FLOOR: - m_uiTribunalFloorGUID = pGo->GetGUID(); + case GO_ABEDNEUM: + m_uiGoAbedneumGUID = pGo->GetGUID(); break; - case GO_SJONNIR_CONSOLE: - m_uiSjonnirConsoleGUID = pGo->GetGUID(); + case GO_MARNAK: + m_uiGoMarnakGUID = pGo->GetGUID(); break; } } + void OnPlayerEnter(Unit* pPlayer) + { + if (m_auiEncounter[0] != DONE) + CloseDoor(m_uiGriefDoorGUID); + else OpenDoor(m_uiGriefDoorGUID); + if (m_auiEncounter[1] != DONE) + CloseDoor(m_uiBrannDoorGUID); + else OpenDoor(m_uiBrannDoorGUID); + if (m_auiEncounter[2] != DONE) + CloseDoor(m_uiSjonnirDoorGUID); + else OpenDoor(m_uiSjonnirDoorGUID); + } + void SetData(uint32 uiType, uint32 uiData) { switch(uiType) { - case TYPE_TRIBUNAL: - m_auiEncounter[0] = uiData; + case TYPE_KRYSTALLUS: if (uiData == DONE) - DoRespawnGameObject(m_uiTribunalChestGUID); + OpenDoor(m_uiGriefDoorGUID); + m_auiEncounter[0] = uiData; break; - case TYPE_MAIDEN: + case TYPE_GRIEF: + if (uiData == DONE) + OpenDoor(m_uiBrannDoorGUID); m_auiEncounter[1] = uiData; break; - case TYPE_KRYSTALLUS: + case TYPE_BRANN: + if (uiData == DONE) + { + OpenDoor(m_uiSjonnirDoorGUID); + DoRespawnGameObject(m_uiGoTribunalChestGUID); + OpenDoor(m_uiGoTribunalChestGUID); + } m_auiEncounter[2] = uiData; break; case TYPE_SJONNIR: m_auiEncounter[3] = uiData; break; } + if (uiData == DONE) + { + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + saveStream << m_auiEncounter[i] << " "; + + strSaveData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } + } uint32 GetData(uint32 uiType) { switch(uiType) { - case TYPE_TRIBUNAL: + case TYPE_KRYSTALLUS: return m_auiEncounter[0]; - case TYPE_MAIDEN: + case TYPE_GRIEF: return m_auiEncounter[1]; - case TYPE_KRYSTALLUS: + case TYPE_BRANN: return m_auiEncounter[2]; case TYPE_SJONNIR: return m_auiEncounter[3]; @@ -160,36 +253,62 @@ struct MANGOS_DLL_DECL instance_halls_of_stone : public ScriptedInstance { switch(uiData) { - case NPC_BRANN: + case DATA_KRYSTALLUS: + return m_uiKrystallusGUID; + case DATA_GRIEF: + return m_uiGriefGUID; + case DATA_BRANN: return m_uiBrannGUID; - case NPC_KADDRAK: + case DATA_SJONNIR: + return m_uiSjonnirGUID; + case DATA_KADDRAK: return m_uiKaddrakGUID; - case NPC_ABEDNEUM: + case DATA_ABEDNEUM: return m_uiAbedneumGUID; - case NPC_MARNAK: + case DATA_MARNAK: return m_uiMarnakGUID; - case GO_DOOR_SJONNIR: - return m_uiSjonnirDoorGUID; - case GO_DOOR_TRIBUNAL: - return m_uiTribunalDoorGUID; - case GO_TRIBUNAL_CHEST: - case GO_TRIBUNAL_CHEST_H: - return m_uiTribunalChestGUID; - case GO_TRIBUNAL_HEAD_RIGHT: - return m_uiTribunalHeadRightGUID; - case GO_TRIBUNAL_HEAD_CENTER: - return m_uiTribunalHeadCenterGUID; - case GO_TRIBUNAL_HEAD_LEFT: - return m_uiTribunalHeadLeftGUID; - case GO_TRIBUNAL_CONSOLE: - return m_uiTribunalConsoleGUID; - case GO_TRIBUNAL_FLOOR: - return m_uiTribunalFloorGUID; - case GO_SJONNIR_CONSOLE: - return m_uiSjonnirConsoleGUID; + case DATA_GO_TRIBUNAL_CONSOLE: + return m_uiGoTribunalConsoleGUID; + case DATA_GO_SKY_FLOOR: + return m_uiGoTribunalSkyFloorGUID; + case DATA_GO_KADDRAK: + return m_uiGoKaddrakGUID; + case DATA_GO_ABEDNEUM: + return m_uiGoAbedneumGUID; + case DATA_GO_MARNAK: + return m_uiGoMarnakGUID; } return 0; } + + const char* Save() + { + return strSaveData.c_str(); + } + + void Load(const char* chrIn) + { + if (!chrIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + loadStream >> m_auiEncounter[i]; + + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + } + }; InstanceData* GetInstanceData_instance_halls_of_stone(Map* pMap) @@ -205,3 +324,4 @@ void AddSC_instance_halls_of_stone() newscript->GetInstanceData = &GetInstanceData_instance_halls_of_stone; newscript->RegisterSelf(); } + diff --git a/scripts/northrend/ulduar/ulduar/boss_algalon.cpp b/scripts/northrend/ulduar/ulduar/boss_algalon.cpp index 9758b5e..7a3d729 100644 --- a/scripts/northrend/ulduar/ulduar/boss_algalon.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_algalon.cpp @@ -1,58 +1,921 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_algalon -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: cosmic smash, phase punch, black hole phasing need some core support SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_INTRO_1 = -1603106, - SAY_INTRO_2 = -1603107, - SAY_INTRO_3 = -1603108, + SAY_INTRO1 = -1603270, + SAY_INTRO2 = -1603271, + SAY_INTRO3 = -1603272, + SAY_ENGAGE = -1603141, + SAY_AGGRO = -1603140, + SAY_SLAY1 = -1603145, + SAY_SLAY2 = -1603146, + SAY_SUMMON_STAR = -1603148, + SAY_BIGBANG1 = -1603142, + SAY_BIGBANG2 = -1603143, + SAY_PHASE2 = -1603144, + SAY_BERSERK = -1603147, + SAY_DESPAWN1 = -1603273, + SAY_DESPAWN2 = -1603274, + SAY_DESPAWN3 = -1603275, + SAY_OUTRO1 = -1603276, + SAY_OUTRO2 = -1603277, + SAY_OUTRO3 = -1603278, + SAY_OUTRO4 = -1603149, + SAY_OUTRO5 = -1603279, - SAY_ENGAGE = -1603109, - SAY_AGGRO = -1603110, - SAY_SLAY_1 = -1603111, - SAY_SLAY_2 = -1603112, - SAY_SUMMON_STAR = -1603113, - SAY_BIG_BANG_1 = -1603114, - SAY_BIG_BANG_2 = -1603115, - SAY_PHASE_2 = -1603116, - SAY_BERSERK = -1603117, + ITEM_PLANETARIUM_KEY = 45796, + ITEM_PLANETARIUM_KEY_H = 45798, - SAY_DESPAWN_1 = -1603118, - SAY_DESPAWN_2 = -1603119, - SAY_DESPAWN_3 = -1603120, + SPELL_ALGALON_EVENT_BEAM = 64367, + SPELL_ALGALON_EVENT_CLIMAX = 64580, // This spells are used for environment - SAY_OUTRO_1 = -1603121, - SAY_OUTRO_2 = -1603122, - SAY_OUTRO_3 = -1603123, - SAY_OUTRO_4 = -1603124, - SAY_OUTRO_5 = -1603125, + //spells to be casted + SPELL_QUANTUM_STRIKE = 64395, //Normal Quantum Strike + SPELL_QUANTUM_STRIKE_H = 64592, //Heroic Quantum Strike + SPELL_PHASE_PUNCH = 64412, //Phase punch + SPELL_PHASE_PUNCH_SHIFT = 64417, + SPELL_CONSTELLATION_TRIGGER = 65508, // this should make the space effect + SPELL_COSMIC_SMASH = 62301, //Normal Cosmic Smash + SPELL_COSMIC_SMASH_H = 64598, //Heroic Cosmic Smash + SPELL_COSMIC_SMASH_MISSILE = 62304, + SPELL_BIG_BANG = 64443, //Normal Big Bang + SPELL_BIG_BANG_H = 64584, //Heroic Big Bang + SPELL_ASCEND = 64487, //Ascend to the Heavens + SPELL_BERSERK = 47008, //Berserk + NPC_SMASH_TARGET_DUMMY = 33105, + // mobs + NPC_COLLAPSING_STAR = 32955, // they lose 1%hp per sec & cast black hole explosion when they die -> leave a black hole + SPELL_BLACK_HOLE_EXPLOSION = 64122, + SPELL_BLACK_HOLE_EXPLOSION_H = 65108, + SPELL_BLACK_HOLE_DESPAWN = 64391, // dummy spell + SPELL_SUMMON_BLACK_HOLE = 62189, + SPELL_BLACK_HOLE_VISUAL = 64135, + SPELL_BLACK_HOLE_SPAWN = 62003, + SPELL_BLACK_HOLE_TRIGG = 62185, // shifts the phase + SPELL_BLACK_HOLE_SHIFT = 62168, + SPELL_BLACK_HOLE_DMG = 62169, + + NPC_BLACK_HOLE = 32953, // players must stay inside to avoid big bang + + NPC_LIVING_CONSTELLATION = 33052, // if one enters a black hole they are despawned + SPELL_ARCANE_BARRAGE = 64599, //Arcane Barage + SPELL_ARCANE_BARRAGE_H = 64607, //Heroic Arcane Barage? + + NPC_DARK_MATTER = 33089, // populates the black holes + NPC_UNLEASHED_DARK_MATTER = 34097, // summoned by black holes in phase 2 + NPC_COSMIC_SMASH = 33104, + + ACHIEV_FEED_TEARS = 3004, + ACHIEV_FEED_TEARS_H = 3005, // nobody dies in the raid lockout + ACHIEV_HERALD_OF_TITANS = 3316, + ACHIEV_OBSERVED = 3036, + ACHIEV_OBSERVED_H = 3037, + ACHIEV_SUPERMASSIVE = 3003, + ACHIEV_SUPERMASSIVE_H = 3002, + + UI_STATE_ALGALON_TIMER_ON = 4132, + UI_STATE_ALGALON_TIMER_COUNT = 4131, }; -void AddSC_boss_algalon() +//Positional defines +struct LocationsXY +{ + float x, y; + uint32 id; +}; + +static LocationsXY PositionLoc[]= +{ + {1620, -320.75f}, + {1620, -290.75f }, + {1645.5f, -290.75f }, + {1645.5f, -320.75f }, +}; + +//Black hole +struct MANGOS_DLL_DECL mob_black_holeAI : public ScriptedAI +{ + mob_black_holeAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + + bool m_bHasAura; + uint32 m_uiRaidCheckTimer; + bool m_bIsPhase2; + uint32 m_uiSummonTimer; + + void Reset() + { + m_bHasAura = false; + m_uiRaidCheckTimer = 1000; + m_bIsPhase2 = false; + m_uiSummonTimer = 5000; + DoCast(m_creature, SPELL_BLACK_HOLE_SPAWN); + m_creature->SetRespawnDelay(DAY); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_ALGALON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // summon unleashed dark matter in phase 2 + if (m_uiSummonTimer < uiDiff && m_bIsPhase2) + { + if(Creature* pTemp = m_creature->SummonCreature(NPC_UNLEASHED_DARK_MATTER, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + pTemp->SetInCombatWithZone(); + m_uiSummonTimer = urand(10000, 15000); + } + else m_uiSummonTimer -= uiDiff; + + // phase players into the void + if (m_uiRaidCheckTimer < uiDiff && !m_bIsPhase2) + { + if(!m_bHasAura) + { + DoCast(m_creature, SPELL_BLACK_HOLE_TRIGG); + m_bHasAura = true; + } + + if(Creature *pConstellation = GetClosestCreatureWithEntry(m_creature, NPC_LIVING_CONSTELLATION, 2)) + { + pConstellation->DealDamage(pConstellation, pConstellation->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + m_uiRaidCheckTimer = 500; + } + else m_uiRaidCheckTimer -= uiDiff; + } +}; + +//Algalon +struct MANGOS_DLL_DECL boss_algalonAI : public ScriptedAI +{ + boss_algalonAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bHasStarted = false; // flag used to check if the encounter has been started from the console + m_bIsInProgress = false; // flag used for time counter + m_bIsFirstTime = true; // flag used to show if this is the first aggro + m_uiDespawnTimer = 3600000; // 1h; + m_uiLastTimer = 3600000; // 1h; + m_bFeedOnTears = true; // flag used to check the Fead on Tears achiev + pCreature->SetVisibility(VISIBILITY_OFF); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiBerserk_Timer; + uint32 m_uiBigBang_Timer; + uint32 m_uiCosmicSmash_Timer; + uint32 m_uiPhasePunch_Timer; + uint32 m_uiQuantumStrike_Timer; + uint32 m_uiCollapsingStar_Timer; + uint32 m_uiLivingConstellationTimer; + uint32 m_uiRaidCheckTimer; + uint32 m_uiDarkMaterTimer; + uint32 m_uiDespawnTimer; + uint32 m_uiLastTimer; + + // intro & outro + bool m_bIsOutro; + uint32 m_uiOutroTimer; + uint32 m_uiOutroStep; + bool m_bIsIntro; + uint32 m_uiIntroTimer; + uint32 m_uiIntroStep; + + bool m_bHasStarted; + bool m_bIsFirstTime; + bool m_bIsInProgress; + + uint8 m_uiCombatPhase; + bool m_bIsPhase2; + + bool m_bIsDespawned; + bool m_bFeedOnTears; + + void Reset() + { + m_uiQuantumStrike_Timer = 4000 + rand()%10000; + m_uiBerserk_Timer = 360000; //6 minutes + m_uiCollapsingStar_Timer = urand(15000, 20000); //Spawns between 15 to 20 seconds + m_uiLivingConstellationTimer = 60000; + m_uiBigBang_Timer = 90000; + m_uiDarkMaterTimer = 90000; + m_uiPhasePunch_Timer = 8000; + m_uiCosmicSmash_Timer = urand(30000, 60000); + m_uiRaidCheckTimer = 1000; + + m_uiCombatPhase = 0; // it's 0 for idle, 1 for intro and 2 for combat + m_bIsPhase2 = false; // flag used below 30% hp + + m_uiOutroTimer = 10000; + m_uiOutroStep = 1; + m_bIsIntro = true; + m_uiIntroTimer = 10000; + m_uiIntroStep = 1; + m_bIsOutro = false; + + m_bIsDespawned = false; // flaged used to show that time has run out + } + + void KilledUnit(Unit *victim) + { + switch(urand(0, 1)) + { + case 0: DoScriptText(SAY_SLAY1, m_creature); break; + case 1: DoScriptText(SAY_SLAY2, m_creature); break; + } + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_ALGALON, NOT_STARTED); + m_bIsFirstTime = false; + } + + void DoOutro() + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_ALGALON, DONE); + m_pInstance->DoUpdateWorldState(UI_STATE_ALGALON_TIMER_ON, 0); + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_OBSERVED : ACHIEV_OBSERVED_H); + + if(m_bFeedOnTears) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_FEED_TEARS : ACHIEV_FEED_TEARS_H); + } + + m_creature->ForcedDespawn(); + } + + void AttackStart(Unit* pWho) + { + if(!m_bIsInProgress) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho); + } + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!pWho) + return; + + if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(pWho) && + pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 40) && m_uiCombatPhase == 0 && m_bHasStarted && m_bIsFirstTime) + m_uiCombatPhase = 1; + } + + void StartEncounter() + { + m_creature->SetVisibility(VISIBILITY_ON); + m_bIsFirstTime = true; + m_bHasStarted = true; + m_bIsInProgress = false; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(m_creature->GetHealthPercent() < 1.0f) + { + uiDamage = 0; + m_bIsOutro = true; + } + } + + void SummonCreature(uint32 m_uiCreatureEntry) + { + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = 1630.475f + urand(15, 30)*cos(angle*(M_PI/180)); + float homeY = -286.989f + urand(15, 30)*sin(angle*(M_PI/180)); + if(Creature* pTemp = m_creature->SummonCreature(m_uiCreatureEntry, homeX, homeY, 417.32f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->SetInCombatWithZone(); + if(pTemp->GetEntry() == NPC_DARK_MATTER) + pTemp->CastSpell(pTemp, SPELL_BLACK_HOLE_SHIFT, false); + } + } + + void Aggro(Unit* pWho) + { + // set combat phase + m_uiCombatPhase = 2; + + if(m_bIsFirstTime) + { + m_bIsInProgress = true; + DoScriptText(SAY_ENGAGE, m_creature); + if(m_pInstance) + { + m_pInstance->DoUpdateWorldState(UI_STATE_ALGALON_TIMER_ON, 1); + m_pInstance->DoUpdateWorldState(UI_STATE_ALGALON_TIMER_COUNT, m_uiDespawnTimer / 60000); + } + } + else + DoScriptText(SAY_AGGRO, m_creature); + + m_creature->SetInCombatWithZone(); + DoCast(m_creature, SPELL_CONSTELLATION_TRIGGER); + + if (m_pInstance) + m_pInstance->SetData(TYPE_ALGALON, IN_PROGRESS); + } + + void UpdateAI(const uint32 uiDiff) + { + // despawn timer + if(m_uiDespawnTimer < uiDiff && !m_bIsDespawned && m_bIsInProgress) + { + m_bIsDespawned = true; + m_bIsOutro = true; + m_bIsInProgress = false; + } + else m_uiDespawnTimer -= uiDiff; + + // update world state + if(m_uiDespawnTimer < m_uiLastTimer - 60000 && !m_bIsDespawned) + { + m_uiLastTimer = m_uiDespawnTimer; + uint32 tMinutes = m_uiDespawnTimer / 60000; + if(m_pInstance) + m_pInstance->DoUpdateWorldState(UI_STATE_ALGALON_TIMER_COUNT, tMinutes); + } + + if(!m_bIsOutro) + { + // intro + if(m_uiCombatPhase == 1) + { + if(m_bIsIntro && m_bIsFirstTime) + { + switch(m_uiIntroStep) + { + case 1: + DoScriptText(SAY_INTRO1, m_creature); + ++m_uiIntroStep; + m_uiIntroTimer = 8000; + break; + case 3: + DoScriptText(SAY_INTRO2, m_creature); + ++m_uiIntroStep; + m_uiIntroTimer = 6000; + break; + case 5: + DoScriptText(SAY_INTRO3, m_creature); + ++m_uiIntroStep; + m_uiIntroTimer = 10000; + break; + case 7: + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsIntro = false; + ++m_uiIntroStep; + m_uiIntroTimer = 10000; + break; + } + } + else return; + + if (m_uiIntroTimer <= uiDiff) + { + ++m_uiIntroStep; + m_uiIntroTimer = 330000; + } m_uiIntroTimer -= uiDiff; + } + + // combat + if(m_uiCombatPhase == 2) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // spells + if(m_uiQuantumStrike_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_QUANTUM_STRIKE : SPELL_QUANTUM_STRIKE_H); + m_uiQuantumStrike_Timer = 4000 + rand()%10000; + }else m_uiQuantumStrike_Timer -= uiDiff; + + if(m_uiBigBang_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_BIG_BANG : SPELL_BIG_BANG_H); + m_uiBigBang_Timer = 90000; + m_uiDarkMaterTimer = 1000; + }else m_uiBigBang_Timer -= uiDiff; + + if(m_uiCosmicSmash_Timer < uiDiff) + { + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_COSMIC_SMASH : SPELL_COSMIC_SMASH_H); + m_uiCosmicSmash_Timer = urand(30000, 60000); + }else m_uiCosmicSmash_Timer -= uiDiff; + + if(m_uiPhasePunch_Timer < uiDiff) + { + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget,SPELL_PHASE_PUNCH); + m_uiPhasePunch_Timer = 15000; + }else m_uiPhasePunch_Timer -= uiDiff; + + // hack, phase punch needs core support + // PLEASE REMOVE FOR REVISION! + if(m_uiRaidCheckTimer < uiDiff) + { + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_PHASE_PUNCH, EFFECT_INDEX_0)) + { + Aura *phasePunch = i->getSource()->GetAura(SPELL_PHASE_PUNCH, EFFECT_INDEX_0); + if(phasePunch->GetStackAmount() > 4) + { + i->getSource()->RemoveAurasDueToSpell(SPELL_PHASE_PUNCH); + i->getSource()->CastSpell(i->getSource(), SPELL_PHASE_PUNCH_SHIFT, false); + } + } + if (!i->getSource()->isAlive()) + m_bFeedOnTears = false; + } + } + m_uiRaidCheckTimer = 1000; + }else m_uiRaidCheckTimer -= uiDiff; + + // berserk + if(m_uiBerserk_Timer < uiDiff) + { + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserk_Timer = 360000; + }else m_uiBerserk_Timer -= uiDiff; + + // summons + if(m_uiCollapsingStar_Timer < uiDiff && !m_bIsPhase2) + { + DoScriptText(SAY_SUMMON_STAR, m_creature); + SummonCreature(NPC_COLLAPSING_STAR); + m_uiCollapsingStar_Timer = urand(15000, 20000); + }else m_uiCollapsingStar_Timer -= uiDiff; + + if(m_uiLivingConstellationTimer < uiDiff && !m_bIsPhase2) + { + for(uint8 i = 0; i < urand (1, 3); i++) + SummonCreature(NPC_LIVING_CONSTELLATION); + m_uiLivingConstellationTimer = 30000; + }else m_uiLivingConstellationTimer -= uiDiff; + + if(m_uiDarkMaterTimer < uiDiff && !m_bIsPhase2) + { + for(uint8 i = 0; i < 7; i++) + SummonCreature(NPC_DARK_MATTER); + m_uiDarkMaterTimer = 90000; + }else m_uiDarkMaterTimer -= uiDiff; + + // hp check -> start phase 2 + if(!m_bIsPhase2 && m_creature->GetHealthPercent() < 20) + { + DoScriptText(SAY_PHASE2, m_creature); + m_bIsPhase2 = true; + + std::list lAdds; + GetCreatureListWithEntryInGrid(lAdds, m_creature, NPC_COLLAPSING_STAR, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lAdds, m_creature, NPC_BLACK_HOLE, DEFAULT_VISIBILITY_INSTANCE); + + if (!lAdds.empty()) + { + for(std::list::iterator iter = lAdds.begin(); iter != lAdds.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); + } + } + + for (uint8 i = 0; i < 4; ++i) + { + if(Creature* pTemp = m_creature->SummonCreature(NPC_BLACK_HOLE, PositionLoc[i].x, PositionLoc[i].y, m_creature->GetPositionZ(), 0, TEMPSUMMON_MANUAL_DESPAWN, 0)) + ((mob_black_holeAI*)pTemp->AI())->m_bIsPhase2 = true; + } + } + + DoMeleeAttackIfReady(); + + EnterEvadeIfOutOfCombatArea(uiDiff); + } + } + // outro: both for defeat and despawn + if(m_bIsOutro) + { + switch(m_uiOutroStep) + { + case 1: + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->GetMotionMaster()->MovePoint(0, 1631.970f, -302.635f, 417.321f); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + ++m_uiOutroStep; + m_uiOutroTimer = 5000; + break; + case 3: + // make boss kneel + m_creature->SetSplineFlags(SPLINEFLAG_UNKNOWN12); + if(m_bIsDespawned) + { + DoScriptText(SAY_DESPAWN1, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 15000; + } + else + { + DoScriptText(SAY_OUTRO1, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 37000; + } + break; + case 5: + if(m_bIsDespawned) + { + DoScriptText(SAY_DESPAWN2, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 8000; + } + else + { + DoScriptText(SAY_OUTRO2, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 17000; + } + break; + case 7: + if(m_bIsDespawned) + { + DoScriptText(SAY_DESPAWN3, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 7000; + } + else + { + DoScriptText(SAY_OUTRO3, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 12000; + } + break; + case 9: + if(m_bIsDespawned) + { + DoCast(m_creature, SPELL_ASCEND); + ++m_uiOutroStep; + m_uiOutroTimer = 5000; + } + else + { + DoScriptText(SAY_OUTRO4, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 11000; + } + break; + case 11: + if(m_bIsDespawned) + { + if(m_pInstance) + { + m_pInstance->DoUpdateWorldState(UI_STATE_ALGALON_TIMER_ON, 0); + m_pInstance->SetData(TYPE_ALGALON, FAIL); + } + m_creature->ForcedDespawn(); + } + else + { + DoScriptText(SAY_OUTRO5, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 13000; + } + break; + case 13: + DoOutro(); + ++m_uiOutroStep; + m_uiOutroTimer = 10000; + break; + } + } + else + return; + + if (m_uiOutroTimer <= uiDiff) + { + ++m_uiOutroStep; + m_uiOutroTimer = 330000; + } m_uiOutroTimer -= uiDiff; + } +}; + +//Collapsing Star +struct MANGOS_DLL_DECL mob_collapsing_starAI : public ScriptedAI +{ + mob_collapsing_starAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiHealthTimer; + uint32 m_uiDieTimer; + uint32 m_uiSummonTimer; + + void Reset() + { + m_uiHealthTimer = 1000; + m_uiDieTimer = 600000; + m_uiSummonTimer = 600000; + m_creature->SetRespawnDelay(DAY); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if(uiDamage > m_creature->GetHealth()) + { + uiDamage = 0; + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_uiDieTimer = 1500; + m_uiSummonTimer = 1000; + DoCast(m_creature, m_bIsRegularMode ? SPELL_BLACK_HOLE_EXPLOSION : SPELL_BLACK_HOLE_EXPLOSION_H); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_ALGALON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSummonTimer < uiDiff) + { + DoCast(m_creature, SPELL_SUMMON_BLACK_HOLE); + m_uiSummonTimer = 60000; + } + else m_uiSummonTimer -= uiDiff; + + if (m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else + m_uiDieTimer -= uiDiff; + + // movement should be improved + // npc should ignore threat tables + if(m_uiHealthTimer < uiDiff && m_creature->GetHealthPercent() > 1.0f) + { + m_creature->GetMotionMaster()->MoveConfused(); + m_creature->DealDamage(m_creature, (m_creature->GetMaxHealth() * 0.01), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_uiHealthTimer = 1000; + }else m_uiHealthTimer -= uiDiff; + } +}; + +//Living constellation +struct MANGOS_DLL_DECL mob_living_constellationAI : public ScriptedAI +{ + mob_living_constellationAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiArcaneBarrageTimer; + + void Reset() + { + m_uiArcaneBarrageTimer = 15000; + m_creature->SetRespawnDelay(DAY); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_ALGALON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiArcaneBarrageTimer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)){ + DoCast(target, m_bIsRegularMode ? SPELL_ARCANE_BARRAGE : SPELL_ARCANE_BARRAGE_H); + } + m_uiArcaneBarrageTimer = 15000; + }else m_uiArcaneBarrageTimer -= uiDiff; + } +}; + +struct MANGOS_DLL_DECL mob_cosmic_smash_targetAI : public ScriptedAI +{ + mob_cosmic_smash_targetAI(Creature *pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->SetDisplayId(11686); // make invisible + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiSpellTimer; + + void Reset() + { + m_uiSpellTimer = 5000; + m_creature->SetRespawnDelay(DAY); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_ALGALON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpellTimer < uiDiff) + { + DoCast(m_creature, SPELL_COSMIC_SMASH_MISSILE); + m_uiSpellTimer = 60000; + }else m_uiSpellTimer -= uiDiff; + } +}; + + +bool GOHello_go_celestial_acces(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* m_pInstance = (ScriptedInstance*)pGo->GetInstanceData(); + bool m_bIsRegularMode = pGo->GetMap()->IsRegularDifficulty(); + bool m_bHasItem = false; + + // check if the player has the key + if (m_bIsRegularMode) + { + if(pPlayer->HasItemCount(ITEM_PLANETARIUM_KEY, 1) || pPlayer->HasItemCount(ITEM_PLANETARIUM_KEY_H, 1)) + m_bHasItem = true; + } + else + { + if(pPlayer->HasItemCount(ITEM_PLANETARIUM_KEY_H, 1)) + m_bHasItem = true; + } + + if(!m_bHasItem) + return false; + + if (!m_pInstance) + return false; + + // disable if encounter is already done + if (m_pInstance->GetData(TYPE_ALGALON) == DONE) + { + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + return false; + } + + // start encounter + if (Creature* pAlgalon = pGo->GetMap()->GetCreature(m_pInstance->GetData64(NPC_ALGALON))) + { + if(pAlgalon->isAlive()) + { + ((boss_algalonAI*)pAlgalon->AI())->StartEncounter(); + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + + // open celestial door + if(GameObject* pDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_CELESTIAL_DOOR))) + m_pInstance->DoUseDoorOrButton(pDoor->GetGUID()); + } + } + + return false; +} + +CreatureAI* GetAI_boss_algalon(Creature* pCreature) +{ + return new boss_algalonAI(pCreature); +} + +CreatureAI* GetAI_mob_collapsing_star(Creature* pCreature) { + return new mob_collapsing_starAI(pCreature); +} + +CreatureAI* GetAI_mob_living_constellation(Creature* pCreature) +{ + return new mob_living_constellationAI(pCreature); +} +CreatureAI* GetAI_mob_cosmic_smash_target(Creature* pCreature) +{ + return new mob_cosmic_smash_targetAI(pCreature); +} + +CreatureAI* GetAI_mob_black_hole(Creature* pCreature) +{ + return new mob_black_holeAI(pCreature); } + +void AddSC_boss_algalon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_algalon"; + newscript->GetAI = &GetAI_boss_algalon; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_collapsing_star"; + newscript->GetAI = &GetAI_mob_collapsing_star; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_living_constellation"; + newscript->GetAI = &GetAI_mob_living_constellation; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_cosmic_smash_target"; + newscript->GetAI = &GetAI_mob_cosmic_smash_target; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_black_hole"; + newscript->GetAI = &GetAI_mob_black_hole; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "go_celestial_acces"; + newscript->pGOHello = &GOHello_go_celestial_acces; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp b/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp index 95b0c7a..c6f129c 100644 --- a/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp @@ -1,41 +1,564 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_auriaya -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: need correct setstack for feral defender buff SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_AGGRO = -1603079, - SAY_SLAY_1 = -1603080, - SAY_SLAY_2 = -1603081, - SAY_BERSERK = -1603082, - SAY_DEATH = -1603083, - EMOTE_SCREECH = -1603084, - EMOTE_DEFENDER = -1603085, + //yells + SAY_AGGRO = -1603070, + SAY_SLAY1 = -1603071, + SAY_SLAY2 = -1603072, + SAY_BERSERK = -1603073, + SAY_DEATH = -1603074, + EMOTE_SCREECH = -1603358, + EMOTE_DEFENDER = -1603359, + + //auriaya + SPELL_BERSERK = 47008, + SPELL_GUARDIAN_SWARM = 64396, // broken + SPELL_SENTINEL_BLAST = 64389, + SPELL_SENTINEL_BLAST_H = 64678, + SPELL_SONIC_SCREECH = 64422, + SPELL_SONIC_SCREECH_H = 64688, + SPELL_FEAR = 64386, + + //feral defender + SPELL_FEIGN_DEATH = 57685, + SPELL_FERAL_ESSENCE = 64455, + SPELL_FERAL_POUNCE = 64478, + SPELL_FERAL_POUNCE_H = 64669, + SPELL_FERAL_RUSH = 64496, + SPELL_FERAL_RUSH_H = 64674, + + //sanctum sentry + SPELL_RIP_FLESH = 64375, + SPELL_RIP_FLESH_H = 64667, + SPELL_SAVAGE_POUNCE = 64666, + SPELL_SAVAGE_POUNCE_H = 64374, + SPELL_STRENGHT_OF_PACK = 64369, + //seeping feral essence + AURA_VOID_ZONE = 64458, + AURA_VOID_ZONE_H = 64676, + //NPC ids + MOB_VOID_ZONE = 34098, + MOB_FERAL_DEFENDER = 34035, + MOB_GUARDIAN_SWARN = 34034, + + ACHIEV_CRAZY_CAT_LADY = 3006, + ACHIEV_CRAZY_CAT_LADY_H = 3007, + + ACHIEV_NINE_LIVES = 3076, + ACHIEV_NINE_LIVES_H = 3077, }; -void AddSC_boss_auriaya() +bool m_bCrazyCatLady; +bool m_bNineLives; + +// Seeping Feral Essence +struct MANGOS_DLL_DECL mob_seeping_feral_essenceAI : public ScriptedAI { + mob_seeping_feral_essenceAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + pCreature->setFaction(14); + pCreature->SetDisplayId(11686); // make invisible + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + void Reset() + { + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, m_bIsRegularMode ? AURA_VOID_ZONE : AURA_VOID_ZONE_H); + m_creature->SetRespawnDelay(DAY); + } + void UpdateAI(const uint32 diff) + { + } +}; + +CreatureAI* GetAI_mob_seeping_feral_essence(Creature* pCreature) +{ + return new mob_seeping_feral_essenceAI(pCreature); } + +// Sanctum Sentry +struct MANGOS_DLL_DECL mob_sanctum_sentryAI : public ScriptedAI +{ + mob_sanctum_sentryAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiRip_Flesh_Timer; + uint32 m_uiJump_Timer; + + std::list lSentrys; + + void Reset() + { + m_uiRip_Flesh_Timer = 13000; + m_uiJump_Timer = 0; + + lSentrys.clear(); + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_AURIAYA))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + } + + GetCreatureListWithEntryInGrid(lSentrys, m_creature, NPC_SANCTUM_SENTRY, DEFAULT_VISIBILITY_INSTANCE); + if (!lSentrys.empty()) + { + for(std::list::iterator iter = lSentrys.begin(); iter != lSentrys.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->SetInCombatWithZone(); + } + } + + DoCast(m_creature, SPELL_STRENGHT_OF_PACK); + } + + void JustDied(Unit* pKiller) + { + m_bCrazyCatLady = false; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + { + // they should follow Auriaya, but this looks ugly! + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_AURIAYA))) + { + if (pTemp->isAlive()) + { + m_creature->GetMotionMaster()->MoveFollow(pTemp,0.0f,0.0f); + m_creature->GetMap()->CreatureRelocation(m_creature, pTemp->GetPositionX(), pTemp->GetPositionY(), pTemp->GetPositionZ(), 0.0f); + } + } + } + + if (m_uiRip_Flesh_Timer < diff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_RIP_FLESH : SPELL_RIP_FLESH_H); + m_uiRip_Flesh_Timer = 13000; + }else m_uiRip_Flesh_Timer -= diff; + + if (m_uiJump_Timer < diff) + { + if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 8) && m_creature->IsWithinDistInMap(m_creature->getVictim(), 25)) + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SAVAGE_POUNCE : SPELL_SAVAGE_POUNCE_H); + m_uiJump_Timer = 1000; + }else m_uiJump_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_sanctum_sentry(Creature* pCreature) +{ + return new mob_sanctum_sentryAI(pCreature); +} + +// Feral Defender +struct MANGOS_DLL_DECL mob_feral_defenderAI : public ScriptedAI +{ + mob_feral_defenderAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiPounce_Timer; + uint32 m_uiRush_Start_Timer; + uint32 m_uiRush_Finish_Timer; + uint32 m_uiRush_Delay; + uint32 m_uiRevive_Delay; + + bool m_bIsRush; + bool m_bIsDead; + + bool m_bHasAura; + + void Reset() + { + m_uiPounce_Timer = 5000; + m_uiRush_Start_Timer = 9000; + m_bIsRush = false; + m_bIsDead = false; + m_bHasAura = false; + m_creature->SetRespawnDelay(DAY); + } + + void Aggro(Unit* pWho) + { + DoCast(m_creature, SPELL_FERAL_ESSENCE); + } + + void JustDied(Unit* pKiller) + { + m_bNineLives = true; + } + + // feign death + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage > m_creature->GetHealth()) + { + uiDamage = 0; + m_creature->CastStop(); + m_creature->RemoveArenaAuras(true); + m_creature->SummonCreature(MOB_VOID_ZONE, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_DEAD_DESPAWN, 0); + DoCast(m_creature, SPELL_FEIGN_DEATH); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (m_creature->HasAura(SPELL_FERAL_ESSENCE)) + { + // remove 1 stack of the aura + if(SpellAuraHolder* strenght = m_creature->GetSpellAuraHolder(SPELL_FERAL_ESSENCE)) + { + if(strenght->ModStackAmount(-1)) + m_creature->RemoveAurasDueToSpell(SPELL_FERAL_ESSENCE); + } + + m_uiRevive_Delay = 35000; + m_bIsDead = true; + } + } + } + + void UpdateAI(const uint32 diff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_AURIAYA) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // hacky way of stacking aura, needs fixing + if(SpellAuraHolder* essence = m_creature->GetSpellAuraHolder(SPELL_FERAL_ESSENCE)) + { + if(essence->GetStackAmount() < 9 && !m_bHasAura) + { + m_bHasAura = true; + essence->SetStackAmount(9); + } + } + + if (m_uiPounce_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCast(target, m_bIsRegularMode ? SPELL_FERAL_POUNCE : SPELL_FERAL_POUNCE_H); + m_creature->AddThreat(target,0.0f); + m_creature->AI()->AttackStart(target); + } + m_uiPounce_Timer = 5000; + }else m_uiPounce_Timer -= diff; + + if (m_uiRush_Start_Timer < diff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCast(target, m_bIsRegularMode ? SPELL_FERAL_RUSH : SPELL_FERAL_RUSH_H); + m_creature->AddThreat(target,0.0f); + m_creature->AI()->AttackStart(target); + } + m_uiRush_Start_Timer = 35000; + m_uiRush_Finish_Timer = m_bIsRegularMode ? 2500 : 5000; + m_uiRush_Delay = 500; + m_bIsRush = true; + }else m_uiRush_Start_Timer -= diff; + + if (m_uiRush_Delay < diff && m_bIsRush) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCast(target, m_bIsRegularMode ? SPELL_FERAL_RUSH : SPELL_FERAL_RUSH_H); + m_creature->AddThreat(target,0.0f); + m_creature->AI()->AttackStart(target); + } + m_uiRush_Delay = 500; + }else m_uiRush_Delay -= diff; + + if (m_uiRush_Finish_Timer < diff) + m_bIsRush = false; + else m_uiRush_Finish_Timer -= diff; + + if (m_uiRevive_Delay < diff && m_bIsDead) + { + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->RemoveAurasDueToSpell(SPELL_FEIGN_DEATH); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsDead = false; + }else m_uiRevive_Delay -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_feral_defender(Creature* pCreature) +{ + return new mob_feral_defenderAI(pCreature); +} + +// Auriaya +struct MANGOS_DLL_DECL boss_auriayaAI : public ScriptedAI +{ + boss_auriayaAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiEnrage_Timer; + uint32 m_uiSwarm_Timer; + uint32 m_uiSonic_Screech_Timer; + uint32 m_uiSentinel_Blast_Timer; + uint32 m_uiFear_Timer; + uint32 m_uiSummon_Timer; + uint8 m_uiSwarmcount; + + std::list lSentrys; + + bool m_bHasBerserk; + bool m_bIsDefender; + + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_uiEnrage_Timer = 600000; + m_uiSwarm_Timer = urand(50000, 60000); + m_uiSonic_Screech_Timer = urand(90000, 100000); + m_uiSentinel_Blast_Timer = 62000; + m_uiFear_Timer = 60000; + m_uiSummon_Timer = urand(60000, 70000); + m_uiSwarmcount = 10; + m_bHasBerserk = false; + m_bIsDefender = false; + + lSentrys.clear(); + + // achievs + m_bCrazyCatLady = true; + m_bNineLives = false; + } + + void JustDied(Unit* pKiller) + { + //death yell + DoScriptText(SAY_DEATH, m_creature); + + if (m_pInstance) + m_pInstance->SetData(TYPE_AURIAYA, DONE); + + // hacky way to complete achievements; use only if you have this function + if (m_bCrazyCatLady) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CRAZY_CAT_LADY : ACHIEV_CRAZY_CAT_LADY_H); + } + + if (m_bNineLives) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_NINE_LIVES : ACHIEV_NINE_LIVES_H); + } + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_AURIAYA, IN_PROGRESS); + + GetCreatureListWithEntryInGrid(lSentrys, m_creature, NPC_SANCTUM_SENTRY, DEFAULT_VISIBILITY_INSTANCE); + if (!lSentrys.empty()) + { + for(std::list::iterator iter = lSentrys.begin(); iter != lSentrys.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->SetInCombatWithZone(); + } + } + + DoScriptText(SAY_AGGRO, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_AURIAYA, FAIL); + + GetCreatureListWithEntryInGrid(lSentrys, m_creature, NPC_SANCTUM_SENTRY, DEFAULT_VISIBILITY_INSTANCE); + if (!lSentrys.empty()) + { + for(std::list::iterator iter = lSentrys.begin(); iter != lSentrys.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiFear_Timer < uiDiff) + { + DoScriptText(EMOTE_SCREECH, m_creature); + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_FEAR); + m_uiFear_Timer = 35000; + m_uiSentinel_Blast_Timer = 2500; + }else m_uiFear_Timer -= uiDiff; + + if (m_uiSentinel_Blast_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_SENTINEL_BLAST : SPELL_SENTINEL_BLAST_H); + m_uiSentinel_Blast_Timer = urand(30000, 40000); + }else m_uiSentinel_Blast_Timer -= uiDiff; + + if (m_uiSummon_Timer < uiDiff && !m_bIsDefender) + { + if (Creature* pTemp = m_creature->SummonCreature(MOB_FERAL_DEFENDER, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTemp->AddThreat(pTarget,0.0f); + pTemp->AI()->AttackStart(pTarget); + } + DoScriptText(EMOTE_DEFENDER, m_creature); + m_bIsDefender = true; + } + }else m_uiSummon_Timer -= uiDiff; + + if (m_uiSonic_Screech_Timer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SONIC_SCREECH : SPELL_SONIC_SCREECH_H); + m_uiSonic_Screech_Timer = 27000; + }else m_uiSonic_Screech_Timer -= uiDiff; + + // summon swarm, spell needs core fix + if (m_uiSwarm_Timer < uiDiff) + { + for(int i = 0; i < 10; i++) + { + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = m_creature->GetPositionX() + 10*cos(angle*(M_PI/180)); + float homeY = m_creature->GetPositionY() + 10*sin(angle*(M_PI/180)); + if (Creature* pTemp = m_creature->SummonCreature(MOB_GUARDIAN_SWARN, homeX, homeY, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCast(pTarget, SPELL_GUARDIAN_SWARM); + pTemp->AddThreat(pTarget, 100.0f); + pTemp->SetInCombatWithZone(); + } + } + } + m_uiSwarm_Timer = 35000; + }else m_uiSwarm_Timer -= uiDiff; + + if (m_uiEnrage_Timer < uiDiff && !m_bHasBerserk) + { + DoScriptText(SAY_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_BERSERK); + m_bHasBerserk = true; + }else m_uiEnrage_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_auriaya(Creature* pCreature) +{ + return new boss_auriayaAI(pCreature); +} + +void AddSC_boss_auriaya() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_auriaya"; + NewScript->GetAI = GetAI_boss_auriaya; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_seeping_feral_essence"; + NewScript->GetAI = &GetAI_mob_seeping_feral_essence; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_sanctum_sentry"; + NewScript->GetAI = &GetAI_mob_sanctum_sentry; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_feral_defender"; + NewScript->GetAI = &GetAI_mob_feral_defender; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_freya.cpp b/scripts/northrend/ulduar/ulduar/boss_freya.cpp index 4857334..816b4fe 100644 --- a/scripts/northrend/ulduar/ulduar/boss_freya.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_freya.cpp @@ -1,64 +1,1509 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_freya -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: aura stacking need core support after the recent aura changes SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_AGGRO = -1603000, - SAY_AGGRO_HARD = -1603001, - SAY_ADDS_CONSERVATOR = -1603002, - SAY_ADDS_TRIO = -1603003, - SAY_ADDS_LASHER = -1603004, - SAY_SLAY_1 = -1603005, - SAY_SLAY_2 = -1603006, - SAY_DEATH = -1603007, - SAY_BERSERK = -1603008, - SAY_HELP_YOGG = -1603009, - - EMOTE_ALLIES_NATURE = -1603010, - EMOTE_LIFEBINDER = -1603011, - EMOTE_TREMOR = -1603012, - EMOTE_IRON_ROOTS = -1603013, - - SAY_AGGRO_BRIGHT = -1603014, - SAY_SLAY_1_BRIGHT = -1603015, - SAY_SLAY_2_BRIGHT = -1603016, - SAY_DEATH_BRIGHT = -1603017, - - SAY_AGGRO_IRON = -1603018, - SAY_SLAY_1_IRON = -1603019, - SAY_SLAY_2_IRON = -1603020, - SAY_DEATH_IRON = -1603021, - - SAY_AGGRO_STONE = -1603022, - SAY_SLAY_1_STONE = -1603023, - SAY_SLAY_2_STONE = -1603024, - SAY_DEATH_STONE = -1603025, + /* YELLS */ + // freya + SAY_AGGRO = -1603000, + SAY_AGGRO_HARD = -1603001, + SAY_SUMMON1 = -1603002, + SAY_SUMMON2 = -1603003, + SAY_SUMMON3 = -1603004, + SAY_SLAY1 = -1603005, + SAY_SLAY2 = -1603006, + SAY_DEATH = -1603007, + SAY_BERSERK = -1603008, + EMOTE_ALLIES_NATURE = -1603362, + EMOTE_LIFEBINDERS_GIFT = -1603363, + EMOTE_GROUND_TREMMOR = -1603364, + EMOTE_IRON_ROOTS = -1603365, + //brightleaf + SAY_BRIGHTLEAF_AGGRO = -1603160, + SAY_BRIGHTLEAF_SLAY1 = -1603161, + SAY_BRIGHTLEAF_SLAY2 = -1603162, + SAY_BRIGHTLEAF_DEATH = -1603163, + //Ironbranch + SAY_IRONBRANCH_AGGRO = -1603170, + SAY_IRONBRANCH_SLAY1 = -1603171, + SAY_IRONBRANCH_SLAY2 = -1603172, + SAY_IRONBRANCH_DEATH = -1603173, + //Stonebark + SAY_STONEBARK_AGGRO = -1603180, + SAY_STONEBARK_SLAY1 = -1603181, + SAY_STONEBARK_SLAY2 = -1603182, + SAY_STONEBARK_DEATH = -1603183, + + /* BOSS SPELLS */ + SPELL_ATTUNED_TO_NATURE = 62519, //increases healing, start at 150 stacks + SPELL_ATTUNED_10_STACKS = 62525, + SPELL_ATTUNED_2_STACKS = 62524, + SPELL_ATTUNED_25_STACKS = 62521, + SPELL_TOUCH_OF_EONAR = 62528, //heals Freya, 6k per second + SPELL_TOUCH_OF_EONAR_H = 62892, //heals Freya, 24k per second + SPELL_SUNBEAM = 62623, + SPELL_SUNBEAM_H = 62872, + SPELL_BERSERK = 47008, // 10 min + + /* HARD MODE SPELLS */ + SPELL_DRAINED_OF_POWER = 62467, + // brightleaf + SPELL_UNSTABLE_ENERGY_FREYA = 62451, + SPELL_UNSTABLE_ENERGY_FREYA_H = 62865, + SPELL_BRIGHTLEAFS_ESSENCE = 62968, //62385, + SPELL_EFFECT_BRIGHTLEAF = 63294, + // ironbrach + SPELL_STRENGHTEN_IRON_ROOTS = 63601, + NPC_STRENGHENED_IRON_ROOTS = 33168, + SPELL_IRON_ROOTS_FREYA = 62438, + SPELL_IRON_ROOTS_FREYA_H = 62861, + SPELL_IRONBRANCH_ESSENCE = 62713, //62387, + SPELL_EFFECT_IRONBRANCH = 63292, + // stonebark + SPELL_GROUND_TREMOR_FREYA = 62437, + SPELL_GROUND_TREMOR_FREYA_H = 62859, + SPELL_STONEBARKS_ESSENCE = 65590, //62386, + SPELL_EFFECT_STONEBARK = 63295, + + NPC_SUN_BEAM = 33170, + NPC_UNSTABLE_SUN_BEAM = 33050, + + // sanctuary adds + NPC_EONARS_GIFT = 33228, + SPELL_LIFEBINDERS_GIFT = 62584, // after 12 secs, heals Freya & her allies for 30% + SPELL_LIFEBINDERS_GIFT_H = 64185, // the same but for 60% + SPELL_PHEROMONES = 62619, // protects from conservators grip + NPC_HEALTHY_SPORE = 33215, + + /* ADDS */ + // 6 waves of adds. 1 of the 3 each min + NPC_DETONATING_LASHER = 32918, // recude 2 stacks + // spells + SPELL_FLAME_LASH = 62608, + SPELL_DETONATE = 62598, + SPELL_DETONATE_H = 62937, + + NPC_ANCIENT_CONSERVATOR = 33203, // reduce 30 stacks + //spells + SPELL_CONSERVATORS_GRIP = 62532, + SPELL_NATURES_FURY = 62589, + SPELL_NATURES_FURY_H = 63571, + + /* elemental adds */ // each one reduces 10 stacks + NPC_WATER_SPIRIT = 33202, + // spells + SPELL_TIDAL_WAVE = 62653, + SPELL_TIDAL_WAVE_H = 62935, + + NPC_STORM_LASHER = 32919, + // spells + SPELL_STORMBOLT = 62649, + SPELL_STORMBOLT_H = 62938, + SPELL_LIGHTNING_LASH = 62648, // 3 targets + SPELL_LIGHTNING_LASH_H = 62939, // 5 targets + + NPC_SNAPLASHER = 32916, + // spells + SPELL_HARDENED_BARK = 62663, + SPELL_HARDENED_BARK_H = 64190, + + // nature bomb + NPC_NATURE_BOMB = 34129, + GO_NATURE_BOMB = 194902, + SPELL_NATURE_BOMB = 64587, + SPELL_NATURE_BOMB_H = 64650, + + /* ELDERS */ // used in phase 1 + ELDER_BRIGHTLEAF = 32915, + ELDER_IRONBRANCH = 32913, + ELDER_STONEBARK = 32914, + + // brightleaf spells + SPELL_BRIGHTLEAF_FLUX = 62262, + SPELL_SOLAR_FLARE = 62240, + SPELL_SOLAR_FLARE_H = 62920, + SPELL_UNSTABLE_SUN_BEAM = 62211, + SPELL_UNSTABLE_SUN_BEAM_A = 62243, + SPELL_UNSTABLE_ENERGY = 62217, // cancels sun bean + SPELL_UNSTABLE_ENERGY_H = 62922, + SPELL_PHOTOSYNTHESIS = 62209, + + // ironbrach spells + SPELL_IMPALE = 62310, + SPELL_IMPALE_H = 62928, + SPELL_IRON_ROOTS = 62283, + SPELL_IRON_ROOTS_H = 62930, + NPC_IRON_ROOTS = 33088, + SPELL_THORM_SWARM = 62285, + SPELL_THORM_SWARM_H = 62931, + + // stonebark spells + SPELL_FIST_OF_STONE = 62344, + SPELL_BROKEN_BONES = 62356, + SPELL_GROUND_TREMOR = 62325, + SPELL_GROUND_TREMOR_H = 62932, + SPELL_PETRIFIED_BARK = 62337, + SPELL_PETRIFIED_BARK_H = 62933, + + // not used because summoned chest doesn't despawn after looted + SPELL_SUMMON_CHEST_1 = 62950, + SPELL_SUMMON_CHEST_2 = 62952, + SPELL_SUMMON_CHEST_3 = 62953, + SPELL_SUMMON_CHEST_4 = 62954, + SPELL_SUMMON_CHEST_5 = 62955, + SPELL_SUMMON_CHEST_6 = 62956, + SPELL_SUMMON_CHEST_7 = 62957, + SPELL_SUMMON_CHEST_8 = 62958, + + SPELL_SUMMON_ALLIES_OF_NATURE = 62678, //better do that in sd2 + SPELL_SUMMON_LASHERS = 62688, // lashers - broken + SPELL_SUMMON_ELEMENTALS = 62686, // elementals -> better in sd2 + SPELL_SUMMON_CONSERVATOR = 62685, // conservator + SPELL_LIFEBINDERS_GIFT_SUMMON = 62869, + SPELL_NATURE_BOMB_SUMMON = 64606, + + SPELL_SPORE_SUMMON_NE = 62591, + SPELL_SPORE_SUMMON_SE = 62592, + SPELL_SPORE_SUMMON_SW = 62593, + SPELL_SPORE_SUMMON_NW = 62582, + + SPELL_HEALTHY_SPORE_VISUAL = 62538, + SPELL_NATURE_BOMB_VISUAL = 64604, + SPELL_LIFEBINDERS_VISUAL = 62579, + SPELL_LIFEBINDER_GROW = 44833, + + SPELL_PHEROMONES_LG = 62619, + SPELL_POTENT_PHEROMONES = 62541, + + ACHIEV_BACK_TO_NATURE = 2982, + ACHIEV_BACK_TO_NATURE_H = 2983, + ACHIEV_KNOCK_WOOD = 3177, + ACHIEV_KNOCK_WOOD_H = 3185, + ACHIEV_KNOCK_KNOCK_WOOD = 3178, + ACHIEV_KNOCK_KNOCK_WOOD_H = 3186, + ACHIEV_KNOCK_KNOCK_KNOCK_WOOD = 3179, + ACHIEV_KNOCK_KNOCK_KNOCK_WOOD_H = 3187, +}; + +// Iron roots & stranghned iron roots +struct MANGOS_DLL_DECL mob_iron_rootsAI : public ScriptedAI +{ + mob_iron_rootsAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + uint64 m_uiVictimGUID; + uint32 m_uiCreatureEntry; + + void Reset() + { + m_uiVictimGUID = 0; + m_uiCreatureEntry = m_creature->GetEntry(); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > m_creature->GetHealth()) + { + if (m_uiVictimGUID) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit(m_uiVictimGUID)) + { + switch(m_uiCreatureEntry) + { + case NPC_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); + break; + case NPC_STRENGHENED_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); + break; + } + } + } + } + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim) + { + switch(m_uiCreatureEntry) + { + case NPC_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); + break; + case NPC_STRENGHENED_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); + break; + } + } + } + + void JustDied(Unit* Killer) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit(m_uiVictimGUID)) + { + switch(m_uiCreatureEntry) + { + case NPC_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); + break; + case NPC_STRENGHENED_IRON_ROOTS: + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); + break; + } + } + } + + void UpdateAI(const uint32 uiuiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + } +}; + +// Elder Brightleaf +struct MANGOS_DLL_DECL boss_elder_brightleafAI : public ScriptedAI +{ + boss_elder_brightleafAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + uint32 m_uiBrightleafFluxTimer; + uint32 m_uiSolarFlareTimer; + uint32 m_uiUnstableSunBeanTimer; + uint32 m_uiUnstabelEnergyTimer; + uint32 m_uiSunbeamStacks; + uint32 m_uiHealTimer; + bool m_bHasSunbeam; + + void Reset() + { + m_uiBrightleafFluxTimer = 5000; + m_uiSolarFlareTimer = 10000 + urand(1000, 5000); + m_uiUnstableSunBeanTimer = 15000; + m_uiUnstabelEnergyTimer = 30000; + m_uiSunbeamStacks = 1; + m_bHasSunbeam = false; + } + + void Aggro(Unit* pWho) + { + DoScriptText(SAY_BRIGHTLEAF_AGGRO, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_BRIGHTLEAF_SLAY1, m_creature); + else + DoScriptText(SAY_BRIGHTLEAF_SLAY2, m_creature); + } + + void JustDied(Unit *killer) + { + DoScriptText(SAY_BRIGHTLEAF_DEATH, m_creature); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // this needs core suport + if(m_uiBrightleafFluxTimer < uiDiff) + { + DoCast(m_creature, SPELL_BRIGHTLEAF_FLUX); + m_uiBrightleafFluxTimer = 5000; + } + else m_uiBrightleafFluxTimer -= uiDiff; + + if(m_uiSolarFlareTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_SOLAR_FLARE : SPELL_SOLAR_FLARE_H); + m_uiSolarFlareTimer = 10000 + urand(1000, 5000); + } + else m_uiSolarFlareTimer -= uiDiff; + + // also the following spells need some core support -> hacky way of use + // PLEASE FIX FOR REVISION! + if(m_uiUnstableSunBeanTimer < uiDiff) + { + DoCast(m_creature, SPELL_UNSTABLE_SUN_BEAM); + m_bHasSunbeam = true; + m_uiHealTimer = 1000; + m_uiUnstableSunBeanTimer = urand(7000, 12000); + } + else m_uiUnstableSunBeanTimer -= uiDiff; + + // cast after the unstable sun bean + if (m_uiHealTimer < uiDiff && m_bHasSunbeam) + { + DoCast(m_creature, SPELL_PHOTOSYNTHESIS); + m_bHasSunbeam = false; + } + else m_uiHealTimer -= uiDiff; + + // removes photosynthesis when standing inside + if(m_uiUnstabelEnergyTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY: SPELL_UNSTABLE_ENERGY_H); + m_creature->RemoveAurasDueToSpell(SPELL_UNSTABLE_SUN_BEAM_A); + m_creature->RemoveAurasDueToSpell(SPELL_PHOTOSYNTHESIS); + m_uiSunbeamStacks = 1; + m_uiUnstabelEnergyTimer = urand(20000, 30000); + } + else m_uiUnstabelEnergyTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_elder_brightleaf(Creature* pCreature) +{ + return new boss_elder_brightleafAI(pCreature); +} + +// Elder Ironbranch +struct MANGOS_DLL_DECL boss_elder_ironbranchAI : public ScriptedAI +{ + boss_elder_ironbranchAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + uint32 m_uiImpaleTimer; + uint32 m_uiIronrootsTimer; + uint32 m_uiThornSwarmTimer; + + void Reset() + { + m_uiImpaleTimer = 10000 + urand (1000, 5000); + m_uiIronrootsTimer = 20000 + urand (1000, 7000); + m_uiThornSwarmTimer = 30000; + } + + void Aggro(Unit* pWho) + { + DoScriptText(SAY_IRONBRANCH_AGGRO, m_creature); + } + + void JustDied(Unit *killer) + { + DoScriptText(SAY_IRONBRANCH_DEATH, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_IRONBRANCH_SLAY1, m_creature); + else + DoScriptText(SAY_IRONBRANCH_SLAY2, m_creature); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiImpaleTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_IMPALE : SPELL_IMPALE_H); + m_uiImpaleTimer = 10000 + urand (1000, 5000); + } + else m_uiImpaleTimer -= uiDiff; + + if(m_uiIronrootsTimer < uiDiff) + { + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(target, m_bIsRegularMode ? SPELL_IRON_ROOTS : SPELL_IRON_ROOTS_H); + m_uiIronrootsTimer = 20000 + urand (1000, 7000); + } + else m_uiIronrootsTimer -= uiDiff; + + if(m_uiThornSwarmTimer < uiDiff) + { + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(target, m_bIsRegularMode ? SPELL_THORM_SWARM : SPELL_THORM_SWARM_H); + m_uiThornSwarmTimer = 30000; + } + else m_uiThornSwarmTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_elder_ironbranch(Creature* pCreature) +{ + return new boss_elder_ironbranchAI(pCreature); +} + +// Stonebark +struct MANGOS_DLL_DECL boss_elder_stonebarkAI : public ScriptedAI +{ + boss_elder_stonebarkAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + uint32 m_uiFistsOfStoneTimer; + uint32 m_uiGroundTremorTimer; + uint32 m_uiPetrifiedBarkTimer; + + void Reset() + { + m_uiFistsOfStoneTimer = 20000; + m_uiGroundTremorTimer = 15000; + m_uiPetrifiedBarkTimer = 25000; + } + + void Aggro(Unit* pWho) + { + DoScriptText(SAY_STONEBARK_AGGRO, m_creature); + } + + void JustDied(Unit *killer) + { + DoScriptText(SAY_STONEBARK_DEATH, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_STONEBARK_SLAY1, m_creature); + else + DoScriptText(SAY_STONEBARK_SLAY2, m_creature); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiFistsOfStoneTimer < uiDiff) + { + DoCast(m_creature, SPELL_FIST_OF_STONE); + m_uiFistsOfStoneTimer = 30000; + } + else m_uiFistsOfStoneTimer -= uiDiff; + + if(m_uiGroundTremorTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_GROUND_TREMOR : SPELL_GROUND_TREMOR_H); + m_uiGroundTremorTimer = 15000 + urand (1000, 5000); + } + else m_uiGroundTremorTimer -= uiDiff; + + if(m_uiPetrifiedBarkTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_PETRIFIED_BARK : SPELL_PETRIFIED_BARK_H); + m_uiPetrifiedBarkTimer = 20000 + urand (1000, 5000); + } + else m_uiPetrifiedBarkTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_elder_stonebark(Creature* pCreature) +{ + return new boss_elder_stonebarkAI(pCreature); +} + +// Freya +struct MANGOS_DLL_DECL boss_freyaAI : public ScriptedAI +{ + boss_freyaAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiSummonTimer; + uint32 m_uiWaveNumber; + uint32 m_uiWaveType; + uint32 m_uiWaveTypeInc; + uint32 m_uiSunbeamTimer; + uint32 m_uiEnrageTimer; + + bool m_bIsHardMode; + bool m_bHasAura; + + uint32 m_uiNatureBombTimer; + uint32 m_uiLifebindersGiftTimer; + + bool m_bIsOutro; + uint32 m_uiOutroTimer; + uint32 m_uiStep; + + // hard mode timers + uint32 m_uiUnstableEnergyTimer; + uint32 m_uiStrenghtenIronRootsTimer; + uint32 m_uiGroundTremorTimer; + + uint32 m_uiThreeWaveCheckTimer; + bool m_bWaveCheck; + uint64 m_uiWaterSpiritGUID; + uint64 m_uiStormLasherGUID; + uint64 m_uiSnapLasherGUID; + + bool m_bIsBrightleafAlive; + bool m_bIsIronbranchAlive; + bool m_bIsStonebarkAlive; + + uint32 m_uiAchievProgress; + bool m_bNature; + + void Reset() + { + m_uiSummonTimer = 15000; + m_uiWaveNumber = 0; + m_uiWaveType = irand(0,2); + m_uiWaveTypeInc = irand(1,2); + m_uiSunbeamTimer = rand()%10000; + m_uiEnrageTimer = 600000; //10 minutes + m_bIsHardMode = false; + m_uiLifebindersGiftTimer = 30000; + m_uiUnstableEnergyTimer = 25000; + m_uiStrenghtenIronRootsTimer = 25000 + urand(1000, 5000); + m_uiGroundTremorTimer = 20000; + m_uiNatureBombTimer = 7000; + m_uiThreeWaveCheckTimer = 1000; + m_uiAchievProgress = 10000; + m_bWaveCheck = false; + m_uiWaterSpiritGUID = 0; + m_uiStormLasherGUID = 0; + m_uiSnapLasherGUID = 0; + + m_uiOutroTimer = 10000; + m_uiStep = 1; + m_bIsOutro = false; + + m_uiAchievProgress = 0; + m_bNature = false; + m_bHasAura = false; + + if(m_pInstance) + { + // remove elder auras + if (Creature* pBrightleaf = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRIGHTLEAF))) + { + if (pBrightleaf->isAlive()) + pBrightleaf->RemoveAllAuras(); + } + if (Creature* pIronbranch = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_IRONBRACH))) + { + if (pIronbranch->isAlive()) + pIronbranch->RemoveAllAuras(); + } + if (Creature* pStonebark = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STONEBARK))) + { + if (pStonebark->isAlive()) + pStonebark->RemoveAllAuras(); + } + } + } + + void Aggro(Unit *who) + { + // aura should stack up to 150 when casted, need core support + DoCast(m_creature, SPELL_ATTUNED_TO_NATURE); + + if(m_pInstance) + { + m_pInstance->SetData(TYPE_FREYA, IN_PROGRESS); + + // check brightleaf + if (Creature* pBrightleaf = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRIGHTLEAF))) + { + if (pBrightleaf->isAlive()) + { + pBrightleaf->CastSpell(pBrightleaf, SPELL_DRAINED_OF_POWER, false); + pBrightleaf->CastSpell(m_creature, SPELL_EFFECT_BRIGHTLEAF, false); + m_bIsBrightleafAlive = true; + m_uiAchievProgress += 1; + } + else + m_bIsBrightleafAlive = false; + } + + // check ironbranch + if (Creature* pIronbranch = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_IRONBRACH))) + { + if (pIronbranch->isAlive()) + { + pIronbranch->CastSpell(pIronbranch, SPELL_DRAINED_OF_POWER, false); + pIronbranch->CastSpell(m_creature, SPELL_EFFECT_IRONBRANCH, false); + m_bIsIronbranchAlive = true; + m_uiAchievProgress += 1; + } + else + m_bIsIronbranchAlive = false; + } + + // check stonebark + if (Creature* pStonebark = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STONEBARK))) + { + if (pStonebark->isAlive()) + { + pStonebark->CastSpell(pStonebark, SPELL_DRAINED_OF_POWER, false); + pStonebark->CastSpell(m_creature, SPELL_EFFECT_STONEBARK, false); + m_bIsStonebarkAlive = true; + m_uiAchievProgress += 1; + } + else + m_bIsStonebarkAlive = false; + } + } + + m_bIsHardMode = CheckHardMode(); + + if(!m_bIsHardMode) + DoScriptText(SAY_AGGRO, m_creature); + else + DoScriptText(SAY_AGGRO_HARD, m_creature); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_FREYA, FAIL); + } + + void DoOutro() + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_FREYA_HARD, 0); + + // hacky way to complete achievements; use only if you have this function + if(m_uiAchievProgress == 1) + { + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_KNOCK_WOOD : ACHIEV_KNOCK_WOOD_H); + m_pInstance->SetData(TYPE_FREYA_HARD, 1); + } + else if (m_uiAchievProgress == 2) + { + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_KNOCK_KNOCK_WOOD : ACHIEV_KNOCK_KNOCK_WOOD_H); + m_pInstance->SetData(TYPE_FREYA_HARD, 2); + } + else if (m_uiAchievProgress == 3) + { + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_KNOCK_KNOCK_KNOCK_WOOD : ACHIEV_KNOCK_KNOCK_KNOCK_WOOD_H); + m_pInstance->SetData(TYPE_FREYA_HARD, 3); + } + + if (m_bNature) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_BACK_TO_NATURE : ACHIEV_BACK_TO_NATURE_H); + + m_pInstance->SetData(TYPE_FREYA, DONE); + } + + m_creature->ForcedDespawn(); + } + + // for debug only! + void JustDied(Unit* pKiller) + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_FREYA, DONE); + if(m_bIsHardMode) + m_pInstance->SetData(TYPE_FREYA_HARD, DONE); + } + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(m_creature->GetHealthPercent() < 1.0f) + { + uiDamage = 0; + m_bIsOutro = true; + } + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); + } + + // summon 12 Lashers. Should be done by a spell which needs core fix + void SummonLashers() + { + DoScriptText(SAY_SUMMON3, m_creature); + int i; + float x,y; + for(i = 0; i < 12; ++i) + { + x = (rand_norm() * 30.0f) - 15.0f; + y = (rand_norm() * 30.0f) - 15.0f; + if(Creature* pLasher = DoSpawnCreature(NPC_DETONATING_LASHER, x, y, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) + { + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pLasher->AddThreat(pTarget, 1.0f); + } + } + } + + // summon conservator. Should be done by a spell which needs core fix + void SummonConservator() + { + DoScriptText(SAY_SUMMON1, m_creature); + float x = (rand_norm() * 30.0f) - 15.0f; + float y = (rand_norm() * 30.0f) - 15.0f; + if(Creature* pAdd = DoSpawnCreature(NPC_ANCIENT_CONSERVATOR, x, y, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) + { + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pAdd->AddThreat(pTarget, 1.0f); + } + } + + // summmon the 3 elementals. Should be done by a spell which needs core fix. + void SummonElementals() + { + DoScriptText(SAY_SUMMON2, m_creature); + m_bWaveCheck = true; + m_uiThreeWaveCheckTimer = 2000; + + if(Creature* pSpirit = DoSpawnCreature(NPC_WATER_SPIRIT, 0, 0, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) + { + m_uiWaterSpiritGUID = pSpirit->GetGUID(); + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pSpirit->AddThreat(pTarget, 1.0f); + } + + if(Creature* pStormLasher = DoSpawnCreature(NPC_STORM_LASHER, 0, 0, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) + { + m_uiStormLasherGUID = pStormLasher->GetGUID(); + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pStormLasher->AddThreat(pTarget, 1.0f); + } + + if(Creature* pSnapLasher = DoSpawnCreature(NPC_SNAPLASHER, 0, 0, 0, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) + { + m_uiSnapLasherGUID = pSnapLasher->GetGUID(); + if(Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pSnapLasher->AddThreat(pTarget, 1.0f); + } + } + + bool CheckHardMode() + { + if(m_bIsBrightleafAlive && m_bIsIronbranchAlive && m_bIsStonebarkAlive) + return true; + return false; + } + + void UpdateAI(const uint32 uiDiff) + { + if(!m_bIsOutro) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // hacky way of stacking aura. Please remove when fixed in core! + if(SpellAuraHolder* natureAura = m_creature->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) + { + if(natureAura->GetStackAmount() < 150 && !m_bHasAura) + { + m_bHasAura = true; + natureAura->SetStackAmount(150); + } + } + + if(!m_creature->HasAura(m_bIsRegularMode ? SPELL_TOUCH_OF_EONAR : SPELL_TOUCH_OF_EONAR_H)) + DoCast(m_creature, m_bIsRegularMode ? SPELL_TOUCH_OF_EONAR : SPELL_TOUCH_OF_EONAR_H); + + // check if the 3 elementals die at the same time + if(m_uiThreeWaveCheckTimer < uiDiff && m_bWaveCheck) + { + Creature* pWaterSpirit = m_pInstance->instance->GetCreature(m_uiWaterSpiritGUID); + Creature* pStormLasher = m_pInstance->instance->GetCreature(m_uiStormLasherGUID); + Creature* pSnapLasher = m_pInstance->instance->GetCreature(m_uiSnapLasherGUID); + + if(pWaterSpirit && pStormLasher && pSnapLasher) + { + if(!pWaterSpirit->isAlive() && !pStormLasher->isAlive() && !pSnapLasher->isAlive()) + { + m_bWaveCheck = false; + if(SpellAuraHolder* natureAura = m_creature->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) + { + if(natureAura->ModStackAmount(-30)) + m_creature->RemoveAurasDueToSpell(SPELL_ATTUNED_TO_NATURE); + } + } + else + { + // respawn the dead ones + if(!pWaterSpirit->isAlive()) + pWaterSpirit->Respawn(); + if(!pSnapLasher->isAlive()) + pSnapLasher->Respawn(); + if(!pStormLasher->isAlive()) + pStormLasher->Respawn(); + } + } + m_uiThreeWaveCheckTimer = 2000; + } + else + m_uiThreeWaveCheckTimer -= uiDiff; + + // Hardmode + if(m_bIsBrightleafAlive) + { + if(!m_creature->HasAura(SPELL_BRIGHTLEAFS_ESSENCE, EFFECT_INDEX_0)) + DoCast(m_creature, SPELL_BRIGHTLEAFS_ESSENCE); + + // hacky way, should be done by spell + if(m_uiUnstableEnergyTimer < uiDiff) + { + //DoCast(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY_FREYA : SPELL_UNSTABLE_ENERGY_FREYA_H); + for(int8 i = 0; i < 3; ++i) + { + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + { + float x = target->GetPositionX(); + float y = target->GetPositionY(); + float z = target->GetPositionZ(); + m_creature->SummonCreature(NPC_SUN_BEAM, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 20000); + } + } + m_uiUnstableEnergyTimer = urand(25000, 30000); + } + else m_uiUnstableEnergyTimer -= uiDiff; + } + + if(m_bIsIronbranchAlive) + { + if(!m_creature->HasAura(SPELL_IRONBRANCH_ESSENCE, EFFECT_INDEX_0)) + DoCast(m_creature, SPELL_IRONBRANCH_ESSENCE); + + if(m_uiStrenghtenIronRootsTimer < uiDiff) + { + if(Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + { + DoScriptText(EMOTE_IRON_ROOTS, m_creature, target); + DoCast(target, m_bIsRegularMode ? SPELL_IRON_ROOTS_FREYA : SPELL_IRON_ROOTS_FREYA_H); + } + m_uiStrenghtenIronRootsTimer = 50000 + urand(10000, 20000); + } + else m_uiStrenghtenIronRootsTimer -= uiDiff; + } + + if(m_bIsStonebarkAlive) + { + // aura doesn't work. Needs core fix + if(!m_creature->HasAura(SPELL_STONEBARKS_ESSENCE, EFFECT_INDEX_0)) + DoCast(m_creature, SPELL_STONEBARKS_ESSENCE); + + if(m_uiGroundTremorTimer < uiDiff) + { + DoScriptText(EMOTE_GROUND_TREMMOR, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_GROUND_TREMOR_FREYA : SPELL_GROUND_TREMOR_FREYA_H); + m_uiGroundTremorTimer = 20000; + } + else m_uiGroundTremorTimer -= uiDiff; + } + + //Phase 1, waves of adds + if(m_uiWaveNumber < 6) + { + if(m_uiSummonTimer < uiDiff) + { + DoScriptText(EMOTE_ALLIES_NATURE, m_creature); + switch(m_uiWaveType) + { + case 0: SummonLashers(); break; + case 1: SummonConservator(); break; + case 2: SummonElementals(); break; + } + m_uiWaveType = (m_uiWaveType + m_uiWaveTypeInc) % 3; + ++m_uiWaveNumber; + m_uiSummonTimer = 60000; + } + else m_uiSummonTimer -= uiDiff; + } + // Phase 2 + else + { + // nature bomb. Should be done by spell, not by summon. + if(m_uiNatureBombTimer < uiDiff) + { + DoCast(m_creature, SPELL_NATURE_BOMB_VISUAL); + DoCast(m_creature, SPELL_NATURE_BOMB_SUMMON); + + int8 count = urand(8,10); + for(int8 i = 0; i < count; ++i) + { + float radius = 30* rand_norm_f(); + float angle = 2.0f * M_PI_F * rand_norm_f(); + float x = m_creature->GetPositionX() + cos(angle) * radius; + float y = m_creature->GetPositionY() + sin(angle) * radius; + float z = m_creature->GetTerrain()->GetHeight(x, y, MAX_HEIGHT); + m_creature->SummonCreature(NPC_NATURE_BOMB, x, y, z, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 20000); + } + m_uiNatureBombTimer = urand(7000, 12000); + } + else m_uiNatureBombTimer -= uiDiff; + } + + //All phases + if(m_uiSunbeamTimer < uiDiff) + { + if( Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_SUNBEAM : SPELL_SUNBEAM_H); + m_uiSunbeamTimer = 6000 + rand()%10000; + } + else m_uiSunbeamTimer -= uiDiff; + + if(m_uiLifebindersGiftTimer < uiDiff) + { + DoScriptText(EMOTE_LIFEBINDERS_GIFT, m_creature); + if(Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_LIFEBINDERS_GIFT_SUMMON); + m_uiLifebindersGiftTimer = 30000; + } + else m_uiLifebindersGiftTimer -= uiDiff; + + if(m_uiEnrageTimer < uiDiff) + { + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_BERSERK); + m_uiEnrageTimer = 30000; + } + else m_uiEnrageTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + + // outro + if(m_bIsOutro) + { + switch(m_uiStep) + { + case 1: + if(m_creature->HasAura(SPELL_ATTUNED_TO_NATURE, EFFECT_INDEX_0)) + { + if(m_creature->GetAura(SPELL_ATTUNED_TO_NATURE, EFFECT_INDEX_0)->GetStackAmount() >= 25) + m_bNature = true; + } + m_creature->setFaction(35); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->GetMotionMaster()->MovePoint(0, 2359.40f, -52.39f, 425.64f); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + ++m_uiStep; + m_uiOutroTimer = 7000; + break; + case 3: + DoScriptText(SAY_DEATH, m_creature); + ++m_uiStep; + m_uiOutroTimer = 10000; + break; + case 5: + DoOutro(); + ++m_uiStep; + m_uiOutroTimer = 10000; + break; + } + } + else return; + + if (m_uiOutroTimer <= uiDiff) + { + ++m_uiStep; + m_uiOutroTimer = 330000; + } m_uiOutroTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_boss_freya(Creature* pCreature) +{ + return new boss_freyaAI(pCreature); +} + +// Script for all the npcs found on the ground during Freya encounter +struct MANGOS_DLL_DECL mob_freya_groundAI : public ScriptedAI +{ + mob_freya_groundAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiNatureBomb_Timer; + uint32 m_uiDieTimer; + uint32 m_uiEonarsGift_Timer; + uint32 m_uiNonSelectable_Timer; + uint32 m_uiGrow_Timer; + uint32 m_uiSunBeamDespawn_Timer; + uint32 m_uiUnstableEnergy_Timer; + uint32 m_uiHealthyGrow_Timer; + uint64 m_uiNatureBombGUID; + float m_fSize; + + bool m_bNpcNatureBomb; + bool m_bNpcEonarsGift; + bool m_bNpcHealthySpore; + bool m_bNpcSunBeamFreya; + bool m_bNpcSunBeamBright; + + bool m_bHasGrow; + + void Reset() + { + m_uiNatureBomb_Timer = urand(9000,11000); + m_uiDieTimer = 60000; + m_uiEonarsGift_Timer = urand(11000,13000); + m_uiNonSelectable_Timer = 5000; + m_uiUnstableEnergy_Timer = 1000; + m_uiGrow_Timer = 0; + m_uiSunBeamDespawn_Timer = urand(10000,11000); + m_bHasGrow = true; + m_uiHealthyGrow_Timer = urand(3000,12000); + m_bNpcNatureBomb = false; + m_bNpcEonarsGift = false; + m_bNpcHealthySpore = false; + m_bNpcSunBeamFreya = false; + m_bNpcSunBeamBright = false; + + // the invisible displayIds should be set in DB. + switch(m_creature->GetEntry()) + { + case NPC_NATURE_BOMB: + m_bNpcNatureBomb = true; + m_creature->setFaction(14); + m_fSize = 1; + m_creature->SetDisplayId(25865); // invisible + DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL); + break; + case NPC_EONARS_GIFT: + m_bNpcEonarsGift = true; + m_fSize = float(0.1); + DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL); + break; + case NPC_HEALTHY_SPORE: + m_bNpcHealthySpore = true; + DoCast(m_creature, SPELL_HEALTHY_SPORE_VISUAL); + DoCast(m_creature, SPELL_POTENT_PHEROMONES); + break; + case NPC_SUN_BEAM: + m_bNpcSunBeamFreya = true; + m_creature->SetDisplayId(25865); // invisible + DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL); + DoCast(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY_FREYA : SPELL_UNSTABLE_ENERGY_FREYA_H); + break; + case NPC_UNSTABLE_SUN_BEAM: + m_bNpcSunBeamBright = true; + m_creature->SetDisplayId(25865); // invisible + DoCast(m_creature, SPELL_LIFEBINDERS_VISUAL); + //DoCast(m_creature, SPELL_PHOTOSYNTHESIS); // spell needs core fix, should be casted on Brighleaf! + break; + } + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetRespawnDelay(DAY); + } + + void AttackStart(Unit* pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_FREYA) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if(!m_creature->isAlive()) + return; + + // NATURE BOMB + if(m_bNpcNatureBomb) + { + if(m_uiNatureBomb_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_NATURE_BOMB : SPELL_NATURE_BOMB_H); + m_uiDieTimer = 500; + m_uiNatureBomb_Timer = 10000; + }else m_uiNatureBomb_Timer -= uiDiff; + + if(m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, NULL, false); + else m_uiDieTimer -= uiDiff; + } + + // EONAR GIFT + if(m_bNpcEonarsGift) + { + if (m_uiGrow_Timer > 500 && m_fSize < 1.5) + { + m_fSize += float(m_uiGrow_Timer)/8000; + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fSize); + m_uiGrow_Timer = 0; + }else m_uiGrow_Timer += uiDiff; + + if(m_uiEonarsGift_Timer < uiDiff) + { + if (Creature* pFreya = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_FREYA))) + DoCast(pFreya, m_bIsRegularMode ? SPELL_LIFEBINDERS_GIFT : SPELL_LIFEBINDERS_GIFT_H); + m_uiEonarsGift_Timer = 1000; + }else m_uiEonarsGift_Timer -= uiDiff; + + if(m_uiNonSelectable_Timer < uiDiff && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE)) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_PHEROMONES_LG); + }else m_uiNonSelectable_Timer -= uiDiff; + } + + // HEALTHY SPORE + if(m_bNpcHealthySpore) + { + if(!m_bHasGrow && m_fSize < 0.25) + m_creature->ForcedDespawn(); + + if(m_uiHealthyGrow_Timer < uiDiff) + { + if(m_bHasGrow) + { + m_fSize = float(urand(150,225))/100; + m_bHasGrow = false; + } + else + m_fSize = float(urand(1,300))/100; + if(m_fSize < 1) + m_fSize = 0.1f; + m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fSize); + m_uiHealthyGrow_Timer = urand(3000,5000); + }else m_uiHealthyGrow_Timer -= uiDiff; + } + + // SUN BEAM + if(m_bNpcSunBeamBright) + { + if(m_uiUnstableEnergy_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_UNSTABLE_ENERGY : SPELL_UNSTABLE_ENERGY_H); + m_uiUnstableEnergy_Timer = 1000; + }else m_uiUnstableEnergy_Timer -= uiDiff; + } + + if(m_bNpcSunBeamFreya || m_bNpcSunBeamBright) + { + if(m_uiSunBeamDespawn_Timer < uiDiff) + m_creature->ForcedDespawn(); + else m_uiSunBeamDespawn_Timer -= uiDiff; + } + } +}; + +// Script for Freya's adds +struct MANGOS_DLL_DECL mob_freya_spawnedAI : public ScriptedAI +{ + mob_freya_spawnedAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + bool m_bAncientConservator; + bool m_bDetonatingLasher; + bool m_bAncientWaterSpirit; + bool m_bStormLasher; + bool m_bSnaplasher; + bool m_bHasExploded; + + uint32 m_uiDeathCountdown; + uint32 m_uiTidalWave_Timer; + uint32 m_uiStormbolt_Timer; + uint32 m_uiLightningLash_Timer; + uint32 m_uiFlameLash_Timer; + uint32 m_uiNaturesFury_Timer; + uint32 m_uiWave3_DeathCountdown; + uint32 m_uiRespawnSpores_Timer; + uint32 m_uiDieTimer; + uint8 m_uiHealthMultiplier; + + void Reset() + { + m_bAncientWaterSpirit = false; + m_bStormLasher = false; + m_bSnaplasher = false; + m_bAncientConservator = false; + m_bDetonatingLasher = false; + m_bHasExploded = false; + m_uiDieTimer = 120000; + m_uiDeathCountdown = 10000; + m_uiTidalWave_Timer = urand(2000,4000); + m_uiStormbolt_Timer = 1000; + m_uiLightningLash_Timer = urand(11000,14000); + m_uiFlameLash_Timer = urand(5000,10000); + m_uiNaturesFury_Timer = urand(8000,10000); + m_uiRespawnSpores_Timer = 5000; + m_uiHealthMultiplier = 1; + + switch(m_creature->GetEntry()) + { + // The Conservator's Grip needs core fix. It should be canceled by pheronomes! + case NPC_ANCIENT_CONSERVATOR: + m_bAncientConservator = true; + //DoCast(m_creature, SPELL_CONSERVATORS_GRIP); //spell disabled because it isn't negated by pheronomes + DoSpores(10); + break; + case NPC_DETONATING_LASHER: + m_bDetonatingLasher = true; + break; + case NPC_WATER_SPIRIT: + m_bAncientWaterSpirit = true; + break; + case NPC_SNAPLASHER: + m_bSnaplasher = true; + DoCast(m_creature, m_bIsRegularMode ? SPELL_HARDENED_BARK : SPELL_HARDENED_BARK_H); + break; + case NPC_STORM_LASHER: + m_bStormLasher = true; + break; + } + m_creature->SetRespawnDelay(DAY); + } + + void JustDied(Unit* Killer) + { + // remove some stacks from Freya's aura + // hacky way. Should be done by spell which needs core support + if (m_bAncientConservator) + { + if (Creature* pFreya = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_FREYA))) + { + if(SpellAuraHolder* natureAura = pFreya->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) + { + if(natureAura->ModStackAmount(-25)) + m_creature->RemoveAurasDueToSpell(SPELL_ATTUNED_TO_NATURE); + } + } + } + + if (m_bDetonatingLasher) + { + if (Creature* pFreya = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_FREYA))) + { + if(SpellAuraHolder* natureAura = pFreya->GetSpellAuraHolder(SPELL_ATTUNED_TO_NATURE)) + { + if(natureAura->ModStackAmount(-2)) + m_creature->RemoveAurasDueToSpell(SPELL_ATTUNED_TO_NATURE); + } + } + } + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if (m_bDetonatingLasher && uiDamage > m_creature->GetHealth() && !m_bHasExploded) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_DETONATE : SPELL_DETONATE_H); + uiDamage = 0; + m_bHasExploded = true; + m_uiDieTimer = 500; + } + } + + void DoSpores(int8 times) + { + for(int8 i = 0; i < times; ++i) + { + for(int8 itr = 0; i < 3; ++i) + DoCast(m_creature, SPELL_SPORE_SUMMON_NE + itr); + DoCast(m_creature, SPELL_SPORE_SUMMON_NW); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_FREYA) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if(!m_creature->isAlive()) + return; + + // DETONATING LASHERS + if(m_bDetonatingLasher) + { + if(m_uiFlameLash_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_FLAME_LASH); + m_uiFlameLash_Timer = urand(5000,10000); + }else m_uiFlameLash_Timer -= uiDiff; + + if(m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, NULL, false); + else m_uiDieTimer -= uiDiff; + } + + // CONSERVATOR + if(m_bAncientConservator) + { + if(m_uiNaturesFury_Timer < uiDiff) + { + DoCast(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0), m_bIsRegularMode ? SPELL_NATURES_FURY : SPELL_NATURES_FURY_H); + m_uiNaturesFury_Timer = urand(5000,6000); + }else m_uiNaturesFury_Timer -= uiDiff; + + if(m_uiRespawnSpores_Timer < uiDiff) + { + DoSpores(3); + m_uiRespawnSpores_Timer = 5000; + }else m_uiRespawnSpores_Timer -= uiDiff; + } + + // ELEMENTAL ADDS + // waterspirit + if(m_bAncientWaterSpirit && m_uiTidalWave_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_TIDAL_WAVE : SPELL_TIDAL_WAVE_H); + m_uiTidalWave_Timer = urand(7000,9000); + }else m_uiTidalWave_Timer -= uiDiff; + + // stormlasher + if(m_bStormLasher) + { + if (m_uiLightningLash_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_LIGHTNING_LASH : SPELL_LIGHTNING_LASH_H); + m_uiLightningLash_Timer = urand(11000,14000); + } + else + { + m_uiLightningLash_Timer -= uiDiff; + if (m_uiStormbolt_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_STORMBOLT : SPELL_STORMBOLT_H); + m_uiStormbolt_Timer = 2000; + }else m_uiStormbolt_Timer -= uiDiff; + } + } + + DoMeleeAttackIfReady(); + } }; +CreatureAI* GetAI_mob_freya_ground(Creature* pCreature) +{ + return new mob_freya_groundAI(pCreature); +} + +CreatureAI* GetAI_mob_freya_spawned(Creature* pCreature) +{ + return new mob_freya_spawnedAI(pCreature); +} + +CreatureAI* GetAI_mob_iron_roots(Creature* pCreature) +{ + return new mob_iron_rootsAI(pCreature); +} + void AddSC_boss_freya() { + Script *newscript; + newscript = new Script; + newscript->Name = "boss_freya"; + newscript->GetAI = &GetAI_boss_freya; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_elder_brightleaf"; + newscript->GetAI = &GetAI_boss_elder_brightleaf; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_elder_ironbranch"; + newscript->GetAI = &GetAI_boss_elder_ironbranch; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_elder_stonebark"; + newscript->GetAI = &GetAI_boss_elder_stonebark; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_freya_ground"; + newscript->GetAI = &GetAI_mob_freya_ground; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_freya_spawned"; + newscript->GetAI = &GetAI_mob_freya_spawned; + newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "mob_iron_roots"; + newscript->GetAI = &GetAI_mob_iron_roots; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/boss_hodir.cpp b/scripts/northrend/ulduar/ulduar/boss_hodir.cpp index 8cc7e64..77fb44d 100644 --- a/scripts/northrend/ulduar/ulduar/boss_hodir.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_hodir.cpp @@ -1,45 +1,1098 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_hodir -SD%Complete: 0% -SDComment: +SD%Complete: 60% +SDComment:Auras needs core fix SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_AGGRO = -1603086, - SAY_SLAY_1 = -1603087, - SAY_SLAY_2 = -1603088, - SAY_FLASH_FREEZE = -1603089, - SAY_FROZEN_BLOWS = -1603090, - SAY_DEATH = -1603091, - SAY_BERSERK = -1603092, - SAY_HELP_YOGG = -1603093, + SPELL_ENRAGE = 26662, + + SPELL_FROZEN_BLOWS = 62478, + SPELL_FROZEN_BLOWS_H = 63512, + SPELL_FREEZE = 62469, + SPELL_BITTER_COLD = 62038, // SPELL BROKEN!!!! + SPELL_ICICLE = 62460, // full spell -> needs core fix + SPELL_ICE_SHARDS = 65370, // icicle damage -> 14k + SPELL_ICICLE_DUMMY = 62453, + SPELL_SNOWDRIFT = 62463, + SPELL_FLASH_FREEZE = 61968, + SPELL_FLASH_FREEZE_VIS = 62148, + SPELL_FLASH_FREEZE_STUN = 64175, + SPELL_FLASH_FREEZE_KILL = 62226, + SPELL_FLASH_FREEZE_NPC_STUN = 61990, // used to freeze npcs + + NPC_SNOWDRIFT_TARGET = 33174, + NPC_ICICLE = 33169, + NPC_SNOW_ICICLE = 33173, + NPC_FLASH_FREEZE = 32926, + NPC_FLASH_FREEZE_NPC = 32938, + + SAY_AGGRO = -1603085, + SAY_DEATH = -1603084, + SAY_SLAY01 = -1603083, + SAY_SLAY02 = -1603082, + SAY_FLASH_FREEZE = -1603081, + SAY_FROZEN_BLOWS = -1603080, + SAY_BERSERK = -1603087, + EMOTE_FLASH_FREEZE = -1603360, + EMOTE_FROZEN_BLOWS = -1603361, + + ACHIEV_RARE_CACHE = 3182, + ACHIEV_RARE_CACHE_H = 3184, + ACHIEV_COOLEST_FRIEND = 2963, + ACHIEV_COOLEST_FRIEND_H = 2965, + ACHIEV_GETTING_COLD = 2967, + ACHIEV_GETTING_COLD_H = 2968, + ACHIEV_CHEESE_FREEZE = 2961, + ACHIEV_CHEESE_FREEZE_H = 2962, + + // helper npcs + // druid + SPELL_WRATH = 62793, + SPELL_STARLIGHT = 62807, // friendly + + // shaman + SPELL_LAVA_BURST = 61924, + SPELL_STORM_CLOUD = 65123, // friendly + SPELL_STORM_CLOUD_H = 65133, + SPELL_STORM_POWER = 65134, // friendly + + // mage + SPELL_FIREBALL = 61909, + SPELL_TOASTY_FIRE = 62823, // friendly -> summon + NPC_TOASTY_FIRE = 33342, + SPELL_TOASTY_FIRE_A = 62821, + SPELL_MELT_ICE = 64528, + SPELL_SIGNED = 65280, + + // priest + SPELL_SMITE = 61923, + SPELL_GREAT_HEAL = 62809, //friendly + SPELL_DISPEL_MAGIC = 63499, //friendly - EMOTE_FLASH_FREEZE = -1603094, - EMOTE_FROZEN_BLOWS = -1603095, }; -void AddSC_boss_hodir() +#define CENTER_X 2000.0f +#define CENTER_Y -234.21f + +bool m_bCoolestFriend; + +// script for Flash freeze +struct MANGOS_DLL_DECL mob_flashFreezeAI : public ScriptedAI +{ + mob_flashFreezeAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->SetDisplayId(11686); // make invisible + SetCombatMovement(false); + Reset(); + } + + bool m_bIsRegularMode; + uint64 m_uiVictimGUID; + + void Reset() + { + m_uiVictimGUID = 0; + if(m_bIsRegularMode) + m_creature->SetMaxHealth(35000); + m_creature->SetRespawnDelay(DAY); + } + + void Aggro(Unit* pWho) + { + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoCast(pWho, SPELL_FLASH_FREEZE_STUN); + pWho->CastSpell(pWho, SPELL_FLASH_FREEZE_STUN, false); + m_uiVictimGUID = pWho->GetGUID(); + // kill targets that are frozen + if(pWho->HasAura(SPELL_FREEZE, EFFECT_INDEX_0)) + { + pWho->CastSpell(pWho, SPELL_FLASH_FREEZE_KILL, false); + m_creature->ForcedDespawn(); + } + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim) + pVictim->RemoveAurasDueToSpell(SPELL_FLASH_FREEZE_STUN); + } + + void JustDied(Unit* Killer) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit( m_uiVictimGUID)) + pVictim->RemoveAurasDueToSpell(SPELL_FLASH_FREEZE_STUN); + + if (Killer) + Killer->RemoveAurasDueToSpell(SPELL_FLASH_FREEZE_STUN); + } + + void UpdateAI(const uint32 diff) {} +}; + +// script for Icicles +struct MANGOS_DLL_DECL mob_icicleAI : public ScriptedAI +{ + mob_icicleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + SetCombatMovement(false); + pCreature->setFaction(14); + Reset(); + } + + uint32 m_uiSpellDelayTimer; + + void Reset() + { + DoCast(m_creature, SPELL_ICICLE); + m_uiSpellDelayTimer = 500; + } + + void AttackStart(Unit* pWho) + { + return; + } + + void UpdateAI(const uint32 diff) + { + if(m_uiSpellDelayTimer < diff) + { + DoCast(m_creature, SPELL_ICICLE_DUMMY); + m_uiSpellDelayTimer = 30000; + } + else m_uiSpellDelayTimer -= diff; + } +}; + +// Toasty fire. Used by mage +struct MANGOS_DLL_DECL mob_toasty_fireAI : public ScriptedAI +{ + mob_toasty_fireAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pCreature->SetDisplayId(11686); // make invisible + SetCombatMovement(false); + Reset(); + } + + void Reset() + { + DoCast(m_creature, SPELL_TOASTY_FIRE_A); + } + + void UpdateAI(const uint32 diff) {} +}; + +// Script for the Flash freeze which is enchasing the npcs in ice at the begginign of the fight +// this needs some fixing on spells +struct MANGOS_DLL_DECL mob_npc_flashFreezeAI : public ScriptedAI +{ + mob_npc_flashFreezeAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetDisplayId(25865); // invisible + pCreature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + std::list lVictims; + + void Reset() + { + lVictims.clear(); + SetVictim(); + DoCast(m_creature, SPELL_FLASH_FREEZE_NPC_STUN); + } + + void Aggro(Unit *who) + { + if (Creature* pHodir = GetClosestCreatureWithEntry(m_creature, NPC_HODIR, 100.0f)) + { + pHodir->AI()->AttackStart(who); + pHodir->AddThreat(who, 0.0f); + } + } + + void SetVictim() + { + // druids + GetCreatureListWithEntryInGrid(lVictims, m_creature, 33325, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 32901, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 32941, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 33333, 2.0f); + // shamys + GetCreatureListWithEntryInGrid(lVictims, m_creature, 33328, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 32900, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 33332, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 32950, 2.0f); + // mages + GetCreatureListWithEntryInGrid(lVictims, m_creature, 32893, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 33327, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 33331, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 32946, 2.0f); + // priests + GetCreatureListWithEntryInGrid(lVictims, m_creature, 32897, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 33326, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 32948, 2.0f); + GetCreatureListWithEntryInGrid(lVictims, m_creature, 33330, 2.0f); + if (!lVictims.empty()) + { + for(std::list::iterator iter = lVictims.begin(); iter != lVictims.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive() && !(*iter)->HasAura(SPELL_FLASH_FREEZE_NPC_STUN, EFFECT_INDEX_0)) + (*iter)->CastSpell((*iter), SPELL_FLASH_FREEZE_NPC_STUN, false); + } + } + } + + void JustDied(Unit* Killer) + { + if (!lVictims.empty()) + { + for(std::list::iterator iter = lVictims.begin(); iter != lVictims.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive() && (*iter)->HasAura(SPELL_FLASH_FREEZE_NPC_STUN, EFFECT_INDEX_0)) + { + (*iter)->RemoveAurasDueToSpell(SPELL_FLASH_FREEZE_NPC_STUN); + if (Creature* pHodir = GetClosestCreatureWithEntry(m_creature, NPC_HODIR, 100.0f)) + (*iter)->AddThreat(pHodir, 100.0f); + } + } + } + } + + void UpdateAI(const uint32 diff) + { } +}; + +// Hodir +struct MANGOS_DLL_DECL boss_hodirAI : public ScriptedAI +{ + boss_hodirAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + // hard mode timer + uint32 m_uiSpeedKillTimer; + + uint32 m_uiEnrageTimer; + uint32 m_uiFlashFreezeTimer; + uint32 m_uiFlashFreezeCastTimer; + uint32 m_uiFrozenBlowsTimer; + uint32 m_uiFreezeTimer; + uint32 m_uiIcicleTimer; + uint8 m_uiIcicleCount; + bool m_bIsCheese; + + bool m_bIsOutro; + uint32 m_uiOutroTimer; + uint32 m_uiStep; + + std::list lFriends; + + void Reset() + { + m_uiSpeedKillTimer = 0; + m_bCoolestFriend = true; + m_uiEnrageTimer = 480000; + m_uiFlashFreezeTimer = 50000; + m_uiFlashFreezeCastTimer= 90000; + m_uiFrozenBlowsTimer = 60000; + m_uiFreezeTimer = urand(15000, 20000); + m_uiIcicleTimer = 10000; + m_uiIcicleCount = 0; + m_uiOutroTimer = 10000; + m_uiStep = 1; + m_bIsOutro = false; + m_bIsCheese = true; + + // respawn friendly npcs + // druids + GetCreatureListWithEntryInGrid(lFriends, m_creature, 33325, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32901, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32941, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 33333, DEFAULT_VISIBILITY_INSTANCE); + // shamys + GetCreatureListWithEntryInGrid(lFriends, m_creature, 33328, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32900, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 33332, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32950, DEFAULT_VISIBILITY_INSTANCE); + // mages + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32893, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 33327, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 33331, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32946, DEFAULT_VISIBILITY_INSTANCE); + // priests + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32897, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 33326, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32948, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFriends, m_creature, 33330, DEFAULT_VISIBILITY_INSTANCE); + // flash freeze for them: + GetCreatureListWithEntryInGrid(lFriends, m_creature, 32938, DEFAULT_VISIBILITY_INSTANCE); + if (!lFriends.empty()) + { + for(std::list::iterator iter = lFriends.begin(); iter != lFriends.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); + } + } + } + + void JustReachedHome() + { + if(m_pInstance) + m_pInstance->SetData(TYPE_HODIR, NOT_STARTED); + } + + void Aggro(Unit *who) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_HODIR, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, m_creature); + + DoCast(m_creature, SPELL_BITTER_COLD); + } + + void DoOutro() + { + if(m_pInstance) + { + if(m_uiSpeedKillTimer < 180000) + { + m_pInstance->SetData(TYPE_HODIR_HARD, DONE); + m_pInstance->SetData(TYPE_HODIR, DONE); + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_RARE_CACHE : ACHIEV_RARE_CACHE_H); + } + else + m_pInstance->SetData(TYPE_HODIR, DONE); + + // hacky way to complete achievements; use only if you have this function + if (m_bCoolestFriend) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_COOLEST_FRIEND : ACHIEV_COOLEST_FRIEND_H); + + if (m_bIsCheese) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CHEESE_FREEZE : ACHIEV_CHEESE_FREEZE_H); + } + m_creature->ForcedDespawn(); + } + + // for debug only + void JustDied(Unit* pKiller) + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_HODIR, DONE); + if(m_uiSpeedKillTimer > 0) + m_pInstance->SetData(TYPE_HODIR_HARD, DONE); + } + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(m_creature->GetHealthPercent() < 1.0f) + { + uiDamage = 0; + m_bIsOutro = true; + } + } + + void KilledUnit(Unit *who) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY01, m_creature); + else + DoScriptText(SAY_SLAY02, m_creature); + } + + // Flash freeze. Hacky way, needs core support + // PLEASE REMOVE FOR REVISION! + void DoFlashFreeze() + { + std::list lSnowdrift; + GetCreatureListWithEntryInGrid(lSnowdrift, m_creature, NPC_SNOWDRIFT_TARGET, DEFAULT_VISIBILITY_INSTANCE); + + Map* pMap = m_creature->GetMap(); + if(pMap) + { + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + if (!lPlayers.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if(pPlayer && pPlayer->isAlive()) + { + if (!lSnowdrift.empty()) + { + for(std::list::iterator iter = lSnowdrift.begin(); iter != lSnowdrift.end(); ++iter) + { + if ((*iter) && pPlayer->GetDistance2d((*iter)) > 5.0f) + { + if(Creature* pTemp = m_creature->SummonCreature(NPC_FLASH_FREEZE, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000)) + pTemp->AddThreat(pPlayer, 100.0f); + // don't complete achievement + m_bIsCheese = false; + } + } + } + else + { + if(Creature* pTemp = m_creature->SummonCreature(NPC_FLASH_FREEZE, pPlayer->GetPositionX(), pPlayer->GetPositionY(), pPlayer->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 9000)) + pTemp->AddThreat(pPlayer, 100.0f); + } + } + } + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if(!m_bIsOutro) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // reset if fighting only the npcs + // this gets bugged if some of the npcs get top aggro + if(m_creature->getVictim()->GetTypeId() != TYPEID_PLAYER) + EnterEvadeMode(); + + // hard mode check + m_uiSpeedKillTimer += uiDiff; + + // Flash freeze visual + if(m_uiFlashFreezeTimer < uiDiff) + { + DoScriptText(EMOTE_FLASH_FREEZE, m_creature); + DoScriptText(SAY_FLASH_FREEZE, m_creature); + DoCast(m_creature, SPELL_FLASH_FREEZE); + m_uiFlashFreezeTimer = 50000; + m_uiFlashFreezeCastTimer = 9000; + } + else m_uiFlashFreezeTimer -= uiDiff; + + // hacky way for flash freeze + if (m_uiFlashFreezeCastTimer < uiDiff) + { + DoFlashFreeze(); + DoCast(m_creature, SPELL_FLASH_FREEZE_VIS); + m_uiFlashFreezeCastTimer = 90000; + } + else m_uiFlashFreezeCastTimer -= uiDiff; + + // icicles + // should be done be spell + if(m_uiIcicleTimer < uiDiff) + { + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = CENTER_X + urand(0, 30)*cos(angle*(M_PI/180)); + float homeY = CENTER_Y + urand(0, 30)*sin(angle*(M_PI/180)); + m_creature->SummonCreature(NPC_ICICLE, homeX, homeY, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 3000); + m_uiIcicleTimer = urand(2000, 5000); + } + else m_uiIcicleTimer -= uiDiff; + + // frozen blows + if(m_uiFrozenBlowsTimer < uiDiff) + { + DoScriptText(SAY_FROZEN_BLOWS, m_creature); + DoScriptText(EMOTE_FROZEN_BLOWS, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FROZEN_BLOWS : SPELL_FROZEN_BLOWS_H); + m_uiFrozenBlowsTimer = urand(50000, 60000); + } + else m_uiFrozenBlowsTimer -= uiDiff; + + // freeze + if(m_uiFreezeTimer < uiDiff) + { + if(Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, SPELL_FREEZE); + m_uiFreezeTimer = urand(5000, 10000); + } + else m_uiFreezeTimer -= uiDiff; + + // enrage + if(m_uiEnrageTimer < uiDiff) + { + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_ENRAGE); + m_uiEnrageTimer = 30000; + } + else m_uiEnrageTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } + // outro + if(m_bIsOutro) + { + switch(m_uiStep) + { + case 1: + m_creature->setFaction(35); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MovePoint(0, 1984.64f, -206.37f, 432.68f); + ++m_uiStep; + m_uiOutroTimer = 10000; + break; + case 3: + DoScriptText(SAY_DEATH, m_creature); + ++m_uiStep; + m_uiOutroTimer = 5000; + break; + case 5: + DoOutro(); + ++m_uiStep; + m_uiOutroTimer = 10000; + break; + } + } + else return; + + if (m_uiOutroTimer <= uiDiff) + { + ++m_uiStep; + m_uiOutroTimer = 330000; + } m_uiOutroTimer -= uiDiff; + } +}; + +// Helper npcs +struct MANGOS_DLL_DECL npc_hodir_druidAI : public ScriptedAI +{ + npc_hodir_druidAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 spellTimer; + std::list FriendlyList; + + void Reset() + { + spellTimer = 5000; + FriendlyList.clear(); + } + + void JustDied(Unit* pKiller) + { + m_bCoolestFriend = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + // friendly list + if (!m_creature->IsHostileTo(pWho) && !ListContains(FriendlyList, pWho->GetGUID()) && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 40, true)) + FriendlyList.push_back(pWho->GetGUID()); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho, 20.0f); + } + } + + uint64 SelectRandomPlayer() + { + //This should not appear! + if (FriendlyList.empty()){ + spellTimer = 5000; + return m_creature->GetGUID(); + } + + std::list::iterator iter = FriendlyList.begin(); + advance(iter, urand(0, FriendlyList.size()-1)); + + return *iter; + } + + bool ListContains(std::list &plist, uint64 element) + { + if (plist.empty()) + return false; + + std::list::iterator i; + for (i = plist.begin(); i!=plist.end(); ++i) + { + if ((*i) == element) + return true; + } + return false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (spellTimer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: + if(Creature *pHodir = GetClosestCreatureWithEntry(m_creature, NPC_HODIR, 100.0f)) + DoCast(pHodir, SPELL_WRATH); + break; + case 1: + Unit *pTemp = m_creature->GetMap()->GetUnit((SelectRandomPlayer())); + if (pTemp && pTemp->isAlive() && m_creature->GetDistance(pTemp) < 40) + DoCast(pTemp, SPELL_STARLIGHT); + break; + } + spellTimer = urand(2000, 5000); + }else spellTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_hodir_druid(Creature* pCreature) +{ + return new npc_hodir_druidAI(pCreature); +} + +struct MANGOS_DLL_DECL npc_hodir_shamanAI : public ScriptedAI +{ + npc_hodir_shamanAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance *pInstance; + + uint32 spellTimer; + std::list FriendlyList; + + void Reset() + { + spellTimer = 5000; + FriendlyList.clear(); + } + + void JustDied(Unit* pKiller) + { + m_bCoolestFriend = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + // friendly list + if (!m_creature->IsHostileTo(pWho) && !ListContains(FriendlyList, pWho->GetGUID()) && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 40, true)) + FriendlyList.push_back(pWho->GetGUID()); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho, 20.0f); + } + } + + uint64 SelectRandomPlayer() + { + //This should not appear! + if (FriendlyList.empty()){ + spellTimer = 5000; + return m_creature->GetGUID(); + } + + std::list::iterator iter = FriendlyList.begin(); + advance(iter, urand(0, FriendlyList.size()-1)); + + return *iter; + } + + bool ListContains(std::list &plist, uint64 element) + { + if (plist.empty()) + return false; + + std::list::iterator i; + for (i = plist.begin(); i!=plist.end(); ++i) + { + if ((*i) == element) + return true; + } + return false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (spellTimer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: + if(Creature *pHodir = GetClosestCreatureWithEntry(m_creature, NPC_HODIR, 100.0f)) + DoCast(pHodir, SPELL_LAVA_BURST); + break; + case 1: + Unit *pTemp = m_creature->GetMap()->GetUnit((SelectRandomPlayer())); + if (pTemp && pTemp->isAlive() && m_creature->GetDistance(pTemp) < 40) + DoCast(pTemp, m_bIsRegularMode ? SPELL_STORM_CLOUD : SPELL_STORM_CLOUD_H); + break; + } + spellTimer = urand(2000,5000); + }else spellTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_hodir_shaman(Creature* pCreature) +{ + return new npc_hodir_shamanAI(pCreature); +} + +struct MANGOS_DLL_DECL npc_hodir_mageAI : public ScriptedAI +{ + npc_hodir_mageAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 spellTimer; + std::list FriendlyList; + + void Reset() + { + spellTimer = 5000; + FriendlyList.clear(); + } + + void JustDied(Unit* pKiller) + { + m_bCoolestFriend = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + // friendly list + if (!m_creature->IsHostileTo(pWho) && !ListContains(FriendlyList, pWho->GetGUID()) && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 40, true)) + FriendlyList.push_back(pWho->GetGUID()); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho, 20.0f); + } + } + + uint64 SelectRandomPlayer() + { + //This should not appear! + if (FriendlyList.empty()){ + spellTimer = 5000; + return m_creature->GetGUID(); + } + + std::list::iterator iter = FriendlyList.begin(); + advance(iter, urand(0, FriendlyList.size()-1)); + + return *iter; + } + + bool ListContains(std::list &plist, uint64 element) + { + if (plist.empty()) + return false; + + std::list::iterator i; + for (i = plist.begin(); i!=plist.end(); ++i) + { + if ((*i) == element) + return true; + } + return false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (spellTimer < uiDiff) + { + switch(urand(0, 4)) + { + case 0: + if(Creature *pHodir = GetClosestCreatureWithEntry(m_creature, NPC_HODIR, 100.0f)) + DoCast(pHodir, SPELL_FIREBALL); + break; + case 1: + case 2: + if(Creature *pHodir = GetClosestCreatureWithEntry(m_creature, NPC_HODIR, 100.0f)) + DoCast(pHodir, SPELL_SIGNED); + break; + case 3: + if(Creature *pTemp = GetClosestCreatureWithEntry(m_creature, NPC_FLASH_FREEZE, 50.0f)) + DoCast(pTemp, SPELL_MELT_ICE); + break; + case 4: + Unit *pTemp = m_creature->GetMap()->GetUnit((SelectRandomPlayer())); + if (pTemp && pTemp->isAlive() && m_creature->GetDistance(pTemp) < 40) + DoCast(pTemp, SPELL_TOASTY_FIRE); + break; + } + spellTimer = urand(2000,5000); + }else spellTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_hodir_mage(Creature* pCreature) +{ + return new npc_hodir_mageAI(pCreature); +} + +struct MANGOS_DLL_DECL npc_hodir_priestAI : public ScriptedAI +{ + npc_hodir_priestAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance *pInstance; + + uint32 spellTimer; + std::list FriendlyList; + + void Reset() + { + spellTimer = 5000; + FriendlyList.clear(); + } + + void JustDied(Unit* pKiller) + { + m_bCoolestFriend = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + // friendly list + if (!m_creature->IsHostileTo(pWho) && !ListContains(FriendlyList, pWho->GetGUID()) && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 40, true)) + FriendlyList.push_back(pWho->GetGUID()); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho, 20.0f); + } + } + + uint64 SelectRandomPlayer() + { + //This should not appear! + if (FriendlyList.empty()){ + spellTimer = 5000; + return m_creature->GetGUID(); + } + + std::list::iterator iter = FriendlyList.begin(); + advance(iter, urand(0, FriendlyList.size()-1)); + + return *iter; + } + + bool ListContains(std::list &plist, uint64 element) + { + if (plist.empty()) + return false; + + std::list::iterator i; + for (i = plist.begin(); i!=plist.end(); ++i) + { + if ((*i) == element) + return true; + } + return false; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (spellTimer < uiDiff) + { + switch(urand(0, 4)) + { + case 0: + if(Creature *pHodir = GetClosestCreatureWithEntry(m_creature, NPC_HODIR, 100.0f)) + DoCast(pHodir, SPELL_SMITE); + break; + case 1: + case 2: + case 3: + if (Unit* pHealTarget = DoSelectLowestHpFriendly(40.0f)) + DoCast(pHealTarget, SPELL_GREAT_HEAL); + break; + case 4: + if (Unit* pTemp = m_creature->GetMap()->GetUnit((SelectRandomPlayer()))) + DoCast(m_creature, SPELL_DISPEL_MAGIC); + break; + } + spellTimer = urand(2000,5000); + }else spellTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_hodir_priest(Creature* pCreature) +{ + return new npc_hodir_priestAI(pCreature); +} + +CreatureAI* GetAI_boss_hodir(Creature* pCreature) { + return new boss_hodirAI(pCreature); +} + +CreatureAI* GetAI_mob_flashFreeze(Creature* pCreature) +{ + return new mob_flashFreezeAI(pCreature); +} +CreatureAI* GetAI_mob_icicle(Creature* pCreature) +{ + return new mob_icicleAI(pCreature); +} + +CreatureAI* GetAI_mob_toasty_fire(Creature* pCreature) +{ + return new mob_toasty_fireAI(pCreature); +} + +CreatureAI* GetAI_mob_npc_flashFreeze(Creature* pCreature) +{ + return new mob_npc_flashFreezeAI(pCreature); } + +void AddSC_boss_hodir() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_hodir"; + newscript->GetAI = &GetAI_boss_hodir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_flashFreeze"; + newscript->GetAI = &GetAI_mob_flashFreeze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_npc_flashFreeze"; + newscript->GetAI = &GetAI_mob_npc_flashFreeze; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_icicle"; + newscript->GetAI = &GetAI_mob_icicle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_toasty_fire"; + newscript->GetAI = &GetAI_mob_toasty_fire; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_hodir_priest"; + newscript->GetAI = &GetAI_npc_hodir_priest; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_hodir_mage"; + newscript->GetAI = &GetAI_npc_hodir_mage; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_hodir_druid"; + newscript->GetAI = &GetAI_npc_hodir_druid; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_hodir_shaman"; + newscript->GetAI = &GetAI_npc_hodir_shaman; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_ignis.cpp b/scripts/northrend/ulduar/ulduar/boss_ignis.cpp index ea98109..9655367 100644 --- a/scripts/northrend/ulduar/ulduar/boss_ignis.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_ignis.cpp @@ -1,45 +1,529 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_ignis -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: slag pot damage missing SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_AGGRO = -1603026, - SAY_SCORCH_1 = -1603027, - SAY_SCORCH_2 = -1603028, - SAY_SLAGPOT = -1603029, - SAY_ADDS = -1603030, - SAY_SLAY_1 = -1603031, - SAY_SLAY_2 = -1603032, - SAY_BERSERK = -1603033, - SAY_DEATH = -1603034, - - EMOTE_FLAME_JETS = -1603035, + //yells + SAY_AGGRO = -1603010, + SAY_SCORCH1 = -1603011, + SAY_SCORCH2 = -1603012, + SAY_SLAGPOT = -1603013, + EMOTE_FLAMEJETS = -1603014, + SAY_SUMMON = -1603015, + SAY_SLAY1 = -1603016, + SAY_SLAY2 = -1603017, + SAY_BERSERK = -1603018, + SAY_DEATH = -1603019, + + //ignis the furnace master + SPELL_FLAME_JETS = 62680, + SPELL_FLAME_JETS_H = 63472, + SPELL_SLAG_POT = 62717, + SPELL_SLAG_POT_H = 63477, + SPELL_SLAG_POT_DMG = 65722, + SPELL_SLAG_POT_DMG_H = 65723, + SPELL_SCORCH = 62546, + SPELL_SCORCH_H = 63474, + BUFF_STRENGHT_OF_CREATOR = 64473, + SPELL_STRENGHT_OF_CREATOR2 = 64474, + SPELL_STRENGHT_OF_CREATOR3 = 64475, + SPELL_HASTE = 66045, + SPELL_ENRAGE = 26662, + //iron construct + SPELL_HEAT = 65667, + SPELL_MOLTEN = 62373, + SPELL_BRITTLE = 62382, + SPELL_SHATTER = 62383, + //scorch target + AURA_SCORCH = 62548, + AURA_SCORCH_H = 63476, + AURA_HEAT = 65667, + SPELL_FREEZE_ANIM = 16245, + //NPC ids + MOB_IRON_CONSTRUCT = 33121, + MOB_SCORCH_TARGET = 33221, + + ACHIEV_STOKIN_THE_FURNACE = 2930, + ACHIEV_STOKIN_THE_FURNACE_H = 2929, + ACHIEV_SHATTERED = 2925, + ACHIEV_SHATTERED_H = 2926, }; -void AddSC_boss_ignis() +#define HOME_X 586.747009f +#define HOME_Y 381.997986f + +// scorch target +struct MANGOS_DLL_DECL mob_scorch_targetAI : public ScriptedAI +{ + mob_scorch_targetAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiDeath_Timer; + + void Reset() + { + m_uiDeath_Timer = 55000; + m_creature->SetDisplayId(11686); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, m_bIsRegularMode ? AURA_SCORCH : AURA_SCORCH_H); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + if (m_uiDeath_Timer < diff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDeath_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_scorch_target(Creature* pCreature) +{ + return new mob_scorch_targetAI(pCreature); +} + +// iron construct +struct MANGOS_DLL_DECL mob_iron_constructAI : public ScriptedAI +{ + mob_iron_constructAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiDeath_Timer; + uint32 m_uiAura_Check_Timer; + uint32 m_uiScorchTimer; + uint32 m_uiMoltenTimer; + uint32 m_uiBrittleTimer; + bool m_bIsBrittle; + bool m_bIsShatter; + bool m_bIsMolten; + bool m_bIsInCombat; + + uint32 m_uiWaterCheckTimer; + + void Reset() + { + m_bIsShatter = false; + m_bIsBrittle = false; + m_bIsMolten = false; + m_bIsInCombat = false; + m_uiWaterCheckTimer = 1000; + m_uiScorchTimer = 5000; + m_uiAura_Check_Timer = 1000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + DoCast(m_creature, SPELL_FREEZE_ANIM); + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + + // remove 1 stack of the buff from Ignis, hacky way, should be done by spell + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_IGNIS))) + { + if (pTemp->isAlive()) + { + if (pTemp->HasAura(BUFF_STRENGHT_OF_CREATOR)) + { + if(SpellAuraHolder* strenght = pTemp->GetSpellAuraHolder(BUFF_STRENGHT_OF_CREATOR)) + { + if(strenght->ModStackAmount(-1)) + pTemp->RemoveAurasDueToSpell(BUFF_STRENGHT_OF_CREATOR); + } + } + } + } + } + + // shatter if is brittle + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if (m_bIsBrittle) + { + if (uiDamage > 5000) + { + DoCast(m_creature, SPELL_SHATTER); + m_bIsShatter = true; + m_bIsBrittle = false; + m_uiDeath_Timer = 500; + } + } + } + + void AttackStart(Unit* pWho) + { + if(!m_bIsInCombat) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho); + } + } + + // set in combat + void GetInCombat() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + if (m_creature->HasAura(SPELL_FREEZE_ANIM, EFFECT_INDEX_0)) + m_creature->RemoveAurasDueToSpell(SPELL_FREEZE_ANIM); + m_bIsInCombat = true; + + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_IGNIS))) + { + if (pTemp->isAlive()) + { + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->GetMotionMaster()->MovePoint(0, pTemp->GetPositionX(), pTemp->GetPositionY(), pTemp->GetPositionZ()); + + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + m_creature->AddThreat(pTarget,100.0f); + m_creature->AI()->AttackStart(pTarget); + m_creature->SetInCombatWithZone(); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // death after casted shatter + if (m_uiDeath_Timer < uiDiff && m_bIsShatter) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDeath_Timer -= uiDiff; + + // check for aura + if (m_uiAura_Check_Timer < uiDiff && !m_bIsMolten) + { + if(Aura* aura = m_creature->GetAura(SPELL_HEAT,EFFECT_INDEX_0)) + { + if(aura->GetStackAmount() > 9) + { + DoCast(m_creature, SPELL_MOLTEN); + m_creature->RemoveAurasDueToSpell(SPELL_HEAT); + m_uiMoltenTimer = 30000; + m_bIsMolten = true; + } + } + m_uiAura_Check_Timer = 1000; + }else m_uiAura_Check_Timer -= uiDiff; + + //Water checks + if(m_bIsMolten) + { + // should work with Vmaps3 + if (m_uiWaterCheckTimer <= uiDiff) + { + if(m_creature->IsInWater()) + { + DoCast(m_creature, SPELL_BRITTLE); + m_bIsBrittle = true; + m_bIsMolten = false; + } + // workaround + /* else use workaround + if( m_creature->GetDistance2d(524.15f, 277.0f) < 18 || m_creature->GetDistance2d(648.5f, 277.0f) < 18) + { + DoCast(m_creature, SPELL_BRITTLE); + m_creature->RemoveAurasDueToSpell(SPELL_MOLTEN); + m_bIsBrittle = true; + m_bIsMolten = false; + }*/ + m_uiWaterCheckTimer = 500; + }else m_uiWaterCheckTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_iron_construct(Creature* pCreature) { + return new mob_iron_constructAI(pCreature); +} + +//ignis the furnace master +struct MANGOS_DLL_DECL boss_ignisAI : public ScriptedAI +{ + boss_ignisAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + std::list m_lIronConstructGUIDList; + uint32 m_uiFlame_Jets_Timer; + uint32 m_uiSlag_Pot_Timer; + uint32 m_uiSlag_Pot_Dmg_Timer; + uint32 m_uiScorch_Timer; + uint32 m_uiSummon_Timer; + uint32 m_uiPotDmgCount; + uint32 m_uiEnrageTimer; + + uint64 m_uiPotTargetGUID; + std::list lConstructs; + + uint32 m_uiEncounterTimer; + bool m_bHasSlagPotCasted; + + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + + m_uiFlame_Jets_Timer = 20000; + m_uiSlag_Pot_Timer = 25000; + m_uiSlag_Pot_Dmg_Timer = 26000; + m_uiScorch_Timer = 13000; + m_uiSummon_Timer = 10000; + m_uiEnrageTimer = 600000; // 10 MIN + m_uiPotDmgCount = 0; + m_uiPotTargetGUID = 0; + m_lIronConstructGUIDList.clear(); + + m_uiEncounterTimer = 0; + m_bHasSlagPotCasted = false; + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_IGNIS, DONE); + + DoScriptText(SAY_DEATH, m_creature); + + if (m_uiEncounterTimer < 240000) + { + // hacky way to complete achievements; use only if you have this function + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_STOKIN_THE_FURNACE : ACHIEV_STOKIN_THE_FURNACE_H); + } + } + + Creature* SelectRandomConstruct(float fRange) + { + std::list lConstructList; + GetCreatureListWithEntryInGrid(lConstructList, m_creature, MOB_IRON_CONSTRUCT, fRange); + + if (lConstructList.empty()){ + m_uiSummon_Timer = 5000; + return NULL; + } + + std::list::iterator iter = lConstructList.begin(); + advance(iter, urand(0, lConstructList.size()-1)); + + if((*iter)->isAlive()) + return *iter; + else + { + m_uiSummon_Timer = 500; + return NULL; + } + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_IGNIS, IN_PROGRESS); + + DoScriptText(SAY_AGGRO, m_creature); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_IGNIS, FAIL); + + // respawn constructs + GetCreatureListWithEntryInGrid(lConstructs, m_creature, MOB_IRON_CONSTRUCT, DEFAULT_VISIBILITY_INSTANCE); + if (!lConstructs.empty()) + { + for(std::list::iterator iter = lConstructs.begin(); iter != lConstructs.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + m_uiEncounterTimer += uiDiff; + + // enrage + if(m_uiEnrageTimer < uiDiff) + { + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_ENRAGE); + m_uiEnrageTimer = 30000; + } + else m_uiEnrageTimer -= uiDiff; + + if (m_uiFlame_Jets_Timer < uiDiff) + { + DoScriptText(EMOTE_FLAMEJETS, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_JETS : SPELL_FLAME_JETS_H); + m_uiFlame_Jets_Timer = 35000; + }else m_uiFlame_Jets_Timer -= uiDiff; + + // need vehicle support!!! + if (m_uiSlag_Pot_Timer < uiDiff) + { + DoScriptText(SAY_SLAGPOT, m_creature); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + { + DoCast(target, m_bIsRegularMode ? SPELL_SLAG_POT : SPELL_SLAG_POT_H); + m_uiPotTargetGUID = target->GetGUID(); + } + m_uiSlag_Pot_Timer = 30000; + m_uiSlag_Pot_Dmg_Timer = 1000; + m_bHasSlagPotCasted = true; + m_uiPotDmgCount = 0; + }else m_uiSlag_Pot_Timer -= uiDiff; + + // hacky way of doing damage + if (m_uiSlag_Pot_Dmg_Timer < uiDiff && m_bHasSlagPotCasted) + { + if (Unit* pPotTarget = m_creature->GetMap()->GetUnit( m_uiPotTargetGUID)) + { + if (m_uiPotDmgCount < 10) + DoCast(pPotTarget, m_bIsRegularMode ? SPELL_SLAG_POT_DMG : SPELL_SLAG_POT_DMG_H); + else if (m_uiPotDmgCount == 10) + { + if(pPotTarget->isAlive()) + pPotTarget->CastSpell(pPotTarget, SPELL_HASTE, false); + m_bHasSlagPotCasted = false; + } + } + ++m_uiPotDmgCount; + m_uiSlag_Pot_Dmg_Timer = 1000; + }else m_uiSlag_Pot_Dmg_Timer -= uiDiff; + + // call the golems + if (m_uiSummon_Timer < uiDiff) + { + DoScriptText(SAY_SUMMON, m_creature); + + if(Creature* pConstruct = SelectRandomConstruct(200.0f)) + { + ((mob_iron_constructAI*)pConstruct->AI())->GetInCombat(); + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pConstruct->AddThreat(target, 100.0f); + } + + m_uiSummon_Timer = 40000; + + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, BUFF_STRENGHT_OF_CREATOR); + }else m_uiSummon_Timer -= uiDiff; + + if (m_uiScorch_Timer < uiDiff) + { + if(irand(0,1)) + DoScriptText(SAY_SCORCH1, m_creature); + else + DoScriptText(SAY_SCORCH2, m_creature); + + DoCast(m_creature, m_bIsRegularMode ? SPELL_SCORCH : SPELL_SCORCH_H); + if (Creature* pTemp = m_creature->SummonCreature(MOB_SCORCH_TARGET, m_creature->getVictim()->GetPositionX(), m_creature->getVictim()->GetPositionY(), m_creature->getVictim()->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pTemp->AddThreat(m_creature->getVictim(),0.0f); + pTemp->AI()->AttackStart(m_creature->getVictim()); + } + m_uiScorch_Timer = 28000; + }else m_uiScorch_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + + if (m_creature->GetDistance2d(HOME_X, HOME_Y) > 200) + EnterEvadeMode(); + } +}; + +CreatureAI* GetAI_boss_ignis(Creature* pCreature) +{ + return new boss_ignisAI(pCreature); } + +void AddSC_boss_ignis() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_ignis"; + NewScript->GetAI = GetAI_boss_ignis; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_scorch_target"; + NewScript->GetAI = &GetAI_mob_scorch_target; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_iron_construct"; + NewScript->GetAI = &GetAI_mob_iron_construct; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_iron_council.cpp b/scripts/northrend/ulduar/ulduar/boss_iron_council.cpp new file mode 100644 index 0000000..eb5b292 --- /dev/null +++ b/scripts/northrend/ulduar/ulduar/boss_iron_council.cpp @@ -0,0 +1,1209 @@ +/* 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_iron_council +SD%Complete: +SDComment: Supercharge is bugged +SDCategory: Ulduar +EndScriptData */ + +#include "precompiled.h" +#include "def_ulduar.h" + +enum +{ + //yells + SAY_MOLGEIM_AGGRO = -1603040, + SAY_MOLGEIM_DEATH1 = -1603041, + SAY_MOLGEIM_DEATH2 = -1603042, + SAY_MOLGEIM_DEATH_RUNE = -1603043, + SAY_MOLGEIM_SUMMON = -1603044, + SAY_MOLGEIM_SLAY1 = -1603045, + SAY_MOLGEIM_SLAY2 = -1603046, + SAY_MOLGEIM_BERSERK = -1603047, + + SAY_STEEL_AGGRO = -1603050, + SAY_STEEL_DEATH1 = -1603051, + SAY_STEEL_DEATH2 = -1603052, + SAY_STEEL_SLAY1 = -1603053, + SAY_STEEL_SLAY2 = -1603054, + SAY_STEEL_OVERWHELMING = -1603055, + SAY_STEEL_BERSERK = -1603056, + + SAY_BRUNDIR_AGGR0 = -1603060, + SAY_BRUNDIR_WHIRL = -1603062, + SAY_BRUNDIR_DEATH1 = -1603063, + SAY_BRUNDIR_DEATH2 = -1603064, + SAY_BRUNDIR_SLAY1 = -1603065, + SAY_BRUNDIR_SLAY2 = -1603066, + SAY_BRUNDIR_BERSERK = -1603067, + SAY_BRUNDIR_FLY = -1603068, + + //all + SPELL_BERSERK = 47008, + SPELL_SUPERCHARGE = 61920, // spell is bugged. Should be cast on other bosses not on players!!! + //steelbreaker + SPELL_HIGH_VOLTAGE = 61890, + SPELL_HIGH_VOLTAGE_H = 63498, + SPELL_FUSION_PUNCH = 61903, + SPELL_FUSION_PUNCH_H = 63493, + SPELL_STATIC_DISRUPTION = 44008, + SPELL_STATIC_DISRUPTION_H = 63494, + SPELL_POWER = 64637, + SPELL_POWER_H = 61888, + SPELL_ELECTRICAL_CHARGE = 61902, + //runemaster molgeim + SPELL_SHIELD = 62274, + SPELL_SHIELD_H = 63489, + SPELL_RUNE_OF_POWER = 63513, + SPELL_RUNE_OF_DEATH = 62269, + SPELL_RUNE_OF_DEATH_H = 63490, + SPELL_RUNE_OF_SUMMONING = 62273, + //rune of power + AURA_RUNE_OF_POWER = 61974, + //rune of summoning + AURA_RUNE_OF_SUMMONING = 62019, + //lightning elemental + SPELL_LIGHTNING_BLAST = 62054, + SPELL_LIGHTNING_BLAST_H = 63491, + //stormcaller brundir + SPELL_CHAIN_LIGHTNING = 61879, + SPELL_CHAIN_LIGHTNING_H = 63479, + SPELL_OVERLOAD = 61869, + SPELL_LIGHTNING_WHIRL = 61915, + SPELL_LIGHTNING_WHIRL_H = 63483, + SPELL_STORMSHIELD = 64187, + SPELL_LIGHTNING_TENDRILS = 61887, + SPELL_LIGHTNING_TENDRILS_H = 63486, + LIGHTNING_TENDRILS_VISUAL = 61883, + //NPC ids + MOB_LIGHTNING_ELEMENTAL = 32958, + + ACHIEV_ON_YOUR_SIDE = 2945, + ACHIEV_ON_YOUR_SIDE_H = 2946, + SPELL_IRON_BOOT_AURA = 58501, + + ACHIEV_CHOOSE_BRUNDIR = 2940, + ACHIEV_CHOOSE_BRUNDIR_H = 2943, + ACHIEV_CHOOSE_MOLGEIM = 2939, + ACHIEV_CHOOSE_MOLGEIM_H = 2942, + ACHIEV_CHOOSE_STEELBREAKER = 2941, + ACHIEV_CHOOSE_STEELBREAKER_H= 2944, +}; + +// Rune of Power +struct MANGOS_DLL_DECL mob_rune_of_powerAI : public ScriptedAI +{ + mob_rune_of_powerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SetCombatMovement(false); + Reset(); + } + + uint32 m_uiDeath_Timer; + + void Reset() + { + m_uiDeath_Timer = 60000; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, AURA_RUNE_OF_POWER); + } + + void UpdateAI(const uint32 diff) + { + if (m_uiDeath_Timer < diff) + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + }else m_uiDeath_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_rune_of_power(Creature* pCreature) +{ + return new mob_rune_of_powerAI(pCreature); +} + +// Lightning Elemental +struct MANGOS_DLL_DECL mob_ulduar_lightning_elementalAI : public ScriptedAI +{ + mob_ulduar_lightning_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiDeath_Timer; + uint32 m_uiCheck_Timer; + bool m_bWillExplode; + + void Reset() + { + m_bWillExplode = false; + m_uiCheck_Timer = 1000; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiDeath_Timer < diff && m_bWillExplode) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDeath_Timer -= diff; + + if (m_uiCheck_Timer < diff) + { + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 15)) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_BLAST : SPELL_LIGHTNING_BLAST_H); + m_bWillExplode = true; + m_uiDeath_Timer = 500; + m_uiCheck_Timer = 5000; + } + m_uiCheck_Timer = 1000; + }else m_uiCheck_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_ulduar_lightning_elemental(Creature* pCreature) +{ + return new mob_ulduar_lightning_elementalAI(pCreature); +} + +// Rune of Summoning +struct MANGOS_DLL_DECL mob_rune_of_summoningAI : public ScriptedAI +{ + mob_rune_of_summoningAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiDeath_Timer; + uint32 m_uiSummon_Timer; + uint32 m_uiSummonNum; + + void Reset() + { + m_uiDeath_Timer = 0; + m_uiSummon_Timer = 5000; + m_uiSummonNum = 0; + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, AURA_RUNE_OF_SUMMONING); + } + + void JustSummoned(Creature* pSummoned) + { + pSummoned->SetInCombatWithZone(); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + pSummoned->AddThreat(pTarget, 100.0f); + } + + void UpdateAI(const uint32 diff) + { + if (m_uiSummon_Timer < diff) + { + if (Creature* pTemp = m_creature->SummonCreature(MOB_LIGHTNING_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + ++m_uiSummonNum; + + if (m_uiSummonNum > 9) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + m_uiSummon_Timer = 500; + } else m_uiSummon_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_rune_of_summoning(Creature* pCreature) +{ + return new mob_rune_of_summoningAI(pCreature); +} + +//Stormcaller Brundir +struct MANGOS_DLL_DECL boss_brundirAI : public ScriptedAI +{ + boss_brundirAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiChain_Lightning_Timer; + uint32 m_uiOverload_Timer; + uint32 m_uiWhirl_Timer; + uint32 m_uiTendrils_start_Timer; + uint32 m_uiTendrils_Change; + uint32 m_uiTendrils_end_Timer; + uint32 m_uiDie_delay; + uint32 m_uiEnrage_Timer; + uint32 m_uiCheckTimer; + + bool m_bHasSupercharge1; + bool m_bHasSupercharge2; + bool m_bIsTendrils; + bool m_bMustDie; + bool m_bIsSteelbreakerDead; + bool m_bIsMolgeimDead; + bool m_bIsEnrage; + + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_uiChain_Lightning_Timer = 0; + m_uiOverload_Timer = 35000; + m_uiEnrage_Timer = 900000; + m_uiCheckTimer = 1000; + m_bIsEnrage = false; + m_bHasSupercharge1 = false; + m_bHasSupercharge2 = false; + m_bIsTendrils = false; + m_bIsSteelbreakerDead = false; + m_bIsMolgeimDead = false; + m_bMustDie = false; + if (m_creature->HasAura(SPELL_SUPERCHARGE)) + m_creature->RemoveAurasDueToSpell(SPELL_SUPERCHARGE); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage > m_creature->GetHealth() && !m_bMustDie) + { + uiDamage = 0; + m_creature->CastStop(); + m_creature->RemoveAllAuras(); + DoCast(m_creature, SPELL_SUPERCHARGE); + m_uiDie_delay = 500; + m_bMustDie = true; + } + } + + void OnYourSide() + { + /* hacky way to complete achievements; use only if you have this function + Map* pMap = m_creature->GetMap(); + AchievementEntry const *AchievYourSide = GetAchievementStore()->LookupEntry(m_bIsRegularMode ? ACHIEV_ON_YOUR_SIDE : ACHIEV_ON_YOUR_SIDE_H); + if(AchievYourSide && pMap) + { + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + if (!lPlayers.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if(pPlayer->HasAura(SPELL_IRON_BOOT_AURA, EFFECT_INDEX_0)) + pPlayer->CompletedAchievement(AchievYourSide); + } + } + } + } + */ + } + + void JustDied(Unit* pKiller) + { + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + // if all of them are dead + if (m_pInstance) + { + // remove supercharge from players -> spell bug + //m_pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SUPERCHARGE); + // if the others are dead then give loot + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (!pTemp->isAlive()) + { + if (Creature* p2Temp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (!p2Temp->isAlive()) + { + m_pInstance->SetData(TYPE_ASSEMBLY, DONE); + // only the current one has loot, because loot modes are implemented in sql + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + // I'm on your side + OnYourSide(); + + // ChooseBrundir + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CHOOSE_BRUNDIR : ACHIEV_CHOOSE_BRUNDIR_H); + } + } + } + } + + // else make them full hp + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + } + + if(irand(0,1)) + DoScriptText(SAY_BRUNDIR_DEATH1, m_creature); + else + DoScriptText(SAY_BRUNDIR_DEATH2, m_creature); + } + + void Aggro(Unit* pWho) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + if (m_pInstance) + { + if(m_pInstance->GetData(TYPE_ASSEMBLY) != IN_PROGRESS) + m_pInstance->SetData(TYPE_ASSEMBLY, IN_PROGRESS); + } + + DoScriptText(SAY_BRUNDIR_AGGR0, m_creature); + } + + void JustReachedHome() + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (m_pInstance) + { + if(m_pInstance->GetData(TYPE_ASSEMBLY) != FAIL) + m_pInstance->SetData(TYPE_ASSEMBLY, FAIL); + } + } + + void KilledUnit(Unit *who) + { + if(irand(0,1)) + DoScriptText(SAY_BRUNDIR_SLAY1, m_creature); + else + DoScriptText(SAY_BRUNDIR_SLAY2, m_creature); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // level 1 spells + if (m_uiChain_Lightning_Timer < uiDiff && !m_bIsTendrils) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H); + m_uiChain_Lightning_Timer = 2000; + }else m_uiChain_Lightning_Timer -= uiDiff; + + if (m_uiOverload_Timer < uiDiff && !m_bIsTendrils) + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_OVERLOAD); + m_uiOverload_Timer = 40000; + }else m_uiOverload_Timer -= uiDiff; + + // level 2 spells + if (m_uiWhirl_Timer < uiDiff && !m_bIsTendrils && m_bHasSupercharge1) + { + m_creature->CastStop(); + DoScriptText(SAY_BRUNDIR_WHIRL, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_WHIRL : SPELL_LIGHTNING_WHIRL_H); + m_uiWhirl_Timer = 15000; + }else m_uiWhirl_Timer -= uiDiff; + + // level 3 spells + // boss doesn't fly during tendrils, needs fixing! + if (m_uiTendrils_start_Timer < uiDiff && m_bHasSupercharge2) + { + if (!m_bIsTendrils) + { + DoScriptText(SAY_BRUNDIR_FLY, m_creature); + m_creature->CastStop(); + DoCast(m_creature, LIGHTNING_TENDRILS_VISUAL); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + m_creature->AddThreat(pTarget,0.0f); + m_creature->AI()->AttackStart(pTarget); + } + m_bIsTendrils = true; + m_creature->SetSpeedRate(MOVE_RUN, 0.8f); + m_uiTendrils_start_Timer = 3000; + m_uiTendrils_end_Timer = 40000; + m_uiTendrils_Change = 5000; + } + else + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_TENDRILS : SPELL_LIGHTNING_TENDRILS_H); + m_uiTendrils_start_Timer = 90000; + } + }else m_uiTendrils_start_Timer -= uiDiff; + + if (m_uiTendrils_Change < uiDiff && m_bIsTendrils) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + m_creature->AddThreat(pTarget,0.0f); + m_creature->AI()->AttackStart(pTarget); + } + m_uiTendrils_Change = 6000; + }else m_uiTendrils_Change -= uiDiff; + + if (m_uiTendrils_end_Timer < uiDiff && m_bIsTendrils) + { + if (m_creature->HasAura(SPELL_LIGHTNING_TENDRILS)) + m_creature->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS); + if (m_creature->HasAura(SPELL_LIGHTNING_TENDRILS_H)) + m_creature->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS_H); + if (m_creature->HasAura(LIGHTNING_TENDRILS_VISUAL)) + m_creature->RemoveAurasDueToSpell(LIGHTNING_TENDRILS_VISUAL); + m_uiTendrils_start_Timer = 90000; + m_creature->SetSpeedRate(MOVE_RUN, 1.8f); + m_bIsTendrils = false; + m_uiChain_Lightning_Timer = 5000; + m_uiOverload_Timer = 35000; + m_uiWhirl_Timer = 10000; + }else m_uiTendrils_end_Timer -= uiDiff; + + // die after casting supercharge + if (m_uiDie_delay < uiDiff && m_bMustDie) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDie_delay -= uiDiff; + + if (m_uiEnrage_Timer < uiDiff && !m_bIsEnrage) + { + DoScriptText(SAY_BRUNDIR_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_BERSERK); + m_bIsEnrage = true; + }else m_uiEnrage_Timer -= uiDiff; + + // check if the others are dead + if (m_uiCheckTimer < uiDiff && !m_bHasSupercharge2) + { + if (!m_bIsSteelbreakerDead) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (!pTemp->isAlive()) + { + m_bIsSteelbreakerDead = true; + if (!m_bHasSupercharge1) + { + m_bHasSupercharge1 = true; + m_uiWhirl_Timer = 10000; + } + else + { + m_bHasSupercharge2 = true; + m_uiTendrils_start_Timer = 40000; + m_uiTendrils_end_Timer = 60000; + m_uiTendrils_Change = 6000; + } + } + } + } + if (!m_bIsMolgeimDead) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (!pTemp->isAlive()) + { + m_bIsMolgeimDead = true; + if (!m_bHasSupercharge1) + { + m_bHasSupercharge1 = true; + m_uiWhirl_Timer = 10000; + } + else + { + m_bHasSupercharge2 = true; + m_uiTendrils_start_Timer = 40000; + m_uiTendrils_end_Timer = 60000; + m_uiTendrils_Change = 6000; + } + } + } + } + m_uiCheckTimer = 1000; + }else m_uiCheckTimer -= uiDiff; + + if (!m_bIsTendrils && !m_bMustDie) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_brundir(Creature* pCreature) +{ + return new boss_brundirAI(pCreature); +} + +//Runemaster Molgeim +struct MANGOS_DLL_DECL boss_molgeimAI : public ScriptedAI +{ + boss_molgeimAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiShield_Timer; + uint32 m_uiRune_Power_Timer; + uint32 m_uiRune_Death_Timer; + uint32 m_uiRune_Summon_Timer; + uint32 m_uiDie_delay; + uint32 m_uiEnrage_Timer; + uint32 m_uiCheckTimer; + + bool m_bSupercharge1; + bool m_bSupercharge2; + bool m_bMustDie; + bool m_bBrundirDead; + bool m_bSteelbreakerDead; + bool m_bEnrage; + + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_uiShield_Timer = 20000; + m_uiRune_Power_Timer = 10000; + m_uiEnrage_Timer = 900000; + m_uiCheckTimer = 1000; + m_bEnrage = false; + m_bBrundirDead = false; + m_bSteelbreakerDead = false; + m_bSupercharge1 = false; + m_bSupercharge2 = false; + m_bMustDie = false; + if (m_creature->HasAura(SPELL_SUPERCHARGE)) + m_creature->RemoveAurasDueToSpell(SPELL_SUPERCHARGE); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage > m_creature->GetHealth() && !m_bMustDie) + { + uiDamage = 0; + m_creature->RemoveAllAuras(); + m_creature->CastStop(); + DoCast(m_creature, SPELL_SUPERCHARGE); + m_uiDie_delay = 500; + m_bMustDie = true; + } + } + + void OnYourSide() + { + /* hacky way to complete achievements; use only if you have this function + Map* pMap = m_creature->GetMap(); + AchievementEntry const *AchievYourSide = GetAchievementStore()->LookupEntry(m_bIsRegularMode ? ACHIEV_ON_YOUR_SIDE : ACHIEV_ON_YOUR_SIDE_H); + if(AchievYourSide && pMap) + { + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + if (!lPlayers.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if(pPlayer->HasAura(SPELL_IRON_BOOT_AURA, EFFECT_INDEX_0)) + pPlayer->CompletedAchievement(AchievYourSide); + } + } + } + } + */ + } + + void JustDied(Unit* pKiller) + { + //death yell + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (m_pInstance) + { + // remove supercharge from players -> spell bug + //m_pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SUPERCHARGE); + // if the others are dead then give loot + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (!pTemp->isAlive()) + { + if (Creature* p2Temp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (!p2Temp->isAlive()) + { + m_pInstance->SetData(TYPE_ASSEMBLY, DONE); + // only the current one has loot, because loot modes are implemented in sql + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + // I'm on your side + OnYourSide(); + + // ChooseMolgeim + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CHOOSE_MOLGEIM : ACHIEV_CHOOSE_MOLGEIM_H); + } + } + } + } + + // else make them full hp + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + } + + if(irand(0,1)) + DoScriptText(SAY_MOLGEIM_DEATH1, m_creature); + else + DoScriptText(SAY_MOLGEIM_DEATH2, m_creature); + } + + void Aggro(Unit* pWho) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + if (m_pInstance) + { + if(m_pInstance->GetData(TYPE_ASSEMBLY) != IN_PROGRESS) + m_pInstance->SetData(TYPE_ASSEMBLY, IN_PROGRESS); + } + + DoScriptText(SAY_MOLGEIM_AGGRO, m_creature); + } + + void JustReachedHome() + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (m_pInstance) + { + if(m_pInstance->GetData(TYPE_ASSEMBLY) != FAIL) + m_pInstance->SetData(TYPE_ASSEMBLY, FAIL); + } + } + + void KilledUnit(Unit *who) + { + if(irand(0,1)) + DoScriptText(SAY_MOLGEIM_SLAY1, m_creature); + else + DoScriptText(SAY_MOLGEIM_SLAY2, m_creature); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // level 1 spells + if (m_uiShield_Timer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHIELD : SPELL_SHIELD_H); + m_uiShield_Timer = 50000; + }else m_uiShield_Timer -= uiDiff; + + if (m_uiRune_Power_Timer < uiDiff) + { + switch(urand(0, 2)) + { + case 0: + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (pTemp->isAlive()) + DoCast(pTemp, SPELL_RUNE_OF_POWER); + else + DoCast(m_creature, SPELL_RUNE_OF_POWER); + } + break; + case 1: + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (pTemp->isAlive()) + DoCast(pTemp, SPELL_RUNE_OF_POWER); + else + DoCast(m_creature, SPELL_RUNE_OF_POWER); + } + break; + case 2: + DoCast(m_creature, SPELL_RUNE_OF_POWER); + break; + } + m_uiRune_Power_Timer = 30000; + }else m_uiRune_Power_Timer -= uiDiff; + + // level2 spells + if (m_uiRune_Death_Timer < uiDiff && m_bSupercharge1) + { + DoScriptText(SAY_MOLGEIM_DEATH_RUNE, m_creature); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_RUNE_OF_DEATH : SPELL_RUNE_OF_DEATH_H); + m_uiRune_Death_Timer = 30000; + }else m_uiRune_Death_Timer -= uiDiff; + + // level 3 spells + if (m_uiRune_Summon_Timer < uiDiff && m_bSupercharge2) + { + DoScriptText(SAY_MOLGEIM_SUMMON, m_creature); + m_creature->CastStop(); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_RUNE_OF_SUMMONING); + m_uiRune_Summon_Timer = 30000; + }else m_uiRune_Summon_Timer -= uiDiff; + + // die after overloading + if (m_uiDie_delay < uiDiff && m_bMustDie) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDie_delay -= uiDiff; + + if (m_uiEnrage_Timer < uiDiff && !m_bEnrage) + { + DoScriptText(SAY_MOLGEIM_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_BERSERK); + m_bEnrage = true; + }else m_uiEnrage_Timer -= uiDiff; + + if (m_uiCheckTimer < uiDiff) + { + if (!m_bSteelbreakerDead) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_STEELBREAKER))) + { + if (!pTemp->isAlive()) + { + m_bSteelbreakerDead = true; + if (!m_bSupercharge1) + { + m_bSupercharge1 = true; + m_uiRune_Death_Timer = 10000; + } + else + { + m_bSupercharge2 = true; + m_uiRune_Summon_Timer = 20000; + } + } + } + } + if (!m_bBrundirDead) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (!pTemp->isAlive()) + { + m_bBrundirDead = true; + if (!m_bSupercharge1) + { + m_bSupercharge1 = true; + m_uiRune_Death_Timer = 10000; + } + else + { + m_bSupercharge2 = true; + m_uiRune_Summon_Timer = 20000; + } + } + } + } + m_uiCheckTimer = 1000; + }else m_uiCheckTimer -= uiDiff; + + if (!m_bMustDie) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_molgeim(Creature* pCreature) +{ + return new boss_molgeimAI(pCreature); +} + +//Steelbreaker +struct MANGOS_DLL_DECL boss_steelbreakerAI : public ScriptedAI +{ + boss_steelbreakerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiFusion_Punch_Timer; + uint32 m_uiStatic_Disruption_Timer; + uint32 m_uiPower_Timer; + uint32 m_uiDie_delay; + uint32 m_uiEnrage_Timer; + uint32 m_uiCheckTimer; + + bool m_bBrundirDead; + bool m_bMolgeimDead; + bool m_bSupercharge1; + bool m_bSupercharge2; + bool m_bMustDie; + bool m_bEnrage; + + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_uiFusion_Punch_Timer = 20000; + m_uiEnrage_Timer = 900000; + m_uiCheckTimer = 1000; + m_bEnrage = false; + m_bBrundirDead = false; + m_bMolgeimDead = false; + m_bSupercharge1 = false; + m_bSupercharge2 = false; + m_bMustDie = false; + if (m_creature->HasAura(SPELL_SUPERCHARGE)) + m_creature->RemoveAurasDueToSpell(SPELL_SUPERCHARGE); + if (m_creature->HasAura(SPELL_ELECTRICAL_CHARGE)) + m_creature->RemoveAurasDueToSpell(SPELL_ELECTRICAL_CHARGE); + if (m_creature->HasAura(SPELL_HIGH_VOLTAGE)) + m_creature->RemoveAurasDueToSpell(SPELL_HIGH_VOLTAGE); + if (m_creature->HasAura(SPELL_HIGH_VOLTAGE_H)) + m_creature->RemoveAurasDueToSpell(SPELL_HIGH_VOLTAGE_H); + } + + void KilledUnit(Unit* pVictim) + { + if (m_bSupercharge2) + DoCast(m_creature, SPELL_ELECTRICAL_CHARGE); + + if(irand(0,1)) + DoScriptText(SAY_STEEL_SLAY1, m_creature); + else + DoScriptText(SAY_STEEL_SLAY2, m_creature); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage > m_creature->GetHealth() && !m_bMustDie) + { + uiDamage = 0; + m_creature->CastStop(); + m_creature->RemoveAllAuras(); + DoCast(m_creature, SPELL_SUPERCHARGE); + m_uiDie_delay = 500; + m_bMustDie = true; + } + } + + void OnYourSide() + { + /* hacky way to complete achievements; use only if you have this function + Map* pMap = m_creature->GetMap(); + AchievementEntry const *AchievYourSide = GetAchievementStore()->LookupEntry(m_bIsRegularMode ? ACHIEV_ON_YOUR_SIDE : ACHIEV_ON_YOUR_SIDE_H); + if(AchievYourSide && pMap) + { + Map::PlayerList const &lPlayers = pMap->GetPlayers(); + if (!lPlayers.isEmpty()) + { + for(Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr) + { + if (Player* pPlayer = itr->getSource()) + { + if(pPlayer->HasAura(SPELL_IRON_BOOT_AURA, EFFECT_INDEX_0)) + pPlayer->CompletedAchievement(AchievYourSide); + } + } + } + } + */ + } + + void JustDied(Unit* pKiller) + { + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if (m_pInstance) + { + // remove supercharge from players -> spell bug + // m_pInstance->DoRemoveAurasDueToSpellOnPlayers(SPELL_SUPERCHARGE); + // if the others are dead then give loot + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (!pTemp->isAlive()) + { + if (Creature* p2Temp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (!p2Temp->isAlive()) + { + m_pInstance->SetData(TYPE_ASSEMBLY, DONE); + m_pInstance->SetData(TYPE_ASSEMBLY_HARD, DONE); + // only the current one has loot, because loot modes are implemented in sql + m_creature->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + + // I'm on your side + OnYourSide(); + + // ChooseSteelbreaker + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_CHOOSE_STEELBREAKER : ACHIEV_CHOOSE_STEELBREAKER_H); + } + } + } + } + + // else make them full hp + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (pTemp->isAlive()) + pTemp->SetHealth(pTemp->GetMaxHealth()); + } + } + + if(irand(0,1)) + DoScriptText(SAY_STEEL_DEATH1, m_creature); + else + DoScriptText(SAY_STEEL_DEATH2, m_creature); + } + + void Aggro(Unit* pWho) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + DoCast(m_creature, m_bIsRegularMode ? SPELL_HIGH_VOLTAGE : SPELL_HIGH_VOLTAGE_H); + if (m_pInstance) + { + if(m_pInstance->GetData(TYPE_ASSEMBLY) != IN_PROGRESS) + m_pInstance->SetData(TYPE_ASSEMBLY, IN_PROGRESS); + } + + DoScriptText(SAY_STEEL_AGGRO, m_creature); + } + + void JustReachedHome() + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (m_pInstance) + { + if(m_pInstance->GetData(TYPE_ASSEMBLY) != FAIL) + m_pInstance->SetData(TYPE_ASSEMBLY, FAIL); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // level 1 spells + if (m_uiFusion_Punch_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FUSION_PUNCH : SPELL_FUSION_PUNCH_H); + m_uiFusion_Punch_Timer = 20000; + }else m_uiFusion_Punch_Timer -= uiDiff; + + // level 2 spells + if (m_uiStatic_Disruption_Timer < uiDiff && m_bSupercharge1) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_STATIC_DISRUPTION : SPELL_STATIC_DISRUPTION_H); + m_uiStatic_Disruption_Timer = 60000; + }else m_uiStatic_Disruption_Timer -= uiDiff; + + // level 3 spells + if (m_uiPower_Timer < uiDiff && m_bSupercharge2) + { + m_creature->CastStop(); + DoScriptText(SAY_STEEL_OVERWHELMING, m_creature); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_POWER : SPELL_POWER_H); + m_uiPower_Timer = m_bIsRegularMode ? 65000 : 35000; + }else m_uiPower_Timer -= uiDiff; + + if (m_uiDie_delay < uiDiff && m_bMustDie) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDie_delay -= uiDiff; + + if (m_uiEnrage_Timer < uiDiff && !m_bEnrage) + { + DoScriptText(SAY_STEEL_BERSERK, m_creature); + m_creature->CastStop(); + DoCast(m_creature, SPELL_BERSERK); + m_bEnrage = true; + }else m_uiEnrage_Timer -= uiDiff; + + if (m_uiCheckTimer < uiDiff) + { + if (!m_bBrundirDead) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_BRUNDIR))) + { + if (!pTemp->isAlive()) + { + m_bBrundirDead = true; + if (!m_bSupercharge1) + { + m_bSupercharge1 = true; + m_uiStatic_Disruption_Timer = 12000; + } + else + { + m_bSupercharge2 = true; + m_uiPower_Timer = 5000; + } + } + } + } + if (!m_bMolgeimDead) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MOLGEIM))) + { + if (!pTemp->isAlive()) + { + m_bMolgeimDead = true; + if (!m_bSupercharge1) + { + m_bSupercharge1 = true; + m_uiStatic_Disruption_Timer = 22000; + } + else + { + m_bSupercharge2 = true; + m_uiPower_Timer = 5000; + } + } + } + } + m_uiCheckTimer = 1000; + }else m_uiCheckTimer -= uiDiff; + + if (!m_bMustDie) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_steelbreaker(Creature* pCreature) +{ + return new boss_steelbreakerAI(pCreature); +} + +void AddSC_boss_iron_council() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_brundir"; + NewScript->GetAI = GetAI_boss_brundir; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_molgeim"; + NewScript->GetAI = GetAI_boss_molgeim; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_steelbreaker"; + NewScript->GetAI = GetAI_boss_steelbreaker; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_rune_of_power"; + NewScript->GetAI = &GetAI_mob_rune_of_power; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_rune_of_summoning"; + NewScript->GetAI = &GetAI_mob_rune_of_summoning; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_ulduar_lightning_elemental"; + NewScript->GetAI = &GetAI_mob_ulduar_lightning_elemental; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp b/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp index 37980c8..775a7c0 100644 --- a/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp @@ -1,47 +1,633 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_kologarn -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: stone grip and arms need vehicles SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_AGGRO = -1603126, - SAY_SHOCKWAVE = -1603127, - SAY_GRAB = -1603128, - SAY_ARM_LOST_LEFT = -1603129, - SAY_ARM_LOST_RIGHT = -1603130, - SAY_SLAY_1 = -1603131, - SAY_SLAY_2 = -1603132, - SAY_BERSERK = -1603133, - SAY_DEATH = -1603134, - - EMOTE_ARM_RIGHT = -1603135, - EMOTE_ARM_LEFT = -1603136, - EMOTE_STONE_GRIP = -1603137, + //yells + SAY_AGGRO = -1603150, + SAY_SHOCKWEAVE = -1603151, + SAY_GRAB = -1603152, + SAY_LEFT_ARM_LOST = -1603153, + SAY_RIGHT_ARM_LOST = -1603154, + SAY_SLAY1 = -1603155, + SAY_SLAY2 = -1603156, + SAY_BERSERK = -1603157, + SAY_DEATH = -1603158, + EMOTE_RIGHT_ARM = -1603355, + EMOTE_LEFT_ARM = -1603356, + EMOTE_STONE_GRIP = -1603357, + + //kologarn + SPELL_OVERHEAD_SMASH = 63356, + SPELL_OVERHEAD_SMASH_H = 64003, + SPELL_ONE_ARMED_SMASH = 63573, + SPELL_ONE_ARMED_SMASH_H = 64006, + SPELL_STONE_SHOUT = 63716, + SPELL_STONE_SHOUT_H = 64005, + SPELL_PETRIFYING_BREATH = 62030, + SPELL_PETRIFYING_BREATH_H = 63980, + SPELL_FOCUSED_EYEBEAM = 63346, + SPELL_FOCUSED_EYEBEAM_H = 63976, + SPELL_FOCUSED_EYEBEAM_TRIG = 63369, + SPELL_FOCUSED_EYEBEAM_VISUAL= 63368, + SPELL_ENRAGE = 26662, + //left arm + SPELL_SHOCKWAVE = 63783, + SPELL_SHOCKWAVE_H = 63982, + //right arm + SPELL_STONE_GRIP_GRAB = 63981, // not working + SPELL_STONE_GRIP = 64290, + SPELL_STONE_GRIP_H = 64292, + //both + SPELL_ARM_VISUAL = 64753, + //rubble + SPELL_RUMBLE = 63818, // on 10 man + SPELL_STONE_NOVA = 63978, // on 25 man + //NPC ids + MOB_RUBBLE = 33768, + + ACHIEV_RUBBLE_AND_ROLL = 2959, + ACHIEV_RUBBLE_AND_ROLL_H = 2960, + ACHIEV_WITH_OPEN_ARMS = 2951, + ACHIEV_WITH_OPEN_ARMS_H = 2952, + ACHIEV_DISARMED = 2953, + ACHIEV_DISARMED_H = 2954, + ACHIEV_IF_LOOKS_COULD_KILL = 2955, + ACHIEV_IF_LOOKS_COULD_KILL_H= 2956, }; -void AddSC_boss_kologarn() +float LeftArm[3] = {1784.742f, -39.962f, 448.805f}; +float RightArm[3] = {1785.615f, -5.516f, 448.810f}; +const float KoloFront[3] = {1771.683f, -24.230f, 448.806f}; + +// Rubble +struct MANGOS_DLL_DECL mob_ulduar_rubbleAI : public ScriptedAI +{ + mob_ulduar_rubbleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiStone_Nova_Timer; + + void Reset() + { + m_uiStone_Nova_Timer = urand(8000, 12000); + m_creature->SetRespawnDelay(DAY); + } + + void UpdateAI(const uint32 diff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_KOLOGARN) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiStone_Nova_Timer < diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_RUMBLE : SPELL_STONE_NOVA); + m_uiStone_Nova_Timer = urand(7000, 9000); + }else m_uiStone_Nova_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_ulduar_rubble(Creature* pCreature) +{ + return new mob_ulduar_rubbleAI(pCreature); +} + +// Left Arm +struct MANGOS_DLL_DECL boss_left_armAI : public ScriptedAI +{ + boss_left_armAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiShockwave_Timer; + + void Reset() + { + m_uiShockwave_Timer = 30000; + DoCast(m_creature, SPELL_ARM_VISUAL); + m_creature->SetRespawnDelay(DAY); + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RIGHT_ARM))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_KOLOGARN))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_KOLOGARN))) + { + DoScriptText(SAY_LEFT_ARM_LOST, pTemp); + if (pTemp->isAlive()) + pTemp->DealDamage(pTemp, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiShockwave_Timer < diff) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_KOLOGARN))) + DoScriptText(SAY_SHOCKWEAVE, pTemp); + + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHOCKWAVE : SPELL_SHOCKWAVE_H); + m_uiShockwave_Timer = 17000; + }else m_uiShockwave_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_left_arm(Creature* pCreature) +{ + return new boss_left_armAI(pCreature); +} + +// Right Arm +struct MANGOS_DLL_DECL boss_right_armAI : public ScriptedAI +{ + boss_right_armAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiStone_Grip_Timer; + uint32 m_uiFreeDamage; + uint32 m_uiMaxDamage; + uint64 m_uiGripTargetGUID[3]; + uint8 m_uiMaxTargets; + + void Reset() + { + m_uiStone_Grip_Timer = 20000; + m_uiMaxTargets = m_bIsRegularMode ? 1 : 3; + for(int i = 0; i < m_uiMaxTargets; i++) + m_uiGripTargetGUID[i] = 0; + m_uiFreeDamage = 0; + m_uiMaxDamage = m_bIsRegularMode ? 100000 : 480000; + + DoCast(m_creature, SPELL_ARM_VISUAL); + m_creature->SetRespawnDelay(DAY); + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEFT_ARM))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_KOLOGARN))) + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim) + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H); + } + + void JustReachedHome() + { + //if (m_pInstance) + //m_pInstance->DoRemoveAurasDueToSpellOnPlayers(m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + m_uiFreeDamage += uiDamage; + } + + void JustDied(Unit* pKiller) + { + if (!m_pInstance) + return; + + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_KOLOGARN))) + { + DoScriptText(SAY_RIGHT_ARM_LOST, pTemp); + if (pTemp->isAlive()) + pTemp->DealDamage(pTemp, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + for(int i = 0; i < m_uiMaxTargets; i++) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit( m_uiGripTargetGUID[i])) + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiFreeDamage > m_uiMaxDamage) + { + m_uiFreeDamage = 0; + for(int i = 0; i < m_uiMaxTargets; i++) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit( m_uiGripTargetGUID[i])) + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H); + } + } + + if (m_uiStone_Grip_Timer < diff) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_KOLOGARN))) + DoScriptText(SAY_GRAB, pTemp); + + DoScriptText(EMOTE_STONE_GRIP, m_creature); + + // this needs vehicles! + for(int i = 0; i < m_uiMaxTargets; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)){ + pTarget->CastSpell(pTarget, m_bIsRegularMode ? SPELL_STONE_GRIP : SPELL_STONE_GRIP_H, false); + m_uiGripTargetGUID[i] = pTarget->GetGUID(); + } + } + m_uiStone_Grip_Timer = 30000; + }else m_uiStone_Grip_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_right_arm(Creature* pCreature) +{ + return new boss_right_armAI(pCreature); +} + +// Kologarn +struct MANGOS_DLL_DECL boss_kologarnAI : public ScriptedAI { + boss_kologarnAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiSpell_Timer; + uint32 m_uiCheck_Timer; + uint32 m_uiEyebeah_Timer; + uint32 m_uiRespawnRightTimer; + uint32 m_uiRespawnLeftTimer; + uint32 m_uiEnrageTimer; + + uint32 m_uiRubbleNo; + bool m_bHasLeftDied; + bool m_bHasRightDied; + uint32 m_uiDisarmedTimer; + bool m_bOpenArms; + + bool m_bIsRightDead; + bool m_bIsLeftDead; + + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + + m_uiSpell_Timer = 10000; + m_uiCheck_Timer = 6300; + m_uiEnrageTimer = 600000; + m_uiEyebeah_Timer = 10000 + urand(1000, 5000); + m_bIsRightDead = false; + m_bIsLeftDead = false; + + m_uiRubbleNo = 0; + m_bHasLeftDied = false; + m_bHasRightDied = false; + m_bOpenArms = true; + m_uiDisarmedTimer = 0; + } + + void JustDied(Unit* pKiller) + { + DoScriptText(SAY_DEATH, m_creature); + + // hacky way to complete achievements; use only if you have this function + // Rubble and roll + if (m_uiRubbleNo >= 25) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_RUBBLE_AND_ROLL : ACHIEV_RUBBLE_AND_ROLL_H); + } + + // With open arms + if (m_bOpenArms) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_WITH_OPEN_ARMS : ACHIEV_WITH_OPEN_ARMS_H); + } + + // Disarmed + if (m_bHasLeftDied && m_bHasRightDied && m_uiDisarmedTimer <= 12000) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_DISARMED : ACHIEV_DISARMED_H); + } + + //death yell + if (m_pInstance) + { + m_pInstance->SetData(TYPE_KOLOGARN, DONE); + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEFT_ARM))) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RIGHT_ARM))) + { + if (pTemp->isAlive()) + pTemp->ForcedDespawn(); + } + } + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_KOLOGARN, IN_PROGRESS); + + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEFT_ARM))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RIGHT_ARM))) + { + if (pTemp->isAlive()) + pTemp->SetInCombatWithZone(); + } + } + //aggro yell + DoScriptText(SAY_AGGRO, m_creature); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); + } + + void JustReachedHome() + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_KOLOGARN, FAIL); + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEFT_ARM))) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RIGHT_ARM))) + { + if (!pTemp->isAlive()) + pTemp->Respawn(); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + if (!m_bIsRightDead && !m_bIsLeftDead) + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_OVERHEAD_SMASH : SPELL_OVERHEAD_SMASH_H); + else if (m_bIsRightDead && m_bIsLeftDead) + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_STONE_SHOUT : SPELL_STONE_SHOUT_H); + else + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ONE_ARMED_SMASH : SPELL_ONE_ARMED_SMASH_H); + m_uiSpell_Timer = 20000; + }else m_uiSpell_Timer -= uiDiff; + // to be fixed -> only damage, no animation + if (m_uiEyebeah_Timer < uiDiff) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + DoCast(target, SPELL_FOCUSED_EYEBEAM_VISUAL); + DoCast(target, m_bIsRegularMode ? SPELL_FOCUSED_EYEBEAM : SPELL_FOCUSED_EYEBEAM_H, true); + } + m_uiEyebeah_Timer = 20000; + }else m_uiEyebeah_Timer -= uiDiff; + + // respawn arms + if (m_uiRespawnLeftTimer < uiDiff && m_bIsLeftDead) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEFT_ARM))) + { + if (!pTemp->isAlive()) + { + pTemp->Respawn(); + m_bIsLeftDead = false; + m_bHasLeftDied = false; + DoScriptText(EMOTE_LEFT_ARM, m_creature); + } + } + }else m_uiRespawnLeftTimer -= uiDiff; + + if (m_uiRespawnRightTimer < uiDiff && m_bIsRightDead) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RIGHT_ARM))) + { + if (!pTemp->isAlive()) + { + pTemp->Respawn(); + m_bIsRightDead = false; + m_bHasRightDied = false; + DoScriptText(EMOTE_RIGHT_ARM, m_creature); + } + } + }else m_uiRespawnRightTimer -= uiDiff; + + // check if arms are dead and if there is no player in melee range + if (m_uiCheck_Timer < uiDiff) + { + if (Creature* lArm = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEFT_ARM))) + { + if (!lArm->isAlive() && !m_bIsLeftDead) + { + m_bHasLeftDied = true; + m_bOpenArms = false; + m_uiDisarmedTimer = 0; + + for(uint8 i = 0; i < 5; i ++) + { + if(Creature* pRubble = m_creature->SummonCreature(MOB_RUBBLE, LeftArm[0] - urand(0, 5), LeftArm[1] + urand(0, 10), LeftArm[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pRubble->GetMotionMaster()->MovePoint(0, KoloFront[0], KoloFront[1], KoloFront[2]); + + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pRubble->AddThreat(pTarget,0.0f); + pRubble->AI()->AttackStart(pTarget); + pRubble->SetInCombatWithZone(); + } + + m_uiRubbleNo += 1; + } + } + m_bIsLeftDead = true; + m_uiRespawnLeftTimer = 47000; + } + } + if (Creature* rArm = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RIGHT_ARM))) + { + if (!rArm->isAlive() && !m_bIsRightDead) + { + m_bHasRightDied = true; + m_bOpenArms = false; + m_uiDisarmedTimer = 0; + + for(uint8 i = 0; i < 5; i ++) + { + if(Creature* pRubble = m_creature->SummonCreature(MOB_RUBBLE, RightArm[0] - urand(0, 5), RightArm[1] + urand(0, 10), RightArm[2], 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pRubble->GetMotionMaster()->MovePoint(0, KoloFront[0], KoloFront[1], KoloFront[2]); + + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pRubble->AddThreat(pTarget,0.0f); + pRubble->AI()->AttackStart(pTarget); + pRubble->SetInCombatWithZone(); + } + + m_uiRubbleNo += 1; + } + } + m_bIsRightDead = true; + m_uiRespawnRightTimer = 47000; + } + } + + //Petrifying breath + if (!m_creature->IsWithinDistInMap(m_creature->getVictim(), 5)) + DoCast(m_creature, m_bIsRegularMode ? SPELL_PETRIFYING_BREATH : SPELL_PETRIFYING_BREATH_H); + + m_uiCheck_Timer = 500; + }else m_uiCheck_Timer -= uiDiff; + + // disarmed achiev check + if (m_bHasLeftDied || m_bHasRightDied) + m_uiDisarmedTimer += uiDiff; + + if(m_uiEnrageTimer < uiDiff) + { + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_ENRAGE); + m_uiEnrageTimer = 30000; + } + else m_uiEnrageTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_kologarn(Creature* pCreature) +{ + return new boss_kologarnAI(pCreature); } + +void AddSC_boss_kologarn() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_kologarn"; + NewScript->GetAI = GetAI_boss_kologarn; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_ulduar_rubble"; + NewScript->GetAI = &GetAI_mob_ulduar_rubble; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_left_arm"; + NewScript->GetAI = &GetAI_boss_left_arm; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "boss_right_arm"; + NewScript->GetAI = &GetAI_boss_right_arm; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_leviathan.cpp b/scripts/northrend/ulduar/ulduar/boss_leviathan.cpp new file mode 100644 index 0000000..c87c9e4 --- /dev/null +++ b/scripts/northrend/ulduar/ulduar/boss_leviathan.cpp @@ -0,0 +1,397 @@ +/* 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_leviathan +SD%Complete: +SDComment: needs vehicles +SDCategory: Ulduar +EndScriptData */ + +#include "precompiled.h" +#include "def_ulduar.h" +#include "Vehicle.h" + +enum say +{ + SAY_AGGRO = -1603203, + SAY_DEATH = -1603202, + SAY_SLAY = -1603201, + SAY_CHANGE1 = -1603204, + SAY_CHANGE2 = -1603205, + SAY_CHANGE3 = -1603206, + SAY_PLAYER_ON_TOP = -1603207, + SAY_OVERLOAD1 = -1603208, + SAY_OVERLOAD2 = -1603209, + SAY_OVERLOAD3 = -1603210, + SAY_HARD_MODE = -1603211, + SAY_TOWERS_DOWN = -1603212, + SAY_FROST_TOWER = -1603213, + SAY_FIRE_TOWER = -1603214, + SAY_ENERGY_TOWER = -1603215, + SAY_NATURE_TOWER = -1603216, + + EMOTE_PURSUE = -1603352, +}; + +enum spells +{ + SPELL_PURSUED = 62374, + + SPELL_MISSILE_BARRAGE = 62400, + SPELL_FLAME_VENTS = 62396, + SPELL_BATTERING_RAM = 62376, + + SPELL_GATHERING_SPEED = 62375, + // interupted by + SPELL_OVERLOAD_CIRCUIT = 62399, + + SPELL_SEARING_FLAME = 62402, // used by defense turret + // interupted by + SPELL_SYSTEMS_SHUTDOWN = 62475, + + SPELL_FLAME_CANNON = 62395, + //SPELL_FLAME_CANNON = 64692, trigger the same spell + SPELL_BLAZE = 62292, + + // used by players -> to be added later + SPELL_ELECTROSHOCK = 62522, + SPELL_SMOKE_TRAIL = 63575, + + // tower of nature + SPELL_FREYAS_WARD = 62906, + SPELL_TOWER_OF_LIFE = 64482, + // tower of flames + SPELL_MIMIRON_INFERNO = 62910, + SPELL_TOWER_OF_FLAMES = 65075, + // tower of frost + SPELL_HODIR_FURY = 62297, // also + 10% hp + // tower of storms + SPELL_THORIMS_HAMMER = 62912, + SPELL_TOWER_OF_STORMS = 65076 +}; + +enum Mobs +{ + MOB_MECHANOLIFT = 33214, + MOB_LIQUID = 33189, + MOB_CONTAINER = 33218, + + DEFENSE_TURRET = 33142, + KEEPER_OF_NORGANNON = 33686 +}; + +enum Seats +{ + SEAT_PLAYER = 0, + SEAT_TURRET = 1, + SEAT_DEVICE = 2, +}; + + +struct MANGOS_DLL_DECL boss_flame_leviathan : public ScriptedAI +{ + boss_flame_leviathan(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + // ### unit disabled, please remove if you want to test it! +// pCreature->setFaction(35); // remove this when vehicules fixed! +// pCreature->SetVisibility(VISIBILITY_OFF); + // ### + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiBatteringRamTimer; + uint32 m_uiFlameVentsTimer; + uint32 m_uiMissileBarrageTimer; + uint32 m_uiPursueTimer; + uint32 m_uiGatheringSpeedTimer; + uint32 m_uiSummonFlyerTimer; + uint8 maxFlyers; + + bool isHardMode; + bool isHodirsTower; + bool isFreyasTower; + bool isMimironsTower; + bool isThorimsTower; + + uint32 m_uiFreyaWardTimer; + uint32 m_uiMimironInfernoTimer; + uint32 m_uiHodirFuryTimer; + uint32 m_uiThorimHammerTimer; + + void Reset() + { + m_uiBatteringRamTimer = 15000 + rand()%20000; + m_uiFlameVentsTimer = 15000 + rand()%10000; + m_uiMissileBarrageTimer = 1000; + m_uiPursueTimer = 30000; + m_uiGatheringSpeedTimer = 50000; + m_uiSummonFlyerTimer = 2000; + maxFlyers = 10; + + isHardMode = false; + isHodirsTower = false; + isFreyasTower = false; + isMimironsTower = false; + isThorimsTower = false; + + m_uiFreyaWardTimer = 40000 + urand(1000, 10000); + m_uiMimironInfernoTimer = 40000 + urand(1000, 10000); + m_uiHodirFuryTimer = 40000 + urand(1000, 10000); + m_uiThorimHammerTimer = 40000 + urand(1000, 10000); + + m_creature->SetSpeedRate(MOVE_RUN, 0.3f); + } + + void Aggro(Unit *who) + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_LEVIATHAN, IN_PROGRESS); + if(m_pInstance->GetData(TYPE_LEVIATHAN_TP) != DONE) + m_pInstance->SetData(TYPE_LEVIATHAN_TP, DONE); + } + + DoScriptText(SAY_AGGRO, m_creature); + } + + void JustDied(Unit *killer) + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_LEVIATHAN, DONE); + if(isHardMode) + m_pInstance->SetData(TYPE_LEVIATHAN_HARD, DONE); + } + + DoScriptText(SAY_DEATH, m_creature); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_LEVIATHAN, FAIL); + } + + void KilledUnit(Unit *who) + { + DoScriptText(SAY_SLAY, m_creature); + } + + // TODO: effect 0 and effect 1 may be on different target + void SpellHitTarget(Unit *pTarget, const SpellEntry *spell) + { + if (spell->Id == SPELL_PURSUED) + AttackStart(pTarget); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + /*if(spell->Id == 62472) + vehicle->InstallAllAccessories(); + else if(spell->Id == SPELL_ELECTROSHOCK) + m_creature->InterruptSpell(CURRENT_CHANNELED_SPELL);*/ + } + + void DamageTaken(Unit *pDoneBy, uint32 &uiDamage) + { + uiDamage *= 4; + if(m_creature->HasAura(SPELL_SYSTEMS_SHUTDOWN, EFFECT_INDEX_0)) + uiDamage += uiDamage/2; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // pursue + if(m_uiPursueTimer < uiDiff) + { + switch(urand(0, 3)) + { + case 0: DoScriptText(SAY_CHANGE1, m_creature); break; + case 1: DoScriptText(SAY_CHANGE2, m_creature); break; + case 2: DoScriptText(SAY_CHANGE3, m_creature); break; + } + DoScriptText(EMOTE_PURSUE, m_creature); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + m_creature->AddThreat(pTarget, 100.0f); + DoCast(pTarget, SPELL_PURSUED); + } + + m_uiPursueTimer = 30000; + } + else m_uiPursueTimer -= uiDiff; + + // flame vents + if(m_uiFlameVentsTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_FLAME_VENTS); + m_uiFlameVentsTimer = 30000 + rand()%20000; + } + else m_uiFlameVentsTimer -= uiDiff; + + // battering ram + if(m_uiBatteringRamTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_BATTERING_RAM); + m_uiBatteringRamTimer = 25000 + rand()%15000; + } + else m_uiBatteringRamTimer -= uiDiff; + + /* flyers + it should summon some flyers. needs more research! + if(m_uiSummonFlyerTimer < uiDiff) + { + m_creature->SummonCreature(MOB_MECHANOLIFT, m_creature->GetPositionX() + rand()%20, m_creature->GetPositionY() + rand()%20, m_creature->GetPositionZ() + 50, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 40000); + m_uiSummonFlyerTimer = 2000; + } + else m_uiSummonFlyerTimer -= uiDiff;*/ + + // missile barrage + if(m_uiMissileBarrageTimer < uiDiff) + { + DoCast(m_creature, SPELL_MISSILE_BARRAGE); + m_uiMissileBarrageTimer = 3000 + rand()%2000; + } + else m_uiMissileBarrageTimer -= uiDiff; + + if(m_uiGatheringSpeedTimer < uiDiff) + { + DoCast(m_creature, SPELL_GATHERING_SPEED); + m_uiGatheringSpeedTimer = urand(50000, 60000); + } + else m_uiGatheringSpeedTimer -= uiDiff; + + // Hard mode event. need more research and scripting + // this part should be done in other way + + // tower of freya + if(isFreyasTower) + { + DoCast(m_creature, SPELL_TOWER_OF_LIFE); + + if(m_uiFreyaWardTimer < uiDiff) + { + DoCast(m_creature, SPELL_FREYAS_WARD); + m_uiFreyaWardTimer = 40000 + urand(1000, 10000); + } + else m_uiFreyaWardTimer -= uiDiff; + } + + // tower of mimiron + if(isMimironsTower) + { + DoCast(m_creature, SPELL_TOWER_OF_FLAMES); + + if(m_uiMimironInfernoTimer < uiDiff) + { + DoCast(m_creature, SPELL_FREYAS_WARD); + m_uiMimironInfernoTimer = 40000 + urand(1000, 10000); + } + else m_uiMimironInfernoTimer -= uiDiff; + } + + // tower of hodir + if(isHodirsTower) + { + m_creature->SetHealth(m_creature->GetHealth() + 0.1* m_creature->GetHealth()); + + if(m_uiHodirFuryTimer < uiDiff) + { + DoCast(m_creature, SPELL_HODIR_FURY); + m_uiHodirFuryTimer = 40000 + urand(1000, 10000); + } + else m_uiHodirFuryTimer -= uiDiff; + } + + // tower of thorim + if(isThorimsTower) + { + DoCast(m_creature, SPELL_TOWER_OF_STORMS); + + if(m_uiThorimHammerTimer < uiDiff) + { + DoCast(m_creature, SPELL_THORIMS_HAMMER); + m_uiThorimHammerTimer = 40000 + urand(1000, 10000); + } + else m_uiThorimHammerTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_defense_turretAI : public ScriptedAI +{ + mob_defense_turretAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(10000, 15000); + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if(spell->Id == SPELL_SYSTEMS_SHUTDOWN) + m_creature->ForcedDespawn(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + DoCast(m_creature, SPELL_SEARING_FLAME); + m_uiSpell_Timer = urand(10000, 15000); + }else m_uiSpell_Timer -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_defense_turret(Creature* pCreature) +{ + return new mob_defense_turretAI(pCreature); +} + +CreatureAI* GetAI_boss_flame_leviathan(Creature* pCreature) +{ + return new boss_flame_leviathan(pCreature); +} + +void AddSC_boss_leviathan() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_flame_leviathan"; + newscript->GetAI = &GetAI_boss_flame_leviathan; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_defense_turret"; + newscript->GetAI = &GetAI_mob_defense_turret; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp b/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp index 0e09458..1824101 100644 --- a/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp @@ -1,61 +1,2265 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_mimiron -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: needs vehicles SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_AGGRO = -1603176, - SAY_HARD_MODE = -1603177, - SAY_BERSERK = -1603178, + //yells + SAY_AGGRO = -1603241, + SAY_HARD_MODE = -1603242, + SAY_BERSERK = -1603243, + SAY_TANK_ACTIVE = -1603244, + SAY_TANK_SLAY1 = -1603245, + SAY_TANK_SLAY2 = -1603246, + SAY_TANK_DEATH = -1603247, + SAY_TORSO_ACTIVE = -1603248, + SAY_TORSO_SLAY1 = -1603249, + SAY_TORSO_SLAY2 = -1603250, + SAY_TORSO_DEATH = -1603251, + SAY_HEAD_ACTIVE = -1603252, + SAY_HEAD_SLAY1 = -1603253, + SAY_HEAD_SLAY2 = -1603254, + SAY_HEAD_DEATH = -1603255, + SAY_ROBOT_ACTIVE = -1603256, + SAY_ROBOT_SLAY1 = -1603257, + SAY_ROBOT_SLAY2 = -1603258, + SAY_ROBOT_DEATH = -1603259, - SAY_TANK_ACTIVE = -1603179, - SAY_TANK_SLAY_1 = -1603180, - SAY_TANK_SLAY_2 = -1603181, - SAY_TANK_DEATH = -1603182, + EMOTE_PLASMA_BLAST = -1603371, - SAY_TORSO_ACTIVE = -1603183, - SAY_TORSO_SLAY_1 = -1603184, - SAY_TORSO_SLAY_2 = -1603185, - SAY_TORSO_DEATH = -1603186, + SPELL_JET_PACK = 63341, // used by mimiron to change seats + SPELL_SELF_REPAIR = 64383, - SAY_HEAD_ACTIVE = -1603187, - SAY_HEAD_SLAY_1 = -1603188, - SAY_HEAD_SLAY_2 = -1603189, - SAY_HEAD_DEATH = -1603190, + // hard mode spells + SPELL_SELF_DESTRUCTION = 64613, // visual aura + SPELL_SELF_DESTRUCT = 64610, // damage aura + SPELL_EMERGENCY_MODE_AURA = 65101, + NPC_MIMIRON_INFERNO = 33370, // used to cast the self destruct - SAY_ROBOT_ACTIVE = -1603191, - SAY_ROBOT_SLAY_1 = -1603192, - SAY_ROBOT_SLAY_2 = -1603193, - SAY_ROBOT_DEATH = -1603194, + SPELL_FLAMES = 64561, // may be the fires spells + SPELL_FLAMES_SUMMON = 64563, // 64567 + SPELL_FLAMES_SPREAD = 64562, + NPC_FLAME = 34121, + NPC_FLAME_INITIAL = 34363, - SAY_HELP_YOGG = -1603195, + //spells + //leviathan + SPELL_PROXIMITY_MINES = 63016, // also in phase 4 + SPELL_MINE_SUMMON = 65347, + MOB_PROXIMITY_MINE = 34362, + SPELL_EXPLOSION = 66351, + SPELL_EXPLOSION_H = 63009, + SPELL_NAPALM_SHELL = 63666, + SPELL_NAPALM_SHELL_H = 65026, + SPELL_PLASMA_BLAST = 62997, + SPELL_PLASMA_BLAST_H = 64529, + SPELL_SHOCK_BLAST = 63631, // also in phase 4 + SPELL_FLAME_SUPRESSANT = 64570, // hard mode + LEVIATHAN_TURRET = 34071, - EMOTE_PLASMA_BLAST = -1603196, + //vx001 + SPELL_RAPID_BURST = 63387, + SPELL_RAPID_BURST_H = 64531, + SPELL_LASER_BARRAGE = 63293, // also in phase 4 + SPELL_LASER_VISUAL = 63300, + SPELL_LASER_TRIGG = 63274, + SPELL_ROCKET_STRIKE = 64064, + NPC_MIMIRON_FOCUS = 33835, //33369 + SPELL_HEAT_WAVE = 63677, + SPELL_HEAT_WAVE_H = 64533, + SPELL_HAND_PULSE = 64348, // only in phase 4 + SPELL_FLAME_SUPRESS = 65192, // used by robot in melee range + SPELL_HAND_PULSE_H = 64536, + + // frostbomb + SPELL_FROST_BOMB_EXPL = 64626, + SPELL_FROST_BOMB_AURA = 64624, // before explode + SPELL_FROST_BOMB_VISUAL = 64625, // bomb grows + SPELL_FROST_BOMB_SUMMON = 64627, // summon the frostbomb + + //aerial unit + SPELL_PLASMA_BALL = 63689, // also in phase 4 + SPELL_PLASMA_BALL_H = 64535, // also in phase 4 + MOB_ASSALT_BOT = 34057, + MOB_BOMB_BOT = 33836, + MOB_BOMB_BOT_321 = 33346, + MOB_BOMB_BOT_500 = 34192, + MOB_JUNK_BOT = 33855, + SPELL_MAGNETIC_FIELD = 64668, + SPELL_MAGNETIC_CORE = 64436, // increase dmg taken by 50%, used by magnetic core + MOB_MAGNETIC_CORE = 34068, + ITEM_MAGNETIC_CORE = 46029, + SPELL_BOMB_BOT_SUMMON = 63811, + SPELL_BOMB_BOT = 63767, + + //hard mode + // summons fires + SPELL_EMERGENCY_MODE = 64582, + MOB_FROST_BOMB = 34149, + MOB_EMERGENCY_FIRE_BOT = 34147, + SPELL_DEAFENING_SIREN = 64616, + SPELL_WATER_SPRAY = 64619, + + SPELL_MIMIRONS_INFERNO = 62910, // maybe used by rocket + SPELL_MIMIRONS_INFERNO2 = 62909, // maybe hard mode + SPELL_BERSERK = 26662, + + ACHIEV_FIREFIGHTER = 3180, + ACHIEV_FIREFIGHTER_H = 3189, +}; + +enum MimironPhase +{ + PHASE_IDLE = 0, + PHASE_INTRO = 1, + PHASE_LEVIATHAN = 2, + PHASE_TRANS_1 = 3, + PHASE_VX001 = 4, + PHASE_TRANS_2 = 5, + PHASE_AERIAL = 6, + PHASE_TRANS_3 = 7, + PHASE_ROBOT = 8, + PHASE_OUTRO = 9, +}; + +#define CENTER_X 2744.732f +#define CENTER_Y 2569.479f +#define CENTER_Z 364.312f + +const float PosTankHome[2]= {2794.86f, 2597.83f}; +struct LocationsXY +{ + float x, y; + uint32 id; +}; +static LocationsXY SummonLoc[]= +{ + {2753.665f, 2584.712f}, + {2754.150f, 2554.445f}, + {2726.966f, 2569.032f}, + {2759.085f, 2594.249f}, + {2759.977f, 2544.345f}, + {2715.542f, 2569.160f}, + {2765.070f, 2604.337f}, + {2765.676f, 2534.558f}, + {2703.810f, 2569.132f}, +}; + +// Leviathan Mk script +struct MANGOS_DLL_DECL boss_leviathan_mkAI : public ScriptedAI +{ + boss_leviathan_mkAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + bool m_bStartAttack; + + uint32 m_uiMinesTimer; + uint32 m_uiNapalmTimer; + uint32 m_uiPlasmaBlastTimer; + uint32 m_uiShockBlastTimer; + + bool m_bHasSuppresed; + uint32 m_uiSupressTimer; + uint32 m_uiSetFireTimer; + + // outro + bool m_bIsOutro; + uint32 m_uiOutroTimer; + uint32 m_uiOutroStep; + + bool m_bMustRepair; + uint32 m_uiRepairTimer; + + void Reset() + { + m_bStartAttack = false; + m_uiMinesTimer = 5000; + m_uiNapalmTimer = 20000; + m_uiPlasmaBlastTimer = 10000; + m_uiShockBlastTimer = 30000; + m_bHasSuppresed = false; + m_uiSetFireTimer = 10000; + m_uiSupressTimer = 10000; + + m_uiOutroTimer = 10000; + m_uiOutroStep = 1; + m_bIsOutro = false; + m_bMustRepair = false; + m_uiRepairTimer = 15000; + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if(m_pInstance) + m_pInstance->SetData(TYPE_LEVIATHAN_MK, NOT_STARTED); + } + + void AttackStart(Unit* pWho) + { + if(!m_bStartAttack) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + DoStartMovement(pWho); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + { + if(m_creature->GetHealthPercent() < 1.0f) + { + uiDamage = 0; + m_bIsOutro = true; + } + } + // hacky way for feign death + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) + { + if(uiDamage > m_creature->GetHealth() && !m_bMustRepair) + { + uiDamage = 0; + m_creature->SetHealth(0); + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->CombatStop(); + m_creature->SetStandState(UNIT_STAND_STATE_DEAD); + m_bMustRepair = true; + m_uiRepairTimer = 15000; + DoCast(m_creature, SPELL_SELF_REPAIR); + + if(m_pInstance) + m_pInstance->SetData(TYPE_LEVIATHAN_MK, SPECIAL); + } + } + } + + void KilledUnit(Unit* pVictim) + { + if (Creature* pMimiron = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MIMIRON))) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + { + if(irand(0,1)) + DoScriptText(SAY_TANK_SLAY1, pMimiron); + else + DoScriptText(SAY_TANK_SLAY2, pMimiron); + } + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) + { + if(irand(0,1)) + DoScriptText(SAY_ROBOT_SLAY1, pMimiron); + else + DoScriptText(SAY_ROBOT_SLAY2, pMimiron); + } + } + } + + // hacky way for phase 4. needs rewriging when vehicles are fixed + void SetPhase() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsOutro = false; + m_uiMinesTimer = 10000; + m_uiShockBlastTimer = 30000; + m_bStartAttack = true; + // look like a robot + SetCombatMovement(false); + } + + // hacky way for phase 4. needs rewriging when vehicles are fixed + void Repair() + { + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->SetHealth(m_creature->GetMaxHealth() * 0.5); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->AI()->AttackStart(m_creature->getVictim()); + SetPhase(); + + if(m_pInstance) + m_pInstance->SetData(TYPE_LEVIATHAN_MK, IN_PROGRESS); + } + + void JustSummoned(Creature* pSummon) + { + pSummon->SetInCombatWithZone(); + } + + void SuppressFires() + { + std::list lFires; + GetCreatureListWithEntryInGrid(lFires, m_creature, 34363, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFires, m_creature, 34121, DEFAULT_VISIBILITY_INSTANCE); + if (!lFires.empty()) + { + for(std::list::iterator iter = lFires.begin(); iter != lFires.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if(!m_bIsOutro) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiRepairTimer < uiDiff && m_bMustRepair) + { + SetPhase(); + Repair(); + m_bMustRepair = false; + } + else m_uiRepairTimer -= uiDiff; + + // return if repairing + if(m_bMustRepair) + return; + + // this should be removed when vehicles are implemented! The are casted by the turret + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + { + if(m_uiPlasmaBlastTimer < uiDiff) + { + DoScriptText(EMOTE_PLASMA_BLAST, m_creature); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_PLASMA_BLAST : SPELL_PLASMA_BLAST_H); + m_uiPlasmaBlastTimer = 30000; + } + else m_uiPlasmaBlastTimer -= uiDiff; + + if(m_uiNapalmTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if(!m_creature->IsWithinDistInMap(pTarget, 15)) + { + DoCast(pTarget, m_bIsRegularMode ? SPELL_NAPALM_SHELL : SPELL_NAPALM_SHELL_H); + m_uiNapalmTimer = 7000; + } + } + } + else m_uiNapalmTimer -= uiDiff; + } + + // proximity mines + if(m_uiMinesTimer < uiDiff) + { + //DoCast(m_crreature, SPELL_PROXIMITY_MINES); + for(uint8 i = 0; i < urand(8, 10); i++) + { + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = m_creature->GetPositionX() + 15*cos(angle*(M_PI/180)); + float homeY = m_creature->GetPositionY() + 15*sin(angle*(M_PI/180)); + m_creature->SummonCreature(MOB_PROXIMITY_MINE, homeX, homeY, m_creature->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 10000); + } + m_uiMinesTimer = 30000; + } + else m_uiMinesTimer -= uiDiff; + + // shock blast + if(m_uiShockBlastTimer < uiDiff) + { + DoCast(m_creature, SPELL_SHOCK_BLAST); + m_uiShockBlastTimer = 50000; + } + else m_uiShockBlastTimer -= uiDiff; + + // hard mode script + if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS && m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_LEVIATHAN) + { + if(m_creature->GetHealthPercent() < 50.0f && !m_bHasSuppresed) + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_FLAME_SUPRESSANT); + m_bHasSuppresed = true; + m_uiSupressTimer = 2000; + m_uiSetFireTimer = 10000; + } + + if(m_uiSupressTimer < uiDiff && m_bHasSuppresed) + { + SuppressFires(); + m_uiSupressTimer = 600000; + } + else m_uiSupressTimer -= uiDiff; + + if(m_uiSetFireTimer < uiDiff && m_bHasSuppresed) + { + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); + } + } + m_uiSetFireTimer = 600000; + } + else m_uiSetFireTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } + // outro for phase 1 + if(m_bIsOutro) + { + switch(m_uiOutroStep) + { + case 1: + m_bStartAttack = false; + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->GetMotionMaster()->MovePoint(0, PosTankHome[0], PosTankHome[1], CENTER_Z); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (Creature* pMimiron = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MIMIRON))) + DoScriptText(SAY_TANK_DEATH, pMimiron); + ++m_uiOutroStep; + m_uiOutroTimer = 12000; + break; + case 3: + if(m_pInstance) + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_TRANS_1); + // reset the miniboss for phase 4 + EnterEvadeMode(); + ++m_uiOutroStep; + m_uiOutroTimer = 3000; + break; + } + } + else return; + + if (m_uiOutroTimer <= uiDiff) + { + ++m_uiOutroStep; + m_uiOutroTimer = 330000; + } m_uiOutroTimer -= uiDiff; + } +}; + +// VX001 script +struct MANGOS_DLL_DECL boss_vx001AI : public ScriptedAI +{ + boss_vx001AI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + bool m_bStartAttack; + uint32 m_uiAttackStartTimer; + + uint32 m_uiRapidBurstTimer; + uint32 m_uiLaserBarrageTimer; + uint32 m_uiRocketStrikeTimer; + uint32 m_uiHeatWaveTimer; + uint32 m_uiHandPulseTimer; + + uint32 m_uiFlameSuppressTimer; + uint32 m_uiFrostBombTimer; + uint32 m_uiSpreadFiresTimer; + + uint32 m_uiRepairTimer; + bool m_bMustRepair; + + void Reset() + { + m_bStartAttack = false; + m_uiAttackStartTimer = 12000; + m_bMustRepair = false; + m_uiRepairTimer = 15000; + + m_uiRapidBurstTimer = 1000; + m_uiLaserBarrageTimer = 60000; + m_uiRocketStrikeTimer = 25000; + m_uiHeatWaveTimer = 20000; + m_uiHandPulseTimer = 1000; + + m_uiFlameSuppressTimer = urand(10000, 15000); + m_uiFrostBombTimer = urand(25000, 30000); + m_uiSpreadFiresTimer = urand(40000, 50000); + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if(m_pInstance) + m_pInstance->SetData(TYPE_VX001, NOT_STARTED); + } + + void AttackStart(Unit* pWho) + { + if(!m_bStartAttack) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void KilledUnit(Unit* pVictim) + { + if (Creature* pMimiron = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MIMIRON))) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) + { + if(irand(0,1)) + DoScriptText(SAY_TORSO_SLAY1, pMimiron); + else + DoScriptText(SAY_TORSO_SLAY2, pMimiron); + } + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) + { + if(irand(0,1)) + DoScriptText(SAY_ROBOT_SLAY1, pMimiron); + else + DoScriptText(SAY_ROBOT_SLAY2, pMimiron); + } + } + } + + // hacky way for phase 4. needs rewriging when vehicles are fixed + void SetPhase() + { + //SetCombatMovement(true); + m_uiLaserBarrageTimer = 60000; + m_uiRocketStrikeTimer = 25000; + m_uiHandPulseTimer = 1000; + + // look like a robot + m_creature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 3, 0.0f); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 3, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + } + + void JustDied(Unit* pKiller) + { + if(m_pInstance) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) + { + if (Creature* pMimiron = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MIMIRON))) + DoScriptText(SAY_TORSO_DEATH, pMimiron); + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_TRANS_2); + m_pInstance->SetData(TYPE_VX001, DONE); + } + } + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) + return; + + // hacky way for feign death, needs fixing + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) + { + if(uiDamage > m_creature->GetHealth()) + { + uiDamage = 0; + m_creature->SetHealth(0); + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->CombatStop(); + m_bMustRepair = true; + m_uiRepairTimer = 15000; + m_creature->SetStandState(UNIT_STAND_STATE_DEAD); + if(m_pInstance) + m_pInstance->SetData(TYPE_VX001, SPECIAL); + } + } + } + + // hacky way for phase 4. needs rewriging when vehicles are fixed + void Repair() + { + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->SetHealth(m_creature->GetMaxHealth() * 0.5); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->AI()->AttackStart(m_creature->getVictim()); + SetPhase(); + + if(m_pInstance) + m_pInstance->SetData(TYPE_VX001, IN_PROGRESS); + } + + void SuppressFires() + { + std::list lFires; + GetCreatureListWithEntryInGrid(lFires, m_creature, 34363, 10.0f); + GetCreatureListWithEntryInGrid(lFires, m_creature, 34121, 10.0f); + if (!lFires.empty()) + { + for(std::list::iterator iter = lFires.begin(); iter != lFires.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); + } + } + } + + Creature* SelectRandomFire() + { + std::list lFires; + GetCreatureListWithEntryInGrid(lFires, m_creature, 34363, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lFires, m_creature, 34121, DEFAULT_VISIBILITY_INSTANCE); + + //This should not appear! + if (lFires.empty()){ + m_uiFrostBombTimer = 5000; + return NULL; + } + + std::list::iterator iter = lFires.begin(); + advance(iter, urand(0, lFires.size()-1)); + + if((*iter)->isAlive()) + return *iter; + else + { + m_uiFrostBombTimer = 500; + return NULL; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiAttackStartTimer < uiDiff && !m_bStartAttack) + { + if(GameObject* pLift = GetClosestGameObjectWithEntry(m_creature, GO_MIMIRON_ELEVATOR, DEFAULT_VISIBILITY_INSTANCE)) + pLift->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWithZone(); + m_bStartAttack = true; + } + else m_uiAttackStartTimer -= uiDiff; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiRepairTimer < uiDiff && m_bMustRepair) + { + SetPhase(); + Repair(); + m_bMustRepair = false; + } + else m_uiRepairTimer -= uiDiff; + + // return if repairing + if(m_bMustRepair) + return; + + // only in VX001 phase + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) + { + if(m_uiRapidBurstTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_RAPID_BURST : SPELL_RAPID_BURST_H); + m_uiRapidBurstTimer = 1000; + } + else m_uiRapidBurstTimer -= uiDiff; + + if(m_uiHeatWaveTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_HEAT_WAVE : SPELL_HEAT_WAVE_H); + m_uiHeatWaveTimer = 10000; + } + else m_uiHeatWaveTimer -= uiDiff; + } + + // only in robot phase + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) + { + if(m_uiHandPulseTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_HAND_PULSE : SPELL_HAND_PULSE_H); + m_uiHandPulseTimer = 1000; + } + else m_uiHandPulseTimer -= uiDiff; + } + + if(m_uiLaserBarrageTimer < uiDiff) + { + DoCast(m_creature, SPELL_LASER_TRIGG); + m_uiLaserBarrageTimer = urand(50000, 60000); + } + else m_uiLaserBarrageTimer -= uiDiff; + + // this needs vehicles in order to make the rocket move to the target + if(m_uiRocketStrikeTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if(Creature* pTemp = m_creature->SummonCreature(NPC_MIMIRON_FOCUS, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 30000)) + { + pTemp->setFaction(14); + pTemp->GetMotionMaster()->MoveIdle(); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTemp->CombatStop(); + pTemp->SetDisplayId(11686); // make invisible + pTemp->CastSpell(pTemp, SPELL_ROCKET_STRIKE, false); + } + } + m_uiRocketStrikeTimer = urand(25000, 30000); + } + else m_uiRocketStrikeTimer -= uiDiff; + + // hard mode + if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + { + // only in VX001 phase + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_VX001) + { + if(m_uiFlameSuppressTimer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_FLAME_SUPRESS); + SuppressFires(); + m_uiFlameSuppressTimer = urand(9000, 10000); + } + else m_uiFlameSuppressTimer -= uiDiff; + } + + if(m_uiFrostBombTimer < uiDiff) + { + if(Creature* pFire = SelectRandomFire()) + m_creature->SummonCreature(MOB_FROST_BOMB, pFire->GetPositionX(), pFire->GetPositionY(), pFire->GetPositionZ(), 0, TEMPSUMMON_CORPSE_DESPAWN, 10000); + m_uiFrostBombTimer = urand(50000, 60000); + m_uiSpreadFiresTimer = urand(15000, 20000); + } + else m_uiFrostBombTimer -= uiDiff; + + if(m_uiSpreadFiresTimer < uiDiff) + { + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); + } + } + m_uiSpreadFiresTimer = 60000; + } + else m_uiSpreadFiresTimer -= uiDiff; + } + + DoMeleeAttackIfReady(); + } +}; + +// Aerial command unit script +struct MANGOS_DLL_DECL boss_aerial_command_unitAI : public ScriptedAI +{ + boss_aerial_command_unitAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + bool m_bStartAttack; + uint32 m_uiAttackStartTimer; + + uint32 m_uiPlasmaBallTimer; + uint32 m_uiSummonWavesTimer; + uint32 m_uiGroundTimer; + bool m_bIsGrounded; + uint32 m_uiSpreadFiresTimer; + + uint32 m_uiRepairTimer; + bool m_bMustRepair; + + void Reset() + { + m_bStartAttack = false; + m_uiAttackStartTimer = 5000; + m_uiSpreadFiresTimer = urand(40000, 50000); + + m_uiPlasmaBallTimer = 3000; + m_uiSummonWavesTimer = 10000; + m_bIsGrounded = false; + + m_bMustRepair = false; + m_uiRepairTimer = 15000; + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + + if(m_pInstance) + m_pInstance->SetData(TYPE_AERIAL_UNIT, NOT_STARTED); + + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void AttackStart(Unit* pWho) + { + if(!m_bStartAttack) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + } + + void Aggro(Unit *who) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) + { + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 7, 0.0f); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 7, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + } + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) + { + if(m_creature->HasAura(SPELL_MAGNETIC_CORE, EFFECT_INDEX_0)) + uiDamage += uiDamage; + return; + } + + // hacky way for feign death + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) + { + if(uiDamage > m_creature->GetHealth()) + { + uiDamage = 0; + m_creature->SetHealth(0); + m_creature->InterruptNonMeleeSpells(true); + m_creature->RemoveAllAuras(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MovementExpired(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->CombatStop(); + m_bMustRepair = true; + m_uiRepairTimer = 15000; + m_creature->SetStandState(UNIT_STAND_STATE_DEAD); + + if(m_pInstance) + m_pInstance->SetData(TYPE_AERIAL_UNIT, SPECIAL); + } + } + } + + // hacky way for phase 4. needs rewriging when vehicles are fixed + void Repair() + { + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->SetHealth(m_creature->GetMaxHealth() * 0.5); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_creature->AI()->AttackStart(m_creature->getVictim()); + SetPhase(); + + if(m_pInstance) + m_pInstance->SetData(TYPE_AERIAL_UNIT, IN_PROGRESS); + } + + void JustDied(Unit *killer) + { + if(m_pInstance) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) + { + if (Creature* pMimiron = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MIMIRON))) + DoScriptText(SAY_HEAD_DEATH, pMimiron); + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_TRANS_3); + m_pInstance->SetData(TYPE_AERIAL_UNIT, DONE); + } + } + } + + void KilledUnit(Unit* pVictim) + { + if (Creature* pMimiron = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_MIMIRON))) + { + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) + { + if(irand(0,1)) + DoScriptText(SAY_HEAD_SLAY1, pMimiron); + else + DoScriptText(SAY_HEAD_SLAY2, pMimiron); + } + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_ROBOT) + { + if(irand(0,1)) + DoScriptText(SAY_ROBOT_SLAY1, pMimiron); + else + DoScriptText(SAY_ROBOT_SLAY2, pMimiron); + } + } + } + + // hacky way for phase 4. needs rewriging when vehicles are fixed + void SetPhase() + { + m_uiPlasmaBallTimer = 3000; + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + SetCombatMovement(false); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 6.5f, 0.0f); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 6.5f, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + } + + // get the boss down by the magnetic core + void SetToGround() + { + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), CENTER_Z, 0); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), CENTER_Z, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + m_bIsGrounded = true; + // make boss land + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_uiGroundTimer = 20000; + } + + void JustSummoned(Creature* pSummon) + { + pSummon->SetInCombatWithZone(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiAttackStartTimer < uiDiff && !m_bStartAttack) + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWithZone(); + m_bStartAttack = true; + } + else m_uiAttackStartTimer -= uiDiff; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiRepairTimer < uiDiff && m_bMustRepair) + { + SetPhase(); + Repair(); + m_bMustRepair = false; + } + else m_uiRepairTimer -= uiDiff; + + // return if repairing + if(m_bMustRepair) + return; + + if (m_creature->HasAura(SPELL_MAGNETIC_CORE, EFFECT_INDEX_0)) + return; + + if (m_uiGroundTimer < uiDiff && m_bIsGrounded) + { + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 7, 0.0f); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 7, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + m_bIsGrounded = false; + // make boss fly + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->InterruptNonMeleeSpells(true); + DoCast(m_creature, SPELL_BOMB_BOT_SUMMON); + }else m_uiGroundTimer -= uiDiff; + + if(m_uiPlasmaBallTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_PLASMA_BALL : SPELL_PLASMA_BALL_H); + m_uiPlasmaBallTimer = urand(3000, 5000); + } + else m_uiPlasmaBallTimer -= uiDiff; + + // spawn adds in arena, only in phase 3 + if(m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_AERIAL) + { + if(m_uiSummonWavesTimer < uiDiff) + { + uint32 m_uiCreatureEntry; + // summon emergency boots + if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + { + switch(urand(0, 4)) + { + case 0: + case 1: + m_uiCreatureEntry = MOB_JUNK_BOT; + break; + case 2: + case 3: + m_uiCreatureEntry = MOB_EMERGENCY_FIRE_BOT; + break; + case 4: + m_uiCreatureEntry = MOB_ASSALT_BOT; + break; + } + } + else + { + switch(urand(0, 2)) + { + case 0: + case 1: + m_uiCreatureEntry = MOB_JUNK_BOT; + break; + case 2: + m_uiCreatureEntry = MOB_ASSALT_BOT; + break; + } + } + uint8 m_uiSummonLoc = urand(0, 8); + if(m_uiCreatureEntry != 0) + m_creature->SummonCreature(m_uiCreatureEntry, SummonLoc[m_uiSummonLoc].x, SummonLoc[m_uiSummonLoc].y, CENTER_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); + + m_uiSummonWavesTimer = urand (10000, 15000); + } + else m_uiSummonWavesTimer -= uiDiff; + + if(m_pInstance->GetData(TYPE_MIMIRON_HARD) == IN_PROGRESS) + { + if(m_uiSpreadFiresTimer < uiDiff) + { + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); + } + } + m_uiSpreadFiresTimer = urand(40000, 50000); + } + else m_uiSpreadFiresTimer -= uiDiff; + } + } + } }; +// Mimiron, event controller +// boss should be placed inside the vehicles when they are supported by mangos +struct MANGOS_DLL_DECL boss_mimironAI : public ScriptedAI +{ + boss_mimironAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance *m_pInstance; + + bool m_bIsHardMode; + uint32 m_uiSelfDestructTimer; + uint32 m_uiUseLiftTimer; + uint32 m_uiPhaseDelayTimer; + uint32 m_uiRobotDelayTimer; + uint32 m_uiSelfRepairTimer; + uint32 m_uiBerserkTimer; + bool m_bHasChecked; + uint32 m_uiOutroTimer; + uint32 m_uiHpCheckTimer; + bool m_bHasMoreHp; + + uint32 m_uiIntroTimer; + uint32 m_uiIntroStep; + bool m_bIsIntro; + bool m_bIsRobotReady; + + uint64 m_uiTankGUID; + uint64 m_uiTorsoGUID; + uint64 m_uiHeadGUID; + + bool m_bIsTankDead; + bool m_bIsTorsoDead; + bool m_bIsHeadDead; + + void Reset() + { + m_bIsHardMode = false; + m_uiSelfDestructTimer = 460000; // 8 min + m_bIsIntro = true; + m_uiPhaseDelayTimer = 7000; + m_uiUseLiftTimer = 4000; + m_uiBerserkTimer = 900000; // 15 min + m_bHasChecked = false; + m_bHasMoreHp = false; + m_bIsRobotReady = false; + + m_uiIntroTimer = 10000; + m_uiIntroStep = 1; + + m_bIsTankDead = false; + m_bIsTorsoDead = false; + m_bIsHeadDead = false; + + m_uiTankGUID = 0; + m_uiTorsoGUID = 0; + m_uiHeadGUID = 0; + + // reset button + if(GameObject* pButton = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_MIMIRON_BUTTON))) + pButton->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + + // reset elevator + if(GameObject* pLift = GetClosestGameObjectWithEntry(m_creature, GO_MIMIRON_ELEVATOR, DEFAULT_VISIBILITY_INSTANCE)) + pLift->SetGoState(GO_STATE_ACTIVE); + + // kill torso and Head + if(Creature* pTorso = GetClosestCreatureWithEntry(m_creature, NPC_VX001, 80.0f)) + pTorso->DealDamage(pTorso, pTorso->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + if(Creature* pHead = GetClosestCreatureWithEntry(m_creature, NPC_AERIAL_UNIT, 80.0f)) + pHead->DealDamage(pHead, pHead->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + + // reset tank + if (Creature* pTank = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEVIATHAN_MK))) + { + if(pTank->isAlive()) + pTank->AI()->EnterEvadeMode(); + else + pTank->Respawn(); + } + + if(m_pInstance) + { + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_IDLE); + m_pInstance->SetData(TYPE_MIMIRON_HARD, NOT_STARTED); + } + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void JustReachedHome() + { + if(m_pInstance) + m_pInstance->SetData(TYPE_MIMIRON, NOT_STARTED); + } + + // start event + void Aggro(Unit *who) + { + DoScriptText(SAY_AGGRO, m_creature); + if (m_pInstance) + { + m_pInstance->SetData(TYPE_MIMIRON, IN_PROGRESS); + // activate teleporter + if(m_pInstance->GetData(TYPE_MIMIRON_TP) != DONE) + m_pInstance->SetData(TYPE_MIMIRON_TP, DONE); + // start intro + if(m_pInstance->GetData(TYPE_MIMIRON) != DONE) + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_INTRO); + } + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + + void DoOutro() + { + if(m_pInstance) + { + if(m_bIsHardMode) + { + m_pInstance->SetData(TYPE_MIMIRON_HARD, DONE); + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_FIREFIGHTER : ACHIEV_FIREFIGHTER_H); + } + m_pInstance->SetData(TYPE_MIMIRON, DONE); + } + m_creature->ForcedDespawn(); + } + + // for debug only + void JustDied(Unit* pKiller) + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_MIMIRON, DONE); + if(m_bIsHardMode) + m_pInstance->SetData(TYPE_MIMIRON_HARD, DONE); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(m_pInstance->GetData(TYPE_MIMIRON_PHASE)) + { + case PHASE_INTRO: + { + if(m_bIsIntro) + { + //hard mode check + switch(m_uiIntroStep) + { + case 1: + ++m_uiIntroStep; + m_uiIntroTimer = 10000; + break; + case 3: + if(GameObject* pButton = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(GO_MIMIRON_BUTTON))) + pButton->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + if(m_bIsHardMode) + { + DoScriptText(SAY_HARD_MODE, m_creature); + ++m_uiIntroStep; + m_uiIntroTimer = 15000; + } + else + { + ++m_uiIntroStep; + m_uiIntroTimer = 1000; + } + break; + case 5: + if (Creature* pTank = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEVIATHAN_MK))) + { + if(pTank->isAlive()) + { + DoScriptText(SAY_TANK_ACTIVE, m_creature); + pTank->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); + m_uiTankGUID = pTank->GetGUID(); + } + else + EnterEvadeMode(); + } + ++m_uiIntroStep; + m_uiIntroTimer = 18000; + break; + case 7: + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + { + if(m_bIsHardMode) + { + pTank->CastSpell(pTank, SPELL_EMERGENCY_MODE, false); + ++m_uiIntroStep; + m_uiIntroTimer = 1000; + } + else + { + if(m_pInstance) + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_LEVIATHAN); + ((boss_leviathan_mkAI*)pTank->AI())->m_bStartAttack = true; + pTank->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTank->SetInCombatWithZone(); + m_uiBerserkTimer = 900000; // 15 min + m_bIsIntro = false; + ++m_uiIntroStep; + m_uiIntroTimer = 9000; + } + } + break; + case 9: + if(m_bIsHardMode) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_LEVIATHAN); + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + { + pTank->SetHealth(pTank->GetMaxHealth()+ (pTank->GetMaxHealth() * 0.3)); + ((boss_leviathan_mkAI*)pTank->AI())->m_bStartAttack = true; + pTank->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pTank->SetInCombatWithZone(); + } + m_uiSelfDestructTimer = 460000; // 8 min + m_bIsIntro = false; + ++m_uiIntroStep; + m_uiIntroTimer = 9000; + } + break; + } + } + else return; + + if (m_uiIntroTimer <= uiDiff) + { + ++m_uiIntroStep; + m_uiIntroTimer = 330000; + } + m_uiIntroTimer -= uiDiff; + + break; + } + case PHASE_LEVIATHAN: + // leviathan MK phase: see above script + break; + case PHASE_TRANS_1: + { + if(m_uiUseLiftTimer < uiDiff) + { + if(GameObject* pLift = GetClosestGameObjectWithEntry(m_creature, GO_MIMIRON_ELEVATOR, DEFAULT_VISIBILITY_INSTANCE)) + m_pInstance->DoUseDoorOrButton(pLift->GetGUID()); + m_uiUseLiftTimer = 60000; + } + else m_uiUseLiftTimer -= uiDiff; + + if(m_uiPhaseDelayTimer < uiDiff && !m_bHasMoreHp) + { + DoScriptText(SAY_TORSO_ACTIVE, m_creature); + if(Creature* pTorso = m_creature->SummonCreature(NPC_VX001, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) + { + if(m_bIsHardMode) + { + pTorso->CastSpell(pTorso, SPELL_EMERGENCY_MODE, false); + m_bHasMoreHp = true; + m_uiHpCheckTimer = 1000; + m_uiTorsoGUID = pTorso->GetGUID(); + } + else + { + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_VX001); + m_uiPhaseDelayTimer = 10000; + } + } + } + else m_uiPhaseDelayTimer -= uiDiff; + + if (m_uiHpCheckTimer <= uiDiff && m_bHasMoreHp) + { + if(Creature* pTorso = m_pInstance->instance->GetCreature(m_uiTorsoGUID)) + pTorso->SetHealth(pTorso->GetMaxHealth()+ (pTorso->GetMaxHealth() * 0.3)); + m_bHasMoreHp = false; + m_uiPhaseDelayTimer = 10000; + m_uiHpCheckTimer = 10000; + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_VX001); + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); + } + } + } + else m_uiHpCheckTimer -= uiDiff; + + break; + } + case PHASE_VX001: + // VX001 phase: see above script + break; + case PHASE_TRANS_2: + { + if(m_uiPhaseDelayTimer < uiDiff && !m_bHasMoreHp) + { + DoScriptText(SAY_HEAD_ACTIVE, m_creature); + if(Creature* pHead = m_creature->SummonCreature(NPC_AERIAL_UNIT, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) + { + if(m_bIsHardMode) + { + pHead->CastSpell(pHead, SPELL_EMERGENCY_MODE, false); + m_bHasMoreHp = true; + m_uiHpCheckTimer = 1000; + } + else + { + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_AERIAL); + m_uiPhaseDelayTimer = 15000; + } + m_uiHeadGUID = pHead->GetGUID(); + } + } + else m_uiPhaseDelayTimer -= uiDiff; + + if (m_uiHpCheckTimer <= uiDiff && m_bHasMoreHp) + { + if(Creature* pHead = m_pInstance->instance->GetCreature(m_uiHeadGUID)) + pHead->SetHealth(pHead->GetMaxHealth()+ (pHead->GetMaxHealth() * 0.3)); + m_bHasMoreHp = false; + m_uiPhaseDelayTimer = 15000; + m_uiHpCheckTimer = 10000; + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_AERIAL); + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); + } + } + } + else m_uiHpCheckTimer -= uiDiff; + + break; + } + case PHASE_AERIAL: + // Aerial Unit phase: see above script + break; + case PHASE_TRANS_3: + { + if(m_uiPhaseDelayTimer < uiDiff && !m_bIsRobotReady) + { + if (Creature* pTank = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEVIATHAN_MK))) + { + if(pTank->isAlive()) + { + pTank->GetMotionMaster()->MovePoint(0, CENTER_X, CENTER_Y, CENTER_Z); + m_uiTankGUID = pTank->GetGUID(); + m_bIsRobotReady = true; + m_uiRobotDelayTimer = 15000; + } + else + EnterEvadeMode(); + } + m_uiPhaseDelayTimer = 100000; + } + else m_uiPhaseDelayTimer -= uiDiff; + + if(m_uiRobotDelayTimer < uiDiff && m_bIsRobotReady && !m_bHasMoreHp) + { + DoScriptText(SAY_ROBOT_ACTIVE, m_creature); + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + ((boss_leviathan_mkAI*)pTank->AI())->SetPhase(); + + if(Creature* pTorso = m_creature->SummonCreature(NPC_VX001, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000)) + { + ((boss_vx001AI*)pTorso->AI())->SetPhase(); + m_uiTorsoGUID = pTorso->GetGUID(); + } + + if(Creature* pHead = m_creature->SummonCreature(NPC_AERIAL_UNIT, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000)) + { + ((boss_aerial_command_unitAI*)pHead->AI())->SetPhase(); + m_uiHeadGUID = pHead->GetGUID(); + } + + if(m_bIsHardMode) + { + if(Creature* pTorso = m_pInstance->instance->GetCreature(m_uiTorsoGUID)) + pTorso->CastSpell(pTorso, SPELL_EMERGENCY_MODE, false); + if(Creature* pHead = m_pInstance->instance->GetCreature(m_uiHeadGUID)) + pHead->CastSpell(pHead, SPELL_EMERGENCY_MODE, false); + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + pTank->CastSpell(pTank, SPELL_EMERGENCY_MODE, false); + m_bHasMoreHp = true; + m_uiHpCheckTimer = 1000; + } + else + { + if(Creature* pTorso = m_pInstance->instance->GetCreature(m_uiTorsoGUID)) + pTorso->SetHealth(pTorso->GetMaxHealth() * 0.5); + if(Creature* pHead = m_pInstance->instance->GetCreature(m_uiHeadGUID)) + pHead->SetHealth(pHead->GetMaxHealth() * 0.5); + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + pTank->SetHealth(pTank->GetMaxHealth() * 0.5); + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_ROBOT); + } + m_uiRobotDelayTimer = 100000; + } + else m_uiRobotDelayTimer -= uiDiff; + + if (m_uiHpCheckTimer <= uiDiff && m_bHasMoreHp) + { + if(Creature* pHead = m_pInstance->instance->GetCreature(m_uiHeadGUID)) + pHead->SetHealth(pHead->GetMaxHealth() * 0.5); + if(Creature* pTorso = m_pInstance->instance->GetCreature(m_uiTorsoGUID)) + pTorso->SetHealth(pTorso->GetMaxHealth()* 0.5); + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + pTank->SetHealth(pTank->GetMaxHealth()* 0.5); + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_ROBOT); + // start again 3 fires + for(uint8 i = 0; i < 3; i++) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTarget->InterruptNonMeleeSpells(true); + pTarget->CastSpell(pTarget, SPELL_FLAMES_SUMMON, false); + } + } + m_uiHpCheckTimer = 10000; + } + else m_uiHpCheckTimer -= uiDiff; + + break; + } + case PHASE_ROBOT: + { + if(m_pInstance->GetData(TYPE_LEVIATHAN_MK) == SPECIAL && !m_bHasChecked) + { + m_uiSelfRepairTimer = 15000; + m_bIsTankDead = true; + m_bHasChecked = true; + } + if(m_pInstance->GetData(TYPE_VX001) == SPECIAL && !m_bHasChecked) + { + m_uiSelfRepairTimer = 15000; + m_bIsTorsoDead = true; + m_bHasChecked = true; + } + if(m_pInstance->GetData(TYPE_AERIAL_UNIT) == SPECIAL && !m_bHasChecked) + { + m_uiSelfRepairTimer = 15000; + m_bIsHeadDead = true; + m_bHasChecked = true; + } + + if(m_uiSelfRepairTimer < uiDiff && m_bHasChecked) + { + if(m_pInstance->GetData(TYPE_LEVIATHAN_MK) == SPECIAL) + m_bIsTankDead = true; + if(m_pInstance->GetData(TYPE_VX001) == SPECIAL) + m_bIsTorsoDead = true; + if(m_pInstance->GetData(TYPE_AERIAL_UNIT) == SPECIAL) + m_bIsHeadDead = true; + + if(m_bIsTankDead && m_bIsTorsoDead && m_bIsHeadDead) + { + DoScriptText(SAY_ROBOT_DEATH, m_creature); + m_uiOutroTimer = 15000; + m_pInstance->SetData(TYPE_MIMIRON_PHASE, PHASE_OUTRO); + } + else + { + m_bHasChecked = false; + if(m_bIsTankDead) + { + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + ((boss_leviathan_mkAI*)pTank->AI())->Repair(); + } + if(m_bIsTorsoDead) + { + if(Creature* pTorso = m_pInstance->instance->GetCreature(m_uiTorsoGUID)) + ((boss_vx001AI*)pTorso->AI())->Repair(); + } + if(m_bIsHeadDead) + { + if(Creature* pHead = m_pInstance->instance->GetCreature(m_uiHeadGUID)) + ((boss_aerial_command_unitAI*)pHead->AI())->Repair(); + } + } + m_uiSelfRepairTimer = 1000; + } + else m_uiSelfRepairTimer -= uiDiff; + + break; + } + case PHASE_OUTRO: + { + if(m_uiOutroTimer < uiDiff) + { + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + m_creature->DealDamage(pTank, pTank->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if(Creature* pHead = m_pInstance->instance->GetCreature(m_uiHeadGUID)) + m_creature->DealDamage(pHead, pHead->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + if(Creature* pTorso = m_pInstance->instance->GetCreature(m_uiTorsoGUID)) + m_creature->DealDamage(pTorso, pTorso->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + DoOutro(); + m_uiOutroTimer = 60000; + } + else m_uiOutroTimer -= uiDiff; + + break; + } + } + + // berserk + if (m_uiBerserkTimer <= uiDiff) + { + if(Creature* pTank = m_pInstance->instance->GetCreature(m_uiTankGUID)) + { + if(pTank && pTank->isAlive()) + pTank->CastSpell(pTank, SPELL_BERSERK, false); + } + + if(Creature* pTorso = m_pInstance->instance->GetCreature(m_uiTorsoGUID)) + { + if(pTorso && pTorso->isAlive()) + pTorso->CastSpell(pTorso, SPELL_BERSERK, false); + } + + if(Creature* pHead = m_pInstance->instance->GetCreature(m_uiHeadGUID)) + { + if(pHead && pHead->isAlive()) + pHead->CastSpell(pHead, SPELL_BERSERK, false); + } + + m_uiBerserkTimer = 330000; + } + else + m_uiBerserkTimer -= uiDiff; + + // self destruct platform in hard mode + if (m_uiSelfDestructTimer < uiDiff && m_bIsHardMode) + { + m_creature->SummonCreature(NPC_MIMIRON_INFERNO, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + // visual part, hacky way + if(Creature* pTemp = m_creature->SummonCreature(NPC_MIMIRON_FOCUS, CENTER_X, CENTER_Y, CENTER_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) + { + pTemp->GetMotionMaster()->MoveIdle(); + pTemp->CombatStop(); + pTemp->SetDisplayId(11686); // make invisible + pTemp->CastSpell(pTemp, SPELL_SELF_DESTRUCTION, false); + } + m_uiSelfDestructTimer = 60000; + } + else m_uiSelfDestructTimer -= uiDiff; + } +}; + +// Leviathan MK turret +// used in phase 1; should be attached by a vehicle seat to the Leviathan MK +struct MANGOS_DLL_DECL leviathan_turretAI : public ScriptedAI +{ + leviathan_turretAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->SetVisibility(VISIBILITY_OFF); + //pCreature->setFaction(14); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiPlasmaBlastTimer; + uint32 m_uiNapalmShellTimer; + + void Reset() + { + m_uiPlasmaBlastTimer = 20000; + m_uiNapalmShellTimer = 10000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiPlasmaBlastTimer < uiDiff) + { + if (Creature* pTank = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEVIATHAN_MK))) + { + DoScriptText(EMOTE_PLASMA_BLAST, m_creature); + if (Unit* pTarget = pTank->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_PLASMA_BLAST : SPELL_PLASMA_BLAST_H); + } + m_uiPlasmaBlastTimer = 30000; + } + else m_uiPlasmaBlastTimer -= uiDiff; + + if(m_uiNapalmShellTimer < uiDiff) + { + if (Creature* pTank = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_LEVIATHAN_MK))) + { + if (Unit* pTarget = pTank->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if(!pTank->IsWithinDistInMap(pTarget, 15)) + { + DoCast(pTarget, m_bIsRegularMode ? SPELL_NAPALM_SHELL : SPELL_NAPALM_SHELL_H); + m_uiNapalmShellTimer = 7000; + } + } + } + } + else m_uiNapalmShellTimer -= uiDiff; + } +}; + +struct MANGOS_DLL_DECL mob_proximity_mineAI : public ScriptedAI +{ + mob_proximity_mineAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiExplosionTimer; + uint32 m_uiRangeCheckTimer; + uint32 m_uiDieTimer; + + void Reset() + { + m_uiExplosionTimer = 60000; + m_uiRangeCheckTimer = 1000; + m_uiDieTimer = 65000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_MIMIRON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else + m_uiDieTimer -= uiDiff; + + if(m_uiExplosionTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_EXPLOSION : SPELL_EXPLOSION_H); + m_uiDieTimer = 500; + m_uiExplosionTimer = 20000; + } + else m_uiExplosionTimer -= uiDiff; + + if (m_uiRangeCheckTimer < uiDiff) + { + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 2)) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_EXPLOSION : SPELL_EXPLOSION_H); + m_uiDieTimer = 500; + m_uiRangeCheckTimer = 5000; + } + else + m_uiRangeCheckTimer = 500; + } + else m_uiRangeCheckTimer -= uiDiff; + } +}; + +struct MANGOS_DLL_DECL mob_bomb_botAI : public ScriptedAI +{ + mob_bomb_botAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiRangeCheckTimer; + uint32 m_uiDieTimer; + + void Reset() + { + m_uiRangeCheckTimer = 1000; + m_uiDieTimer = 600000; + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if(uiDamage > m_creature->GetHealth()) + { + DoCast(m_creature, SPELL_BOMB_BOT); + m_creature->SetHealth(m_creature->GetMaxHealth()); + uiDamage = 0; + m_uiDieTimer = 500; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else + m_uiDieTimer -= uiDiff; + + if (m_uiRangeCheckTimer < uiDiff) + { + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), 2)) + { + DoCast(m_creature, SPELL_BOMB_BOT); + m_uiDieTimer = 500; + m_uiRangeCheckTimer = 5000; + } + else + m_uiRangeCheckTimer = 500; + } + else m_uiRangeCheckTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_assault_botAI : public ScriptedAI +{ + mob_assault_botAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiMagneticFieldTimer; + + void Reset() + { + m_uiMagneticFieldTimer = 5000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiMagneticFieldTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MAGNETIC_FIELD); + m_uiMagneticFieldTimer = urand(10000, 15000); + } + else m_uiMagneticFieldTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_emergency_botAI : public ScriptedAI +{ + mob_emergency_botAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + uint32 m_uiWaterSprayTimer; + + void Reset() + { + m_uiWaterSprayTimer = urand(5000, 10000); + if(!m_bIsRegularMode) + DoCast(m_creature, SPELL_DEAFENING_SIREN); + } + + void SuppressFires() + { + std::list lFires; + GetCreatureListWithEntryInGrid(lFires, m_creature, 34363, 15.0f); + GetCreatureListWithEntryInGrid(lFires, m_creature, 34121, 15.0f); + if (!lFires.empty()) + { + for(std::list::iterator iter = lFires.begin(); iter != lFires.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiWaterSprayTimer < uiDiff) + { + DoCast(m_creature, SPELL_WATER_SPRAY); + SuppressFires(); + m_uiWaterSprayTimer = urand(7000, 12000); + } + else m_uiWaterSprayTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_frost_bomb_ulduarAI : public ScriptedAI +{ + mob_frost_bomb_ulduarAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->setFaction(14); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance *pInstance; + bool m_bIsRegularMode; + + uint32 m_uiExplosionTimer; + uint32 m_uiDieTimer; + + void Reset() + { + m_uiExplosionTimer = 10000; + m_uiDieTimer = 15000; + DoCast(m_creature, SPELL_FROST_BOMB_VISUAL); + } + + void SuppressFires() + { + std::list lFires; + GetCreatureListWithEntryInGrid(lFires, m_creature, 34363, 30.0f); + GetCreatureListWithEntryInGrid(lFires, m_creature, 34121, 30.0f); + if (!lFires.empty()) + { + for(std::list::iterator iter = lFires.begin(); iter != lFires.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiDieTimer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else + m_uiDieTimer -= uiDiff; + + if (m_uiExplosionTimer < uiDiff) + { + DoCast(m_creature, SPELL_FROST_BOMB_EXPL); + SuppressFires(); + m_uiExplosionTimer = 100000; + m_uiDieTimer = 500; + } + else m_uiExplosionTimer -= uiDiff; + } +}; + +// Flames used in hard mode +struct MANGOS_DLL_DECL mob_mimiron_flamesAI : public ScriptedAI +{ + mob_mimiron_flamesAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->setFaction(14); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiFlamesSpreadTimer; + + void Reset() + { + DoCast(m_creature, SPELL_FLAMES); + m_uiFlamesSpreadTimer = 5000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_MIMIRON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + // spread flames + if(m_uiFlamesSpreadTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_FLAMES_SPREAD); + m_uiFlamesSpreadTimer = urand(2000, 5000); + } + else m_uiFlamesSpreadTimer -= uiDiff; + } +}; + +struct MANGOS_DLL_DECL mob_mimiron_infernoAI : public ScriptedAI +{ + mob_mimiron_infernoAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->setFaction(14); + pCreature->SetDisplayId(11686); // make invisible + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiFlamesTimer; + + void Reset() + { + DoCast(m_creature, SPELL_SELF_DESTRUCTION); + m_uiFlamesTimer = 2000; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_MIMIRON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if(m_uiFlamesTimer < uiDiff) + { + DoCast(m_creature, SPELL_SELF_DESTRUCT); + m_uiFlamesTimer = 1000; + } + else m_uiFlamesTimer -= uiDiff; + } +}; + +// item script, used to bring the aerial unit down +struct MANGOS_DLL_DECL mob_magnetic_coreAI : public ScriptedAI +{ + mob_magnetic_coreAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiSpellTimer; + uint32 m_uiDieTimer; + + void Reset() + { + m_uiSpellTimer = 2000; + m_uiDieTimer = 23000; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiSpellTimer < uiDiff) + { + if(Creature* pAerial = GetClosestCreatureWithEntry(m_creature, NPC_AERIAL_UNIT, 10.0f)) + { + DoCast(pAerial, SPELL_MAGNETIC_CORE); + ((boss_aerial_command_unitAI*)pAerial->AI())->SetToGround(); + } + m_uiSpellTimer = 100000; + } + else m_uiSpellTimer -= uiDiff; + + if (m_uiDieTimer < uiDiff) + m_creature->ForcedDespawn(); + else + m_uiDieTimer -= uiDiff; + } +}; + +// Red button -> used to start the hard mode +bool GOHello_go_red_button(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* m_pInstance = (ScriptedInstance*)pGo->GetInstanceData(); + + if (!m_pInstance) + return false; + + if (Creature* pMimiron = pGo->GetMap()->GetCreature(m_pInstance->GetData64(NPC_MIMIRON))) + { + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + pPlayer->CastSpell(pPlayer, SPELL_FLAMES_SUMMON, false); + if(pMimiron->isAlive() && m_pInstance->GetData(TYPE_MIMIRON_PHASE) == PHASE_INTRO) + ((boss_mimironAI*)pMimiron->AI())->m_bIsHardMode = true; + m_pInstance->SetData(TYPE_MIMIRON_HARD, IN_PROGRESS); + } + + return false; +} + +CreatureAI* GetAI_boss_mimiron(Creature* pCreature) +{ + return new boss_mimironAI(pCreature); +} + +CreatureAI* GetAI_boss_leviathan_mk(Creature* pCreature) +{ + return new boss_leviathan_mkAI(pCreature); +} + +CreatureAI* GetAI_boss_vx001(Creature* pCreature) +{ + return new boss_vx001AI(pCreature); +} + +CreatureAI* GetAI_boss_aerial_command_unit(Creature* pCreature) +{ + return new boss_aerial_command_unitAI(pCreature); +} + +CreatureAI* GetAI_leviathan_turret(Creature* pCreature) +{ + return new leviathan_turretAI(pCreature); +} + +CreatureAI* GetAI_mob_proximity_mine(Creature* pCreature) +{ + return new mob_proximity_mineAI(pCreature); +} + +CreatureAI* GetAI_mob_bomb_bot(Creature* pCreature) +{ + return new mob_bomb_botAI(pCreature); +} + +CreatureAI* GetAI_mob_assault_bot(Creature* pCreature) +{ + return new mob_assault_botAI(pCreature); +} + +CreatureAI* GetAI_mob_emergency_bot(Creature* pCreature) +{ + return new mob_emergency_botAI(pCreature); +} + +CreatureAI* GetAI_mob_frost_bomb_ulduar(Creature* pCreature) +{ + return new mob_frost_bomb_ulduarAI(pCreature); +} + +CreatureAI* GetAI_mob_mimiron_flames(Creature* pCreature) +{ + return new mob_mimiron_flamesAI(pCreature); +} + +CreatureAI* GetAI_mob_mimiron_inferno(Creature* pCreature) +{ + return new mob_mimiron_infernoAI(pCreature); +} + +CreatureAI* GetAI_mob_magnetic_core(Creature* pCreature) +{ + return new mob_magnetic_coreAI(pCreature); +} + void AddSC_boss_mimiron() { + Script *newscript; + newscript = new Script; + newscript->Name = "boss_mimiron"; + newscript->GetAI = &GetAI_boss_mimiron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_leviathan_mk"; + newscript->GetAI = &GetAI_boss_leviathan_mk; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "leviathan_turret"; + newscript->GetAI = &GetAI_leviathan_turret; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_vx001"; + newscript->GetAI = &GetAI_boss_vx001; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_aerial_command_unit"; + newscript->GetAI = &GetAI_boss_aerial_command_unit; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_proximity_mine"; + newscript->GetAI = &GetAI_mob_proximity_mine; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_bomb_bot"; + newscript->GetAI = &GetAI_mob_bomb_bot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_assault_bot"; + newscript->GetAI = &GetAI_mob_assault_bot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_emergency_bot"; + newscript->GetAI = &GetAI_mob_emergency_bot; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_frost_bomb_ulduar"; + newscript->GetAI = &GetAI_mob_frost_bomb_ulduar; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_mimiron_flames"; + newscript->GetAI = &GetAI_mob_mimiron_flames; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_mimiron_inferno"; + newscript->GetAI = &GetAI_mob_mimiron_inferno; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_magnetic_core"; + newscript->GetAI = &GetAI_mob_magnetic_core; + newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "go_red_button"; + newscript->pGOHello = &GOHello_go_red_button; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp b/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp index 6c401d1..560b26e 100644 --- a/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp @@ -1,5 +1,5 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 - * This program is free software; you can redistribute it and/or modify +/* 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. @@ -16,29 +16,874 @@ /* ScriptData SDName: boss_razorscale -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: harpoons display should change when clicked SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_INTRO_WELCOME = -1603036, - SAY_INTRO_1 = -1603037, - SAY_INTRO_2 = -1603038, - SAY_INTRO_3 = -1603039, - SAY_GROUNDED = -1603040, - SAY_EXTINGUISH_FIRE = -1603041, + //yells/emotes + SAY_INTRO = -1603020, + SAY_AGGRO1 = -1603021, + SAY_AGGRO2 = -1603022, + SAY_AGGRO3 = -1603023, + SAY_GROUND = -1603024, + EMOTE_DEEP_BREATH = -1603025, + SAY_FIRES_EXTINGUISH = -1603026, + EMOTE_HARPOON = -1603353, + EMOTE_GROUNDED = -1603354, - EMOTE_BREATH = -1603042, - EMOTE_HARPOON_READY = -1603043, - EMOTE_GROUNDED = -1603044, + //razorscale air phase + SPELL_FIREBALL = 62796, + SPELL_FIREBALL_H = 63815, + SPELL_WING_BUFFET = 62666, + SPELL_STUN = 62794, + SPELL_SUMMON_DWARF = 62916, + //both + SPELL_BERSERK = 47008, + DEVOURING_FLAME_VISUAL = 63236, + SPELL_FLAME_BREATH = 63317, + SPELL_FLAME_BREATH_H = 64021, + //ground + SPELL_FLAME_BUFFET = 64016, + SPELL_FLAME_BUFFET_H = 64023, + SPELL_FUSE_ARMOR = 64771, + + //devouring flame target + AURA_DEVOURING_FLAME = 64709, + AURA_DEVOURING_FLAME_H = 64734, + + // mole machine + NPC_MOLE_MACHINE = 33245, // used to summon adds in phase 1 + NPC_HARPOONS_DUMMY = 33282, // used to cast spells for harpoons + SPELL_SUMMON_MOLE_MACHINE = 73071, + + // harpoons + SPELL_HARPOON_SHOT = 63659, + GO_HARPOON = 194543, // 41, 42, 194519 + + //dark rune watcher + SPELL_LIGHTNING_BOLT = 63809, + SPELL_LIGHTNING_BOLT_H = 64696, + SPELL_CHAIN_LIGHTNING = 64758, + SPELL_CHAIN_LIGHTNING_H = 64759, + + //dark rune sentinel + SPELL_BATTLE_SHOUT = 46763, + SPELL_BATTLE_SHOUT_H = 64062, + SPELL_WHIRLWIND = 63808, + + //dark rune guardian + SPELL_STORMSTRIKE = 64757, + + //NPC ids + MOB_DARK_RUNE_WATCHER = 33453, + MOB_DARK_RUNE_SENTINEL = 33846, + MOB_DARK_RUNE_GUARDIAN = 33388, + + NPC_EXP_ENGINEER = 33287, + + ACHIEV_QUICK_SHAVE = 2919, + ACHIEV_QUICK_SHAVE_H = 2921, + ACHIEV_MEDIUM_RARE = 2923, + ACHIEV_MEDIUM_RARE_H = 2924, }; -void AddSC_boss_razorscale() +//Positional defines +struct LocationsXY +{ + float x, y, z, o; + uint32 id; +}; + +static LocationsXY PositionLoc[]= +{ + {621.633301f, -228.671371f, 391.180328f},//right + {564.140198f, -222.049149f, 391.517212f},//left + {591.629761f, -209.629761f, 392.629761f},//middle + {587.629761f, -179.022522f, 391.625061f},//ground + {587.629761f, -179.022522f, 435.415070f},//air +}; + +#define HOME_X 587.546997f +#define HOME_Y -174.927002f + +#define GOSSIP_START "Bring Razorscale down!" + +//expedition commander +// start the event +struct MANGOS_DLL_DECL npc_expedition_commanderAI : public ScriptedAI +{ + npc_expedition_commanderAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bHasPlayerNear = false; + Reset(); + } + + ScriptedInstance* m_pInstance; + + bool m_bHasPlayerNear; + bool m_bIsIntro; + uint64 m_uiPlayerGUID; + uint32 m_uiSpeech_Timer; + uint32 m_uiIntro_Phase; + + void Reset() + { + m_uiPlayerGUID = 0; + m_uiSpeech_Timer = 3000; + m_bIsIntro = false; + m_uiIntro_Phase = 0; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (!m_bHasPlayerNear && m_creature->IsWithinDistInMap(pWho, 40.0f)) + { + DoScriptText(SAY_INTRO, m_creature); + m_bHasPlayerNear = true; + } + } + + void GetRazorDown() + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RAZORSCALE))) + { + pTemp->SetInCombatWithZone(); + if(Unit* pPlayer = m_creature->GetMap()->GetUnit( m_uiPlayerGUID)) + { + pTemp->AddThreat(pPlayer,0.0f); + pTemp->AI()->AttackStart(pPlayer); + } + } + } + + void BeginRazorscaleEvent(Player* pPlayer) + { + m_uiPlayerGUID = pPlayer->GetGUID(); + m_bIsIntro = true; + m_uiSpeech_Timer = 3000; + m_uiIntro_Phase = 0; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_bIsIntro) + { + if(m_uiSpeech_Timer < uiDiff) + { + switch(m_uiIntro_Phase) + { + case 0: + if(Creature* pEngineer = GetClosestCreatureWithEntry(m_creature, NPC_EXP_ENGINEER, 50.0f)) + DoScriptText(SAY_AGGRO1, pEngineer); + GetRazorDown(); + ++m_uiIntro_Phase; + m_uiSpeech_Timer = 5000; + break; + case 1: + DoScriptText(SAY_AGGRO2, m_creature); + ++m_uiIntro_Phase; + m_uiSpeech_Timer = 7000; + break; + case 2: + if(Creature* pEngineer = GetClosestCreatureWithEntry(m_creature, NPC_EXP_ENGINEER, 50.0f)) + DoScriptText(SAY_AGGRO3, pEngineer); + ++m_uiIntro_Phase; + m_uiSpeech_Timer = 5000; + break; + case 3: + m_bIsIntro = false; + ++m_uiIntro_Phase; + m_uiSpeech_Timer = 10000; + break; + default: + m_uiSpeech_Timer = 100000; + } + }else m_uiSpeech_Timer -= uiDiff; + } + } +}; + +CreatureAI* GetAI_npc_expedition_commander(Creature* pCreature) +{ + return new npc_expedition_commanderAI(pCreature); +} + +bool GossipHello_npc_expedition_commander(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance* pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + + if(pInstance->GetData(TYPE_RAZORSCALE) != DONE) + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_START, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_npc_expedition_commander(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + pPlayer->CLOSE_GOSSIP_MENU(); + pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + ((npc_expedition_commanderAI*)pCreature->AI())->BeginRazorscaleEvent(pPlayer); + } + + return true; +} + +// devouring_flame_target +struct MANGOS_DLL_DECL mob_devouring_flame_targetAI : public ScriptedAI +{ + mob_devouring_flame_targetAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiDeath_Timer; + + void Reset() + { + m_uiDeath_Timer = 25500; + m_creature->SetDisplayId(11686); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + DoCast(m_creature, m_bIsRegularMode ? AURA_DEVOURING_FLAME : AURA_DEVOURING_FLAME_H); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiDeath_Timer < uiDiff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDeath_Timer -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_devouring_flame_target(Creature* pCreature) +{ + return new mob_devouring_flame_targetAI(pCreature); +} + +// dark rune watcher +struct MANGOS_DLL_DECL mob_dark_rune_watcherAI : public ScriptedAI +{ + mob_dark_rune_watcherAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(5000, 10000); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < diff) + { + switch(urand(0, 1)) + { + case 0: + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_LIGHTNING_BOLT : SPELL_LIGHTNING_BOLT_H); + break; + case 1: + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H); + break; + } + m_uiSpell_Timer = urand(5000, 10000); + }else m_uiSpell_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_watcher(Creature* pCreature) +{ + return new mob_dark_rune_watcherAI(pCreature); +} + +// dark rune sentinel +struct MANGOS_DLL_DECL mob_dark_rune_sentinelAI : public ScriptedAI +{ + mob_dark_rune_sentinelAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiWhirl_Timer; + uint32 m_uiShout_Timer; + + void Reset() + { + m_uiWhirl_Timer = 10000; + m_uiShout_Timer = 2000; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiWhirl_Timer < diff) + { + DoCast(m_creature, SPELL_WHIRLWIND); + m_uiWhirl_Timer = urand(10000, 15000); + }else m_uiWhirl_Timer -= diff; + + if (m_uiShout_Timer < diff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_BATTLE_SHOUT : SPELL_BATTLE_SHOUT_H); + m_uiShout_Timer = 30000; + }else m_uiShout_Timer -= diff; + + DoMeleeAttackIfReady(); + } + +}; + +CreatureAI* GetAI_mob_dark_rune_sentinel(Creature* pCreature) +{ + return new mob_dark_rune_sentinelAI(pCreature); +} + +// dark rune guardian +struct MANGOS_DLL_DECL mob_dark_rune_guardianAI : public ScriptedAI +{ + mob_dark_rune_guardianAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiStormstrike_Timer; + + void Reset() + { + m_uiStormstrike_Timer = 10000; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiStormstrike_Timer < diff) + { + DoCast(m_creature->getVictim(), SPELL_STORMSTRIKE); + m_uiStormstrike_Timer = urand(7000, 13000); + }else m_uiStormstrike_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_guardian(Creature* pCreature) { + return new mob_dark_rune_guardianAI(pCreature); +} + +/// mole machine +// used to summon dwarfes +struct MANGOS_DLL_DECL mob_mole_machineAI : public ScriptedAI +{ + mob_mole_machineAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetDisplayId(11686); // make invisible + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_uiSummonTimer; + bool m_bIsSentinel; + + void Reset() + { + m_uiSummonTimer = 8000; + m_bIsSentinel = false; + DoCast(m_creature, SPELL_SUMMON_MOLE_MACHINE); + } + + void UpdateAI(const uint32 diff) + { + if (m_uiSummonTimer < diff) + { + // summon 2 dwarfes + if(!m_bIsSentinel) + { + if (Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_WATCHER, m_creature->GetPositionX() + 5, m_creature->GetPositionY() + 5, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pTemp->SetInCombatWithZone(); + pTemp->GetMotionMaster()->MovePoint(0, HOME_X, HOME_Y, m_creature->GetPositionZ()); + } + if (Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_GUARDIAN, m_creature->GetPositionX() - 5, m_creature->GetPositionY() - 5, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pTemp->SetInCombatWithZone(); + pTemp->GetMotionMaster()->MovePoint(0, HOME_X, HOME_Y, m_creature->GetPositionZ()); + } + } + // summon 1 sentinel + else + { + if (Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_SENTINEL, m_creature->GetPositionX() - 5, m_creature->GetPositionY() - 5, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000)) + { + pTemp->SetInCombatWithZone(); + pTemp->GetMotionMaster()->MovePoint(0, HOME_X, HOME_Y, m_creature->GetPositionZ()); + } + } + m_uiSummonTimer = 60000; + }else m_uiSummonTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_mole_machine(Creature* pCreature) +{ + return new mob_mole_machineAI(pCreature); } + +//razorscale +struct MANGOS_DLL_DECL boss_razorscaleAI : public ScriptedAI +{ + boss_razorscaleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiFireball_Timer; + uint32 m_uiDevouring_Flame_Timer; + uint32 m_uiFlame_Buffet_Timer; + uint32 m_uiFuse_Armor_Timer; + uint32 m_uiFlame_Breath_Timer; + uint32 m_uiWave1_spawn; //right side, 1 of each + uint32 m_uiWave2_spawn; //left side, 1 of each + uint32 m_uiWave3_spawn; // big guy + uint32 m_uiBerserk_Timer; + uint32 m_uiGrounded_Timer; // 8 secs after ground fase is over, adds come + uint32 m_uiGround_Cast; + uint32 m_uiGround_Knockback; + uint32 m_uiRepairHarpoonTimer; + uint8 m_uiHarpoonsRepaired; + uint8 m_uiMaxHarpoons; + uint64 m_uiHarpoonsGUID[4]; + uint32 m_uiTimetoground; + uint32 m_uiStun_Timer; + bool m_bAirphase; + bool m_bIsGrounded; + bool m_bHasBerserk; + bool m_bKnockback; + uint8 m_uiHarpoonsUsed; + uint8 m_uiFlyNo; + + std::list lHarpoons; + + void Reset() + { + m_uiFireball_Timer = 10000; // 10 secs for the first, fckin spam after that ~2secs + m_uiDevouring_Flame_Timer = 18000; // 18 secs first, 12 seconds after + m_uiWave1_spawn = urand(5000, 10000); + m_uiWave2_spawn = urand(5000, 10000); + m_uiWave3_spawn = urand(5000, 10000); + m_uiBerserk_Timer = 600000; // 10 min + m_uiTimetoground = 80000; + m_uiRepairHarpoonTimer = 53000; + m_uiHarpoonsRepaired = 0; + m_uiMaxHarpoons = m_bIsRegularMode ? 2 : 4; + for(int i = 0; i < m_uiMaxHarpoons; i++) + m_uiHarpoonsGUID[i] = 0; + m_bAirphase = false; + m_bIsGrounded = false; + m_bHasBerserk = false; + m_bKnockback = false; + m_uiFlyNo = 0; + m_uiHarpoonsUsed = 0; + lHarpoons.clear(); + + if(m_creature->GetPositionZ() < 435.0f) + { + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 0.0f); + m_creature->SendMonsterMove(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + } + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->GetMotionMaster()->MoveConfused(); + + if (Creature* pCommander = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_COMMANDER))) + pCommander->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_RAZORSCALE, DONE); + + if (m_uiFlyNo < 2) + { + // hacky way to complete achievements; use only if you have this function + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_QUICK_SHAVE : ACHIEV_QUICK_SHAVE_H); + } + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_RAZORSCALE, IN_PROGRESS); + + GetGameObjectListWithEntryInGrid(lHarpoons, m_creature, GO_BROKEN_HARPOON, 200.0f); + if (!lHarpoons.empty()) + { + int i = 0; + for(std::list::iterator iter = lHarpoons.begin(); iter != lHarpoons.end(); ++iter) + { + if ((*iter)) + { + m_uiHarpoonsGUID[i] = (*iter)->GetGUID(); + i += 1; + } + } + } + + m_bAirphase = true; + SetCombatMovement(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 0.0f); + m_creature->SendMonsterMove(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_RAZORSCALE, NOT_STARTED); + + BreakHarpoons(); + } + + void BreakHarpoons() + { + // reset harpoons + if (!lHarpoons.empty()) + { + for(std::list::iterator iter = lHarpoons.begin(); iter != lHarpoons.end(); ++iter) + { + if ((*iter)) + { + (*iter)->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + //(*iter)->SetUInt32Value(GAMEOBJECT_DISPLAYID, 8631); + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // AIR PHASE + // air position check (sometimes it falls to the ground like a rock + if(m_creature->GetPositionZ() < 430.0f && m_bAirphase && !m_bIsGrounded) + { + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 0.0f); + m_creature->SendMonsterMove(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + } + + // air spells + if (m_uiFireball_Timer < uiDiff && m_bAirphase && !m_bIsGrounded) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, m_bIsRegularMode ? SPELL_FIREBALL : SPELL_FIREBALL_H); + m_uiFireball_Timer = 2000; + }else m_uiFireball_Timer -= uiDiff; + + if (m_uiDevouring_Flame_Timer < uiDiff && !m_bIsGrounded) + { + if (m_bAirphase) + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(target, DEVOURING_FLAME_VISUAL); + } + else + { + if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(target, DEVOURING_FLAME_VISUAL); + } + m_uiDevouring_Flame_Timer = 12000; + }else m_uiDevouring_Flame_Timer -= uiDiff; + + // repair harpoons + if (m_uiRepairHarpoonTimer < uiDiff && m_bAirphase && !m_bIsGrounded && m_uiHarpoonsRepaired <= m_uiMaxHarpoons) + { + if(GameObject* pHarpoon = m_pInstance->instance->GetGameObject(m_uiHarpoonsGUID[m_uiHarpoonsRepaired])) + { + pHarpoon->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + //pHarpoon->SetUInt32Value(GAMEOBJECT_DISPLAYID, 8245); + m_uiHarpoonsRepaired += 1; + } + DoScriptText(EMOTE_HARPOON, m_creature); + m_uiRepairHarpoonTimer = 20000; + } + else m_uiRepairHarpoonTimer -= uiDiff; + + // ground adds + if (m_uiWave1_spawn < uiDiff && m_bAirphase && !m_bIsGrounded) + { + m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[0].x, PositionLoc[0].y, PositionLoc[0].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); + m_uiWave1_spawn = urand(40000, 50000); + }else m_uiWave1_spawn -= uiDiff; + + if (m_uiWave2_spawn < uiDiff && m_bAirphase && !m_bIsGrounded) + { + m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[1].x, PositionLoc[1].y, PositionLoc[1].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000); + m_uiWave2_spawn = urand(40000, 50000); + }else m_uiWave2_spawn -= uiDiff; + + if (m_uiWave3_spawn < uiDiff && m_bAirphase && !m_bIsGrounded) + { + switch(urand(0, 2)) //33% chance of spawning + { + case 0: + break; + case 1: + if(Creature* pTemp = m_creature->SummonCreature(NPC_MOLE_MACHINE, PositionLoc[2].x, PositionLoc[2].y, PositionLoc[2].z, 0, TEMPSUMMON_TIMED_DESPAWN, 15000)) + ((mob_mole_machineAI*)pTemp->AI())->m_bIsSentinel = true; + break; + case 2: + break; + } + m_uiWave3_spawn = urand(40000, 50000); + }else m_uiWave3_spawn -= uiDiff; + + // berserk + if (m_uiBerserk_Timer < uiDiff && !m_bHasBerserk) + { + DoCast(m_creature, SPELL_BERSERK); + m_bHasBerserk = true; + }else m_uiBerserk_Timer -= uiDiff; + + if (m_uiHarpoonsUsed == m_uiMaxHarpoons && m_bAirphase) + { + if(Creature* pCommander = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_COMMANDER))) + DoScriptText(SAY_GROUND, pCommander); + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[3].x, PositionLoc[3].y, PositionLoc[3].z, 1.5); + m_creature->SendMonsterMove(PositionLoc[3].x, PositionLoc[3].y, PositionLoc[3].z, SPLINETYPE_FACINGSPOT, m_creature->GetSplineFlags(), 1); + // timers + m_uiHarpoonsUsed = 0; + m_bIsGrounded = true; + m_uiStun_Timer = 2000; + m_uiGround_Cast = 35000; + m_uiGrounded_Timer = 45000; + // make boss land + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + }else m_uiTimetoground -= uiDiff; + + if (m_uiStun_Timer < uiDiff && m_bIsGrounded) + { + DoCast(m_creature, SPELL_STUN); + m_uiStun_Timer = 60000; + }else m_uiStun_Timer -= uiDiff; + + if (m_uiGround_Cast < uiDiff && m_bIsGrounded) + { + if (Creature* pCommander = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_COMMANDER))) + m_creature->SetUInt64Value(UNIT_FIELD_TARGET, pCommander->GetGUID()); + m_creature->RemoveAurasDueToSpell(SPELL_STUN); + DoScriptText(EMOTE_DEEP_BREATH, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H); + m_uiGround_Cast = 15000; + m_uiGround_Knockback = 7000; + }else m_uiGround_Cast -= uiDiff; + + if (m_uiGround_Knockback < uiDiff && m_bIsGrounded) + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_WING_BUFFET); + m_uiGround_Knockback = 15000; + m_uiGrounded_Timer = 3000; + }else m_uiGround_Knockback -= uiDiff; + + if (m_uiGrounded_Timer < uiDiff && m_bIsGrounded) + { + m_creature->GetMap()->CreatureRelocation(m_creature, PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, 0.0f); + m_creature->SendMonsterMove(PositionLoc[4].x, PositionLoc[4].y, PositionLoc[4].z, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + + m_bIsGrounded = false; + m_uiFireball_Timer = 10000; + m_uiDevouring_Flame_Timer = 18000; + m_uiWave1_spawn = urand(5000, 10000); + m_uiWave2_spawn = urand(5000, 10000); + m_uiWave3_spawn = urand(5000, 10000); + m_uiRepairHarpoonTimer = 50000; + m_uiHarpoonsRepaired = 0; + BreakHarpoons(); + // make boss fly + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + // achiev counter + m_uiFlyNo += 1; + }else m_uiGrounded_Timer -= uiDiff; + + // make boss land at 50% hp + if (m_bAirphase && m_creature->GetHealthPercent() < 50) + { + if (m_creature->HasAura(SPELL_STUN)) + m_creature->RemoveAurasDueToSpell(SPELL_STUN); + + DoScriptText(EMOTE_GROUNDED, m_creature); + m_uiGround_Knockback = m_bIsGrounded ? 0 : 3000; + m_bAirphase = false; + m_bIsGrounded = false; + m_uiDevouring_Flame_Timer = 12000; + m_uiFlame_Buffet_Timer = 10000; //every 10 secs + m_uiFuse_Armor_Timer = 13000; //every ~13 + m_uiFlame_Breath_Timer = 6000; //every 14 + SetCombatMovement(true); + + // make boss land + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 0); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 0); + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + } + + // LAND PHASE + // knockback at the beginning at the land phase + if (m_uiGround_Knockback < uiDiff && !m_bKnockback && !m_bAirphase) + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_WING_BUFFET); + m_bKnockback = true; + }else m_uiGround_Knockback -= uiDiff; + + if (m_uiFuse_Armor_Timer < uiDiff && !m_bAirphase) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, SPELL_FUSE_ARMOR); + m_uiFuse_Armor_Timer = 13000; + } else m_uiFuse_Armor_Timer -= uiDiff; + + if (m_uiFlame_Buffet_Timer < uiDiff && !m_bAirphase) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_BUFFET : SPELL_FLAME_BUFFET_H); + m_uiFlame_Buffet_Timer = 13000; + }else m_uiFlame_Buffet_Timer -= uiDiff; + + if (m_uiFlame_Breath_Timer < uiDiff && !m_bAirphase) + { + DoScriptText(EMOTE_DEEP_BREATH, m_creature); + DoCast(m_creature, m_bIsRegularMode ? SPELL_FLAME_BREATH : SPELL_FLAME_BREATH_H); + m_uiFlame_Breath_Timer = 14000; + }else m_uiFlame_Breath_Timer -= uiDiff; + + if (!m_bAirphase && !m_bIsGrounded) + DoMeleeAttackIfReady(); + + if (m_creature->GetDistance2d(HOME_X, HOME_Y) > 100) + EnterEvadeMode(); + } +}; + +CreatureAI* GetAI_boss_razorscale(Creature* pCreature) +{ + return new boss_razorscaleAI(pCreature); +} + +bool GOHello_go_broken_harpoon(Player* pPlayer, GameObject* pGo) +{ + ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData(); + + if (!pInstance) + return false; + + pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); + if (Creature* pRazor = pGo->GetMap()->GetCreature(pInstance->GetData64(NPC_RAZORSCALE))) + ((boss_razorscaleAI*)pRazor->AI())->m_uiHarpoonsUsed += 1; + + return false; +} + +void AddSC_boss_razorscale() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_razorscale"; + NewScript->GetAI = GetAI_boss_razorscale; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_devouring_flame_target"; + NewScript->GetAI = &GetAI_mob_devouring_flame_target; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_dark_rune_watcher"; + NewScript->GetAI = &GetAI_mob_dark_rune_watcher; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_dark_rune_sentinel"; + NewScript->GetAI = &GetAI_mob_dark_rune_sentinel; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_dark_rune_guardian"; + NewScript->GetAI = &GetAI_mob_dark_rune_guardian; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_mole_machine"; + NewScript->GetAI = &GetAI_mob_mole_machine; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "npc_expedition_commander"; + NewScript->GetAI = &GetAI_npc_expedition_commander; + NewScript->pGossipHello = &GossipHello_npc_expedition_commander; + NewScript->pGossipSelect = &GossipSelect_npc_expedition_commander; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "go_broken_harpoon"; + NewScript->pGOHello = &GOHello_go_broken_harpoon; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_thorim.cpp b/scripts/northrend/ulduar/ulduar/boss_thorim.cpp index 837b785..7eed66b 100644 --- a/scripts/northrend/ulduar/ulduar/boss_thorim.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_thorim.cpp @@ -1,61 +1,1765 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_thorim -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: Implement lightning orbs, summon Sit on the platform in the first 3 min. SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_AGGRO_1 = -1603138, - SAY_AGGRO_2 = -1603139, - SAY_SPECIAL_1 = -1603140, - SAY_SPECIAL_2 = -1603141, - SAY_SPECIAL_3 = -1603142, - SAY_JUMP = -1603143, + //yells + SAY_AGGRO1 = -1603221, + SAY_AGGRO2 = -1603222, + SAY_SPECIAL1 = -1603223, + SAY_SPECIAL2 = -1603224, + SAY_SPECIAL3 = -1603225, + SAY_JUMP = -1603226, + SAY_SLAY1 = -1603227, + SAY_SLAY2 = -1603228, + SAY_BERSERK = -1603229, + SAY_ARENA_WIPE = -1603230, + SAY_DEATH = -1603231, + SAY_OUTRO1 = -1603232, + SAY_OUTRO2 = -1603233, + SAY_OUTRO3 = -1603234, + SAY_OUTRO_HARD1 = -1603235, + SAY_OUTRO_HARD2 = -1603236, + SAY_OUTRO_HARD3 = -1603237, - SAY_SLAY_1 = -1603144, - SAY_SLAY_2 = -1603145, - SAY_BERSERK = -1603146, + // Sif + SAY_SIF_INTRO = -1603185, + SAY_SIF_EVENT = -1603186, + SAY_SIF_DESPAWN = -1603187, - SAY_ARENA_WIPE = -1603147, - SAY_DEFEATED = -1603148, + // spells + // phase1 + SPELL_SHEAT_OF_LIGHTNING = 62276, + SPELL_STORMHAMMER = 62042, + SPELL_DEAFENING_THUNDER = 62470, + SPELL_LIGHTNING_SHOCK = 62017, + SPELL_CHARGE_ORB = 62016, + NPC_THUNDER_ORB = 33378, // npc used to cast charged orb + SPELL_BERSERK_ADDS = 62560, // 5 min phase 1 -> for adds + SPELL_SUMMON_LIGHTNING_ORB = 62391, + // phase2 + SPELL_TOUTCH_OF_DOMINION = 62565, // not available in hard mode + SPELL_CHAIN_LIGHTNING = 62131, + SPELL_CHAIN_LIGHTNING_H = 64390, + SPELL_LIGHTNING_CHARGE = 62279, + SPELL_LIGHTNING_CHARGE_ORB = 62466, + SPELL_UNBALANCING_STRIKE = 62130, + SPELL_BERSERK = 26662, // 5 min phase 2 - SAY_OUTRO_1 = -1603149, - SAY_OUTRO_2 = -1603150, - SAY_OUTRO_3 = -1603151, + // hard mode + SPELL_FROSTBOLT_VOLLEY = 62580, + SPELL_FROSTBOLT_VOLLEY_H = 62604, + SPELL_FROST_NOVA = 62597, + SPELL_FROST_NOVA_H = 62605, + SPELL_BLIZZARD = 62576, + SPELL_BLIZZARD_H = 62602, + NPC_SIF = 33196, + SPELL_SOUL_CHANNEL = 40401, - SAY_OUTRO_HARD_1 = -1603152, - SAY_OUTRO_HARD_2 = -1603153, - SAY_OUTRO_HARD_3 = -1603154, + // arena + MOB_DARK_RUNE_CHAMPION = 32876, + MOB_DARK_RUNE_COMMONER = 32904, + MOB_DARK_RUNE_EVOKER = 32878, + MOB_DARK_RUNE_WARBRINGER = 32877, - SAY_HELP_YOGG = -1603155, + // traps + NPC_TRAP_BUNNY = 33725, + NPC_TRAP_BUNNY2 = 33054, + SPELL_PARALYTIC_FIELD = 63540, + SPELL_PARALYTIC_FIELD2 = 62241, - SAY_SIF_BEGIN = -1603156, - SAY_SIF_EVENT = -1603157, - SAY_SIF_DESPAWN = -1603158, + // mobs spells + // acolyte + SPELL_GREATER_HEAL = 62334, + SPELL_GREATER_HEAL_H = 62442, + SPELL_RENEW = 62333, + SPELL_RENEW_H = 62441, + SPELL_HOLY_SMITE = 62335, + SPELL_HOLY_SMITE_H = 62443, + // champion + SPELL_MORTAL_STRIKE = 35054, + SPELL_CHARGE_CHAMPION = 32323, + SPELL_WHIRLWIND = 15578, + // commoner + SPELL_LOW_BLOW = 62326, + SPELL_PUMMEL = 38313, + // evoker + SPELL_RUNIC_LIGHTNING = 62327, + SPELL_RUNIC_LIGHTNING_H = 62445, + SPELL_RUNIC_MENDING = 62328, + SPELL_RUNIC_MENDING_H = 62446, + SPELL_RUNIC_SHIELD = 62321, + SPELL_RUNIC_SHIELD_H = 62529, + // warbringer + SPELL_RUNIC_STRIKE = 62322, + SPELL_AURA_CELERITY = 62320, + + // ring guard + SPELL_WHIRLING_TRIP = 64151, + SPELL_IMPALE = 62331, + SPELL_IMPALE_H = 62418, + // honor guard + SPELL_CLEAVE = 42724, + SPELL_HAMSTRING = 48639, + SPELL_SHIELD_SMASH = 62332, + SPELL_SHIELD_SMASH_H = 62420, + + // hallway + MOB_DARK_RUNE_ACOLYTE = 33110, + MOB_IRON_RING_GUARD = 32874, + MINIBOSS_RUNIC_COLOSSUS = 32872, + SPELL_SMASH = 62339, + //SPELL_SMASH_RIGHT = 62414, + SPELL_RUNIC_SMASH = 62058, + SPELL_RUNIC_SMASH2 = 62057, + SPELL_RUNIC_SMASH_DMG = 62465, + SPELL_RUNIC_BARRIER = 62338, + SPELL_CHARGE = 62613, + SPELL_CHARGE_H = 62614, + + MOB_IRON_HOHOR_GUARD = 32875, + MINIBOSS_ANCIENT_RUNE_GIANT = 32873, + SPELL_RUNIC_FORTIFICATION = 62942, + SPELL_STOMP = 62411, + SPELL_STOMP_H = 62413, + SPELL_RUNE_DETONATION = 62526, + + // pre adds: + SPELL_ACID_BREATH = 62315, + SPELL_ACID_BREATH_H = 62415, + SPELL_SWEEP = 62316, + SPELL_SWEEP_H = 62417, + // captains + NPC_CAPTAIN_ALY = 32908, + NPC_CAPTAIN_HORDE = 32907, + SPELL_DEVASTATE = 62317, + SPELL_HEROIC_STRIKE = 62444, + // mercenary + NPC_MERCENARY_ALY = 32885, + NPC_MERCENARY_HORDE = 32883, + SPELL_SHOOT = 16496, + SPELL_BARBED_SHOT = 62318, + SPELL_WING_CLIP = 40652, + + ACHIEV_LOSE_ILLUSION = 3176, + ACHIEV_LOSE_ILLUSION_H = 3183, + ACHIEV_SIFFED = 2977, + ACHIEV_SIFFED_H = 2978, +}; + +enum phases +{ + PHASE_PREADDS = 0, + PHASE_INTRO = 1, + PHASE_BALCONY = 2, + PHASE_ARENA = 3, + PHASE_OUTRO = 4, +}; + +#define LOC_Z 419.5f +struct LocationsXY +{ + float x, y, z; + uint32 id; +}; +static LocationsXY ArenaLoc[]= +{ + {2158.082f, -240.572f}, + {2111.883f, -240.561f}, + {2105.243f, -274.499f}, + {2163.927f, -277.834f}, + {2104.865f, -251.027f}, + {2167.612f, -262.128f}, +}; + +static LocationsXY OrbLoc[]= +{ + {2134.57f, -440.31f, 438.33f}, + {2225.91f, -431.68f, 412.17f}, + {2228.26f, -266.46f, 412.17f}, +}; + +// trap bunny +struct MANGOS_DLL_DECL mob_thorim_trap_bunnyAI : public ScriptedAI +{ + mob_thorim_trap_bunnyAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SetCombatMovement(false); + pCreature->setFaction(14); + Reset(); + } + + bool m_bHasStunAura; + uint32 m_uiAuraExpireTimer; + + void Reset() + { + m_bHasStunAura = false; + } + + void MoveInLineOfSight(Unit* pWho) + { + if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && !m_bHasStunAura && + pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 12) && m_creature->IsWithinLOSInMap(pWho)) + { + m_bHasStunAura = true; + m_uiAuraExpireTimer = 15000; + DoCast(m_creature, SPELL_PARALYTIC_FIELD); + } + } + + void AttackStart(Unit* pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiAuraExpireTimer < uiDiff && m_bHasStunAura) + m_bHasStunAura = false; + else m_uiAuraExpireTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_mob_thorim_trap_bunny(Creature* pCreature) +{ + return new mob_thorim_trap_bunnyAI(pCreature); +} + +// dark rune acolyte +struct MANGOS_DLL_DECL mob_dark_rune_acolyteAI : public ScriptedAI +{ + mob_dark_rune_acolyteAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(3000, 6000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + switch(urand(0, 4)) + { + case 0: + case 1: + if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_GREATER_HEAL : SPELL_GREATER_HEAL_H); + break; + case 2: + case 3: + if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_RENEW : SPELL_RENEW_H); + break; + case 4: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_HOLY_SMITE : SPELL_HOLY_SMITE_H); + break; + } + m_uiSpell_Timer = urand(3000, 6000); + }else m_uiSpell_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_acolyte(Creature* pCreature) +{ + return new mob_dark_rune_acolyteAI(pCreature); +} + +// dark rune champion +struct MANGOS_DLL_DECL mob_dark_rune_championAI : public ScriptedAI +{ + mob_dark_rune_championAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(3000, 6000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + switch(urand(0, 2)) + { + case 0: + DoCast(m_creature->getVictim(), SPELL_MORTAL_STRIKE); + break; + case 1: + DoCast(m_creature->getVictim(), SPELL_CHARGE_CHAMPION); + break; + case 2: + DoCast(m_creature->getVictim(), SPELL_WHIRLWIND); + break; + } + m_uiSpell_Timer = urand(3000, 6000); + }else m_uiSpell_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_champion(Creature* pCreature) +{ + return new mob_dark_rune_championAI(pCreature); +} + +// dark rune commoner +struct MANGOS_DLL_DECL mob_dark_rune_commonerAI : public ScriptedAI +{ + mob_dark_rune_commonerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(3000, 6000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: + DoCast(m_creature->getVictim(), SPELL_LOW_BLOW); + break; + case 1: + DoCast(m_creature->getVictim(), SPELL_PUMMEL); + break; + } + m_uiSpell_Timer = urand(3000, 6000); + }else m_uiSpell_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_commoner(Creature* pCreature) +{ + return new mob_dark_rune_commonerAI(pCreature); +} + +// dark rune evoker +struct MANGOS_DLL_DECL mob_dark_rune_evokerAI : public ScriptedAI +{ + mob_dark_rune_evokerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(3000, 6000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + switch(urand(0, 4)) + { + case 0: + case 1: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_RUNIC_LIGHTNING : SPELL_RUNIC_LIGHTNING_H); + break; + case 2: + case 3: + if (Unit* pTarget = DoSelectLowestHpFriendly(50.0f)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_RUNIC_MENDING : SPELL_RUNIC_MENDING_H); + break; + case 4: + DoCast(m_creature, m_bIsRegularMode ? SPELL_RUNIC_SHIELD : SPELL_RUNIC_SHIELD_H); + break; + } + m_uiSpell_Timer = urand(3000, 6000); + }else m_uiSpell_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_evoker(Creature* pCreature) +{ + return new mob_dark_rune_evokerAI(pCreature); +} + +// dark rune warbringer +struct MANGOS_DLL_DECL mob_dark_rune_warbringerAI : public ScriptedAI +{ + mob_dark_rune_warbringerAI(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(4000, 7000); + DoCast(m_creature, SPELL_AURA_CELERITY); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_RUNIC_STRIKE); + m_uiSpell_Timer = urand(4000, 7000); + }else m_uiSpell_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_warbringer(Creature* pCreature) +{ + return new mob_dark_rune_warbringerAI(pCreature); +} + +// dark rune ring guard +struct MANGOS_DLL_DECL mob_dark_rune_ring_guardAI : public ScriptedAI +{ + mob_dark_rune_ring_guardAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(3000, 6000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: + DoCast(m_creature->getVictim(), SPELL_WHIRLING_TRIP); + break; + case 1: + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_IMPALE : SPELL_IMPALE_H); + break; + } + m_uiSpell_Timer = urand(3000, 6000); + }else m_uiSpell_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_ring_guard(Creature* pCreature) +{ + return new mob_dark_rune_ring_guardAI(pCreature); +} + +// dark rune honor guard +struct MANGOS_DLL_DECL mob_dark_rune_honor_guardAI : public ScriptedAI +{ + mob_dark_rune_honor_guardAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + uint32 m_uiSpell_Timer; + + void Reset() + { + m_uiSpell_Timer = urand(3000, 6000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpell_Timer < uiDiff) + { + switch(urand(0, 2)) + { + case 0: + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + break; + case 1: + DoCast(m_creature->getVictim(), SPELL_HAMSTRING); + break; + case 2: + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SHIELD_SMASH : SPELL_SHIELD_SMASH_H); + break; + } + m_uiSpell_Timer = urand(3000, 6000); + }else m_uiSpell_Timer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_dark_rune_honor_guard(Creature* pCreature) +{ + return new mob_dark_rune_honor_guardAI(pCreature); +} + +// thorim +struct MANGOS_DLL_DECL boss_thorimAI : public ScriptedAI +{ + boss_thorimAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + uint32 m_uiPhase; + + uint32 m_uiArenaBerserkTimer; + uint32 m_uiBerserkTimer; + uint32 m_uiArenaYellTimer; + uint32 m_uiStormHammerTimer; + uint32 m_uiDeafeningThunderTimer; + uint32 m_uiChargeOrbTimer; + uint32 m_uiSummonWavesTimer; + uint64 m_uiStormTargetGUID; + + uint32 m_uiChainLightningTimer; + uint32 m_uiLightningChargeTimer; + uint32 m_uiOrbChargeTimer; + uint32 m_uiUnbalancingStrikeTimer; + + uint32 m_uiPhase2Timer; + uint32 m_uiHardModeTimer; + + bool m_bIsPhaseEnd; + bool m_bIsHardMode; + uint32 m_uiPreAddsKilled; + + uint64 m_uiSifGUID; + + // intro & outro + bool m_bIsOutro; + uint32 m_uiOutroTimer; + uint32 m_uiOutroStep; + bool m_bIsIntro; + uint32 m_uiIntroTimer; + uint32 m_uiIntroStep; + + // mob list check + std::list lIronDwarfes; + std::list m_lOrbsGUIDList; + + void Reset() + { + m_uiPreAddsKilled = 0; + m_uiPhase = PHASE_PREADDS; + SetCombatMovement(false); + + m_bIsHardMode = true; + m_bIsPhaseEnd = false; + + m_uiArenaBerserkTimer = 280000; // 5 min - 20 secs intro + m_uiBerserkTimer = 300000; // 5 min + m_uiHardModeTimer = 160000; // 3 min - 20 sec intro + m_uiArenaYellTimer = 30000; + m_uiSummonWavesTimer = 10000; + + m_uiStormHammerTimer = 20000; + m_uiDeafeningThunderTimer = 22000; + m_uiChargeOrbTimer = 15000; + + m_uiChainLightningTimer = urand(10000, 15000); + m_uiLightningChargeTimer = urand(10000, 15000); + m_uiUnbalancingStrikeTimer = urand(15000, 20000); + m_uiOrbChargeTimer = 20000; + + m_uiOutroTimer = 10000; + m_uiOutroStep = 1; + m_bIsIntro = false; + m_uiIntroTimer = 10000; + m_uiIntroStep = 1; + m_bIsOutro = false; + m_uiSifGUID = 0; + lIronDwarfes.clear(); + m_lOrbsGUIDList.clear(); + + // exploit check + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + // respawn adds + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, MOB_IRON_RING_GUARD, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, MOB_DARK_RUNE_ACOLYTE, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, MOB_IRON_HOHOR_GUARD, DEFAULT_VISIBILITY_INSTANCE); + // preadds + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, NPC_MERCENARY_ALY, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, NPC_MERCENARY_HORDE, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, NPC_CAPTAIN_ALY, DEFAULT_VISIBILITY_INSTANCE); + GetCreatureListWithEntryInGrid(lIronDwarfes, m_creature, NPC_CAPTAIN_HORDE, DEFAULT_VISIBILITY_INSTANCE); + if (!lIronDwarfes.empty()) + { + for(std::list::iterator iter = lIronDwarfes.begin(); iter != lIronDwarfes.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); + } + } + + if(m_pInstance) + { + // respawn runic colossus + if (Creature* pColossus = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RUNIC_COLOSSUS))) + { + if (!pColossus->isAlive()) + pColossus->Respawn(); + } + + // respawn ancient rune giant + if (Creature* pRuneGiant = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_RUNE_GIANT))) + { + if (!pRuneGiant->isAlive()) + pRuneGiant->Respawn(); + } + + // respawn jormungar + if (Creature* pJormungar = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_JORMUNGAR_BEHEMOTH))) + { + if (!pJormungar->isAlive()) + pJormungar->Respawn(); + } + } + } + + void SpellHitTarget(Unit* pSpellTarget, const SpellEntry* pSpell) + { + if(pSpell->Id == SPELL_STORMHAMMER) + pSpellTarget->CastSpell(pSpellTarget, SPELL_DEAFENING_THUNDER, false); + } + + void JustReachedHome() + { + if(m_pInstance) + m_pInstance->SetData(TYPE_THORIM, NOT_STARTED); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); + } + + void DoOutro() + { + if(m_pInstance) + { + if(m_bIsHardMode) + { + m_pInstance->SetData(TYPE_THORIM_HARD, DONE); + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_LOSE_ILLUSION : ACHIEV_LOSE_ILLUSION_H); + } + m_pInstance->SetData(TYPE_THORIM, DONE); + } + + m_creature->ForcedDespawn(); + } + + // for debug only + void JustDied(Unit* pKiller) + { + if(m_pInstance) + { + if(m_bIsHardMode) + m_pInstance->SetData(TYPE_THORIM_HARD, DONE); + m_pInstance->SetData(TYPE_THORIM, DONE); + } + } + + // start phase 2 and outro + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + // phase 2 + if(uiDamage > 0 && m_uiPhase == PHASE_BALCONY && !m_bIsPhaseEnd) + { + if(m_pInstance->GetData(TYPE_RUNIC_COLOSSUS) == DONE && m_pInstance->GetData(TYPE_RUNE_GIANT) == DONE) + { + // say + DoScriptText(SAY_JUMP, m_creature); + // move in arena + m_creature->GetMotionMaster()->MovePoint(0, 2134.719f, -263.148f, 419.846f); + m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + m_creature->SetSplineFlags(SPLINEFLAG_FALLING); + m_bIsPhaseEnd = true; + m_uiPhase2Timer = 9000; + } + } + + // outro + if(m_creature->GetHealthPercent() < 1.0f && m_uiPhase == PHASE_ARENA) + { + uiDamage = 0; + m_uiPhase = PHASE_OUTRO; + } + } + + void StartEncounter() + { + m_uiPhase = PHASE_INTRO; + m_bIsIntro = true; + } + + // hacky way for berserk in phase 1 :) + void KillPlayers() + { + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && m_creature->GetDistance(i->getSource()->GetPositionX(), i->getSource()->GetPositionY(), i->getSource()->GetPositionZ()) < 200.0f) + i->getSource()->DealDamage(i->getSource(), i->getSource()->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + } + + Creature* SelectRandomOrb() + { + std::list lThunderList; + GetCreatureListWithEntryInGrid(lThunderList, m_creature, NPC_THUNDER_ORB, 100.0f); + + //This should not appear! + if (lThunderList.empty()){ + m_uiChargeOrbTimer = 5000; + return NULL; + } + + std::list::iterator iter = lThunderList.begin(); + advance(iter, urand(0, lThunderList.size()-1)); + + return *iter; + } + + void UpdateAI(const uint32 uiDiff) + { + switch(m_uiPhase) + { + // start the encounter when all the preadds have died + case PHASE_PREADDS: + if(m_uiPreAddsKilled == 4) + StartEncounter(); + break; + // do intro + case PHASE_INTRO: + { + // intro + if(m_bIsIntro) + { + switch(m_uiIntroStep) + { + case 1: + // wait 10 secs + ++m_uiIntroStep; + m_uiIntroTimer = 10000; + break; + case 3: + DoScriptText(SAY_AGGRO1, m_creature); + DoCast(m_creature, SPELL_SHEAT_OF_LIGHTNING); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetInCombatWithZone(); + if (m_pInstance) + m_pInstance->SetData(TYPE_THORIM, IN_PROGRESS); + ++m_uiIntroStep; + m_uiIntroTimer = 10000; + break; + case 5: + DoScriptText(SAY_AGGRO2, m_creature); + if(Creature* pSif = m_creature->SummonCreature(NPC_SIF, m_creature->GetPositionX() + 10, m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 700000)) + { + pSif->setFaction(35); + m_uiSifGUID = pSif->GetGUID(); + } + ++m_uiIntroStep; + m_uiIntroTimer = 9000; + break; + case 7: + if(Creature* pSif = m_pInstance->instance->GetCreature(m_uiSifGUID)) + DoScriptText(SAY_SIF_INTRO, pSif); + m_uiPhase = PHASE_BALCONY; + m_bIsIntro = false; + ++m_uiIntroStep; + m_uiIntroTimer = 9000; + break; + } + } + else return; + + if (m_uiIntroTimer <= uiDiff) + { + ++m_uiIntroStep; + m_uiIntroTimer = 330000; + } m_uiIntroTimer -= uiDiff; + + break; + } + // balcony phase + case PHASE_BALCONY: + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // phase 2 prepared + if(m_uiPhase2Timer < uiDiff && m_bIsPhaseEnd) + { + m_creature->RemoveSplineFlag(SPLINEFLAG_FALLING); + m_creature->RemoveAurasDueToSpell(SPELL_SHEAT_OF_LIGHTNING); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if(!m_bIsHardMode) + DoCast(m_creature, SPELL_TOUTCH_OF_DOMINION); + if(m_bIsHardMode) + { + if(Creature* Sif = m_pInstance->instance->GetCreature(m_uiSifGUID)) + { + Sif->setFaction(14); + DoScriptText(SAY_SIF_EVENT, Sif); + Sif->SetInCombatWithZone(); + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_SIFFED : ACHIEV_SIFFED_H); + } + } + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + SetCombatMovement(true); + m_uiPhase = PHASE_ARENA; + m_bIsPhaseEnd = false; + } + else m_uiPhase2Timer -= uiDiff; + + // return if jumping to second phase + if(m_bIsPhaseEnd) + return; + + // hard mode check + if (m_uiHardModeTimer <= uiDiff && m_bIsHardMode) + { + m_bIsHardMode = false; + if(Creature* Sif = m_pInstance->instance->GetCreature(m_uiSifGUID)) + { + if(Sif && Sif->isAlive()) + { + DoScriptText(SAY_SIF_DESPAWN, Sif); + Sif->ForcedDespawn(); + } + } + m_uiHardModeTimer = 330000; + } m_uiHardModeTimer -= uiDiff; + + // spawn adds in arena + if(m_uiSummonWavesTimer < uiDiff) + { + // 1-2 warbringer + // 1 evoker + // 5-6 commoners + // 1 champion + // 1 acolyte + uint8 i; + uint8 k; + switch(urand(0, 4)) + { + case 0: + i = urand(0, 5); + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_CHAMPION, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); + if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) + { + pTemp->AI()->AttackStart(m_creature->getVictim()); + pTemp->AddThreat(m_creature->getVictim(), 100.0f); + } + } + break; + case 1: + i = urand(0, 5); + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_EVOKER, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); + if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) + { + pTemp->AI()->AttackStart(m_creature->getVictim()); + pTemp->AddThreat(m_creature->getVictim(), 100.0f); + } + } + break; + case 2: + i = urand(5, 6); + for(uint8 j = 0; j < i; j++) + { + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_COMMONER, ArenaLoc[j].x, ArenaLoc[j].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); + if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) + { + pTemp->AI()->AttackStart(m_creature->getVictim()); + pTemp->AddThreat(m_creature->getVictim(), 100.0f); + } + } + } + break; + case 3: + k = urand(0, 3); + i = urand(k + 1, k + 2); + for(uint8 j = k; j < i; j++) + { + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_WARBRINGER, ArenaLoc[j].x, ArenaLoc[j].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); + if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) + { + pTemp->AI()->AttackStart(m_creature->getVictim()); + pTemp->AddThreat(m_creature->getVictim(), 100.0f); + } + } + } + break; + case 4: + i = urand(0, 5); + if(Creature* pTemp = m_creature->SummonCreature(MOB_DARK_RUNE_ACOLYTE, ArenaLoc[i].x, ArenaLoc[i].y, LOC_Z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, 2134.72f, -263.148f, 419.846f); + if(pTemp->IsWithinLOSInMap(m_creature->getVictim())) + { + pTemp->AI()->AttackStart(m_creature->getVictim()); + pTemp->AddThreat(m_creature->getVictim(), 100.0f); + } + } + break; + } + m_uiSummonWavesTimer = urand (7000, 10000); + } + else m_uiSummonWavesTimer -= uiDiff; + + // phase 1 spells + // charge orb + // doesn't work right, needs fixing + if(m_uiChargeOrbTimer < uiDiff) + { + if (Creature* pOrb = SelectRandomOrb()) + DoCast(pOrb, SPELL_CHARGE_ORB); + m_uiChargeOrbTimer = 20000; + } + else m_uiChargeOrbTimer -= uiDiff; + + // storm hammer + if(m_uiStormHammerTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + // should target only the players in the arena! + //if(pTarget->IsWithinLOSInMap(m_creature)) + { + DoCast(pTarget, SPELL_STORMHAMMER); + m_uiStormHammerTimer = 15000; + } + } + } + else m_uiStormHammerTimer -= uiDiff; + + if(m_uiArenaYellTimer < uiDiff) + { + switch(urand(0, 2)) + { + case 0: DoScriptText(SAY_SPECIAL1, m_creature); break; + case 1: DoScriptText(SAY_SPECIAL2, m_creature); break; + case 2: DoScriptText(SAY_SPECIAL3, m_creature); break; + } + m_uiArenaYellTimer = 30000; + } + else m_uiArenaYellTimer -= uiDiff; + + // phase 1 berserk + if(m_uiArenaBerserkTimer < uiDiff) + { + DoScriptText(SAY_ARENA_WIPE, m_creature); + //DoCast(m_creature, SPELL_BERSERK_ADDS); + // workaround because berserk doesn't work. It's casted on players not on adds. Needs core fix + KillPlayers(); + DoCast(m_creature, SPELL_SUMMON_LIGHTNING_ORB); + m_uiArenaBerserkTimer = 30000; + } + else m_uiArenaBerserkTimer -= uiDiff; + + break; + } + // arena phase + case PHASE_ARENA: + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // all spells + // chain lightning + if(m_uiChainLightningTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_CHAIN_LIGHTNING_H); + m_uiChainLightningTimer = 10000 + rand()%5000; + } + else m_uiChainLightningTimer -= uiDiff; + + // lightning charge + if(m_uiLightningChargeTimer < uiDiff) + { + DoCast(m_creature, SPELL_LIGHTNING_CHARGE); + m_uiLightningChargeTimer = 15000; + m_uiOrbChargeTimer = 2000; + } + else m_uiLightningChargeTimer -= uiDiff; + + if(m_uiOrbChargeTimer < uiDiff) + { + if (Creature* pOrb = SelectRandomOrb()) + DoCast(pOrb, SPELL_LIGHTNING_CHARGE_ORB); + m_uiOrbChargeTimer = 20000; + } + else m_uiOrbChargeTimer -= uiDiff; + + // unbalancing strike + if(m_uiUnbalancingStrikeTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, SPELL_UNBALANCING_STRIKE); + m_uiUnbalancingStrikeTimer = 25000; + } + else m_uiUnbalancingStrikeTimer -= uiDiff; + + // phase 2 berserk + if(m_uiBerserkTimer < uiDiff) + { + m_creature->InterruptNonMeleeSpells(true); + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserkTimer = 30000; + } + else m_uiBerserkTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + break; + } + // outro + case PHASE_OUTRO: + { + switch(m_uiOutroStep) + { + case 1: + m_creature->setFaction(35); + m_creature->RemoveAllAuras(); + m_creature->DeleteThreatList(); + m_creature->CombatStop(true); + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + ++m_uiOutroStep; + m_uiOutroTimer = 1000; + break; + case 3: + m_creature->SetOrientation(4.99f); + DoScriptText(SAY_DEATH, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 3000; + break; + case 5: + if(m_bIsHardMode) + { + DoScriptText(SAY_OUTRO_HARD1, m_creature); + if(Creature* Sif = m_pInstance->instance->GetCreature(m_uiSifGUID)) + DoCast(Sif, SPELL_STORMHAMMER); + } + else + DoScriptText(SAY_OUTRO1, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 1000; + break; + case 7: + if(m_bIsHardMode) + { + if(Creature* Sif = m_pInstance->instance->GetCreature(m_uiSifGUID)) + { + //summon a tentacule + if(Creature* pTentacule = m_creature->SummonCreature(34266, Sif->GetPositionX(), Sif->GetPositionY(), Sif->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 7000)) + { + pTentacule->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pTentacule->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + } + Sif->ForcedDespawn(); + } + } + ++m_uiOutroStep; + m_uiOutroTimer = 7000; + break; + case 9: + if(m_bIsHardMode) + DoScriptText(SAY_OUTRO_HARD2, m_creature); + else + DoScriptText(SAY_OUTRO2, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 13000; + break; + case 11: + if(m_bIsHardMode) + DoScriptText(SAY_OUTRO_HARD3, m_creature); + else + DoScriptText(SAY_OUTRO3, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 15000; + break; + case 13: + DoOutro(); + ++m_uiOutroStep; + m_uiOutroTimer = 10000; + break; + } + + if (m_uiOutroTimer <= uiDiff) + { + ++m_uiOutroStep; + m_uiOutroTimer = 330000; + } m_uiOutroTimer -= uiDiff; + + break; + } + } + } }; +CreatureAI* GetAI_boss_thorim(Creature* pCreature) +{ + return new boss_thorimAI(pCreature); +} + +struct MANGOS_DLL_DECL boss_runic_colossusAI : public ScriptedAI +{ + boss_runic_colossusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + uint32 m_uiSpellTimer; + uint32 m_uiRunicBarrierTimer; + uint32 m_uiSmashTimer; + uint64 m_uiSmashTargetGUID; + bool m_bIsSmash; + bool m_bMustSmash; + + void Reset() + { + m_uiSpellTimer = urand(5000, 10000); + m_uiRunicBarrierTimer = 15000; + m_uiSmashTimer = 3000; + m_uiSmashTargetGUID = 0; + m_bIsSmash = false; + m_bMustSmash = true; + + if(m_pInstance) + m_pInstance->SetData(TYPE_RUNIC_COLOSSUS, NOT_STARTED); + } + + void JustDied(Unit *killer) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_RUNIC_COLOSSUS, DONE); + } + + void MoveInLineOfSight(Unit* pWho) + { + // start smashing + if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && + !m_bIsSmash && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 70) && m_creature->IsWithinLOSInMap(pWho)) + { + m_uiSmashTargetGUID = pWho->GetGUID(); + m_creature->GetMotionMaster()->MoveIdle(); + m_bIsSmash = true; + } + + if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && + m_bIsSmash && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 5) && m_creature->IsWithinLOSInMap(pWho)) + { + m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim()); + m_bMustSmash = false; + } + } + + void UpdateAI(const uint32 uiDiff) + { + // smash, doesn't work. Spell needs core fix + if(m_uiSmashTimer < uiDiff && m_bIsSmash && m_bMustSmash) + { + if(Unit* pTarget = m_creature->GetMap()->GetUnit( m_uiSmashTargetGUID)) + DoCast(pTarget, SPELL_RUNIC_SMASH_DMG); + m_uiSmashTimer = 10000; + } + else m_uiSmashTimer -= uiDiff; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpellTimer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: + DoCast(m_creature, SPELL_SMASH); + break; + case 1: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_CHARGE : SPELL_CHARGE_H); + break; + } + m_uiSpellTimer = urand(5000, 10000); + }else m_uiSpellTimer -= uiDiff; + + if (m_uiRunicBarrierTimer < uiDiff) + { + DoCast(m_creature, SPELL_RUNIC_BARRIER); + m_uiRunicBarrierTimer = urand(25000, 30000); + }else m_uiRunicBarrierTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_runic_colossus(Creature* pCreature) +{ + return new boss_runic_colossusAI(pCreature); +} + +struct MANGOS_DLL_DECL boss_ancient_rune_giantAI : public ScriptedAI +{ + boss_ancient_rune_giantAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + uint32 m_uiSpellTimer; + uint32 m_uiSummonTimer; + bool m_bIsSummoning; + bool m_bSummonStop; + + void Reset() + { + m_uiSpellTimer = urand(5000, 10000); + m_uiSummonTimer = 10000; + m_bIsSummoning = false; + m_bSummonStop = false; + + if(m_pInstance) + m_pInstance->SetData(TYPE_RUNE_GIANT, NOT_STARTED); + } + + void JustDied(Unit *killer) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_RUNE_GIANT, DONE); + } + + void Aggro(Unit *who) + { + // should be cast on adds, spell needs core fix + //DoCast(m_creature, SPELL_RUNIC_FORTIFICATION); + m_bSummonStop = true; + m_bIsSummoning = false; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_pInstance->GetData(TYPE_RUNIC_COLOSSUS) == DONE && !m_bIsSummoning && !m_bSummonStop) + m_bIsSummoning = true; + + // summon adds before aggro and after the runic colossus has died + if(m_uiSummonTimer < uiDiff && m_bIsSummoning) + { + switch(urand(0, 1)) + { + case 0: + // ring guard + if(Creature* pTemp = m_creature->SummonCreature(32874, OrbLoc[0].x + 30, OrbLoc[0].y, OrbLoc[0].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, OrbLoc[1].x, OrbLoc[1].y, OrbLoc[1].z); + pTemp->SetInCombatWithZone(); + } + break; + case 1: + // honor guard + if(Creature* pTemp = m_creature->SummonCreature(33125, OrbLoc[0].x + 30, OrbLoc[0].y, OrbLoc[0].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MovePoint(0, OrbLoc[1].x, OrbLoc[1].y, OrbLoc[1].z); + pTemp->SetInCombatWithZone(); + } + break; + } + m_uiSummonTimer = 10000; + } + else m_uiSummonTimer -= uiDiff; + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpellTimer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: + DoCast(m_creature->getVictim(), m_bIsRegularMode? SPELL_STOMP : SPELL_STOMP_H); + break; + case 1: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_RUNE_DETONATION); + break; + } + m_uiSpellTimer = urand(5000,10000); + }else m_uiSpellTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_ancient_rune_giant(Creature* pCreature) +{ + return new boss_ancient_rune_giantAI(pCreature); +} + +struct MANGOS_DLL_DECL mob_thorim_preaddsAI : public ScriptedAI +{ + mob_thorim_preaddsAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance* m_pInstance; + + // jormungar + uint32 m_uiAcidBreathTimer; + uint32 m_uiSweepTimer; + + // captain + uint32 m_uiDevastateTimer; + uint32 m_uiHeroicStrikeTimer; + + // mercenary + uint32 m_uiShootTimer; + uint32 m_uiBarbedShotTimer; + uint32 m_uiWingClipTimer; + + void Reset() + { + // jormungar + m_uiAcidBreathTimer = urand(7000, 14000); + m_uiSweepTimer = urand(15000, 20000); + + // captain + m_uiDevastateTimer = urand(3000, 7000); + m_uiHeroicStrikeTimer = urand(8000, 15000); + + // mercenary + m_uiShootTimer = 1000; + m_uiBarbedShotTimer = urand(7000, 10000); + m_uiWingClipTimer = urand(10000, 15000); + } + + void AttackStart(Unit* pWho) + { + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + if(m_creature->GetEntry() == NPC_MERCENARY_ALY || m_creature->GetEntry() == NPC_MERCENARY_HORDE) + DoStartMovement(pWho, 20); + else + DoStartMovement(pWho); + } + } + + void JustDied(Unit *killer) + { + // start the encounter + if (Creature* pThorim = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_THORIM))) + { + if(pThorim->isAlive()) + ((boss_thorimAI*)pThorim->AI())->m_uiPreAddsKilled += 1; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + switch(m_creature->GetEntry()) + { + case NPC_JORMUNGAR_BEHEMOTH: + { + if(m_uiAcidBreathTimer < uiDiff) + { + DoCast(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ACID_BREATH : SPELL_ACID_BREATH_H); + m_uiAcidBreathTimer = urand(7000, 14000); + } + else m_uiAcidBreathTimer -= uiDiff; + + if(m_uiSweepTimer < uiDiff) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_SWEEP : SPELL_SWEEP_H); + m_uiSweepTimer = urand(15000, 23000); + } + else m_uiSweepTimer -= uiDiff; + + break; + } + case NPC_CAPTAIN_ALY: + case NPC_CAPTAIN_HORDE: + { + if(m_uiDevastateTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0)) + DoCast(pTarget, SPELL_DEVASTATE); + m_uiDevastateTimer = urand(4000, 7000); + } + else m_uiDevastateTimer -= uiDiff; + + if(m_uiHeroicStrikeTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_HEROIC_STRIKE); + m_uiHeroicStrikeTimer = urand(10000, 15000); + } + else m_uiHeroicStrikeTimer -= uiDiff; + + break; + } + case NPC_MERCENARY_ALY: + case NPC_MERCENARY_HORDE: + { + if(m_uiShootTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_SHOOT); + m_uiShootTimer = urand(1000, 3000); + } + else m_uiShootTimer -= uiDiff; + + if(m_uiBarbedShotTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BARBED_SHOT); + m_uiBarbedShotTimer = urand(7000, 10000); + } + else m_uiBarbedShotTimer -= uiDiff; + + if(m_uiWingClipTimer < uiDiff) + { + DoCast(m_creature->getVictim(), SPELL_WING_CLIP); + m_uiWingClipTimer = urand(10000, 15000); + } + else m_uiWingClipTimer -= uiDiff; + + break; + } + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_thorim_preadds(Creature* pCreature) +{ + return new mob_thorim_preaddsAI(pCreature); +} + +// sif +struct MANGOS_DLL_DECL npc_sifAI : public ScriptedAI +{ + npc_sifAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiSpellTimer; + + void Reset() + { + m_uiSpellTimer = urand(5000, 10000); + m_creature->SetRespawnDelay(DAY); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) + return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->AddThreat(pWho); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + DoStartMovement(pWho, 10.0f); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_THORIM) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSpellTimer < uiDiff) + { + switch(urand(0, 2)) + { + case 0: + DoCast(m_creature, m_bIsRegularMode? SPELL_FROSTBOLT_VOLLEY : SPELL_FROSTBOLT_VOLLEY_H); + break; + case 1: + DoCast(m_creature, m_bIsRegularMode? SPELL_FROST_NOVA : SPELL_FROST_NOVA_H); + break; + case 2: + // it should be casted around the room! + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode? SPELL_BLIZZARD : SPELL_BLIZZARD_H); + break; + } + + m_uiSpellTimer = urand(3000, 6000); + }else m_uiSpellTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_sif(Creature* pCreature) +{ + return new npc_sifAI(pCreature); +} + +// script for the orb on the hallway which should wipe the raid. Needs more research! +struct MANGOS_DLL_DECL npc_lightning_orbAI : public ScriptedAI +{ + npc_lightning_orbAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->setFaction(14); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiMoveTimer; + uint8 m_uiWaypoint; + + void Reset() + { + m_uiMoveTimer = 1000; + m_uiWaypoint = 0; + m_creature->SetRespawnDelay(DAY); + // find the correct aura for raid wipe!!! + } + + void AttackStart(Unit* pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_THORIM) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_uiMoveTimer < uiDiff && m_uiWaypoint < 4) + { + m_creature->GetMotionMaster()->MovePoint(0, OrbLoc[m_uiWaypoint].x, OrbLoc[m_uiWaypoint].y, OrbLoc[m_uiWaypoint].z); + m_uiWaypoint +=1; + m_uiMoveTimer = 10000; + } + else m_uiMoveTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_lightning_orb(Creature* pCreature) +{ + return new npc_lightning_orbAI(pCreature); +} + + void AddSC_boss_thorim() { + Script *newscript; + newscript = new Script; + newscript->Name = "boss_thorim"; + newscript->GetAI = &GetAI_boss_thorim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_runic_colossus"; + newscript->GetAI = &GetAI_boss_runic_colossus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_ancient_rune_giant"; + newscript->GetAI = &GetAI_boss_ancient_rune_giant; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_sif"; + newscript->GetAI = &GetAI_npc_sif; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_lightning_orb"; + newscript->GetAI = &GetAI_npc_lightning_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_rune_acolyte"; + newscript->GetAI = &GetAI_mob_dark_rune_acolyte; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_rune_champion"; + newscript->GetAI = &GetAI_mob_dark_rune_champion; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_rune_commoner"; + newscript->GetAI = &GetAI_mob_dark_rune_commoner; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_rune_evoker"; + newscript->GetAI = &GetAI_mob_dark_rune_evoker; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_rune_warbringer"; + newscript->GetAI = &GetAI_mob_dark_rune_warbringer; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_rune_ring_guard"; + newscript->GetAI = &GetAI_mob_dark_rune_ring_guard; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_dark_rune_honor_guard"; + newscript->GetAI = &GetAI_mob_dark_rune_honor_guard; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_thorim_preadds"; + newscript->GetAI = &GetAI_mob_thorim_preadds; + newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "mob_thorim_trap_bunny"; + newscript->GetAI = &GetAI_mob_thorim_trap_bunny; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/boss_vezax.cpp b/scripts/northrend/ulduar/ulduar/boss_vezax.cpp new file mode 100644 index 0000000..f15e0e9 --- /dev/null +++ b/scripts/northrend/ulduar/ulduar/boss_vezax.cpp @@ -0,0 +1,486 @@ +/* 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_vezax +SD%Complete: +SDComment: mark of the faceless needs core support. Searing flames needs fixing, cannot be interrupted +SDCategory: Ulduar +EndScriptData */ + +#include "precompiled.h" +#include "def_ulduar.h" + +enum +{ + SAY_AGGRO = -1603120, + SAY_SURGE = -1603123, + SAY_HARD = -1603126, + SAY_SLAY1 = -1603121, + SAY_SLAY2 = -1603122, + SAY_BERSERK = -1603125, + SAY_DEATH = -1603124, + EMOTE_VAPORS = -1603366, + EMOTE_SURGE = -1603367, + EMOTE_ANIMUS = -1603368, + + SPELL_AURA_OF_DESPAIR = 62692, + SPELL_SHADOW_CRASH = 62660, + SPELL_MARK_OF_FACELESS = 63276, + SPELL_MARK_SIMPHON = 63278, + SPELL_SEARING_FLAMES = 62661, + SPELL_SURGE_OF_DARKNESS = 62662, + SPELL_BERSERK = 26662, + SPELL_SARONITE_BARRIER = 63364, + SPELL_SUMMON_ANIMUS = 63145, + SPELL_SUMMON_VAPORS = 63081, + + NPC_SARONITE_VAPOR = 33488, + SPELL_SARONITE_VAPORS = 63323, + + NPC_SARONITE_ANIMUS = 33524, + SPELL_PROFOUND_DARKNESS = 63420, + SPELL_ANIMUS_FORMATION = 63319, + + ACHIEV_MORNING_SARONITE = 3181, + ACHIEV_MORNING_SARONITE_H = 3188, +}; + +uint8 m_uiSaroniteVaporCount; + +struct MANGOS_DLL_DECL boss_vezaxAI : public ScriptedAI +{ + boss_vezaxAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiEnrageTimer; + uint32 m_uiCrashTimer; + uint32 m_uiMarkTimer; + uint32 m_uiFlamesTimer; + uint32 m_uiSurgeTimer; + uint32 m_uiSaroniteVaporTimer; + uint32 m_uiSimphonTimer; + uint32 m_uiEndSimphonTimer; + uint32 m_uiSummonAnimusTimer; + uint64 m_uiAnimusGUID; + uint64 m_uiMarkTargetGUID; + uint32 m_uiMarkCheckTimer; + uint32 m_uiMarkEndTimer; + + std::list lVapors; + + bool m_bIsHardMode; + bool m_bActiveHardMode; + bool m_bHasMark; + bool m_bHasSimphon; + bool m_bIsAnimusAlive; + + void Reset() + { + m_uiEnrageTimer = 600000; //10 minutes + m_uiFlamesTimer = urand(8000, 10000); + m_uiSaroniteVaporTimer = 30000; + m_bIsHardMode = false; + m_bActiveHardMode = false; + m_bHasMark = false; + m_bHasSimphon = false; + m_bIsAnimusAlive = false; + + m_uiSurgeTimer = 60000; + m_uiMarkTimer = urand(10000, 35000); + m_uiCrashTimer = 10000; + m_uiSimphonTimer = 1000; + m_uiEndSimphonTimer = 10000; + m_uiAnimusGUID = 0; + m_uiMarkTargetGUID = 0; + + lVapors.clear(); + + m_uiSaroniteVaporCount = 0; + } + + void Aggro(Unit *who) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_VEZAX, IN_PROGRESS); + + DoCast(m_creature, SPELL_AURA_OF_DESPAIR); + + DoScriptText(SAY_AGGRO, m_creature); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_VEZAX, FAIL); + + m_creature->RemoveAurasDueToSpell(SPELL_SARONITE_BARRIER); + } + + void JustDied(Unit *killer) + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_VEZAX, DONE); + + if(m_bIsHardMode) + { + m_pInstance->SetData(TYPE_VEZAX_HARD, DONE); + + // hacky way to complete achievements; use only if you have this function + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_MORNING_SARONITE : ACHIEV_MORNING_SARONITE_H); + // hack used when the hard mode loot is within the Animus corpse + // PLEASE REMOVE FOR REVISION + if(Creature* pAnimus = m_pInstance->instance->GetCreature(m_uiAnimusGUID)) + pAnimus->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + DoScriptText(SAY_DEATH, m_creature); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); + } + + void PrepareHardMode() + { + m_bActiveHardMode = true; + m_uiSummonAnimusTimer = 7000; + + GetCreatureListWithEntryInGrid(lVapors, m_creature, NPC_SARONITE_VAPOR, 200.0f); + + if (!lVapors.empty()) + { + // vapors need more speed + for(std::list::iterator iter = lVapors.begin(); iter != lVapors.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + { + (*iter)->RemoveAllAuras(); + (*iter)->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + (*iter)->SetSpeedRate(MOVE_RUN, 3.0f); + (*iter)->RemoveSplineFlag(SPLINEFLAG_WALKMODE); + (*iter)->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()); + } + } + } + } + + void ActivateHardMode() + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_SARONITE_BARRIER); + //DoCast(m_creature, SPELL_SUMMON_ANIMUS); // make it by summon creature because of better handling the auras + DoScriptText(EMOTE_ANIMUS, m_creature); + DoScriptText(SAY_HARD, m_creature); + + if(Creature* pAnimus = m_creature->SummonCreature(NPC_SARONITE_ANIMUS, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation(), TEMPSUMMON_CORPSE_TIMED_DESPAWN, 900000)) + { + pAnimus->SetInCombatWithZone(); + m_uiAnimusGUID = pAnimus->GetGUID(); + } + + if (!lVapors.empty()) + { + for(std::list::iterator iter = lVapors.begin(); iter != lVapors.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); + } + } + + m_bIsHardMode = true; + m_bIsAnimusAlive = true; + } + + // hacky way for the mark of the faceless, needs core support + // PLEASE REMOVE FOR REVISION! + void CheckForMark(uint64 m_uiTargetGUID) + { + if(m_uiTargetGUID == 0) + return; + + m_bHasSimphon = false; + Map *map = m_creature->GetMap(); + Unit* pTarget = m_creature->GetMap()->GetUnit( m_uiTargetGUID); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if(pTarget && pTarget->isAlive() && !m_bHasSimphon && m_uiTargetGUID != i->getSource()->GetGUID()) + { + if (i->getSource()->isAlive() && pTarget->GetDistance2d(i->getSource()) < 10.0f) + { + DoCast(pTarget, SPELL_MARK_SIMPHON); + m_bHasSimphon = true; + } + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // prepare hard mode + if(m_uiSaroniteVaporCount == 6 && !m_bIsHardMode && !m_bActiveHardMode) + PrepareHardMode(); + + // summon animus + if(m_uiSummonAnimusTimer < uiDiff && !m_bIsHardMode && m_bActiveHardMode) + ActivateHardMode(); + else m_uiSummonAnimusTimer -= uiDiff; + + // saronite vapor + if(m_uiSaroniteVaporTimer < uiDiff && !m_bIsHardMode) + { + m_creature->CastStop(); + DoCast(m_creature, SPELL_SUMMON_VAPORS); + DoScriptText(EMOTE_VAPORS, m_creature); + m_uiSaroniteVaporCount += 1; + m_uiSaroniteVaporTimer = 30000; + } + else m_uiSaroniteVaporTimer -= uiDiff; + + // searing flames + if(m_uiFlamesTimer < uiDiff && !m_bIsAnimusAlive) + { + DoCast(m_creature, SPELL_SEARING_FLAMES); + m_uiFlamesTimer = urand(5000, 10000); + } + else m_uiFlamesTimer -= uiDiff; + + // surge of darkness + if(m_uiSurgeTimer < uiDiff) + { + m_creature->CastStop(); + DoScriptText(SAY_SURGE, m_creature); + DoScriptText(EMOTE_SURGE, m_creature); + DoCast(m_creature, SPELL_SURGE_OF_DARKNESS); + m_uiSurgeTimer = 60000; + } + else m_uiSurgeTimer -= uiDiff; + + // mark of faceless + if(m_uiMarkTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + { + m_uiMarkTargetGUID = pTarget->GetGUID(); + DoCast(pTarget, SPELL_MARK_OF_FACELESS); + } + m_bHasMark = true; + m_uiMarkCheckTimer = 1000; + m_uiMarkEndTimer = 10000; + m_uiMarkTimer = urand(25000, 30000); + } + else m_uiMarkTimer -= uiDiff; + + // HACK FOR MARK OF THE FACELESS + // mark check ending + if(m_uiMarkEndTimer < uiDiff && m_bHasMark) + m_bHasMark = false; + else m_uiMarkEndTimer -= uiDiff; + + // simphon life every sec + if(m_uiMarkCheckTimer < uiDiff && m_bHasMark) + { + CheckForMark(m_uiMarkTargetGUID); + m_uiMarkCheckTimer = 1000; + } + else m_uiMarkCheckTimer -= uiDiff; + + // shadow crash + if(m_uiCrashTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1)) + DoCast(pTarget, SPELL_SHADOW_CRASH); + m_uiCrashTimer = 10000; + } + else m_uiCrashTimer -= uiDiff; + + // enrage 10 min + if(m_uiEnrageTimer < uiDiff) + { + DoScriptText(SAY_BERSERK, m_creature); + DoCast(m_creature, SPELL_BERSERK); + m_uiEnrageTimer = 30000; + } + else m_uiEnrageTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +// Saronite animus +struct MANGOS_DLL_DECL mob_saronite_animusAI : public ScriptedAI +{ + mob_saronite_animusAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiProfoundDarknessTimer; + + void Reset() + { + m_uiProfoundDarknessTimer = 3000; + DoCast(m_creature, SPELL_ANIMUS_FORMATION); + m_creature->SetRespawnDelay(DAY); + } + + void JustDied(Unit *killer) + { + if(m_pInstance) + { + if (Creature* pVezax = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_VEZAX))) + { + if (pVezax->isAlive()) + { + pVezax->RemoveAurasDueToSpell(SPELL_SARONITE_BARRIER); + ((boss_vezaxAI*)pVezax->AI())->m_bIsAnimusAlive = false; + } + } + } + // used for hard mode loot + // REMOVE THIS FOR REVISION + //m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_VEZAX) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(m_uiProfoundDarknessTimer < uiDiff) + { + DoCast(m_creature, SPELL_PROFOUND_DARKNESS); + m_uiProfoundDarknessTimer = urand(2000, 3000); + } + else m_uiProfoundDarknessTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_saronite_vaporAI : public ScriptedAI +{ + mob_saronite_vaporAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiDieTimer; + + void Reset() + { + m_uiDieTimer = 600000; + m_creature->SetRespawnDelay(DAY); + } + + void AttackStart(Unit *pWho) + { + return; + } + + void JustDied(Unit *killer) + { + m_uiSaroniteVaporCount -= 1; + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + // Mana regen pool + if(uiDamage >= m_creature->GetHealth()) + { + uiDamage = 0; + m_uiDieTimer = 500; + DoCast(m_creature, SPELL_SARONITE_VAPORS); + } + } + + void UpdateAI(const uint32 diff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_VEZAX) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_uiDieTimer < diff) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDieTimer -= diff; + } +}; + +CreatureAI* GetAI_boss_vezax(Creature* pCreature) +{ + return new boss_vezaxAI(pCreature); +} + +CreatureAI* GetAI_mob_saronite_animus(Creature* pCreature) +{ + return new mob_saronite_animusAI(pCreature); +} + +CreatureAI* GetAI_mob_saronite_vapor(Creature* pCreature) +{ + return new mob_saronite_vaporAI(pCreature); +} + +void AddSC_boss_vezax() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_vezax"; + newscript->GetAI = &GetAI_boss_vezax; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_saronite_animus"; + newscript->GetAI = &GetAI_mob_saronite_animus; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_saronite_vapor"; + newscript->GetAI = &GetAI_mob_saronite_vapor; + newscript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_xt002.cpp b/scripts/northrend/ulduar/ulduar/boss_xt002.cpp new file mode 100644 index 0000000..fb8a775 --- /dev/null +++ b/scripts/northrend/ulduar/ulduar/boss_xt002.cpp @@ -0,0 +1,804 @@ +/* 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_xt002 +SD%Complete: +SDComment: need core support for light and gravity bomb. correct number of adds in 25man missing +SDCategory: Ulduar +EndScriptData */ + +#include "precompiled.h" +#include "def_ulduar.h" + +enum +{ + //xt yells + SAY_AGGRO = -1603038, + SAY_DEATH = -1603030, + SAY_TANCTRUM = -1603037, + SAY_SLAY_01 = -1603036, + SAY_SLAY_02 = -1603035, + SAY_BERSERK = -1603031, + SAY_ADDS = -1603032, + SAY_HEART_OPEN = -1603034, + SAY_HEART_CLOSE = -1603033, + EMOTE_HEART = -1603350, + EMOTE_REPAIR = -1603351, + + //xt-002 + SPELL_TANCTRUM = 62776, + SPELL_LIGHT_BOMB_TRIG = 65598, + SPELL_LIGHT_BOMB = 63018, + SPELL_LIGHT_BOMB_H = 65121, + SPELL_GRAVITY_BOMB = 63024, + SPELL_GRAVITY_BOMB_H = 64234, + SPELL_ENRAGE = 47008, + SPELL_STUN = 3618, + + // hard mode + SPELL_HEARTBREAK = 65737, + SPELL_HEARTBREAK_H = 64193, + SPELL_VOIDZONE = 64203, + SPELL_VOIDZONE_H = 64235, + SPELL_LIFE_SPARK = 64210, + SPELL_STATIC_CHARGED = 64227, + + NPC_VOIDZONE = 34001, + NPC_LIFESPARK = 34004, + + //heart of the deconstructor + SPELL_EXPOSED_HEART = 63849, + + //XE-321 Boombot + SPELL_BOOM = 38831, // replacing real spell + + //XM-024 Pummeller + SPELL_CLEAVE = 8374, + SPELL_TRAMPLE = 5568, + SPELL_UPPERCUT = 10966, + + //NPC ids + NPC_HEART = 33329, + NPC_SCRAPBOT = 33343, + NPC_BOOMBOT = 33346, + NPC_PUMMELER = 33344, + + // Achievs + ACHIEV_HEARTBREAKER = 3058, + ACHIEV_HEARTBREAKER_H = 3059, + ACHIEV_DECONSTRUCT_FAST = 2937, + ACHIEV_DECONSTRUCT_FAST_H = 2938, + ACHIEV_NERF_ENGINEERING = 2931, + ACHIEV_NERF_ENGINEERING_H = 2932, + ACHIEV_NERF_GRAVITY_BOMBS = 2934, + ACHIEV_NERF_GRAVITY_BOMBS_H = 2936, + ACHIEV_NERF_SCRAPBOTS = 2933, + ACHIEV_NERF_SCRAPBOTS_H = 2935, +}; + +//Positional defines +struct LocationsXY +{ + float x, y, z, o; + uint32 id; +}; + +static LocationsXY SummonLoc[]= +{ + {792.706f, 64.033f, 409.632f}, // lower left + {879.750f, 64.815f, 409.804f}, // upper left + {896.488f, -93.018f, 409.731f}, // upper right + {791.016f, -83.516f, 409.804f}, // lower right +}; + +// void zone +struct MANGOS_DLL_DECL mob_voidzoneAI : public ScriptedAI +{ + mob_voidzoneAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->setFaction(14); + SetCombatMovement(false); + Reset(); + } + + uint32 Spell_Timer; + bool m_bIsRegularMode; + + void Reset() + { + Spell_Timer = 4000; + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // should be an aura here. Couldn't find it + // hacky way, needs fixing! + if (Spell_Timer < diff) + { + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && m_creature->GetDistance2d(i->getSource()->GetPositionX(), i->getSource()->GetPositionY()) < 2) + i->getSource()->DealDamage(i->getSource(), m_bIsRegularMode ? 5000 : 7500, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, NULL, false); + } + } + Spell_Timer = 4000; + }else Spell_Timer -= diff; + } +}; + +CreatureAI* GetAI_mob_voidzone(Creature* pCreature) +{ + return new mob_voidzoneAI(pCreature); +} + +// lifespark +struct MANGOS_DLL_DECL mob_lifesparkAI : public ScriptedAI +{ + mob_lifesparkAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + void Reset() + { + DoCast(m_creature, SPELL_STATIC_CHARGED); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + } +}; + +CreatureAI* GetAI_mob_lifespark(Creature* pCreature) +{ + return new mob_lifesparkAI(pCreature); +} + +// XM-024 Pummeller +struct MANGOS_DLL_DECL mob_pummelerAI : public ScriptedAI +{ + mob_pummelerAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + uint32 Spell_Timer; + + void Reset() + { + Spell_Timer = urand(5000, 10000); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (Spell_Timer < diff) + { + switch(urand(0, 2)) + { + case 0: + DoCast(m_creature->getVictim(), SPELL_CLEAVE); + break; + case 1: + DoCast(m_creature->getVictim(), SPELL_TRAMPLE); + break; + case 2: + DoCast(m_creature->getVictim(), SPELL_UPPERCUT); + break; + } + Spell_Timer = urand(5000, 10000); + }else Spell_Timer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_pummeler(Creature* pCreature) +{ + return new mob_pummelerAI(pCreature); +} + +// XE-321 Boombot +struct MANGOS_DLL_DECL mob_boombotAI : public ScriptedAI +{ + mob_boombotAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + void Reset() + { + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage > m_creature->GetHealth()) + { + uiDamage = 0; + DoCast(m_creature, SPELL_BOOM); + } + } + + void DoMeleeAttackIfReady() + { + //If we are within range melee the target + if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE)) + DoCast(m_creature, SPELL_BOOM); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_mob_boombot(Creature* pCreature) +{ + return new mob_boombotAI(pCreature); +} + +// Heart of the Deconstructor +struct MANGOS_DLL_DECL mob_xtheartAI : public ScriptedAI +{ + mob_xtheartAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiDeathTimer; + uint32 m_uiTotalDamage; + + void Reset() + { + DoCast(m_creature, SPELL_EXPOSED_HEART); + m_creature->SetRespawnDelay(DAY); + m_uiTotalDamage = 0; + m_uiDeathTimer = 30000; + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + m_uiTotalDamage += uiDamage; + // double damage + uiDamage += uiDamage; + } + + void JustDied(Unit* pKiller) + { + // used for hard mode loot only when hard mode loot is within the heart's corpse + // remove this for revision + m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + if(m_pInstance) + m_pInstance->SetData(TYPE_XT002_HARD, IN_PROGRESS); + } + + void UpdateAI(const uint32 diff) + { + // despawns the creature if not killed in 30 secs + if(m_uiDeathTimer < diff) + { + // pass damage to boss + if (Creature* pTemp = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_XT002))) + { + if (pTemp->isAlive()) + pTemp->DealDamage(pTemp, m_uiTotalDamage, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + m_creature->ForcedDespawn(); + } + else + m_uiDeathTimer -= diff; + } +}; + +CreatureAI* GetAI_mob_xtheart(Creature* pCreature) +{ + return new mob_xtheartAI(pCreature); +} + +//XT-002 Deconstructor +struct MANGOS_DLL_DECL boss_xt002AI : public ScriptedAI +{ + boss_xt002AI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + std::list m_lScrapbotsGUIDList; + std::list m_lBoombotsGUIDList; + std::list m_lPummelerGUIDList; + + // spell timers + uint32 m_uiHeart_Timer; + uint32 m_uiLight_Bomb_Timer; + uint32 m_uiGravity_Bomb_Timer; + uint32 m_uiTanctrum_Timer; + uint32 m_uiEnrage_Timer; + uint32 m_uiRange_Check_Timer; + uint32 m_uiVoidZoneTimer; + uint32 m_uiLifeSparkTimer; + + // summon timers + uint32 m_uiScrapbotTimer; + uint32 m_uiBoombotTimer; + uint32 m_uiPummellerTimer; + uint32 m_uiScrapbotCount; + uint32 m_uiBoombotCount; + uint32 m_uiPummellerCount; + uint32 m_uiMaxScrapbot; + uint32 m_uiMaxBoombot; + + // health timers + uint32 m_uiHealthPercent; + uint32 m_uiHpDelayTimer; + bool m_bIsEnrage; + bool m_bPhase2; + + uint64 pLightBombTarGUID; + uint64 pGravityBombTarGUID; + uint64 m_uiXtHeartGUID; + + bool m_bIsHardMode; + bool m_bHasMoreHealth; + + uint32 uiEncounterTimer; + bool m_bIsEngineer; + + void Reset() + { + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + + // spell timers + m_uiLight_Bomb_Timer = 5000; // 7 seconds the first 14 secs all after(7 secs in 25man) + m_uiGravity_Bomb_Timer = 30000; // 11 seconds first 18 secs all after(11 secs in 25man) + m_uiTanctrum_Timer = 35000; // 38 seconds first 40 secs all after + m_uiEnrage_Timer = 600000; // 10 min + m_uiRange_Check_Timer = 1000; + m_uiVoidZoneTimer = 60000; + m_uiLifeSparkTimer = urand (5000, 10000); + // summon timers + m_uiScrapbotTimer = 5000; + m_uiBoombotTimer = 5000; + m_uiPummellerTimer = 5000; + m_uiScrapbotCount = 0; + m_uiBoombotCount = 0; + m_uiPummellerCount = 0; + m_uiMaxScrapbot = 0; + m_uiMaxBoombot = 0; + // health timers + m_uiHealthPercent = 75; + + m_bIsEnrage = false; + m_bPhase2 = false; + m_bIsHardMode = false; + m_bHasMoreHealth = false; + m_lScrapbotsGUIDList.clear(); + m_lBoombotsGUIDList.clear(); + m_lPummelerGUIDList.clear(); + + pLightBombTarGUID = 0; + pGravityBombTarGUID = 0; + m_uiXtHeartGUID = 0; + + uiEncounterTimer = 0; + m_bIsEngineer = true; + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_XT002, DONE); + if(m_bIsHardMode) + { + m_pInstance->SetData(TYPE_XT002_HARD, DONE); + // make the heart give the loot for hard mode + // hacky way of giving hard mode loot, used only when hard mode loot is within the heart's corpse + // PLEASE REMOVE FOR REVISION! + if(Creature* pHeart = m_pInstance->instance->GetCreature(m_uiXtHeartGUID)) + pHeart->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); + } + } + + DoScriptText(SAY_DEATH, m_creature); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if (!m_lScrapbotsGUIDList.empty()) + { + for(std::list::iterator itr = m_lScrapbotsGUIDList.begin(); itr != m_lScrapbotsGUIDList.end(); ++itr) + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + pTemp->ForcedDespawn(); + } + if (!m_lBoombotsGUIDList.empty()) + { + for(std::list::iterator itr = m_lBoombotsGUIDList.begin(); itr != m_lBoombotsGUIDList.end(); ++itr) + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + pTemp->ForcedDespawn(); + } + if (!m_lPummelerGUIDList.empty()) + { + for(std::list::iterator itr = m_lPummelerGUIDList.begin(); itr != m_lPummelerGUIDList.end(); ++itr) + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + pTemp->ForcedDespawn(); + } + + // hacky way to complete achievements; use only if you have this function + // Deconstruct Fast + if (uiEncounterTimer < 205000) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_DECONSTRUCT_FAST : ACHIEV_DECONSTRUCT_FAST_H); + } + + // Heartbreaker + if (m_bIsHardMode) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_HEARTBREAKER : ACHIEV_HEARTBREAKER_H); + } + + // Nerf Engineer + if(m_bIsEngineer) + { + if(m_pInstance) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_NERF_ENGINEERING : ACHIEV_NERF_ENGINEERING_H); + } + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_XT002, IN_PROGRESS); + if(m_pInstance->GetData(TYPE_XT002_TP) != DONE) + m_pInstance->SetData(TYPE_XT002_TP, DONE); + } + + DoScriptText(SAY_AGGRO, m_creature); + } + + void JustReachedHome() + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_XT002, FAIL); + m_pInstance->SetData(TYPE_XT002_HARD, NOT_STARTED); + } + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + } + + void KilledUnit(Unit* pVictim) + { + switch(urand(0, 1)) + { + case 0: DoScriptText(SAY_SLAY_01, m_creature); break; + case 1: DoScriptText(SAY_SLAY_02, m_creature); break; + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // Achiev timer + uiEncounterTimer += uiDiff; + + // light bomb + if (m_uiLight_Bomb_Timer < uiDiff && !m_bPhase2) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + // fix spell range + DoCast(pTarget, m_bIsRegularMode ? SPELL_LIGHT_BOMB : SPELL_LIGHT_BOMB_H); + pLightBombTarGUID = pTarget->GetGUID(); + } + + // spawn a life spark from the target + if(m_bIsHardMode) + m_uiLifeSparkTimer = 9000; + + m_uiLight_Bomb_Timer = urand(10000, 14000); + }else m_uiLight_Bomb_Timer -= uiDiff; + + // graviti bomb + if (m_uiGravity_Bomb_Timer < uiDiff && !m_bPhase2) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + // fix spell range + DoCast(pTarget, m_bIsRegularMode ? SPELL_GRAVITY_BOMB : SPELL_GRAVITY_BOMB_H); + pGravityBombTarGUID = pTarget->GetGUID(); + } + + // spawn a void zone from the target + if(m_bIsHardMode) + m_uiVoidZoneTimer = 9000; + + m_uiGravity_Bomb_Timer = urand(25000, 30000); + }else m_uiGravity_Bomb_Timer -= uiDiff; + + if (m_uiTanctrum_Timer < uiDiff && !m_bPhase2) + { + DoCast(m_creature, SPELL_TANCTRUM); + DoScriptText(SAY_TANCTRUM, m_creature); + m_uiTanctrum_Timer = 60000; + }else m_uiTanctrum_Timer -= uiDiff; + + // enrage timer + if (m_uiEnrage_Timer < uiDiff && !m_bIsEnrage && !m_bPhase2) + { + DoCast(m_creature, SPELL_ENRAGE); + if (m_creature->HasAura(SPELL_ENRAGE)) + { + m_bIsEnrage = true; + DoScriptText(SAY_BERSERK, m_creature); + } + else + m_uiEnrage_Timer = 5000; + }else m_uiEnrage_Timer -= uiDiff; + + // adds range check + if (m_uiRange_Check_Timer < uiDiff) + { + if (!m_lScrapbotsGUIDList.empty()) + { + for(std::list::iterator itr = m_lScrapbotsGUIDList.begin(); itr != m_lScrapbotsGUIDList.end(); ++itr) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + { + if (pTemp->isAlive() && m_creature->IsWithinDistInMap(pTemp, ATTACK_DISTANCE)) + { + m_creature->SetHealth(m_creature->GetHealth() + m_creature->GetMaxHealth() * 0.01); + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + m_bIsEngineer = false; + DoScriptText(EMOTE_REPAIR, m_creature); + } + } + } + } + if (!m_lBoombotsGUIDList.empty()) + { + for(std::list::iterator itr = m_lBoombotsGUIDList.begin(); itr != m_lBoombotsGUIDList.end(); ++itr) + { + if (Creature* pTemp = m_creature->GetMap()->GetCreature(*itr)) + { + if (pTemp->isAlive() && m_creature->IsWithinDistInMap(pTemp, ATTACK_DISTANCE)) + pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + } + m_uiRange_Check_Timer = 1000; + }else m_uiRange_Check_Timer -= uiDiff; + + // Hard mode + if (m_pInstance->GetData(TYPE_XT002_HARD) == IN_PROGRESS && !m_bIsHardMode) + { + DoScriptText(SAY_HEART_CLOSE, m_creature); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->RemoveAurasDueToSpell(SPELL_STUN); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->AI()->AttackStart(m_creature->getVictim()); + + DoCast(m_creature, m_bIsRegularMode ? SPELL_HEARTBREAK : SPELL_HEARTBREAK_H); + m_uiHpDelayTimer = 500; + m_bHasMoreHealth = true; + m_bIsHardMode = true; + } + + if(m_bIsHardMode) + { + m_bPhase2 = false; + + // the spell doesn't increase the boss' heart. Override + if(m_uiHpDelayTimer < uiDiff && m_bHasMoreHealth) + { + m_creature->SetHealth(m_creature->GetMaxHealth()+ (m_creature->GetMaxHealth() * m_bIsRegularMode ? 0.5 : 0.6)); + m_bHasMoreHealth = false; + }else m_uiHpDelayTimer -= uiDiff; + + if (m_uiLifeSparkTimer < uiDiff) + { + if (Unit* pTarget = m_creature->GetMap()->GetUnit( pLightBombTarGUID)) + { + Creature * LifeSpark = m_creature->SummonCreature(NPC_LIFESPARK, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000); + if(m_bIsRegularMode) + LifeSpark->SetHealth(50400); + } + m_uiLifeSparkTimer = 60000; + }else m_uiLifeSparkTimer -= uiDiff; + + if (m_uiVoidZoneTimer < uiDiff) + { + if (Unit* pTarget = m_creature->GetMap()->GetUnit( pGravityBombTarGUID)) + m_creature->SummonCreature(NPC_VOIDZONE, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 180000); + m_uiVoidZoneTimer = 60000; + }else m_uiVoidZoneTimer -= uiDiff; + } + + if (!m_bPhase2 && m_creature->GetHealthPercent() < m_uiHealthPercent && !m_bIsHardMode) + { + m_uiHeart_Timer = 30000; + m_creature->CastStop(); + m_uiHealthPercent = m_uiHealthPercent - 25; + m_bPhase2 = true; + DoScriptText(SAY_HEART_OPEN, m_creature); + DoCast(m_creature, SPELL_STUN); + DoScriptText(EMOTE_HEART, m_creature); + m_creature->SetStandState(UNIT_STAND_STATE_KNEEL); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + // timers + m_uiScrapbotTimer = urand(3000, 5000); + m_uiBoombotTimer = urand(3000, 5000); + m_uiPummellerTimer = 5000; + m_uiMaxScrapbot = urand(7, 10) * 5; + m_uiMaxBoombot = urand(3, 7); + m_uiScrapbotCount = 0; + m_uiBoombotCount = 0; + m_uiPummellerCount = 0; + + if(Creature *Heart = m_creature->SummonCreature(NPC_HEART, 0.0f, 0.0f, 0.0f, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 900000)) + { + m_uiXtHeartGUID = Heart->GetGUID(); + // this needs fixing in DB + if(!m_bIsRegularMode) + Heart->SetMaxHealth(7199999); + } + } + + if (m_bPhase2 && m_uiHeart_Timer < uiDiff) + { + DoScriptText(SAY_HEART_CLOSE, m_creature); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->RemoveAurasDueToSpell(SPELL_STUN); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->AI()->AttackStart(m_creature->getVictim()); + m_bPhase2 = false; + m_uiLight_Bomb_Timer = 7000; + m_uiGravity_Bomb_Timer = 11000; + m_uiTanctrum_Timer = 38000; + }else m_uiHeart_Timer -= uiDiff; + + //adds + if(m_bPhase2 && !m_bIsHardMode) + { + // pummeller + if(m_uiPummellerTimer < uiDiff && m_uiPummellerCount < 2) + { + if(m_uiPummellerCount == 0) + DoScriptText(SAY_ADDS, m_creature); + uint8 i = urand(0, 4); + if (Creature* pTemp = m_creature->SummonCreature(NPC_PUMMELER, SummonLoc[i].x + urand(0, 10), SummonLoc[i].y + urand(0, 10), SummonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + pTemp->AddThreat(pTarget,0.0f); + pTemp->AI()->AttackStart(pTarget); + m_lPummelerGUIDList.push_back(pTemp->GetGUID()); + } + } + m_uiPummellerCount += 1; + m_uiPummellerTimer = 4000; + } + else m_uiPummellerTimer -= uiDiff; + + // boombot + if(m_uiBoombotTimer < uiDiff && m_uiBoombotCount < m_uiMaxBoombot) + { + uint8 i = urand(0, 4); + if (Creature* pTemp = m_creature->SummonCreature(NPC_BOOMBOT, SummonLoc[i].x + urand(0, 10), SummonLoc[i].y + urand(0, 10), SummonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->AddThreat(m_creature->getVictim(),1000.0f); + pTemp->AI()->AttackStart(m_creature->getVictim()); + m_lBoombotsGUIDList.push_back(pTemp->GetGUID()); + } + m_uiBoombotCount += 1; + m_uiBoombotTimer = 4000; + } + else m_uiBoombotTimer -= uiDiff; + + // scrapbot + if(m_uiScrapbotTimer < uiDiff && m_uiScrapbotCount < m_uiMaxScrapbot) + { + uint8 i = urand(0, 4); + for(int j = 0; j < 5; j++) + { + if (Creature* pTemp = m_creature->SummonCreature(NPC_SCRAPBOT, SummonLoc[i].x + urand(0, 10), SummonLoc[i].y + urand(0, 10), SummonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + { + pTemp->GetMotionMaster()->MoveFollow(m_creature, 0, 0); + m_lScrapbotsGUIDList.push_back(pTemp->GetGUID()); + m_uiScrapbotCount += 1; + } + } + m_uiScrapbotTimer = 3000; + } + else m_uiScrapbotTimer -= uiDiff; + } + + if (!m_bPhase2) + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_xt002(Creature* pCreature) +{ + return new boss_xt002AI(pCreature); +} + +void AddSC_boss_xt002() +{ + Script* NewScript; + + NewScript = new Script; + NewScript->Name = "boss_xt002"; + NewScript->GetAI = GetAI_boss_xt002; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_pummeler"; + NewScript->GetAI = &GetAI_mob_pummeler; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_boombot"; + NewScript->GetAI = &GetAI_mob_boombot; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_xtheart"; + NewScript->GetAI = &GetAI_mob_xtheart; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_voidzone"; + NewScript->GetAI = &GetAI_mob_voidzone; + NewScript->RegisterSelf(); + + NewScript = new Script; + NewScript->Name = "mob_lifespark"; + NewScript->GetAI = &GetAI_mob_lifespark; + NewScript->RegisterSelf(); +} \ No newline at end of file diff --git a/scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp b/scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp index 00bb162..d98f73a 100644 --- a/scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp +++ b/scripts/northrend/ulduar/ulduar/boss_yogg_saron.cpp @@ -1,78 +1,2769 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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_yogg_saron -SD%Complete: 0% -SDComment: +SD%Complete: +SDComment: Implement sanity, some other spells need core support. If the topaggro target is teleported into a vision, the boss resets -> needs fixing! SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" enum { - SAY_SARA_INTRO_1 = -1603197, - SAY_SARA_INTRO_2 = -1603198, - SAY_SARA_AGGRO = -1603199, - SAY_SARA_HELP_1 = -1603200, - SAY_SARA_HELP_2 = -1603201, - SAY_SARA_SLAY_1 = -1603202, - SAY_SARA_SLAY_2 = -1603203, - SAY_WIPE_PHASE_1 = -1603204, - - SAY_PHASE_2_INTRO = -1603205, - SAY_SARA_PHASE_2_INTRO_A = -1603206, - SAY_SARA_PHASE_2_INTRO_B = -1603207, - - SAY_MADNESS = -1603209, - SAY_PHASE_3 = -1603210, - SAY_SLAY_1 = -1603211, - SAY_SLAY_2 = -1603212, - SAY_DEATH = -1603213, - SAY_TO_INSANE_1 = -1603214, - SAY_TO_INSANE_2 = -1603215, - - SAY_LICH_KING_1 = -1603216, - SAY_CHAMPION_1 = -1603217, - SAY_CHAMPION_2 = -1603218, - SAY_LICH_KING_2 = -1603219, - SAY_YOGG_V3_1 = -1603220, - SAY_YOGG_V3_2 = -1603221, - - SAY_NELTHARION_1 = -1603222, - SAY_YSERA = -1603223, - SAY_NELTHARION_2 = -1603224, - SAY_MALYGOS = -1603225, - SAY_YOGG_V2 = -1603226, - - SAY_GARONA_1 = -1603227, - SAY_GARONA_2 = -1603228, - SAY_YOGG_V1_1 = -1603229, - SAY_YOGG_V1_2 = -1603230, - SAY_GARONA_3 = -1603231, - SAY_GARONA_4 = -1603232, - SAY_YOGG_V1_3 = -1603233, - - EMOTE_VISION_BLAST = -1603234, - EMOTE_SHATTER_BLAST = -1603235, + //yells + //sara + SAY_INTRO1 = -1603307, + SAY_INTRO2 = -1603308, + SAY_AGGRO = -1603300, + SAY_HELP1 = -1603301, + SAY_HELP2 = -1603302, + SAY_SPECIAL1 = -1603305, + SAY_SPECIAL2 = -1603306, + SAY_KILL1 = -1603303, + SAY_KILL2 = -1603304, + SAY_WIPE = -1603309, + + //yogg + SAY_PHASE2 = -1603321, + SAY_VISION = -1603322, + EMOTE_PORTALS = -1603372, + EMOTE_SHATTER = -1603373, + SAY_PHASE3 = -1603323, + SAY_SLAY1 = -1603324, + SAY_SLAY2 = -1603325, + SAY_DEATH = -1603326, + SAY_INSANITY1 = -1603327, + SAY_INSANITY2 = -1603328, + + //visions + //stormwind + SAY_GARONA1 = -1603341, + SAY_GARONA2 = -1603342, + SAY_YOGG_V1_1 = -1603343, + SAY_YOGG_V1_2 = -1603344, + SAY_GARONA3 = -1603345, + SAY_GARONA4 = -1603346, + SAY_YOGG_V1_3 = -1603347, + + //dragons + SAY_NELTHARION1 = -1603336, + SAY_YSERA = -1603337, + SAY_NELTHARION2 = -1603338, + SAY_MALYGOS = -1603339, + SAY_YOGG_V2 = -1603340, + + //lich king + SAY_LICH_KING1 = -1603330, + SAY_CHAMPION1 = -1603331, + SAY_CHAMPION2 = -1603332, + SAY_LICH_KING2 = -1603333, + SAY_YOGG_V3_1 = -1603334, + SAY_YOGG_V3_2 = -1603335, + + //keepers yells + SAY_HODIR_ACTIVE = -1603086, + SAY_FREYA_ACTIVE = -1603009, + SAY_THORIM_ACTIVE = -1603238, + SAY_MIMIRON_ACTIVE = -1603260, + + //vision npc + //stormwind + NPC_GARONA = 33436, + NPC_KING_LLANE = 33437, + + MOB_SUIT_OF_ARMOR = 33433, + + //dragons + NPC_NELTHARION = 33523, + NPC_YSERA = 33495, + NPC_MALYGOS = 33535, + NPC_ALEXSTRASZA = 33536, + GO_DRAGON_SOUL = 194462, + + MOB_RUBY_CONSORT = 33716, + MOB_AZURE_CONSORT = 33717, + MOB_BRONZE_CONSORT = 33718, + MOB_EMERALD_CONSORT = 33719, + MOB_OBSIDIAN_CONSORT = 33720, + + + //lich king + NPC_LICH_KING = 33441, + NPC_IMMOLATED_CHAMPION = 33442, + + NPC_VOICE_OF_YOGG_SARON = 33280, + MOB_VISION_TENTACLE = 33943, + SPELL_GRIM_REPRISAL = 63305, + // npc hp: 15k on 10 man; 40k on 25 man + // npc no: 10 + + //spells + //phase1 + SPELL_SARAS_FERVOR = 63138, + SPELL_SARAS_BLESSING = 63134, + SPELL_SARAS_ANGER = 63147, + + MOB_GUARDIAN_OF_YOGG = 33136, + SPELL_DARK_VOLLEY = 63038, + SPELL_SHADOW_NOVA = 62714, //when dies + SPELL_SHADOW_NOVA_H = 65209, + SPELL_DOMINATE_MIND = 63713, + + // clouds + SPELL_OMINOUS_CLOUD_VISUAL = 63084, + SPELL_SUMMON_GUARDIAN = 62978, + SPELL_SUMMON_GUARDIAN2 = 63031, + NPC_OMINOUS_CLOUD = 33292, + + //phase2 + SPELL_SHADOWY_BARRIER = 64775, + SPELL_SHADOWY_BARRIER_YOGG = 63894, + SPELL_SANITY = 63050, + SPELL_PHYCHOSIS = 65301, + SPELL_PHYCHOSIS_H = 63795, + SPELL_MALADY_OF_THE_MIND = 63830, + SPELL_BRAIN_LINK = 63802, + SPELL_BRAIN_LINK_DMG = 63803, + SPELL_BRAIN_LINK_NON_DMG = 63804, + SPELL_DEATH_RAY = 63891, //summons orb + SPELL_DEATH_RAY_TRIGG = 63883, + SPELL_DEATH_RAY_VISUAL = 63886, + SPELL_DEATH_RAY_VISUAL_ORI = 63893, + MOB_DEATH_ORB = 33882, + + MODEL_SARA_VALKYR = 29182, + MODEL_SARA_HUMAN = 29117, + + // sanity + SPELL_CLEAR_INSANE = 63122, + SPELL_INSANE = 63120, + SPELL_INSANE_VISUAL = 64464, + SPELL_INSANE_TRIGG = 64554, + + SPELL_LOW_SANITY_EFFECT = 63752, + SPELL_SANITY_TRIGG = 63786, + + // portals + MOB_DESCEND_INTO_MADNESS = 34072, + SPELL_LUNATIC_GAZE = 64167, //affects players which take the portal to madness + NPC_LAUGHING_SKULL = 33990, + SKULL_DISPLAY_ID = 25206, + + // brain's chamber + MOB_BRAIN_OF_YOGG_SARON = 33890, + SPELL_SHATTERED_ILLUSION = 64173, + SPELL_INDUCE_MADNESS = 64059, + SPELL_ILLUSION_ROOM = 63988, // reduce speed + SPELL_ILLUSION_CANCEL = 63993, + + + // tentacules + MOB_CRUSHER_TENTACLE = 33966, + SPELL_ERUPT = 64144, //also used by the corruptor tentacle + SPELL_DIMINISH_POWER = 64145, + SPELL_FOCUSED_ANGER = 57689, + SPELL_FOCUSED_ANGER_TRIGG = 57688, + SPELL_SUMMON_CRUSHER = 64139, + + MOB_CONSTRICTOR_TENTACLE = 33983, + SPELL_SQUEEZE = 64125, + SPELL_SQUEEZE_H = 64126, + SPELL_SUMMON_CONSTRICTOR = 64133, + + MOB_CORRUPTOR_TENTACLE = 33985, + SPELL_APATHY = 64156, + SPELL_BLACK_PLAGUE = 64153, + SPELL_CURSE_OF_DOOM = 64157, + SPELL_DRAINING_POISON = 64152, + + // phase 3 + SPELL_LUNATIC_GAZE_YOGG = 64163, + SPELL_SHADOW_BEACON = 64465, + SPELL_EMPOWERING_SHADOWS = 64468, + SPELL_EMPOWERING_SHADOWS_H = 64486, + SPELL_DEAFENING_ROAR = 64189, //only cast on 25 player with 0-3 keepes active + + MOB_IMMORTAL_GUARDIAN = 33988, + SPELL_EMPOWERED = 65294, //starts with 9 stacks and loses 1 stak at 10% hp + SPELL_EMPOWERED_AURA = 64161, + + SPELL_BERSERK = 64166, //extinguish all life + + // keepers + // freya + SPELL_RESILIENCE_OF_NATURE = 62670, + MOB_SANITY_WELL = 33991, + SPELL_SANITY_WELL = 64169, // regen sanity + SPELL_SANITY_WELL_VISUAL = 63288, + SPELL_SUMMON_SANITY_WELL = 64170, + + // hodir + SPELL_FORTITUDE_OF_FROST = 62650, + SPELL_HODIRS_PROTECTIVE_GAZE= 64174, // saves players from killing blows ~25secs cd + + // thorim + SPELL_SPEED_OF_INVENTION = 62671, + SPELL_DESTABILIZATION_MATRIX= 65210, // cast in phase 2 on the tentacules + + // mimiron + SPELL_FURY_OF_THE_STORM = 62702, + SPELL_TITANIC_STORM = 64171, // used in phase 3 to kill guardians + SPELL_TITANIC_STORM_DMG = 64172, +}; + +enum phases +{ + // yogg phases + PHASE_IDLE = 0, + PHASE_SARA = 1, + PHASE_TENTACLES = 2, + PHASE_OLD_GOD = 3, + // vision phases + PHASE_VISION_STORMWIND = 1, + PHASE_VISION_WYRMREST = 2, + PHASE_VISION_ICECROWN = 3, + PHASE_VISION_RETURN = 4, // used to set the portals to return to main chamber = idle +}; + +enum achievs +{ + ACHIEV_ALONE = 3159, + ACHIEV_ALONE_H = 3164, + ACHIEV_ONE_LIGHT = 3158, + ACHIEV_ONE_LIGHT_H = 3163, + ACHIEV_TWO_LIGHTS = 3141, + ACHIEV_TWO_LIGHTS_H = 3162, + ACHIEV_THREE_LIGHTS = 3157, + ACHIEV_THREE_LIGHTS_H = 3161, + ACHIEV_NOT_GETTING_OLDER = 3012, + ACHIEV_NOT_GETTING_OLDER_H = 3013, +}; + +//Positional defines +struct LocationsXY +{ + float x, y, z, o; + uint32 id; +}; +static LocationsXY SummonLoc[]= +{ + {1951.097412f,-25.42042f, 326.162598f}, + {1970.677490f,-0.211162f, 325.478638f}, + {2001.049805f,-4.201718f, 325.751831f}, + {2009.346924f,-26.001806f,325.603271f}, + {1998.081665f,-46.625187f,325.551605f}, + {1962.782715f,-51.363148f,325.458160f}, + {1988.847778f,-71.143738f,328.647614f}, + {2024.004150f,-40.749989f,327.876617f}, + {2018.806885f,-3.451158f,327.593933f}, + {1978.651001f,18.373478f,328.420532f}, + {1940.641602f,1.761525f, 327.921661f}, + {1941.203735f,-52.999535f,327.246948f}, +}; + +static LocationsXY SanityWellLoc[]= +{ + {1901.237915f, -46.305782f, 331.960754f}, + {1900.753052f, -2.259287f, 332.061249f}, + {1991.020996f, 43.943943f, 331.746979f}, + {2044.219482f, -21.878244f, 329.776855f}, + {1986.226807f, -95.087761f, 330.253998f}, +}; + +static LocationsXY KeepersLoc[]= +{ + {2036.859863f, -74.113884f, 338.415222f, 2.488684f}, //thorim + {1938.328247f, -90.742043f, 338.459442f, 0.992500f}, //hodir + {2036.107056f, 25.702380f, 338.415192f, 4.019527f}, // freya + {1939.021240f, 43.221031f, 338.460663f, 5.214388f}, // mimiron +}; + +static LocationsXY TeleportLoc[]= +{ + {1941.587402f, 43.526680f, 239.666336f}, // stormwind + {2055.460938f, -25.619570f, 239.721176f}, // dragons + {1941.131226f, -94.654694f, 239.989639f}, // icecrown + {1951.097f, -25.420f, 326.162f}, // yogg +}; + +static LocationsXY YoggPortalLoc[]= +{ + {1959.765137f, -20.697853f, 325.352966f}, + {1973.407837f, -6.656567f, 324.889526f}, + {1990.271851f, -47.992981f, 324.959991f}, + {1978.893433f, -49.858326f, 324.777618f}, + {1967.471924f, -46.298458f, 324.840759f}, + {1959.654297f, -39.954502f, 324.997253f}, + {1956.343872f, -25.642859f, 325.188354f}, + {1985.072021f, -2.515451f, 325.20010f}, + {1993.541626f, -10.527716f, 324.889587f}, + {2003.674316f, -23.050785f, 325.384064f}, +}; + +static LocationsXY MadnessPortalLoc[]= +{ + {2001.015f, 4.185f, 242.747f}, + {1999.690f, -54.931f, 242.418f}, + {1946.898f, -25.769f, 242.169f}, +}; +// vison pos +//Positional defines +struct VisionLocXY +{ + float x, y, z, o; + uint32 id; +}; +// dragons +const float PosYsera[4] = {2114.504f, -16.118f, 242.646f, 3.91f}; +const float PosMalygos[4] = {2113.388f, -34.381f, 242.646f, 2.26f}; +const float PosNeltharion[4] = {2117.588f, -25.318f, 242.646f, 3.15f}; +const float PosAlexstrasza[4] = {2091.679f, -25.289f, 242.646f, 6.282f}; +const float PosVoiceDragon[3] = {2104.555f, -25.635f, 242.646f}; +const float DisplayDragons[10] = {2718, 2718, 2717, 2717, 12869, 12869, 1687, 1687, 2719, 2719}; + +static VisionLocXY DragonLoc[]= +{ + {2071.951660f, 1.881840f, 239.794922f, 5.590341f}, + {2093.910156f, 19.939915f, 239.766830f, 4.962034f}, + {2114.737061f, 20.441664f, 239.757309f, 4.259104f}, + {2136.709473f, 4.874056f, 239.718658f, 3.889961f}, + {2147.894287f, -12.416141f, 239.757980f, 3.210588f}, + {2148.479004f, -37.655373f, 239.720169f, 3.033874f}, + {2136.296631f, -56.800838f, 239.754654f, 2.287745f}, + {2114.370117f, -68.110947f, 239.721100f, 1.789017f}, + {2093.946289f, -67.447899f, 239.720734f, 1.305995f}, + {2071.001709f, -54.414040f, 239.719345f, 0.528450f}, +}; + +static VisionLocXY SkullDragonLoc[]= +{ + {2075.898193f, -5.637041f, 239.787735f}, + {2137.949219f, -26.778023f, 239.717712f}, + {2084.131836f, -52.716999f, 239.720703f}, +}; + +// stormwind +const float PosGarona[4] = {1935.398926f, 54.017738f, 240.376465f, 2.008213f}; +const float PosKing[4] = {1930.465670f, 62.674065f, 242.376373f, 5.196925f}; +const float PosVoiceStormwind[3] = {1927.326f, 68.120f, 242.376f}; + +static VisionLocXY KeepLoc[]= +{ + {1930.854370f, 39.910034f, 239.666443f, 1.641476f}, + {1909.771240f, 45.685230f, 239.666443f, 0.962106f}, + {1898.966309f, 64.644989f, 239.666443f, 0.157073f}, + {1904.273926f, 85.369118f, 239.666443f, 5.662714f}, + {1923.474487f, 96.419815f, 239.666443f, 4.826267f}, + {1944.612061f, 91.062439f, 239.666443f, 4.076213f}, + {1955.231079f, 71.870926f, 239.666443f, 3.255475f}, + {1949.701416f, 51.040390f, 239.666443f, 2.481856f}, +}; + +static VisionLocXY SkullKeepLoc[]= +{ + {1908.942261f, 58.934380f, 239.666382f}, + {1916.902954f, 86.755638f, 239.66662f}, + {1944.789307f, 78.614716f, 239.666382f}, +}; + +// lich king +const float PosLichKing[4] = {1910.499268f,-147.709961f,239.989639f, 0.943203f}; +const float PosChampion[4] = {1915.371094f,-139.934219f,239.989639f, 4.159409f}; +const float PosVoiceIcecrown[3] = {1914.332f, -139.317f, 239.989f}; + +static VisionLocXY IcecrownLoc[]= +{ + {1952.521606f, -137.052094f, 239.989716f, 2.513270f}, + {1946.220337f, -130.236008f, 239.989716f, 5.387829f}, + {1942.029541f, -136.833328f, 239.989716f, 0.192416f}, + {1896.965210f, -104.922951f, 239.989716f, 5.647007f}, + {1904.356079f, -113.879349f, 239.989716f, 2.163766f}, + {1907.664795f, -106.186508f, 239.989716f, 2.976653f}, + {1919.831421f, -131.184784f, 239.989716f, 4.213656f}, + {1919.120728f, -145.960281f, 239.989716f, 1.908511f}, + {1907.462891f, -139.149307f, 239.989716f, 0.176708f}, +}; + +static VisionLocXY SkullIcecrownLoc[]= +{ + {1962.658569f, -111.356392f, 239.98986f}, + {1940.515625f, -152.933945f, 239.989868f}, + {1889.130371f, -122.932549f, 239.98986f}, + {1908.828003f, -88.593613f, 239.98986f}, +}; + +// location of the minds eye: +// X: 1981.422974 Y: -22.442831 Z: 236.104813 + +// transfer from brain +// X: 1951.097412 Y: -25.420420 Z: 326.162598 Orientation: 0.131792 +// brain room portal loc: +// sara -> type_flags = 108; original + +// SanityAura, needs core support, not used here +class MANGOS_DLL_DECL SanityAura : public Aura +{ +public: + SanityAura(const SpellEntry *spell, SpellEffectIndex eff, int32 *bp, SpellAuraHolder *holder, Unit *target, Unit *caster) : Aura(spell, eff, bp, holder, target, caster, NULL) + {} +}; + +// Yogg Saron, main event controller +struct MANGOS_DLL_DECL boss_yogg_saronAI : public ScriptedAI +{ + boss_yogg_saronAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiBerserkTimer; + uint32 m_uiSanityTimer; + uint32 m_uiKeepersActive; + + uint32 m_uiLunaticGazaTimer; + uint32 m_uiShadowBeaconTimer; + uint32 m_uiEmpoweringShadowsTimer; + uint32 m_uiSummonTimer; + uint32 m_uiDeafeningRoarTimer; + bool m_bIsShatter; + + uint32 m_uiAchievTimer; + + std::list lClouds; + + void Reset() + { + m_uiSanityTimer = 10000; + m_uiKeepersActive = 0; + + // phase 3 + m_uiLunaticGazaTimer = 20000; + m_uiShadowBeaconTimer = 15000; + m_uiEmpoweringShadowsTimer = 60000; + m_uiSummonTimer = 40000; + m_uiDeafeningRoarTimer = 30000; + m_uiAchievTimer = 0; + m_bIsShatter = false; + m_uiBerserkTimer = 900000; // 15 min + + m_creature->SetVisibility(VISIBILITY_OFF); + + if(m_creature->HasAura(SPELL_SHADOWY_BARRIER_YOGG)) + m_creature->RemoveAurasDueToSpell(SPELL_SHADOWY_BARRIER_YOGG); + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if(m_pInstance) + { + m_pInstance->SetData(TYPE_YOGG_PHASE, PHASE_IDLE); + m_pInstance->SetData(TYPE_VISION_PHASE, PHASE_VISION_RETURN); + } + + // respawn clouds + GetCreatureListWithEntryInGrid(lClouds, m_creature, NPC_OMINOUS_CLOUD, DEFAULT_VISIBILITY_INSTANCE); + if (!lClouds.empty()) + { + for(std::list::iterator iter = lClouds.begin(); iter != lClouds.end(); ++iter) + { + if ((*iter) && !(*iter)->isAlive()) + (*iter)->Respawn(); + } + } + } + + void Aggro(Unit *who) + { + m_creature->SetInCombatWithZone(); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + //StartSanity(); + + if(m_pInstance) + { + m_pInstance->SetData(TYPE_YOGGSARON, IN_PROGRESS); + m_pInstance->SetData(TYPE_YOGG_PHASE, PHASE_SARA); + // summon thorim + if(m_pInstance->GetData(TYPE_KEEPER_THORIM) == DONE) + { + m_creature->SummonCreature(KEEPER_THORIM, KeepersLoc[0].x, KeepersLoc[0].y, KeepersLoc[0].z, KeepersLoc[0].o, TEMPSUMMON_MANUAL_DESPAWN, 0); + m_uiKeepersActive += 1; + } + // summon hodir + if(m_pInstance->GetData(TYPE_KEEPER_HODIR) == DONE) + { + m_creature->SummonCreature(KEEPER_HODIR, KeepersLoc[1].x, KeepersLoc[1].y, KeepersLoc[1].z, KeepersLoc[1].o, TEMPSUMMON_MANUAL_DESPAWN, 0); + m_uiKeepersActive += 1; + } + // summon freya + if(m_pInstance->GetData(TYPE_KEEPER_FREYA) == DONE) + { + m_creature->SummonCreature(KEEPER_FREYA, KeepersLoc[2].x, KeepersLoc[2].y, KeepersLoc[2].z, KeepersLoc[2].o, TEMPSUMMON_MANUAL_DESPAWN, 0); + m_uiKeepersActive += 1; + } + // summon mimiron + if(m_pInstance->GetData(TYPE_KEEPER_MIMIRON) == DONE) + { + m_creature->SummonCreature(KEEPER_MIMIRON, KeepersLoc[3].x, KeepersLoc[3].y, KeepersLoc[3].z, KeepersLoc[3].o, TEMPSUMMON_MANUAL_DESPAWN, 0); + m_uiKeepersActive += 1; + } + + if(Creature* pSara = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_SARA))) + DoScriptText(SAY_AGGRO, pSara); + } + } + + void JustReachedHome() + { + if (m_pInstance) + { + m_pInstance->SetData(TYPE_YOGGSARON, NOT_STARTED); + + if(Creature* pSara = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(NPC_SARA))) + { + if(!pSara->isAlive()) + pSara->Respawn(); + else + pSara->AI()->EnterEvadeMode(); + } + + if (Creature* pYoggBrain = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_YOGG_BRAIN))) + { + if(!pYoggBrain->isAlive()) + pYoggBrain->Respawn(); + else + pYoggBrain->AI()->EnterEvadeMode(); + } + } + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_SLAY1, m_creature); + else + DoScriptText(SAY_SLAY2, m_creature); + } + + void JustDied(Unit *killer) + { + DoScriptText(SAY_DEATH, m_creature); + if(m_pInstance) + { + m_pInstance->SetData(TYPE_YOGGSARON, DONE); + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 0); + + // hacky way to complete achievements; use only if you have this function + if(m_uiKeepersActive == 0) + { + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 4); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_ALONE : ACHIEV_ALONE_H); + } + else if (m_uiKeepersActive == 1) + { + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 3); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_ONE_LIGHT : ACHIEV_ONE_LIGHT_H); + } + else if (m_uiKeepersActive == 2) + { + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 2); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_TWO_LIGHTS : ACHIEV_TWO_LIGHTS_H); + } + else if (m_uiKeepersActive == 3) + { + m_pInstance->SetData(TYPE_YOGGSARON_HARD, 1); + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_THREE_LIGHTS : ACHIEV_THREE_LIGHTS_H); + } + + // under 7 min + if(m_uiAchievTimer < 420000) + m_pInstance->DoCompleteAchievement(m_bIsRegularMode ? ACHIEV_NOT_GETTING_OLDER : ACHIEV_NOT_GETTING_OLDER_H); + + } + + if(Creature* pSara = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_SARA))) + { + if(pSara->isAlive()) + pSara->DealDamage(pSara, pSara->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + if (Creature* pYoggBrain = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_YOGG_BRAIN))) + { + if(pYoggBrain->isAlive()) + pYoggBrain->DealDamage(pYoggBrain, pYoggBrain->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void StartSecondPhase() + { + m_creature->SetVisibility(VISIBILITY_ON); + DoCast(m_creature, SPELL_SHADOWY_BARRIER_YOGG); + StartSanity(); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + GetCreatureListWithEntryInGrid(lClouds, m_creature, NPC_OMINOUS_CLOUD, DEFAULT_VISIBILITY_INSTANCE); + if (!lClouds.empty()) + { + for(std::list::iterator iter = lClouds.begin(); iter != lClouds.end(); ++iter) + { + if ((*iter) && (*iter)->isAlive()) + (*iter)->ForcedDespawn(); + } + } + + m_uiSummonTimer = urand(3000, 7000); + } + + void StartThirdPhase() + { + DoScriptText(SAY_PHASE3, m_creature); + m_creature->RemoveAurasDueToSpell(SPELL_SHADOWY_BARRIER_YOGG); + m_creature->SetHealth(m_creature->GetMaxHealth() * 0.3); + + m_uiSummonTimer = urand(15000, 20000); + + if(Creature* pSara = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_SARA))) + pSara->ForcedDespawn(); + + if (Creature* pYoggBrain = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_YOGG_BRAIN))) + pYoggBrain->DealDamage(pYoggBrain, pYoggBrain->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + + // hacky way of doing sanity before the recent aura changes + void StartSanity() + { + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + SpellEntry* spell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_SANITY); + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive()) + { + /* if(i->getSource()->HasAura(SPELL_SANITY, EFFECT_INDEX_0)) + i->getSource()->GetAura(SPELL_SANITY, EFFECT_INDEX_0)->SetStackAmount(100); + else + { + if(i->getSource()->AddAura(new SanityAura(spell, EFFECT_INDEX_0, NULL, i->getSource(), m_creature))) + i->getSource()->GetAura(SPELL_SANITY, EFFECT_INDEX_0)->SetStackAmount(100); + }*/ + } + } + } + } + + void DoCastSanity() + { + uint8 m_uiStacks; + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive()) + { + // reduce sanity + if(i->getSource()->HasAura(SPELL_SANITY, EFFECT_INDEX_0)) + { + if(Aura *aura = i->getSource()->GetAura(SPELL_SANITY, EFFECT_INDEX_0)) + { + m_uiStacks = aura->GetStackAmount(); + if(m_uiStacks == 100) + DoCast(i->getSource(), SPELL_INSANE); + /*if(m_uiStacks > 1) + i->getSource()->GetAura(SPELL_SANITY, EFFECT_INDEX_0)->SetStackAmount(stack - 1); + else + { + i->getSource()->RemoveAurasDueToSpell(SPELL_SANITY); + DoCast(i->getSource(), SPELL_INSANE); + }*/ + } + } + } + } + } + } + + Creature* SelectRandomGuardian(float fRange) + { + std::list lGuardiansList; + GetCreatureListWithEntryInGrid(lGuardiansList, m_creature, MOB_IMMORTAL_GUARDIAN, fRange); + + //This should not appear! + if (lGuardiansList.empty()){ + m_uiEmpoweringShadowsTimer = 30000; + return NULL; + } + + std::list::iterator iter = lGuardiansList.begin(); + advance(iter, urand(0, lGuardiansList.size()-1)); + + return *iter; + } + + void SummonTentacles() + { + float homeZ = 0; + float creatureDist = 0; + // set tentacle entry + uint32 m_uiTentacles[] = {MOB_CONSTRICTOR_TENTACLE, MOB_CORRUPTOR_TENTACLE, MOB_CRUSHER_TENTACLE}; + uint32 m_uiEntry = urand(0, 2); + if(Creature* pTemp = GetClosestCreatureWithEntry(m_creature, MOB_CRUSHER_TENTACLE, 100.0f)) + { + if(pTemp->isAlive()) + m_uiEntry = urand(0, 1); + } + uint32 m_uiTentacleEntry = m_uiTentacles[m_uiEntry]; + + // set distance + // Z factor needs some fixing, in some cases it should be smaller + switch(urand(0, 1)) + { + case 0: + creatureDist = urand(20, 30); + homeZ = 326 + creatureDist * 0.05f; + break; + case 1: + creatureDist = urand(30, 45); + homeZ = 328 + creatureDist * 0.05f; + break; + } + + // set coordonates + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = m_creature->GetPositionX() + creatureDist*cos(angle*(M_PI/180)); + float homeY = m_creature->GetPositionY() + creatureDist*sin(angle*(M_PI/180)); + // summon tentacle + if(Creature *pTemp = m_creature->SummonCreature(m_uiTentacleEntry, homeX, homeY, homeZ, 0, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000)) + pTemp->SetInCombatWithZone(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // achiev timer + m_uiAchievTimer += uiDiff; + + switch(m_pInstance->GetData(TYPE_YOGG_PHASE)) + { + case PHASE_SARA: + // Friendly Sara phase: see script below + break; + case PHASE_TENTACLES: + { + if (m_uiSanityTimer < uiDiff) + { + //DoCastSanity(); + //DoCast(m_creature, SPELL_SANITY); + m_uiSanityTimer = 20000; + } + else m_uiSanityTimer -= uiDiff; + + // summon tentacles + if (m_uiSummonTimer < uiDiff && !m_bIsShatter) + { + SummonTentacles(); + m_uiSummonTimer = urand(10000, 15000); + } + else m_uiSummonTimer -= uiDiff; + + break; + } + case PHASE_OLD_GOD: + { + if (m_uiSummonTimer < uiDiff) + { + if(Creature *pTemp = m_creature->SummonCreature(MOB_IMMORTAL_GUARDIAN, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000)) + pTemp->SetInCombatWithZone(); + m_uiSummonTimer = 30000; + } + else m_uiSummonTimer -= uiDiff; + + if (m_uiLunaticGazaTimer < uiDiff) + { + DoCast(m_creature, SPELL_LUNATIC_GAZE_YOGG); + m_uiLunaticGazaTimer = urand(10000, 13000); + } + else m_uiLunaticGazaTimer -= uiDiff; + + if (m_uiEmpoweringShadowsTimer < uiDiff) + { + if (Creature* pGuardian = SelectRandomGuardian(80.0f)) + DoCast(pGuardian, SPELL_SHADOW_BEACON); + m_uiEmpoweringShadowsTimer = 45000; + } + else m_uiEmpoweringShadowsTimer -= uiDiff; + + if (m_uiDeafeningRoarTimer < uiDiff && !m_bIsRegularMode && m_uiKeepersActive < 4) + { + DoCast(m_creature, SPELL_DEAFENING_ROAR); + m_uiDeafeningRoarTimer = 30000; + } + else m_uiDeafeningRoarTimer -= uiDiff; + + DoMeleeAttackIfReady(); + + break; + } + } + + // extinguish all life + if (m_uiBerserkTimer < uiDiff) + { + DoCast(m_creature, SPELL_BERSERK); + m_uiBerserkTimer = 10000; + } + else m_uiBerserkTimer -= uiDiff; + } +}; + +struct MANGOS_DLL_DECL mob_madness_portalAI : public ScriptedAI +{ + mob_madness_portalAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint8 m_uiDestination; + uint32 m_uiCheckTimer; + bool m_bHasTeleported; + + void Reset() + { + m_uiCheckTimer = 500; + m_bHasTeleported = false; + m_creature->SetRespawnDelay(DAY); + if(m_pInstance) + m_uiDestination = m_pInstance->GetData(TYPE_VISION_PHASE) - 1; + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_creature->GetPositionZ() < 245.0f) + m_uiDestination = 3; + + // hacky way. This should be done by a spell + // this uses the Type_vision_phase in order to set vision destination + if(m_uiCheckTimer < uiDiff && !m_bHasTeleported) + { + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && m_creature->GetDistance2d(i->getSource()->GetPositionX(), i->getSource()->GetPositionY()) < 2) + { + i->getSource()->TeleportTo(i->getSource()->GetMapId(), TeleportLoc[m_uiDestination].x, TeleportLoc[m_uiDestination].y, TeleportLoc[m_uiDestination].z, i->getSource()->GetOrientation()); + if(m_uiDestination < 3) + { + i->getSource()->CastSpell(i->getSource(), SPELL_ILLUSION_ROOM, false); + m_creature->ForcedDespawn(); + } + else + i->getSource()->RemoveAurasDueToSpell(SPELL_ILLUSION_ROOM); + } + } + } + m_uiCheckTimer = 500; + }else m_uiCheckTimer -= uiDiff; + } +}; + +struct MANGOS_DLL_DECL boss_brain_of_yogg_saronAI : public ScriptedAI +{ + boss_brain_of_yogg_saronAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiVisionPhase; + uint32 m_uiSpeechTimer; + uint32 m_uiMadnessTimer; + uint32 m_uiTentacleCheckTimer; + + bool m_bIsPhaseFinished; + bool m_bIsVisionFinished; + bool m_bHasShattered; + + uint64 m_uiLichKingGUID; + uint64 m_uiChampionGUID; + uint64 m_uiGaronaGUID; + uint64 m_uiKingLlaneGUID; + uint64 m_uiNeltharionGUID; + uint64 m_uiMalygosGUID; + uint64 m_uiYseraGUID; + uint64 m_uiVoiceOfYoggGUID; + + void Reset() + { + m_bIsPhaseFinished = false; + m_bIsVisionFinished = false; + m_bHasShattered = false; + m_uiLichKingGUID = 0; + m_uiChampionGUID = 0; + m_uiGaronaGUID = 0; + m_uiKingLlaneGUID = 0; + m_uiNeltharionGUID = 0; + m_uiMalygosGUID = 0; + m_uiYseraGUID = 0; + m_uiVoiceOfYoggGUID = 0; + + m_uiVisionPhase = 0; + m_uiSpeechTimer = 1000; + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + + if(m_pInstance) + m_pInstance->SetData(TYPE_YOGG_BRAIN, NOT_STARTED); + + // close doors on reset + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR1, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR2, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR3, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_READY); + } + + // for debug + void Aggro(Unit *who) + { + // For vision debug only + //StartVisions(); + //m_pInstance->SetData(TYPE_VISION_PHASE, PHASE_VISION_STORMWIND); + //m_creature->GetMotionMaster()->MoveIdle(); + //m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), 255.011f, 0.0f); + //m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), 255.011f, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(uiDamage > 0 && !m_bHasShattered) + { + if (Creature* pYogg = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_YOGGSARON))) + { + ((boss_yogg_saronAI*)pYogg->AI())->m_bIsShatter = true; + // spell bugged, need core fix. It should be cast on tentacles, not on players! + //pYogg->CastSpell(pYogg, SPELL_SHATTERED_ILLUSION, false); + } + m_bHasShattered = true; + } + } + + void SummonPortals() + { + for(uint8 i = 0; i < 3; i++) + m_creature->SummonCreature(MOB_DESCEND_INTO_MADNESS, MadnessPortalLoc[i].x, MadnessPortalLoc[i].y, MadnessPortalLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + } + + void StartVisions() + { + DoCast(m_creature, SPELL_INDUCE_MADNESS); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiVisionPhase = 0; + m_uiSpeechTimer = 1000; + m_uiTentacleCheckTimer = 1000; + m_uiMadnessTimer = 60000; + m_bIsVisionFinished = false; + m_bHasShattered = false; + } + + // check if all the tentacles are dead + bool IsThereAnyAdd(WorldObject *pSource) + { + if(GetClosestCreatureWithEntry(pSource, MOB_VISION_TENTACLE, 80.0f)) + return true; + + if(m_pInstance) + { + // open doors + switch(m_pInstance->GetData(TYPE_VISION_PHASE)) + { + case PHASE_VISION_STORMWIND: + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR3, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_ACTIVE); + break; + case PHASE_VISION_WYRMREST: + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR1, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_ACTIVE); + break; + case PHASE_VISION_ICECROWN: + if(GameObject* pVisionDoor = GetClosestGameObjectWithEntry(m_creature, GO_BRAIN_DOOR2, 100.0f)) + pVisionDoor->SetGoState(GO_STATE_ACTIVE); + break; + } + } + return false; + } + + void UpdateAI(const uint32 uiDiff) + { + switch(m_pInstance->GetData(TYPE_VISION_PHASE)) + { + case PHASE_VISION_STORMWIND: + { + if(m_uiSpeechTimer < uiDiff) + { + switch(m_uiVisionPhase) + { + case 0: + if(Creature* Garona = m_creature->SummonCreature(NPC_GARONA, PosGarona[0], PosGarona[1], PosGarona[2], PosGarona[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiGaronaGUID = Garona->GetGUID(); + if(Creature* KingLlane = m_creature->SummonCreature(NPC_KING_LLANE, PosKing[0], PosKing[1], PosKing[2], PosKing[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiKingLlaneGUID = KingLlane->GetGUID(); + if(Creature* VoiceOfYogg = m_creature->SummonCreature(NPC_VOICE_OF_YOGG_SARON, PosVoiceStormwind[0], PosVoiceStormwind[1], PosVoiceStormwind[2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) + { + m_uiVoiceOfYoggGUID = VoiceOfYogg->GetGUID(); + VoiceOfYogg->SetDisplayId(11686); // make invisible + } + for(uint8 i = 0; i < 8; i++) + { + if(Creature *pTemp = m_creature->SummonCreature(MOB_VISION_TENTACLE, KeepLoc[i].x, KeepLoc[i].y, KeepLoc[i].z, KeepLoc[i].o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 80000)) + { + pTemp->SetDisplayId(28621); + pTemp->SetMaxHealth(m_bIsRegularMode ? 15000 : 40000); + pTemp->setFaction(7); + pTemp->CastSpell(pTemp, SPELL_GRIM_REPRISAL, false); + } + } + for(uint8 i = 0; i < 3; i++) + m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullKeepLoc[i].x, SkullKeepLoc[i].y, SkullKeepLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + ++m_uiVisionPhase; + m_uiSpeechTimer = 1000; + break; + case 1: + if(Creature* Garona = m_pInstance->instance->GetCreature(m_uiGaronaGUID)) + DoScriptText(SAY_GARONA1, Garona); + ++m_uiVisionPhase; + m_uiSpeechTimer = 12000; + break; + case 2: + if(Creature* Garona = m_pInstance->instance->GetCreature(m_uiGaronaGUID)) + DoScriptText(SAY_GARONA2, Garona); + ++m_uiVisionPhase; + m_uiSpeechTimer = 12000; + break; + case 3: + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V1_1, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 4000; + break; + case 4: + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V1_2, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 4000; + break; + case 5: + if(Creature* KingLlane = m_pInstance->instance->GetCreature(m_uiKingLlaneGUID)) + DoScriptText(SAY_GARONA3, KingLlane); + ++m_uiVisionPhase; + m_uiSpeechTimer = 6000; + break; + case 6: + if(Creature* Garona = m_pInstance->instance->GetCreature(m_uiGaronaGUID)) + Garona->GetMotionMaster()->MovePoint(0, 1931.348f, 61.033f, 241.709f); + ++m_uiVisionPhase; + m_uiSpeechTimer = 6000; + break; + case 7: + if(Creature* Garona = m_pInstance->instance->GetCreature(m_uiGaronaGUID)) + { + DoScriptText(SAY_GARONA4, Garona); + if(Creature* KingLlane = m_pInstance->instance->GetCreature(m_uiKingLlaneGUID)) + { + KingLlane->SetStandState(UNIT_STAND_STATE_DEAD); + KingLlane->SetHealth(0); + Garona->Attack(KingLlane, true); + } + } + ++m_uiVisionPhase; + m_uiSpeechTimer = 6000; + break; + case 8: + if(Creature* Garona = m_pInstance->instance->GetCreature(m_uiGaronaGUID)) + Garona->AttackStop(); + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V1_3, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 8000; + break; + default: + m_uiSpeechTimer = 100000; + } + } + else m_uiSpeechTimer -= uiDiff; + + break; + } + case PHASE_VISION_WYRMREST: + { + if(m_uiSpeechTimer < uiDiff) + { + switch(m_uiVisionPhase) + { + case 0: + m_creature->SummonCreature(NPC_ALEXSTRASZA, PosAlexstrasza[0], PosAlexstrasza[1], PosAlexstrasza[2], PosAlexstrasza[3], TEMPSUMMON_TIMED_DESPAWN, 60000); + if(Creature* Neltharion = m_creature->SummonCreature(NPC_NELTHARION, PosNeltharion[0], PosNeltharion[1], PosNeltharion[2], PosNeltharion[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiNeltharionGUID = Neltharion->GetGUID(); + if(Creature* Malygos = m_creature->SummonCreature(NPC_MALYGOS, PosMalygos[0], PosMalygos[1], PosMalygos[2], PosMalygos[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiMalygosGUID = Malygos->GetGUID(); + if(Creature* Ysera = m_creature->SummonCreature(NPC_YSERA, PosYsera[0], PosYsera[1], PosYsera[2], PosYsera[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiYseraGUID = Ysera->GetGUID(); + if(Creature* VoiceOfYogg = m_creature->SummonCreature(NPC_VOICE_OF_YOGG_SARON, PosVoiceDragon[0], PosVoiceDragon[1], PosVoiceDragon[2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) + { + m_uiVoiceOfYoggGUID = VoiceOfYogg->GetGUID(); + VoiceOfYogg->SetVisibility(VISIBILITY_OFF); + } + for(uint8 i = 0; i < 10; i++) + { + if(Creature *pTemp = m_creature->SummonCreature(MOB_VISION_TENTACLE, DragonLoc[i].x, DragonLoc[i].y, DragonLoc[i].z, DragonLoc[i].o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 80000)) + { + pTemp->SetDisplayId(DisplayDragons[i]); + pTemp->SetMaxHealth(m_bIsRegularMode ? 15000 : 40000); + pTemp->setFaction(7); + pTemp->CastSpell(pTemp, SPELL_GRIM_REPRISAL, false); + } + } + for(uint8 i = 0; i < 3; i++) + m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullDragonLoc[i].x, SkullDragonLoc[i].y, SkullDragonLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + ++m_uiVisionPhase; + m_uiSpeechTimer = 1000; + break; + case 1: + if(Creature* Neltharion = m_pInstance->instance->GetCreature(m_uiNeltharionGUID)) + DoScriptText(SAY_NELTHARION1, Neltharion); + ++m_uiVisionPhase; + m_uiSpeechTimer = 10000; + break; + case 2: + if(Creature* Ysera = m_pInstance->instance->GetCreature(m_uiYseraGUID)) + DoScriptText(SAY_YSERA, Ysera); + ++m_uiVisionPhase; + m_uiSpeechTimer = 7000; + break; + case 3: + if(Creature* Neltharion = m_pInstance->instance->GetCreature(m_uiNeltharionGUID)) + DoScriptText(SAY_NELTHARION2, Neltharion); + ++m_uiVisionPhase; + m_uiSpeechTimer = 6000; + break; + case 4: + if(Creature* Malygos = m_pInstance->instance->GetCreature(m_uiMalygosGUID)) + DoScriptText(SAY_MALYGOS, Malygos); + ++m_uiVisionPhase; + m_uiSpeechTimer = 9000; + break; + case 5: + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V2, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 10000; + break; + default: + m_uiSpeechTimer = 100000; + } + }else m_uiSpeechTimer -= uiDiff; + + break; + } + case PHASE_VISION_ICECROWN: + { + if(m_uiSpeechTimer < uiDiff) + { + switch(m_uiVisionPhase) + { + case 0: + if(Creature* LichKing = m_creature->SummonCreature(NPC_LICH_KING, PosLichKing[0], PosLichKing[1], PosLichKing[2], PosLichKing[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiLichKingGUID = LichKing->GetGUID(); + if(Creature* Champion = m_creature->SummonCreature(NPC_IMMOLATED_CHAMPION, PosChampion[0], PosChampion[1], PosChampion[2], PosChampion[3], TEMPSUMMON_TIMED_DESPAWN, 60000)) + m_uiChampionGUID = Champion->GetGUID(); + if(Creature* VoiceOfYogg = m_creature->SummonCreature(NPC_VOICE_OF_YOGG_SARON, PosVoiceIcecrown[0], PosVoiceIcecrown[1], PosVoiceIcecrown[2], 0, TEMPSUMMON_TIMED_DESPAWN, 60000)) + { + m_uiVoiceOfYoggGUID = VoiceOfYogg->GetGUID(); + VoiceOfYogg->SetVisibility(VISIBILITY_OFF); + } + for(uint8 i = 0; i < 9; i++) + { + if(Creature *pTemp = m_creature->SummonCreature(MOB_VISION_TENTACLE, IcecrownLoc[i].x, IcecrownLoc[i].y, IcecrownLoc[i].z, IcecrownLoc[i].o, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 80000)) + { + pTemp->SetMaxHealth(m_bIsRegularMode ? 15000 : 40000); + pTemp->SetDisplayId(25627); + pTemp->setFaction(7); + pTemp->CastSpell(pTemp, SPELL_GRIM_REPRISAL, false); + } + } + for(uint8 i = 0; i < 4; i++) + m_creature->SummonCreature(NPC_LAUGHING_SKULL, SkullIcecrownLoc[i].x, SkullIcecrownLoc[i].y, SkullIcecrownLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + ++m_uiVisionPhase; + m_uiSpeechTimer = 1000; + break; + case 1: + if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) + { + Champion->SetStandFlags(UNIT_STAND_STATE_KNEEL); + if(Creature* LichKing = m_pInstance->instance->GetCreature(m_uiLichKingGUID)) + { + LichKing->CastSpell(Champion, 54142, false); + DoScriptText(SAY_LICH_KING1, LichKing); + } + } + ++m_uiVisionPhase; + m_uiSpeechTimer = 5000; + break; + case 2: + if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) + DoScriptText(SAY_CHAMPION1, Champion); + ++m_uiVisionPhase; + m_uiSpeechTimer = 8000; + break; + case 3: + if(Creature* Champion = m_pInstance->instance->GetCreature(m_uiChampionGUID)) + DoScriptText(SAY_CHAMPION2, Champion); + ++m_uiVisionPhase; + m_uiSpeechTimer = 8000; + break; + case 4: + if(Creature* LichKing = m_pInstance->instance->GetCreature(m_uiLichKingGUID)) + DoScriptText(SAY_LICH_KING2, LichKing); + ++m_uiVisionPhase; + m_uiSpeechTimer = 7000; + break; + case 5: + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V3_1, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 5000; + break; + case 6: + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + DoScriptText(SAY_YOGG_V3_2, VoiceOfYogg); + ++m_uiVisionPhase; + m_uiSpeechTimer = 10000; + break; + default: + m_uiSpeechTimer = 100000; + } + }else m_uiSpeechTimer -= uiDiff; + + break; + } + } + + // End phase after 30% + if(m_creature->GetHealthPercent() < 30 && !m_bIsPhaseFinished) + { + if(m_pInstance) + { + m_pInstance->SetData(TYPE_YOGG_BRAIN, DONE); + m_pInstance->SetData(TYPE_YOGG_PHASE, PHASE_OLD_GOD); + } + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + if (Creature* pYogg = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_YOGGSARON))) + { + ((boss_yogg_saronAI*)pYogg->AI())->StartThirdPhase(); + pYogg->RemoveAurasDueToSpell(SPELL_SHATTERED_ILLUSION); + } + m_creature->CastStop(); + m_bIsPhaseFinished = true; + } + + // check if tentacles are dead + if (m_uiTentacleCheckTimer < uiDiff && !m_bIsVisionFinished) + { + if(Creature* VoiceOfYogg = m_pInstance->instance->GetCreature(m_uiVoiceOfYoggGUID)) + { + if(!IsThereAnyAdd(VoiceOfYogg)) + { + SummonPortals(); + m_pInstance->SetData(TYPE_VISION_PHASE, PHASE_VISION_RETURN); + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_uiTentacleCheckTimer = 300000; + } + else + m_uiTentacleCheckTimer = 500; + } + } + else m_uiTentacleCheckTimer -= uiDiff; + + // make boss unattackable -> exploit check + // Induced madness need core support, it should make the players insane + if (m_uiMadnessTimer < uiDiff) + { + if (Creature* pYogg = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_YOGGSARON))) + { + ((boss_yogg_saronAI*)pYogg->AI())->m_bIsShatter = false; + ((boss_yogg_saronAI*)pYogg->AI())->m_uiSummonTimer = urand(5000, 8000); + pYogg->RemoveAurasDueToSpell(SPELL_SHATTERED_ILLUSION); + } + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_bIsVisionFinished = true; + m_uiMadnessTimer = 300000; + } + else m_uiMadnessTimer -= uiDiff; + } +}; + +// Sara script +struct MANGOS_DLL_DECL boss_saraAI : public ScriptedAI +{ + boss_saraAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + m_bIsIntroDone = false; + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + // intro + bool m_bIsIntro; + uint32 m_uiIntro_Phase; + uint32 m_uiSpeech_Timer; + bool m_bIsIntroDone; + bool m_bIsFactionSet; + + // phase 1 + uint32 m_uiPhaseYellTimer; + uint32 m_uiSummonTimer; + uint32 m_uiSarasFervorTimer; + uint32 m_uiSarasBlessingTimer; + uint32 m_uiSarasAngerTimer; + uint32 m_uiAllVisions; + + // transition + bool m_bIsOutro; + uint32 m_uiOutroTimer; + uint32 m_uiOutroStep; + + // phase 2 + uint32 m_uiPsychosisTimer; + uint32 m_uiPortalsTimer; + uint32 m_uiMaladyTimer; + uint32 m_uiBrainLinkTimer; + uint32 m_uiDeathRayTimer; + uint32 m_uiBrainLinkEndTimer; + uint32 m_uiBrainLinkTickTimer; + bool m_bIsBrainLink; + + uint32 m_uiFirstVision; + uint32 m_uiSecondVision; + + uint64 m_uiLinkTarget1GUID; + uint64 m_uiLinkTarget2GUID; + + void Reset() + { + // intro + m_bIsIntro = false; + m_uiIntro_Phase = 0; + m_uiSpeech_Timer = 1000; + m_bIsFactionSet = false; + + // phase 1 + m_uiPhaseYellTimer = 30000; + m_uiSummonTimer = 10000 + urand (1000, 5000); + m_uiSarasFervorTimer = urand(10000, 15000); + m_uiSarasBlessingTimer = urand(15000, 20000); + m_uiSarasAngerTimer = urand(20000, 25000); + m_uiAllVisions = 0; + + // transition + m_bIsOutro = false; + m_uiOutroTimer = 10000; + m_uiOutroStep = 1; + + // phase 2 + m_uiPortalsTimer = 60000; + m_uiPsychosisTimer = 15000; + m_uiMaladyTimer = 20000; + m_uiBrainLinkTimer = 25000; + m_uiDeathRayTimer = 30000; + m_uiBrainLinkTickTimer = 1000; + m_uiBrainLinkEndTimer = 0; + m_bIsBrainLink = false; + + m_uiFirstVision = 0; + m_uiSecondVision = 0; + + m_uiLinkTarget1GUID = 0; + m_uiLinkTarget2GUID = 0; + + if(m_creature->HasAura(SPELL_SHADOWY_BARRIER)) + m_creature->RemoveAurasDueToSpell(SPELL_SHADOWY_BARRIER); + + m_creature->SetDisplayId(MODEL_SARA_HUMAN); + m_creature->setFaction(35); + m_creature->SetMaxHealth(199999); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->SetSplineFlags(SPLINEFLAG_FLYING); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f, 5.9f); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + } + + void KilledUnit(Unit* pVictim) + { + if(irand(0,1)) + DoScriptText(SAY_KILL1, m_creature); + else + DoScriptText(SAY_KILL2, m_creature); + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(uiDamage > m_creature->GetHealth()) + { + m_bIsOutro = true; + m_creature->SetHealth(m_creature->GetMaxHealth()); + uiDamage = 0; + } + } + + void MoveInLineOfSight(Unit* pWho) + { + // start intro speech + if(m_pInstance->GetData(TYPE_YOGG_PHASE) == PHASE_IDLE) + { + if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature) && !m_bIsIntro && !m_bIsIntroDone && + pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pWho, 110) && m_creature->IsWithinLOSInMap(pWho)) + m_bIsIntro = true; + } + } + + // return a random npc from the selected entry + Creature* SelectRandomNpc(float fRange, uint32 uiEntry) + { + std::list lNpcList; + GetCreatureListWithEntryInGrid(lNpcList, m_creature, uiEntry, fRange); + + //This should not appear! + if (lNpcList.empty()){ + return NULL; + } + + std::list::iterator iter = lNpcList.begin(); + advance(iter, urand(0, lNpcList.size()-1)); + + return *iter; + } + + void DoBrainLink() + { + // workaround here + } + + void SummonPortals() + { + uint8 maxPortals = m_bIsRegularMode ? 4 : 10; + for(uint8 i = 0; i < maxPortals; i++) + m_creature->SummonCreature(MOB_DESCEND_INTO_MADNESS, YoggPortalLoc[i].x, YoggPortalLoc[i].y, YoggPortalLoc[i].z, 0, TEMPSUMMON_TIMED_DESPAWN, 60000); + } + + // set a random vision + uint32 GetCurrentVision() + { + switch(urand(0, 2)) + { + case 0: + return PHASE_VISION_STORMWIND; + break; + case 1: + return PHASE_VISION_WYRMREST; + break; + case 2: + return PHASE_VISION_ICECROWN; + break; + } + + return 0; + } + + // start a vision + void SetVisionPhase() + { + uint32 m_uiVisionType = 0; + + // set random different destination + if(m_uiFirstVision == 0 && m_uiSecondVision == 0) + { + m_uiVisionType = GetCurrentVision(); + m_uiFirstVision = m_uiVisionType; + } + else if(m_uiSecondVision == 0) + { + do m_uiVisionType = GetCurrentVision(); + while(m_uiVisionType == m_uiFirstVision); + m_uiSecondVision = m_uiVisionType; + } + else + { + do m_uiVisionType = GetCurrentVision(); + while(m_uiVisionType == m_uiFirstVision || m_uiVisionType == m_uiSecondVision); + } + + // set instance data for vision + if(m_uiVisionType != 0) + m_pInstance->SetData(TYPE_VISION_PHASE, m_uiVisionType); + + // summon portals + SummonPortals(); + // start the vision + if (Creature* pYoggBrain = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(NPC_YOGG_BRAIN))) + { + if(pYoggBrain->isAlive()) + ((boss_brain_of_yogg_saronAI*)pYoggBrain->AI())->StartVisions(); + } + // increase the vision no. + m_uiAllVisions += 1; + } + + void UpdateAI(const uint32 uiDiff) + { + switch(m_pInstance->GetData(TYPE_YOGG_PHASE)) + { + case PHASE_IDLE: + { + // intro + if (m_bIsIntro && !m_bIsIntroDone) + { + if(m_uiSpeech_Timer < uiDiff) + { + switch(m_uiIntro_Phase) + { + case 0: + DoScriptText(SAY_INTRO1, m_creature); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->GetMotionMaster()->MoveIdle(); + SetCombatMovement(false); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f, 5.9f); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), 329.397f, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + ++m_uiIntro_Phase; + m_uiSpeech_Timer = 8000; + break; + case 1: + DoScriptText(SAY_INTRO2, m_creature); + ++m_uiIntro_Phase; + m_uiSpeech_Timer = 8000; + break; + case 2: + m_bIsIntro = false; + m_bIsIntroDone = true; + m_uiSpeech_Timer = 12000; + break; + default: + m_uiSpeech_Timer = 100000; + } + } + else m_uiSpeech_Timer -= uiDiff; + } + break; + } + case PHASE_SARA: + { + if(!m_bIsOutro) + { + // wipe check + if(Creature* pYogg = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_YOGGSARON))) + { + if(!pYogg->getVictim() || !pYogg->SelectHostileTarget() || pYogg->getVictim() == m_creature) + { + pYogg->AI()->EnterEvadeMode(); + DoScriptText(SAY_WIPE, m_creature); + } + } + + if (m_uiPhaseYellTimer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: DoScriptText(SAY_HELP1, m_creature); break; + case 1: DoScriptText(SAY_HELP2, m_creature); break; + } + m_uiPhaseYellTimer = 30000; + }else m_uiPhaseYellTimer -= uiDiff; + + if (m_uiSummonTimer < uiDiff) + { + if (Creature* pCloud = SelectRandomNpc(120.0f, NPC_OMINOUS_CLOUD)) + pCloud->CastSpell(pCloud, SPELL_SUMMON_GUARDIAN2, false); + m_uiSummonTimer = urand(15000, 20000); + }else m_uiSummonTimer -= uiDiff; + + if (m_uiSarasFervorTimer < uiDiff) + { + if(Creature* pYogg = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_YOGGSARON))) + { + if (Unit* pTarget = pYogg->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if(pTarget != m_creature) + { + DoCast(pTarget, SPELL_SARAS_FERVOR); + m_uiSarasFervorTimer = urand(20000, 30000); + } + } + } + }else m_uiSarasFervorTimer -= uiDiff; + + if (m_uiSarasBlessingTimer < uiDiff) + { + if(Creature* pYogg = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_YOGGSARON))) + { + if (Unit* pTarget = pYogg->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + if(pTarget != m_creature) + { + DoCast(pTarget, SPELL_SARAS_BLESSING); + m_uiSarasBlessingTimer = urand(20000, 30000); + } + } + } + }else m_uiSarasBlessingTimer -= uiDiff; + + if (m_uiSarasAngerTimer < uiDiff) + { + if (Creature* pGuardian = SelectRandomNpc(80.0f, MOB_GUARDIAN_OF_YOGG)) + DoCast(pGuardian, SPELL_SARAS_ANGER); + m_uiSarasAngerTimer = urand(20000, 30000); + }else m_uiSarasAngerTimer -= uiDiff; + } + // Phase 1 outro + if(m_bIsOutro) + { + switch(m_uiOutroStep) + { + case 1: + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->CombatStop(true); + m_creature->InterruptNonMeleeSpells(false); + ++m_uiOutroStep; + m_uiOutroTimer = 5000; + break; + case 3: + DoScriptText(SAY_PHASE2, m_creature); + ++m_uiOutroStep; + m_uiOutroTimer = 15000; + break; + case 5: + if(Creature* pYogg = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_YOGGSARON))) + { + if (Unit* pTarget = pYogg->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + m_creature->AddThreat(pTarget, 100.0f); + m_creature->AI()->AttackStart(pTarget); + } + } + m_creature->setFaction(14); + m_creature->SetInCombatWithZone(); + SetCombatMovement(false); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetDisplayId(MODEL_SARA_VALKYR); + DoCast(m_creature, SPELL_SHADOWY_BARRIER); + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->GetMap()->CreatureRelocation(m_creature, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 10, 5.9f); + m_creature->SendMonsterMove(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ() + 10, SPLINETYPE_NORMAL, m_creature->GetSplineFlags(), 1); + if(Creature* pYogg = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_YOGGSARON))) + ((boss_yogg_saronAI*)pYogg->AI())->StartSecondPhase(); + m_uiPhaseYellTimer = 30000 + urand(5000, 10000); + m_pInstance->SetData(TYPE_YOGG_PHASE, PHASE_TENTACLES); + ++m_uiOutroStep; + m_uiOutroTimer = 3000; + break; + } + } + else return; + + if (m_uiOutroTimer <= uiDiff) + { + ++m_uiOutroStep; + m_uiOutroTimer = 330000; + } + m_uiOutroTimer -= uiDiff; + + break; + } + case PHASE_TENTACLES: + { + // wipe check + if(Creature* pYogg = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_YOGGSARON))) + { + if(!pYogg->getVictim() || !pYogg->SelectHostileTarget()) + pYogg->AI()->EnterEvadeMode(); + } + + if (m_uiPhaseYellTimer < uiDiff) + { + switch(urand(0, 1)) + { + case 0: DoScriptText(SAY_SPECIAL1, m_creature); break; + case 1: DoScriptText(SAY_SPECIAL2, m_creature); break; + } + m_uiPhaseYellTimer = 30000 + urand(5000, 10000); + } + else m_uiPhaseYellTimer -= uiDiff; + + // summon madness portals + if (m_uiPortalsTimer < uiDiff && m_uiAllVisions < 3) + { + SetVisionPhase(); + if(Creature* pYogg = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_YOGGSARON))) + DoScriptText(SAY_VISION, pYogg); + m_uiPortalsTimer = 85000; + } + else m_uiPortalsTimer -= uiDiff; + + if (m_uiPsychosisTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, m_bIsRegularMode ? SPELL_PHYCHOSIS : SPELL_PHYCHOSIS_H); + m_uiPsychosisTimer = urand(15000, 20000); + } + else m_uiPsychosisTimer -= uiDiff; + + if (m_uiMaladyTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_MALADY_OF_THE_MIND); + m_uiMaladyTimer = urand(20000, 25000); + } + else m_uiMaladyTimer -= uiDiff; + + if (m_uiBrainLinkTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + m_uiLinkTarget1GUID = pTarget->GetGUID(); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + m_uiLinkTarget2GUID = pTarget->GetGUID(); + DoCast(m_creature, SPELL_BRAIN_LINK); + m_bIsBrainLink = true; + m_uiBrainLinkEndTimer = 30000; + m_uiBrainLinkTickTimer = 1000; + m_uiBrainLinkTimer = urand(25000, 30000); + } + else m_uiBrainLinkTimer -= uiDiff; + + // workaround for brainlink + // spell need core support + // REMOVE FOR REVISION! + if (m_uiBrainLinkTickTimer < uiDiff && m_bIsBrainLink) + { + DoBrainLink(); + m_uiBrainLinkTickTimer = 1000; + } + else m_uiBrainLinkTickTimer -= uiDiff; + + if (m_uiBrainLinkEndTimer < uiDiff && m_bIsBrainLink) + m_bIsBrainLink = false; + else m_uiBrainLinkEndTimer -= uiDiff; + + // workaround, should be done by spell + if (m_uiDeathRayTimer < uiDiff) + { + if(Creature* pYogg = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_YOGGSARON))) + { + for(int i = 0; i < irand(3, 4); i++) + { + float angle = (float) rand()*360/RAND_MAX + 1; + float homeX = pYogg->GetPositionX() + urand(20, 40)*cos(angle*(M_PI/180)); + float homeY = pYogg->GetPositionY() + urand(20, 40)*sin(angle*(M_PI/180)); + m_creature->SummonCreature(MOB_DEATH_ORB, homeX, homeY, pYogg->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 10000); + } + } + //DoCast(m_creature, SPELL_DEATH_RAY); + m_uiDeathRayTimer = 30000; + } + else m_uiDeathRayTimer -= uiDiff; + + break; + } + } + } +}; + +/* +* Keepers +*/ +struct MANGOS_DLL_DECL keeper_hodirAI : public ScriptedAI +{ + keeper_hodirAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiHodirProtectivGazeTimer; + + void Reset() + { + m_uiHodirProtectivGazeTimer = 30000; + m_creature->SetRespawnDelay(DAY); + DoCast(m_creature, SPELL_FORTITUDE_OF_FROST); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_uiHodirProtectivGazeTimer < uiDiff) + { + if(Unit* pTemp = DoSelectLowestHpFriendly(100.0f)) + DoCast(pTemp, SPELL_HODIRS_PROTECTIVE_GAZE); + m_uiHodirProtectivGazeTimer = 30000 + urand(10000,30000); + } + else m_uiHodirProtectivGazeTimer -= uiDiff; + } +}; + +struct MANGOS_DLL_DECL keeper_freyaAI : public ScriptedAI +{ + keeper_freyaAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + void Reset() + { + DoCast(m_creature, SPELL_RESILIENCE_OF_NATURE); + m_creature->SetRespawnDelay(DAY); + // Summon Wells + SummonSanityWells(); + } + + void SummonSanityWells() + { + for(uint8 i = 0; i < 5; i++) + m_creature->SummonCreature(MOB_SANITY_WELL, SanityWellLoc[i].x, SanityWellLoc[i].y, SanityWellLoc[i].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 30000); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + } +}; + +struct MANGOS_DLL_DECL keeper_thorimAI : public ScriptedAI +{ + keeper_thorimAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + bool m_bHasTitanicStorm; + + void Reset() + { + m_bHasTitanicStorm = false; + m_creature->SetRespawnDelay(DAY); + DoCast(m_creature, SPELL_FURY_OF_THE_STORM); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_pInstance->GetData(TYPE_YOGG_PHASE) == PHASE_OLD_GOD && !m_bHasTitanicStorm) + { + DoCast(m_creature, SPELL_TITANIC_STORM); + m_bHasTitanicStorm = true; + } + } +}; + +struct MANGOS_DLL_DECL keeper_mimironAI : public ScriptedAI +{ + keeper_mimironAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiDestabilizationMatrixTimer; + std::list lTentacleList; + + void Reset() + { + lTentacleList.clear(); + m_uiDestabilizationMatrixTimer = 10000; + m_creature->SetRespawnDelay(DAY); + DoCast(m_creature, SPELL_SPEED_OF_INVENTION); + } + + Creature* SelectRandomTentacle(float fRange) + { + GetCreatureListWithEntryInGrid(lTentacleList, m_creature, MOB_CRUSHER_TENTACLE, fRange); + GetCreatureListWithEntryInGrid(lTentacleList, m_creature, MOB_CORRUPTOR_TENTACLE, fRange); + + if (lTentacleList.empty()){ + m_uiDestabilizationMatrixTimer = 30000; + return NULL; + } + + std::list::iterator iter = lTentacleList.begin(); + advance(iter, urand(0, lTentacleList.size()-1)); + + return *iter; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_pInstance->GetData(TYPE_YOGG_PHASE) == PHASE_TENTACLES) + { + if (m_uiDestabilizationMatrixTimer < uiDiff) + { + if(Unit* pTentacle = SelectRandomTentacle(120.0f)) + DoCast(pTentacle, SPELL_DESTABILIZATION_MATRIX); + m_uiDestabilizationMatrixTimer = 30000 + urand(10000,30000); + } + else m_uiDestabilizationMatrixTimer -= uiDiff; + } + } +}; + +/* +* Guardians +*/ +struct MANGOS_DLL_DECL mob_immortal_guardianAI : public ScriptedAI +{ + mob_immortal_guardianAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiStack; + uint32 m_uiHealth; + bool m_bHasAura; + + void Reset() + { + m_uiStack = 0; + m_uiHealth = 90; + m_bHasAura = false; + m_creature->SetRespawnDelay(DAY); + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(m_creature->GetHealthPercent() < 5) + { + if(uiDamage > m_creature->GetHealth()) + uiDamage = 0; + } + } + + void SpellHit(Unit *caster, const SpellEntry *spell) + { + if(m_creature->GetHealthPercent() < 5) + { + if(spell->Id == SPELL_TITANIC_STORM_DMG && caster->GetEntry() == KEEPER_THORIM) + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void Aggro(Unit *who) + { + DoCast(m_creature, SPELL_EMPOWERED); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + // hacky way of stacking aura, needs fixing + if(SpellAuraHolder* empoweredAura = m_creature->GetSpellAuraHolder(SPELL_EMPOWERED)) + { + if(empoweredAura->GetStackAmount() < 9 && !m_bHasAura) + { + m_bHasAura = true; + empoweredAura->SetStackAmount(9); + } + } + + if(m_creature->GetHealthPercent() > 10) + { + if(m_creature->GetHealthPercent() < m_uiHealth) + { + if(SpellAuraHolder* empoweredAura = m_creature->GetSpellAuraHolder(SPELL_EMPOWERED)) + { + if(empoweredAura->ModStackAmount(-1)) + m_creature->RemoveAurasDueToSpell(SPELL_EMPOWERED); + } + m_uiHealth -= 10; + } + } + + // empowering shadows, needs more research and core fix + if(m_creature->GetHealthPercent() > m_uiHealth + 10) + { + DoCast(m_creature, SPELL_EMPOWERED); + m_uiHealth += 10; + } + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_guardian_of_yogg_saronAI : public ScriptedAI +{ + mob_guardian_of_yogg_saronAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiDarkVolleyTimer; + uint32 m_uiDieTimer; + uint32 m_uiDominateMindTimer; + bool m_bHasCasted; + + void Reset() + { + m_uiDarkVolleyTimer = 10000; + m_uiDominateMindTimer = 30000; + m_bHasCasted = false; + m_creature->SetRespawnDelay(DAY); + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(uiDamage > m_creature->GetHealth()) + { + uiDamage = 0; + if(!m_bHasCasted) + { + DoCast(m_creature, m_bIsRegularMode ? SPELL_SHADOW_NOVA : SPELL_SHADOW_NOVA_H); + m_bHasCasted = true; + m_uiDieTimer = 500; + m_creature->SetHealth(m_creature->GetMaxHealth()); + + // workaround for dmg Sara + // need to find a way to damage Sara by spell! + if(Creature* pSara = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_SARA))) + { + if(m_creature->IsWithinDist2d(pSara->GetPositionX(), pSara->GetPositionY(), 15.0f)) + { + uint32 maxHealth = m_bIsRegularMode ? 21994 : 27500; + if(pSara->GetHealth() > maxHealth) + pSara->DealDamage(pSara, m_bIsRegularMode ? urand(20000, 21994) : urand(25000, 27500), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_SHADOW, NULL, false); + else + { + ((boss_saraAI*)pSara->AI())->m_bIsOutro = true; + pSara->SetHealth(pSara->GetMaxHealth()); + } + } + } + } + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(Creature* pSara = (Creature*)m_creature->GetMap()->GetUnit(m_pInstance->GetData64(NPC_SARA))) + { + if(m_creature->getVictim() == pSara) + { + m_creature->AddThreat(pSara, -100000.0f); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_BOTTOMAGGRO, 0)) + m_creature->AddThreat(pTarget, 1000000.0f); + } + } + + if (m_uiDarkVolleyTimer < uiDiff) + { + DoCast(m_creature, SPELL_DARK_VOLLEY); + m_uiDarkVolleyTimer = 15000; + } + else m_uiDarkVolleyTimer -= uiDiff; + + if (m_uiDominateMindTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DOMINATE_MIND); + m_uiDominateMindTimer = 30000; + } + else m_uiDominateMindTimer -= uiDiff; + + if (m_uiDieTimer < uiDiff && m_bHasCasted) + m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + else m_uiDieTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +/* +* Tentacules +*/ +struct MANGOS_DLL_DECL mob_corruptor_tentacleAI : public ScriptedAI +{ + mob_corruptor_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiEruptTimer; + bool m_bHasErupted; + uint32 m_uiSpellTimer; + + void Reset() + { + m_uiEruptTimer = 500; + m_bHasErupted = false; + m_uiSpellTimer = 10000; + m_creature->SetRespawnDelay(DAY); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiEruptTimer < uiDiff && !m_bHasErupted) + { + DoCast(m_creature, SPELL_ERUPT); + m_bHasErupted = true; + }else m_uiEruptTimer -= uiDiff; + + if (m_uiSpellTimer < uiDiff) + { + switch(urand(0, 3)) + { + case 0: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_BLACK_PLAGUE); + break; + case 1: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_APATHY); + break; + case 2: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_CURSE_OF_DOOM); + break; + case 3: + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCast(pTarget, SPELL_DRAINING_POISON); + break; + } + m_uiSpellTimer = urand(5000, 10000); + } + else m_uiSpellTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_constrictor_tentacleAI : public ScriptedAI +{ + mob_constrictor_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance *m_pInstance; + + uint32 m_uiSqueezeTimer; + uint64 m_uiVictimGUID; + + void Reset() + { + m_uiSqueezeTimer = 10000; + m_creature->SetRespawnDelay(DAY); + } + + void DamageTaken(Unit* pDoneBy, uint32 &uiDamage) + { + if (uiDamage > m_creature->GetHealth()) + { + if (m_uiVictimGUID) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit( m_uiVictimGUID)) + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_SQUEEZE : SPELL_SQUEEZE_H); + } + } + } + + void JustDied(Unit* pKiller) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit( m_uiVictimGUID)) + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_SQUEEZE : SPELL_SQUEEZE_H); + + if (pKiller) + pKiller->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_SQUEEZE : SPELL_SQUEEZE_H); + } + + void KilledUnit(Unit* pVictim) + { + if (pVictim) + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_SQUEEZE : SPELL_SQUEEZE_H); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + { + if (Unit* pVictim = m_creature->GetMap()->GetUnit( m_uiVictimGUID)) + pVictim->RemoveAurasDueToSpell(m_bIsRegularMode ? SPELL_SQUEEZE : SPELL_SQUEEZE_H); + m_creature->ForcedDespawn(); + } + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiSqueezeTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + { + // spell needs vehicles + //pTarget->CastSpell(pTarget, m_bIsRegularMode ? SPELL_SQUEEZE : SPELL_SQUEEZE_H, false); + m_uiVictimGUID = pTarget->GetGUID(); + } + m_uiSqueezeTimer = 30000; + }else m_uiSqueezeTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_crusher_tentacleAI : public ScriptedAI +{ + mob_crusher_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance *m_pInstance; + bool m_bIsRegularMode; + + uint32 m_uiEruptTimer; + bool m_bHasErupted; + uint32 m_uiDiminishPowerTimer; + + void Reset() + { + m_uiEruptTimer = 500; + m_bHasErupted = false; + m_uiDiminishPowerTimer = 10000; + m_creature->SetRespawnDelay(DAY); + DoCast(m_creature, SPELL_FOCUSED_ANGER_TRIGG); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiEruptTimer < uiDiff && !m_bHasErupted) + { + DoCast(m_creature, SPELL_ERUPT); + m_bHasErupted = true; + } + else m_uiEruptTimer -= uiDiff; + + if (m_uiDiminishPowerTimer < uiDiff) + { + DoCast(m_creature, SPELL_DIMINISH_POWER); + m_uiDiminishPowerTimer = 10000 + urand(1000, 5000); + } + else m_uiDiminishPowerTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +struct MANGOS_DLL_DECL mob_vision_tentacleAI : public ScriptedAI +{ + mob_vision_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature) + { + SetCombatMovement(false); + Reset(); + } + + void Reset() + { + DoCast(m_creature, SPELL_GRIM_REPRISAL); + } + + void DamageTaken(Unit *done_by, uint32 &uiDamage) + { + if(uiDamage > 0 && m_creature->GetDisplayId() != 28813) + m_creature->SetDisplayId(28813); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + DoMeleeAttackIfReady(); + } +}; + +/* +* Other +*/ +struct MANGOS_DLL_DECL mob_death_orbAI : public ScriptedAI +{ + mob_death_orbAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + pCreature->setFaction(14); + Reset(); + } + + uint32 m_uiAuraTimer; + bool m_bHasAura; + + void Reset() + { + m_uiAuraTimer = 500; + m_bHasAura = false; + DoCast(m_creature, SPELL_DEATH_RAY_VISUAL); + m_creature->GetMotionMaster()->MoveConfused(); + } + + void UpdateAI(const uint32 uiDiff) + { + if(m_uiAuraTimer < uiDiff && !m_bHasAura) + { + DoCast(m_creature, SPELL_DEATH_RAY_TRIGG); + m_bHasAura = true; + } + else m_uiAuraTimer -= uiDiff; + } +}; + +struct MANGOS_DLL_DECL mob_sanity_wellAI : public ScriptedAI +{ + mob_sanity_wellAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetDisplayId(11686); // make invisible + pCreature->setFaction(14); + SetCombatMovement(false); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiAuraDelayTimer; + bool m_bHasAura; + + void Reset() + { + m_uiAuraDelayTimer = 1000; + m_bHasAura = false; + DoCast(m_creature, SPELL_SANITY_WELL_VISUAL); + m_creature->SetRespawnDelay(DAY); + } + + void AttackStart(Unit* pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_pInstance && m_pInstance->GetData(TYPE_YOGGSARON) != IN_PROGRESS) + m_creature->ForcedDespawn(); + + if (m_uiAuraDelayTimer < uiDiff && !m_bHasAura) + { + // spell partially broken, it should be triggered by the visual aura + //DoCast(m_creature, SPELL_SANITY_WELL); + m_bHasAura = true; + } + else m_uiAuraDelayTimer -= uiDiff; + } }; +struct MANGOS_DLL_DECL mob_laughing_skullAI : public ScriptedAI +{ + mob_laughing_skullAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + pCreature->SetDisplayId(SKULL_DISPLAY_ID); + pCreature->setFaction(14); + SetCombatMovement(false); + pCreature->GetMotionMaster()->MoveConfused(); + Reset(); + } + + void Reset() + { + m_creature->SetRespawnDelay(DAY); + DoCast(m_creature, SPELL_LUNATIC_GAZE); + } + + void AttackStart(Unit* pWho) + { + return; + } + + void UpdateAI(const uint32 uiDiff) + { + } +}; + +struct MANGOS_DLL_DECL mob_ominous_cloudAI : public ScriptedAI +{ + mob_ominous_cloudAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + SetCombatMovement(false); + pCreature->setFaction(14); + Reset(); + } + + ScriptedInstance *m_pInstance; + + uint32 m_uiRangeCheckTimer; + bool m_bSummonGuardian; + + void Reset() + { + m_uiRangeCheckTimer = 1000; + m_bSummonGuardian = false; + DoCast(m_creature, SPELL_OMINOUS_CLOUD_VISUAL); + m_creature->SetRespawnDelay(DAY); + } + + void AttackStart(Unit* pWho) + { + return; + } + + void JustSummoned(Creature* pSummon) + { + pSummon->SetInCombatWithZone(); + } + + void UpdateAI(const uint32 uiDiff) + { + if (m_uiRangeCheckTimer < uiDiff) + { + Map *map = m_creature->GetMap(); + if (map->IsDungeon()) + { + Map::PlayerList const &PlayerList = map->GetPlayers(); + + if (PlayerList.isEmpty()) + return; + + for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i) + { + if (i->getSource()->isAlive() && m_creature->GetDistance2d(i->getSource()->GetPositionX(), i->getSource()->GetPositionY()) <= 5) + m_bSummonGuardian = true; + + } + } + // cast summon guard + if(m_bSummonGuardian) + { + DoCast(m_creature, SPELL_SUMMON_GUARDIAN2); + m_uiRangeCheckTimer = 11000; + m_bSummonGuardian = false; + } + else + m_uiRangeCheckTimer = 1000; + } + else m_uiRangeCheckTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_boss_yogg_saron(Creature* pCreature) +{ + return new boss_yogg_saronAI(pCreature); +} + +CreatureAI* GetAI_boss_sara(Creature* pCreature) +{ + return new boss_saraAI(pCreature); +} + +CreatureAI* GetAI_mob_madness_portal(Creature* pCreature) +{ + return new mob_madness_portalAI(pCreature); +} + +CreatureAI* GetAI_boss_brain_of_yogg_saron(Creature* pCreature) +{ + return new boss_brain_of_yogg_saronAI(pCreature); +} + +CreatureAI* GetAI_mob_corruptor_tentacle(Creature* pCreature) +{ + return new mob_corruptor_tentacleAI(pCreature); +} + +CreatureAI* GetAI_mob_constrictor_tentacle(Creature* pCreature) +{ + return new mob_constrictor_tentacleAI(pCreature); +} + +CreatureAI* GetAI_mob_crusher_tentacle(Creature* pCreature) +{ + return new mob_crusher_tentacleAI(pCreature); +} + +CreatureAI* GetAI_mob_vision_tentacle(Creature* pCreature) +{ + return new mob_vision_tentacleAI(pCreature); +} + +CreatureAI* GetAI_mob_guardian_of_yogg_saron(Creature* pCreature) +{ + return new mob_guardian_of_yogg_saronAI(pCreature); +} + +CreatureAI* GetAI_mob_immortal_guardian(Creature* pCreature) +{ + return new mob_immortal_guardianAI(pCreature); +} + +CreatureAI* GetAI_keeper_hodir(Creature* pCreature) +{ + return new keeper_hodirAI(pCreature); +} + +CreatureAI* GetAI_keeper_freya(Creature* pCreature) +{ + return new keeper_freyaAI(pCreature); +} + +CreatureAI* GetAI_keeper_thorim(Creature* pCreature) +{ + return new keeper_thorimAI(pCreature); +} + +CreatureAI* GetAI_keeper_mimiron(Creature* pCreature) +{ + return new keeper_mimironAI(pCreature); +} + +CreatureAI* GetAI_mob_death_orb(Creature* pCreature) +{ + return new mob_death_orbAI(pCreature); +} + +CreatureAI* GetAI_mob_sanity_well(Creature* pCreature) +{ + return new mob_sanity_wellAI(pCreature); +} + +CreatureAI* GetAI_mob_laughing_skull(Creature* pCreature) +{ + return new mob_laughing_skullAI(pCreature); +} + +CreatureAI* GetAI_mob_ominous_cloud(Creature* pCreature) +{ + return new mob_ominous_cloudAI(pCreature); +} + void AddSC_boss_yogg_saron() { + Script *newscript; + newscript = new Script; + newscript->Name = "boss_yogg_saron"; + newscript->GetAI = &GetAI_boss_yogg_saron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_sara"; + newscript->GetAI = &GetAI_boss_sara; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_madness_portal"; + newscript->GetAI = &GetAI_mob_madness_portal; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "boss_brain_of_yogg_saron"; + newscript->GetAI = &GetAI_boss_brain_of_yogg_saron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_corruptor_tentacle"; + newscript->GetAI = &GetAI_mob_corruptor_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_constrictor_tentacle"; + newscript->GetAI = &GetAI_mob_constrictor_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_crusher_tentacle"; + newscript->GetAI = &GetAI_mob_crusher_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_vision_tentacle"; + newscript->GetAI = &GetAI_mob_vision_tentacle; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_guardian_of_yogg_saron"; + newscript->GetAI = &GetAI_mob_guardian_of_yogg_saron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_immortal_guardian"; + newscript->GetAI = &GetAI_mob_immortal_guardian; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "keeper_hodir"; + newscript->GetAI = &GetAI_keeper_hodir; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "keeper_freya"; + newscript->GetAI = &GetAI_keeper_freya; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "keeper_thorim"; + newscript->GetAI = &GetAI_keeper_thorim; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "keeper_mimiron"; + newscript->GetAI = &GetAI_keeper_mimiron; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_death_orb"; + newscript->GetAI = &GetAI_mob_death_orb; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_sanity_well"; + newscript->GetAI = &GetAI_mob_sanity_well; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mob_laughing_skull"; + newscript->GetAI = &GetAI_mob_laughing_skull; + newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "mob_ominous_cloud"; + newscript->GetAI = &GetAI_mob_ominous_cloud; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/def_ulduar.h b/scripts/northrend/ulduar/ulduar/def_ulduar.h new file mode 100644 index 0000000..1145e16 --- /dev/null +++ b/scripts/northrend/ulduar/ulduar/def_ulduar.h @@ -0,0 +1,213 @@ +/* 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_ULDUAR_H +#define DEF_ULDUAR_H + +enum +{ + // encounters + MAX_ENCOUNTER = 14, + HARD_ENCOUNTER = 9, + KEEPER_ENCOUNTER = 4, + + // boss types + TYPE_LEVIATHAN = 0, + TYPE_IGNIS = 1, + TYPE_RAZORSCALE = 2, + TYPE_XT002 = 3, + TYPE_ASSEMBLY = 4, + TYPE_KOLOGARN = 5, + TYPE_AURIAYA = 6, + TYPE_MIMIRON = 7, + TYPE_HODIR = 8, + TYPE_THORIM = 9, + TYPE_FREYA = 10, + TYPE_VEZAX = 11, + TYPE_YOGGSARON = 12, + TYPE_ALGALON = 13, + + // hard mode bosses + TYPE_LEVIATHAN_HARD = 37, + TYPE_XT002_HARD = 38, + TYPE_ASSEMBLY_HARD = 39, + TYPE_MIMIRON_HARD = 40, + TYPE_HODIR_HARD = 41, + TYPE_THORIM_HARD = 42, + TYPE_FREYA_HARD = 43, + TYPE_VEZAX_HARD = 44, + TYPE_YOGGSARON_HARD = 45, + + // keepers help at Yogg + TYPE_KEEPER_HODIR = 46, + TYPE_KEEPER_FREYA = 47, + TYPE_KEEPER_THORIM = 48, + TYPE_KEEPER_MIMIRON = 49, + + // teleporters + TYPE_LEVIATHAN_TP = 50, + TYPE_XT002_TP = 51, + TYPE_MIMIRON_TP = 52, + + //other-> these won't be saved to db + TYPE_RUNE_GIANT = 14, + TYPE_RUNIC_COLOSSUS = 15, + TYPE_LEVIATHAN_MK = 16, + TYPE_VX001 = 17, + TYPE_AERIAL_UNIT = 18, + TYPE_YOGG_BRAIN = 22, + TYPE_MIMIRON_PHASE = 23, + TYPE_YOGG_PHASE = 24, + TYPE_VISION_PHASE = 25, + + // siege + NPC_LEVIATHAN = 33113, + NPC_IGNIS = 33118, + NPC_RAZORSCALE = 33186, + NPC_COMMANDER = 33210, + NPC_XT002 = 33293, + // antechamber + NPC_STEELBREAKER = 32867, + NPC_MOLGEIM = 32927, + NPC_BRUNDIR = 32857, + NPC_KOLOGARN = 32930, + NPC_RIGHT_ARM = 32934, + NPC_LEFT_ARM = 32933, + NPC_AURIAYA = 33515, + NPC_SANCTUM_SENTRY = 34014, + NPC_FERAL_DEFENDER = 34035, + // keepers + NPC_MIMIRON = 33350, + NPC_LEVIATHAN_MK = 33432, + NPC_VX001 = 33651, + NPC_AERIAL_UNIT = 33670, + NPC_HODIR = 32845, + NPC_THORIM = 32865, + NPC_RUNIC_COLOSSUS = 32872, + NPC_RUNE_GIANT = 32873, + NPC_JORMUNGAR_BEHEMOTH = 32882, + NPC_FREYA = 32906, + NPC_BRIGHTLEAF = 32915, + NPC_IRONBRACH = 32913, + NPC_STONEBARK = 32914, + // madness + NPC_VEZAX = 33271, + NPC_ANIMUS = 33524, + NPC_YOGGSARON = 33288, + NPC_ALGALON = 32871, + NPC_SARA = 33134, + NPC_YOGG_BRAIN = 33890, + // keepers images used to start the encounter + THORIM_IMAGE = 33413, + MIMIRON_IMAGE = 33412, + HODIR_IMAGE = 33411, + FREYA_IMAGE = 33410, + // Keepers used at yogg saron encounter + KEEPER_FREYA = 33241, + KEEPER_HODIR = 33213, + KEEPER_MIMIRON = 33244, + KEEPER_THORIM = 33242, + + // loot chests + // Kologarn + GO_CACHE_OF_LIVING_STONE = 195046, + GO_CACHE_OF_LIVING_STONE_H = 195047, + // Hodir + GO_CACHE_OF_WINTER = 194307, + GO_CACHE_OF_WINTER_H = 194308, + GO_CACHE_OF_RARE_WINTER = 194200, + GO_CACHE_OF_RARE_WINTER_H = 194201, + // Thorim + GO_CACHE_OF_STORMS = 194312, + GO_CACHE_OF_RARE_STORMS = 194313, + GO_CACHE_OF_STORMS_H = 194314, + GO_CACHE_OF_RARE_STORMS_H = 194315, + // Alagon + GO_GIFT_OF_OBSERVER_H = 194821, + GO_GIFT_OF_OBSERVER = 194822, + GO_GIFT_OF_OBSERVER_HH = 194823, // unk + // Freya -> each chest is for a mode = more elders alive = more items in chest + // 10 man + GO_FREYA_GIFT = 194324,//10 normal + GO_FREYA_GIFT_1 = 194325,//10 1 elder + GO_FREYA_GIFT_2 = 194326,//10 2 elders + GO_FREYA_GIFT_3 = 194327,//10 3 elders + // 25 man + GO_FREYA_GIFT_H = 194328,//25 normal + GO_FREYA_GIFT_H_1 = 194329,//25 1 elder + GO_FREYA_GIFT_H_2 = 194330,//25 2 elder + GO_FREYA_GIFT_H_3 = 194331,//25 3 elders + // Mimiron + GO_CACHE_OF_INOV = 194789, + GO_CACHE_OF_INOV_H = 194956, + GO_CACHE_OF_INOV_HARD = 194957, + GO_CACHE_OF_INOV_HARD_H = 194958, + + // doors + // the siege + GO_SHIELD_WALL = 194416, + GO_LEVIATHAN_GATE = 194630, + GO_XT002_GATE = 194631, + GO_BROKEN_HARPOON = 194565, + // archivum + GO_KOLOGARN_BRIDGE = 194232, + GO_SHATTERED_DOOR = 194553, + GO_IRON_ENTRANCE_DOOR = 194554, + GO_ARCHIVUM_DOOR = 194556, + GO_ARCHIVUM_CONSOLE = 194555, + // planetarium: algalon + GO_CELESTIAL_ACCES = 194628, + GO_CELESTIAL_ACCES_H = 194752, + GO_CELESTIAL_DOOR = 194767, + GO_UNIVERSE_FLOOR_ARCHIVUM = 194715, + GO_UNIVERSE_FLOOR_CELESTIAL = 194716, + GO_AZEROTH_GLOBE = 194148, + // the keepers + // hodir + GO_HODIR_EXIT = 194634, + GO_HODIR_ICE_WALL = 194441, + GO_HODIR_ENTER = 194442, + // mimiron + GO_MIMIRON_TRAM = 194675, + GO_MIMIRON_BUTTON = 194739, + GO_MIMIRON_DOOR_1 = 194774, + GO_MIMIRON_DOOR_2 = 194775, + GO_MIMIRON_DOOR_3 = 194776, + GO_MIMIRON_TEL1 = 194741, + GO_MIMIRON_TEL2 = 194742, + GO_MIMIRON_TEL3 = 194743, + GO_MIMIRON_TEL4 = 194744, + GO_MIMIRON_TEL5 = 194740, + GO_MIMIRON_TEL6 = 194746, + GO_MIMIRON_TEL7 = 194747, + GO_MIMIRON_TEL8 = 194748, + GO_MIMIRON_TEL9 = 194745, + GO_MIMIRON_ELEVATOR = 194749, + // Thorim + GO_DARK_IRON_PORTCULIS = 194560, + GO_RUNED_STONE_DOOR = 194557, + GO_THORIM_STONE_DOOR = 194558, + GO_LIGHTNING_DOOR = 194905, + GO_LIGHTNING_FIELD = 194559, + GO_DOOR_LEVER = 194264, + //Yogg + GO_ANCIENT_GATE = 194255, + GO_VEZAX_GATE = 194750, + GO_YOGG_GATE = 194773, + GO_BRAIN_DOOR1 = 194635, + GO_BRAIN_DOOR2 = 194636, + GO_BRAIN_DOOR3 = 194637, + + ACHIEV_IRON_COUNCIL = 2888, + ACHIEV_IRON_COUNCIL_H = 2889, + + ACHIEV_KEEPERS = 2890, + ACHIEV_KEEPERS_H = 2891, + + ACHIEV_CELESTIAL_DEFENDER = 3259, // realm first algalon + SPELL_ALGALON_ACHIEV_TRIGG = 65184, + ACHIEV_DEATHS_DEMISE = 3117, // realm first yogg +}; + +#endif diff --git a/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp b/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp index 87b5a16..697c032 100644 --- a/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp +++ b/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 - 2010 ScriptDev2 +/* 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 @@ -15,140 +15,254 @@ */ /* ScriptData -SDName: instance_ulduar +SDName: Instance_Ulduar SD%Complete: SDComment: SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" +#include "def_ulduar.h" -struct sSpawnLocation +struct MANGOS_DLL_DECL instance_ulduar : public ScriptedInstance { - float m_fX, m_fY, m_fZ, m_fO; -}; + instance_ulduar(Map* pMap) : ScriptedInstance(pMap) + { + Regular = pMap->IsRegularDifficulty(); + Initialize(); + } -static sSpawnLocation m_aKeepersSpawnLocs[] = -{ - {2036.892f, 25.621f, 411.358f, 3.83f}, // Freya - {1939.215f, 42.677f, 411.355f, 5.31f}, // Mimiron - {1939.195f, -90.662f, 411.357f, 1.06f}, // Hodir - {2036.674f, -73.814f, 411.355f, 2.51f}, // Thorim -}; + bool Regular; + + // initialize the encouter variables + std::string m_strInstData; + uint32 m_auiEncounter[MAX_ENCOUNTER]; + uint32 m_auiHardBoss[HARD_ENCOUNTER]; + uint32 m_auiUlduarKeepers[KEEPER_ENCOUNTER]; + uint32 m_auiUlduarTeleporters[3]; + uint32 m_auiMiniBoss[6]; + + // boss phases which need to be used inside the instance script + uint32 m_uiMimironPhase; + uint32 m_uiYoggPhase; + uint32 m_uiVisionPhase; -instance_ulduar::instance_ulduar(Map* pMap) : ScriptedInstance(pMap), - // Creatures - m_uiLeviathanGUID(0), - m_uiIgnisGUID(0), - m_uiRazorscaleGUID(0), - m_uiCommanderGUID(0), - m_uiXT002GUID(0), - m_uiBrundirGUID(0), - m_uiMolgeimGUID(0), - m_uiSteelbreakerGUID(0), - m_uiKologarnGUID(0), - m_uiAuriayaGUID(0), - m_uiMimironGUID(0), - m_uiHodirGUID(0), - m_uiThorimGUID(0), - m_uiFreyaGUID(0), - m_uiVezaxGUID(0), - m_uiYoggSaronGUID(0), - m_uiAlgalonGUID(0), - m_uiRightArmGUID(0), - m_uiLeftArmGUID(0), - m_uiFeralDefenderGUID(0), - m_uiElderBrightleafGUID(0), - m_uiElderStonebarkGUID(0), - m_uiElderIronbrachGUID(0), - m_uiSaroniteAnimusGUID(0), - m_uiRunicColossusGUID(0), - m_uiRuneGiantGUID(0), - m_uiJormungarGUID(0), - m_uiLeviathanMkGUID(0), - m_uiSaraGUID(0), - m_uiYoggBrainGUID(0), - - // Chests - m_uiKologarnLootGUID(0), - m_uiHodirLootGUID(0), - m_uiHodirRareLootGUID(0), - m_uiThorimLootGUID(0), - m_uiThorimRareLootGUID(0), - m_uiMimironLootGUID(0), - m_uiMimironHardLootGUID(0), - m_uiAlagonLootGUID(0), - - // Doors + // creature guids + uint64 m_uiLeviathanGUID; + uint64 m_uiIgnisGUID; + uint64 m_uiRazorscaleGUID; + uint64 m_uiCommanderGUID; + uint64 m_uiXT002GUID; + uint64 m_auiAssemblyGUIDs[3]; + uint64 m_uiKologarnGUID; + uint64 m_uiAuriayaGUID; + uint64 m_uiMimironGUID; + uint64 m_uiHodirGUID; + uint64 m_uiThorimGUID; + uint64 m_uiFreyaGUID; + uint64 m_uiVezaxGUID; + uint64 m_uiYoggSaronGUID; + uint64 m_uiAlgalonGUID; + uint64 m_uiRightArmGUID; + uint64 m_uiLeftArmGUID; + uint64 m_uiFeralDefenderGUID; + uint64 m_uiElderBrightleafGUID; + uint64 m_uiElderStonebarkGUID; + uint64 m_uiElderIronbrachGUID; + uint64 m_uiSaroniteAnimusGUID; + uint64 m_uiRunicColossusGUID; + uint64 m_uiRuneGiantGUID; + uint64 m_uiJormungarGUID; + uint64 m_uiLeviathanMkGUID; + uint64 m_uiHodirImageGUID; + uint64 m_uiFreyaImageGUID; + uint64 m_uiThorimImageGUID; + uint64 m_uiMimironImageGUID; + uint64 m_uiSaraGUID; + uint64 m_uiYoggBrainGUID; + + //doors & objects // The siege - m_uiShieldWallGUID(0), - m_uiLeviathanGateGUID(0), - m_uiXT002GateGUID(0), - m_uiBrokenHarpoonGUID(0), + uint64 m_uiShieldWallGUID; + uint64 m_uiLeviathanGateGUID; + uint64 m_uiXT002GateGUID; + uint64 m_uiBrokenHarpoonGUID; // Archivum - m_uiIronCouncilDoorGUID(0), - m_uiArchivumDoorGUID(0), - m_uiArchivumConsoleGUID(0), - m_uiUniverseFloorArchivumGUID(0), + uint64 m_uiIronCouncilDoorGUID; + uint64 m_uiArchivumDoorGUID; + uint64 m_uiArchivumConsoleGUID; + uint64 m_uiUniverseFloorArchivumGUID; // Celestial planetarium - m_uiCelestialDoorGUID(0), - m_uiCelestialConsoleGUID(0), - m_uiUniverseFloorCelestialGUID(0), - m_uiAzerothGlobeGUID(0), + uint64 m_uiCelestialDoorGUID; + uint64 m_uiCelestialConsoleGUID; + uint64 m_uiUniverseFloorCelestialGUID; + uint64 m_uiAzerothGlobeGUID; // Kologarn - m_uiShatteredHallsDoorGUID(0), - m_uiKologarnBridgeGUID(0), + uint64 m_uiShatteredHallsDoorGUID; + uint64 m_uiKologarnBridgeGUID; // Hodir - m_uiHodirEnterDoorGUID(0), - m_uiHodirWallGUID(0), - m_uiHodirExitDoorGUID(0), + uint64 m_uiHodirEnterDoorGUID; + uint64 m_uiHodirWallGUID; + uint64 m_uiHodirExitDoorGUID; // Mimiron - m_uiMimironButtonGUID(0), - m_uiMimironDoor1GUID(0), - m_uiMimironDoor2GUID(0), - m_uiMimironDoor3GUID(0), - m_uiMimironElevatorGUID(0), + uint64 m_uiMimironTramGUID; + uint64 m_uiMimironButtonGUID; + uint64 m_uiMimironDoor1GUID; + uint64 m_uiMimironDoor2GUID; + uint64 m_uiMimironDoor3GUID; + uint64 m_uiMimironElevatorGUID; + uint64 m_uiMimironTelGUID[9]; // Thorim - m_uiArenaEnterDoorGUID(0), - m_uiArenaExitDoorGUID(0), - m_uiHallwayDoorGUID(0), - m_uiThorimEnterDoorGUID(0), - m_uiThorimLeverGUID(0), + uint64 m_uiArenaEnterDoorGUID; + uint64 m_uiArenaExitDoorGUID; + uint64 m_uiHallwayDoorGUID; + uint64 m_uiThorimEnterDoorGUID; + uint64 m_uiThorimLeverGUID; // Prison - m_uiAncientGateGUID(0), - m_uiVezaxGateGUID(0), - m_uiYoggGateGUID(0), - m_uiBrainDoor1GUID(0), - m_uiBrainDoor2GUID(0), - m_uiBrainDoor3GUID(0) -{ - Initialize(); -} + uint64 m_uiAncientGateGUID; + uint64 m_uiVezaxGateGUID; + uint64 m_uiYoggGateGUID; + uint64 m_uiBrainDoor1GUID; + uint64 m_uiBrainDoor2GUID; + uint64 m_uiBrainDoor3GUID; -void instance_ulduar::Initialize() -{ - memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); - memset(&m_auiHardBoss, 0, sizeof(m_auiHardBoss)); - memset(&m_auiUlduarKeepers, 0, sizeof(m_auiUlduarKeepers)); - memset(&m_auiUlduarTeleporters, 0, sizeof(m_auiUlduarTeleporters)); - memset(&m_auiMimironTelGUID, 0, sizeof(m_auiMimironTelGUID)); -} + // chests + uint64 m_uiKologarnLootGUID; + uint64 m_uiHodirLootGUID; + uint64 m_uiHodirRareLootGUID; + uint64 m_uiThorimLootGUID; + uint64 m_uiThorimRareLootGUID; + uint64 m_uiFreyaLootGUID; + uint64 m_uiFreyaLoot1GUID; + uint64 m_uiFreyaLoot2GUID; + uint64 m_uiFreyaLoot3GUID; + uint64 m_uiMimironLootGUID; + uint64 m_uiMimironHardLootGUID; + uint64 m_uiAlagonLootGUID; -bool instance_ulduar::IsEncounterInProgress() const -{ - for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + memset(&m_auiHardBoss, 0, sizeof(m_auiHardBoss)); + memset(&m_auiUlduarKeepers, 0, sizeof(m_auiUlduarKeepers)); + memset(&m_auiUlduarTeleporters, 0, sizeof(m_auiUlduarTeleporters)); + + for(uint8 i = 0; i < 6; i++) + m_auiMiniBoss[i] = NOT_STARTED; + + for(uint8 i = 0; i < 9; i++) + m_uiMimironTelGUID[i] = 0; + + m_uiMimironPhase = 0; + m_uiYoggPhase = 0; + m_uiVisionPhase = 0; + + m_uiLeviathanGUID = 0; + m_uiIgnisGUID = 0; + m_uiRazorscaleGUID = 0; + m_uiCommanderGUID = 0; + m_uiXT002GUID = 0; + m_uiKologarnGUID = 0; + m_uiAuriayaGUID = 0; + m_uiMimironGUID = 0; + m_uiHodirGUID = 0; + m_uiThorimGUID = 0; + m_uiFreyaGUID = 0; + m_uiVezaxGUID = 0; + m_uiYoggSaronGUID = 0; + m_uiAlgalonGUID = 0; + m_uiRightArmGUID = 0; + m_uiLeftArmGUID = 0; + m_uiFeralDefenderGUID = 0; + m_uiElderBrightleafGUID = 0; + m_uiElderStonebarkGUID = 0; + m_uiElderIronbrachGUID = 0; + m_uiSaroniteAnimusGUID = 0; + m_uiRunicColossusGUID = 0; + m_uiRuneGiantGUID = 0; + m_uiJormungarGUID = 0; + m_uiLeviathanMkGUID = 0; + m_uiHodirImageGUID = 0; + m_uiFreyaImageGUID = 0; + m_uiThorimImageGUID = 0; + m_uiMimironImageGUID = 0; + m_uiSaraGUID = 0; + m_uiYoggBrainGUID = 0; + + // loot + m_uiKologarnLootGUID = 0; + m_uiHodirLootGUID = 0; + m_uiHodirRareLootGUID = 0; + m_uiThorimLootGUID = 0; + m_uiThorimRareLootGUID = 0; + m_uiFreyaLootGUID = 0; + m_uiFreyaLoot1GUID = 0; + m_uiFreyaLoot2GUID = 0; + m_uiFreyaLoot3GUID = 0; + m_uiMimironLootGUID = 0; + m_uiMimironHardLootGUID = 0; + m_uiAlagonLootGUID = 0; + + // doors + // The siege + m_uiShieldWallGUID = 0; + m_uiLeviathanGateGUID = 0; + m_uiXT002GateGUID = 0; + m_uiBrokenHarpoonGUID = 0; + // Archivum + m_uiIronCouncilDoorGUID = 0; + m_uiArchivumDoorGUID = 0; + m_uiArchivumConsoleGUID = 0; + m_uiUniverseFloorArchivumGUID = 0; + // Celestial planetarium + m_uiCelestialDoorGUID = 0; + m_uiCelestialConsoleGUID = 0; + m_uiUniverseFloorCelestialGUID = 0; + m_uiAzerothGlobeGUID = 0; + // Kologarn + m_uiShatteredHallsDoorGUID = 0; + m_uiKologarnBridgeGUID = 0; + // Hodir + m_uiHodirEnterDoorGUID = 0; + m_uiHodirWallGUID = 0; + m_uiHodirExitDoorGUID = 0; + // Mimiron + m_uiMimironTramGUID = 0; + m_uiMimironButtonGUID = 0; + m_uiMimironDoor1GUID = 0; + m_uiMimironDoor2GUID = 0; + m_uiMimironDoor3GUID = 0; + m_uiMimironElevatorGUID = 0; + // Thorim + m_uiArenaEnterDoorGUID = 0; + m_uiArenaExitDoorGUID = 0; + m_uiHallwayDoorGUID = 0; + m_uiThorimEnterDoorGUID = 0; + m_uiThorimLeverGUID = 0; + // Prison + m_uiAncientGateGUID = 0; + m_uiVezaxGateGUID = 0; + m_uiYoggGateGUID = 0; + m_uiBrainDoor1GUID = 0; + m_uiBrainDoor2GUID = 0; + m_uiBrainDoor3GUID = 0; + } + + bool IsEncounterInProgress() const { - if (m_auiEncounter[i] == IN_PROGRESS) - return true; + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + } + + return false; } - return false; -} -void instance_ulduar::OnCreatureCreate(Creature* pCreature) -{ - switch (pCreature->GetEntry()) + void OnCreatureCreate(Creature* pCreature) { + switch(pCreature->GetEntry()) + { case NPC_LEVIATHAN: m_uiLeviathanGUID = pCreature->GetGUID(); break; @@ -164,15 +278,18 @@ void instance_ulduar::OnCreatureCreate(Creature* pCreature) case NPC_XT002: m_uiXT002GUID = pCreature->GetGUID(); break; + + // Assembly of Iron case NPC_STEELBREAKER: - m_uiSteelbreakerGUID = pCreature->GetGUID(); + m_auiAssemblyGUIDs[0] = pCreature->GetGUID(); break; case NPC_MOLGEIM: - m_uiMolgeimGUID = pCreature->GetGUID(); + m_auiAssemblyGUIDs[1] = pCreature->GetGUID(); break; case NPC_BRUNDIR: - m_uiBrundirGUID = pCreature->GetGUID(); + m_auiAssemblyGUIDs[2] = pCreature->GetGUID(); break; + case NPC_KOLOGARN: m_uiKologarnGUID = pCreature->GetGUID(); break; @@ -190,21 +307,15 @@ void instance_ulduar::OnCreatureCreate(Creature* pCreature) break; case NPC_MIMIRON: m_uiMimironGUID = pCreature->GetGUID(); - if(m_auiEncounter[7] == DONE) - SpawnFriendlyKeeper(NPC_MIMIRON_IMAGE); break; case NPC_LEVIATHAN_MK: m_uiLeviathanMkGUID = pCreature->GetGUID(); break; case NPC_HODIR: m_uiHodirGUID = pCreature->GetGUID(); - if(m_auiEncounter[8] == DONE) - SpawnFriendlyKeeper(NPC_HODIR_IMAGE); break; case NPC_THORIM: m_uiThorimGUID = pCreature->GetGUID(); - if(m_auiEncounter[9] == DONE) - SpawnFriendlyKeeper(NPC_THORIM_IMAGE); break; case NPC_RUNIC_COLOSSUS: m_uiRunicColossusGUID = pCreature->GetGUID(); @@ -217,22 +328,20 @@ void instance_ulduar::OnCreatureCreate(Creature* pCreature) break; case NPC_FREYA: m_uiFreyaGUID = pCreature->GetGUID(); - if(m_auiEncounter[10] == DONE) - SpawnFriendlyKeeper(NPC_FREYA_IMAGE); break; - case NPC_ELDER_BRIGHTLEAF: + case NPC_BRIGHTLEAF: m_uiElderBrightleafGUID = pCreature->GetGUID(); break; - case NPC_ELDER_IRONBRACH: + case NPC_IRONBRACH: m_uiElderIronbrachGUID = pCreature->GetGUID(); break; - case NPC_ELDER_STONEBARK: + case NPC_STONEBARK: m_uiElderStonebarkGUID = pCreature->GetGUID(); break; case NPC_VEZAX: m_uiVezaxGUID = pCreature->GetGUID(); break; - case NPC_SARONITE_ANIMUS: + case NPC_ANIMUS: m_uiSaroniteAnimusGUID = pCreature->GetGUID(); break; case NPC_YOGGSARON: @@ -247,28 +356,54 @@ void instance_ulduar::OnCreatureCreate(Creature* pCreature) case NPC_ALGALON: m_uiAlgalonGUID = pCreature->GetGUID(); break; - } -} + // used to handle the keepers images + // set to invisible by default and only made visible if the encounter is done + case HODIR_IMAGE: + m_uiHodirImageGUID = pCreature->GetGUID(); + pCreature->SetVisibility(VISIBILITY_OFF); + if(m_auiEncounter[8] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + break; + case FREYA_IMAGE: + m_uiFreyaImageGUID = pCreature->GetGUID(); + pCreature->SetVisibility(VISIBILITY_OFF); + if(m_auiEncounter[10] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + break; + case THORIM_IMAGE: + m_uiThorimImageGUID = pCreature->GetGUID(); + pCreature->SetVisibility(VISIBILITY_OFF); + if(m_auiEncounter[9] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + break; + case MIMIRON_IMAGE: + m_uiMimironImageGUID = pCreature->GetGUID(); + pCreature->SetVisibility(VISIBILITY_OFF); + if(m_auiEncounter[7] == DONE) + pCreature->SetVisibility(VISIBILITY_ON); + break; + } + } -void instance_ulduar::OnObjectCreate(GameObject* pGo) -{ - switch(pGo->GetEntry()) + void OnObjectCreate(GameObject *pGo) { - // ----------------- Doors & Other ----------------- - // The siege + switch(pGo->GetEntry()) + { + // doors & other + // The siege case GO_SHIELD_WALL: m_uiShieldWallGUID = pGo->GetGUID(); break; case GO_LEVIATHAN_GATE: m_uiLeviathanGateGUID = pGo->GetGUID(); - if (m_auiEncounter[0] == DONE) + if(m_auiEncounter[0] == DONE) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_XT002_GATE: pGo->SetGoState(GO_STATE_READY); - if (m_auiEncounter[3] == DONE) + if(m_auiEncounter[3] == DONE) pGo->SetGoState(GO_STATE_ACTIVE); - if (m_auiEncounter[1] == DONE && m_auiEncounter[2] == DONE) + if(m_auiEncounter[1] == DONE && m_auiEncounter[2] == DONE) pGo->SetGoState(GO_STATE_ACTIVE); m_uiXT002GateGUID = pGo->GetGUID(); break; @@ -277,13 +412,13 @@ void instance_ulduar::OnObjectCreate(GameObject* pGo) pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); break; - // Archivum + // Archivum case GO_IRON_ENTRANCE_DOOR: m_uiIronCouncilDoorGUID = pGo->GetGUID(); break; case GO_ARCHIVUM_DOOR: m_uiArchivumDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[4]) + if(m_auiEncounter[4]) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_ARCHIVUM_CONSOLE: @@ -292,7 +427,7 @@ void instance_ulduar::OnObjectCreate(GameObject* pGo) case GO_UNIVERSE_FLOOR_ARCHIVUM: m_uiUniverseFloorArchivumGUID = pGo->GetGUID(); break; - // Celestial Planetarium + // Celestial Planetarium case GO_CELESTIAL_ACCES: m_uiCelestialConsoleGUID = pGo->GetGUID(); break; @@ -305,34 +440,45 @@ void instance_ulduar::OnObjectCreate(GameObject* pGo) case GO_AZEROTH_GLOBE: m_uiAzerothGlobeGUID = pGo->GetGUID(); break; - // Shattered Hallway + // Shattered Hallway case GO_KOLOGARN_BRIDGE: m_uiKologarnBridgeGUID = pGo->GetGUID(); pGo->SetGoState(GO_STATE_ACTIVE); - if (m_auiEncounter[5] == DONE) + if(m_auiEncounter[5] == DONE) + { + pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); pGo->SetGoState(GO_STATE_READY); + } break; case GO_SHATTERED_DOOR: m_uiShatteredHallsDoorGUID = pGo->GetGUID(); break; - // ----------------- The Keepers ----------------- - // Hodir + // The keepers + // Hodir case GO_HODIR_EXIT: m_uiHodirExitDoorGUID = pGo->GetGUID(); - if (m_auiEncounter[8]) + if(m_auiEncounter[8]) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_HODIR_ICE_WALL: m_uiHodirWallGUID = pGo->GetGUID(); - if (m_auiEncounter[8]) + if(m_auiEncounter[8]) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_HODIR_ENTER: m_uiHodirEnterDoorGUID = pGo->GetGUID(); break; - // Mimiron - case G0_MIMIRON_BUTTON: + // Mimiron + case GO_MIMIRON_TRAM: + m_uiMimironTramGUID = pGo->GetGUID(); + if (m_auiEncounter[6] == DONE) + { + pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGo->SetGoState(GO_STATE_READY); + } + break; + case GO_MIMIRON_BUTTON: m_uiMimironButtonGUID = pGo->GetGUID(); if (m_auiEncounter[7] == NOT_STARTED) pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); @@ -350,33 +496,33 @@ void instance_ulduar::OnObjectCreate(GameObject* pGo) m_uiMimironElevatorGUID = pGo->GetGUID(); break; case GO_MIMIRON_TEL1: - m_auiMimironTelGUID[0] = pGo->GetGUID(); + m_uiMimironTelGUID[0] = pGo->GetGUID(); break; case GO_MIMIRON_TEL2: - m_auiMimironTelGUID[1] = pGo->GetGUID(); + m_uiMimironTelGUID[1] = pGo->GetGUID(); break; case GO_MIMIRON_TEL3: - m_auiMimironTelGUID[2] = pGo->GetGUID(); + m_uiMimironTelGUID[2] = pGo->GetGUID(); break; case GO_MIMIRON_TEL4: - m_auiMimironTelGUID[3] = pGo->GetGUID(); + m_uiMimironTelGUID[3] = pGo->GetGUID(); break; case GO_MIMIRON_TEL5: - m_auiMimironTelGUID[4] = pGo->GetGUID(); + m_uiMimironTelGUID[4] = pGo->GetGUID(); break; case GO_MIMIRON_TEL6: - m_auiMimironTelGUID[5] = pGo->GetGUID(); + m_uiMimironTelGUID[5] = pGo->GetGUID(); break; case GO_MIMIRON_TEL7: - m_auiMimironTelGUID[6] = pGo->GetGUID(); + m_uiMimironTelGUID[6] = pGo->GetGUID(); break; case GO_MIMIRON_TEL8: - m_auiMimironTelGUID[7] = pGo->GetGUID(); + m_uiMimironTelGUID[7] = pGo->GetGUID(); break; case GO_MIMIRON_TEL9: - m_auiMimironTelGUID[8] = pGo->GetGUID(); + m_uiMimironTelGUID[8] = pGo->GetGUID(); break; - // Thorim + // Thorim case GO_DARK_IRON_PORTCULIS: m_uiArenaExitDoorGUID = pGo->GetGUID(); break; @@ -394,15 +540,15 @@ void instance_ulduar::OnObjectCreate(GameObject* pGo) pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1); break; - // Prison + // Prison case GO_ANCIENT_GATE: m_uiAncientGateGUID = pGo->GetGUID(); - DoOpenMadnessDoorIfCan(); + OpenMadnessDoor(); break; case GO_VEZAX_GATE: m_uiVezaxGateGUID = pGo->GetGUID(); pGo->SetGoState(GO_STATE_READY); - if (m_auiEncounter[11]) + if(m_auiEncounter[11]) pGo->SetGoState(GO_STATE_ACTIVE); break; case GO_YOGG_GATE: @@ -418,119 +564,216 @@ void instance_ulduar::OnObjectCreate(GameObject* pGo) m_uiBrainDoor3GUID = pGo->GetGUID(); break; - // ----------------- Chests ----------------- - // Kologarn + // loot + // Kologarn case GO_CACHE_OF_LIVING_STONE: + if(Regular) + m_uiKologarnLootGUID = pGo->GetGUID(); + break; case GO_CACHE_OF_LIVING_STONE_H: - m_uiKologarnLootGUID = pGo->GetGUID(); + if(!Regular) + m_uiKologarnLootGUID = pGo->GetGUID(); break; - // Hodir + // Hodir case GO_CACHE_OF_WINTER: + if(Regular) + m_uiHodirLootGUID = pGo->GetGUID(); + break; case GO_CACHE_OF_WINTER_H: - m_uiHodirLootGUID = pGo->GetGUID(); + if(!Regular) + m_uiHodirLootGUID = pGo->GetGUID(); break; + // Hodir rare case GO_CACHE_OF_RARE_WINTER: + if(Regular) + m_uiHodirRareLootGUID = pGo->GetGUID(); + break; case GO_CACHE_OF_RARE_WINTER_H: - m_uiHodirRareLootGUID = pGo->GetGUID(); + if(!Regular) + m_uiHodirRareLootGUID = pGo->GetGUID(); break; - // Thorim + // Freya + case GO_FREYA_GIFT: + if(Regular) + m_uiFreyaLootGUID = pGo->GetGUID(); + break; + case GO_FREYA_GIFT_H: + if(!Regular) + m_uiFreyaLootGUID = pGo->GetGUID(); + break; + // Freya rare + case GO_FREYA_GIFT_1: + if(Regular) + m_uiFreyaLoot1GUID = pGo->GetGUID(); + break; + case GO_FREYA_GIFT_H_1: + if(!Regular) + m_uiFreyaLoot1GUID = pGo->GetGUID(); + break; + case GO_FREYA_GIFT_2: + if(Regular) + m_uiFreyaLoot2GUID = pGo->GetGUID(); + break; + case GO_FREYA_GIFT_H_2: + if(!Regular) + m_uiFreyaLoot2GUID = pGo->GetGUID(); + break; + case GO_FREYA_GIFT_3: + if(Regular) + m_uiFreyaLoot3GUID = pGo->GetGUID(); + break; + case GO_FREYA_GIFT_H_3: + if(!Regular) + m_uiFreyaLoot3GUID = pGo->GetGUID(); + break; + + // Thorim case GO_CACHE_OF_STORMS: + if(Regular) + m_uiThorimLootGUID = pGo->GetGUID(); + break; case GO_CACHE_OF_STORMS_H: - m_uiThorimLootGUID = pGo->GetGUID(); + if(!Regular) + m_uiThorimLootGUID = pGo->GetGUID(); break; + // Thorim rare case GO_CACHE_OF_RARE_STORMS: + if(Regular) + m_uiThorimRareLootGUID = pGo->GetGUID(); + break; case GO_CACHE_OF_RARE_STORMS_H: - m_uiThorimRareLootGUID = pGo->GetGUID(); + if(!Regular) + m_uiThorimRareLootGUID = pGo->GetGUID(); break; - // Mimiron + // Mimiron case GO_CACHE_OF_INOV: + if(Regular) + m_uiMimironLootGUID = pGo->GetGUID(); + break; case GO_CACHE_OF_INOV_H: - m_uiMimironLootGUID = pGo->GetGUID(); + if(!Regular) + m_uiMimironLootGUID = pGo->GetGUID(); break; case GO_CACHE_OF_INOV_HARD: + if(Regular) + m_uiMimironHardLootGUID = pGo->GetGUID(); + break; case GO_CACHE_OF_INOV_HARD_H: - m_uiMimironHardLootGUID = pGo->GetGUID(); + if(!Regular) + m_uiMimironHardLootGUID = pGo->GetGUID(); break; - // Alagon + // Alagon case GO_GIFT_OF_OBSERVER: + if(Regular) + m_uiAlagonLootGUID = pGo->GetGUID(); + break; case GO_GIFT_OF_OBSERVER_H: - m_uiAlagonLootGUID = pGo->GetGUID(); + if(!Regular) + m_uiAlagonLootGUID = pGo->GetGUID(); break; + } } -} -Player* instance_ulduar::GetPlayerInMap() -{ - Map::PlayerList const& players = instance->GetPlayers(); + // functions to open or close some doors + void OpenDoor(uint64 guid) + { + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_ACTIVE); + } - if (!players.isEmpty()) + void CloseDoor(uint64 guid) { - for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr) - { - if (Player* plr = itr->getSource()) - return plr; - } + if(!guid) return; + GameObject* pGo = instance->GetGameObject(guid); + if(pGo) pGo->SetGoState(GO_STATE_READY); } - return NULL; -} -// Used in order to unlock the door to Vezax -void instance_ulduar::DoOpenMadnessDoorIfCan() -{ - if (m_auiEncounter[TYPE_MIMIRON] == DONE && m_auiEncounter[TYPE_HODIR] == DONE && m_auiEncounter[TYPE_THORIM] == DONE && m_auiEncounter[TYPE_FREYA] == DONE) + // used in order to unlock the door to Vezax and make vezax attackable + void OpenMadnessDoor() { - if (GameObject* pDoor = instance->GetGameObject(m_uiAncientGateGUID)) - pDoor->SetGoState(GO_STATE_ACTIVE); + if(m_auiEncounter[7] == DONE && m_auiEncounter[8] == DONE && m_auiEncounter[9] == DONE && m_auiEncounter[10] == DONE) + OpenDoor(m_uiAncientGateGUID); + OpenDoor(m_uiAncientGateGUID); } -} -void instance_ulduar::SetData(uint32 uiType, uint32 uiData) -{ - switch (uiType) + // used to open the door to XT (custom script because Leviathan is disabled) + // this will be removed when the Leviathan will be implemented + void OpenXtDoor() + { + if(m_auiEncounter[1] == DONE && m_auiEncounter[2] == DONE) + OpenDoor(m_uiXT002GateGUID); + } + + void SetData(uint32 uiType, uint32 uiData) { + switch(uiType) + { case TYPE_LEVIATHAN: m_auiEncounter[0] = uiData; DoUseDoorOrButton(m_uiShieldWallGUID); if (uiData == DONE) { - DoUseDoorOrButton(m_uiXT002GateGUID); - DoUseDoorOrButton(m_uiLeviathanGateGUID); + OpenDoor(m_uiXT002GateGUID); + OpenDoor(m_uiLeviathanGateGUID); } break; case TYPE_IGNIS: m_auiEncounter[1] = uiData; + OpenXtDoor(); // remove when leviathan implemented break; case TYPE_RAZORSCALE: m_auiEncounter[2] = uiData; + OpenXtDoor(); // remove when leviathan implemented break; case TYPE_XT002: m_auiEncounter[3] = uiData; - DoUseDoorOrButton(m_uiXT002GateGUID); + if (uiData == DONE) + OpenDoor(m_uiXT002GateGUID); + else if (uiData == IN_PROGRESS) + CloseDoor(m_uiXT002GateGUID); break; case TYPE_ASSEMBLY: m_auiEncounter[4] = uiData; - DoUseDoorOrButton(m_uiIronCouncilDoorGUID); if (uiData == DONE) - DoUseDoorOrButton(m_uiArchivumDoorGUID); + { + OpenDoor(m_uiIronCouncilDoorGUID); + OpenDoor(m_uiArchivumDoorGUID); + CheckIronCouncil(); // used for a hacky achiev, remove for revision! + } else if (uiData == IN_PROGRESS) + CloseDoor(m_uiIronCouncilDoorGUID); break; case TYPE_KOLOGARN: m_auiEncounter[5] = uiData; - DoUseDoorOrButton(m_uiShatteredHallsDoorGUID); if (uiData == DONE) { DoRespawnGameObject(m_uiKologarnLootGUID, 30*MINUTE); - if(GameObject* pBridge = instance->GetGameObject(m_uiKologarnBridgeGUID)) - pBridge->SetGoState(GO_STATE_READY); + if(m_auiEncounter[5] == DONE) + if (GameObject* pGo = instance->GetGameObject(m_uiKologarnBridgeGUID)) + { + pGo->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGo->SetGoState(GO_STATE_READY); + } } break; case TYPE_AURIAYA: m_auiEncounter[6] = uiData; + if (uiData == DONE) + { +// CheckIronCouncil(); // used for a hacky achiev, remove for revision! + if (GameObject* pGO = instance->GetGameObject(m_uiMimironTramGUID)) + { + pGO->SetUInt32Value(GAMEOBJECT_LEVEL, 0); + pGO->SetGoState(GO_STATE_READY); + } + } break; - // Keepers + + // Keepers case TYPE_MIMIRON: m_auiEncounter[7] = uiData; DoUseDoorOrButton(m_uiMimironDoor1GUID); @@ -538,9 +781,13 @@ void instance_ulduar::SetData(uint32 uiType, uint32 uiData) DoUseDoorOrButton(m_uiMimironDoor3GUID); if (uiData == DONE) { - if (m_auiHardBoss[3] != DONE) + if(m_auiHardBoss[3] != DONE) DoRespawnGameObject(m_uiMimironLootGUID, 30*MINUTE); - SpawnFriendlyKeeper(NPC_MIMIRON_IMAGE); + // used to make the friendly keeper visible + if(Creature* pImage = instance->GetCreature(m_uiMimironImageGUID)) + pImage->SetVisibility(VISIBILITY_ON); + OpenMadnessDoor(); + CheckKeepers(); // used for a hacky achiev, remove for revision! } break; case TYPE_HODIR: @@ -551,27 +798,51 @@ void instance_ulduar::SetData(uint32 uiType, uint32 uiData) DoUseDoorOrButton(m_uiHodirWallGUID); DoUseDoorOrButton(m_uiHodirExitDoorGUID); DoRespawnGameObject(m_uiHodirLootGUID, 30*MINUTE); - SpawnFriendlyKeeper(NPC_HODIR_IMAGE); + // used to make the friendly keeper visible + if(Creature* pImage = instance->GetCreature(m_uiHodirImageGUID)) + pImage->SetVisibility(VISIBILITY_ON); + OpenMadnessDoor(); + CheckKeepers(); // used for a hacky achiev, remove for revision! } break; case TYPE_THORIM: - m_auiEncounter[9] = uiData; + m_auiEncounter[9] = uiData; DoUseDoorOrButton(m_uiArenaEnterDoorGUID); if (uiData == IN_PROGRESS) DoUseDoorOrButton(m_uiArenaExitDoorGUID); if (uiData == DONE) { - if (m_auiHardBoss[5] != DONE) + if(m_auiHardBoss[5] != DONE) DoRespawnGameObject(m_uiThorimLootGUID, 30*MINUTE); - SpawnFriendlyKeeper(NPC_THORIM_IMAGE); + // used to make the friendly keeper visible + if(Creature* pImage = instance->GetCreature(m_uiThorimImageGUID)) + pImage->SetVisibility(VISIBILITY_ON); + OpenMadnessDoor(); + CheckKeepers(); // used for a hacky achiev, remove for revision! } break; case TYPE_FREYA: m_auiEncounter[10] = uiData; if (uiData == DONE) - SpawnFriendlyKeeper(NPC_FREYA_IMAGE); + { + // do this in order to see how many elders were alive and spawn the correct chest + if(m_auiHardBoss[6] == 0) + DoRespawnGameObject(m_uiFreyaLootGUID, 30*MINUTE); + else if(m_auiHardBoss[6] == 1) + DoRespawnGameObject(m_uiFreyaLoot1GUID, 30*MINUTE); + else if(m_auiHardBoss[6] == 2) + DoRespawnGameObject(m_uiFreyaLoot2GUID, 30*MINUTE); + else if(m_auiHardBoss[6] == 3) + DoRespawnGameObject(m_uiFreyaLoot3GUID, 30*MINUTE); + // used to make the friendly keeper visible + if(Creature* pImage = instance->GetCreature(m_uiFreyaImageGUID)) + pImage->SetVisibility(VISIBILITY_ON); + OpenMadnessDoor(); + CheckKeepers(); // used for a hacky achiev, remove for revision! + } break; - // Prison + + // Prison case TYPE_VEZAX: m_auiEncounter[11] = uiData; if (uiData == DONE) @@ -582,52 +853,51 @@ void instance_ulduar::SetData(uint32 uiType, uint32 uiData) DoUseDoorOrButton(m_uiYoggGateGUID); break; - // Celestial Planetarium + // Celestial Planetarium case TYPE_ALGALON: m_auiEncounter[13] = uiData; - //TODO: need to find the proper way to use these DoUseDoorOrButton(m_uiCelestialDoorGUID); DoUseDoorOrButton(m_uiUniverseFloorCelestialGUID); if (uiData == DONE) DoRespawnGameObject(m_uiAlagonLootGUID, 30*MINUTE); break; - // Hard modes + // Hard modes case TYPE_LEVIATHAN_HARD: - m_auiHardBoss[0] = uiData; // TODO: add extra loot + m_auiHardBoss[0] = uiData; // todo: add extra loot break; case TYPE_XT002_HARD: - m_auiHardBoss[1] = uiData; // TODO: add extra loot + m_auiHardBoss[1] = uiData; // hard mode loot in sql -> hacky way break; case TYPE_HODIR_HARD: m_auiHardBoss[4] = uiData; - if (uiData == DONE) + if(uiData == DONE) DoRespawnGameObject(m_uiHodirRareLootGUID, 30*MINUTE); break; case TYPE_ASSEMBLY_HARD: - m_auiHardBoss[2] = uiData; // TODO: add extra loot + m_auiHardBoss[2] = uiData; // hard mode loot in sql break; case TYPE_FREYA_HARD: - m_auiHardBoss[6] = uiData; // Hard mode loot in in script + m_auiHardBoss[6] = uiData; // hard mode loot in the script above break; case TYPE_THORIM_HARD: m_auiHardBoss[5] = uiData; - if (uiData == DONE) + if(uiData == DONE) DoRespawnGameObject(m_uiThorimRareLootGUID, 30*MINUTE); break; case TYPE_MIMIRON_HARD: m_auiHardBoss[3] = uiData; - if (uiData == DONE) + if(uiData == DONE) DoRespawnGameObject(m_uiMimironHardLootGUID, 30*MINUTE); break; case TYPE_VEZAX_HARD: - m_auiHardBoss[7] = uiData; // TODO: add extra loot + m_auiHardBoss[7] = uiData; // hard mode loot in sql -> hacky way break; case TYPE_YOGGSARON_HARD: - m_auiHardBoss[8] = uiData; // TODO: add extra loot + m_auiHardBoss[8] = uiData; // todo: add extra loot break; - // Ulduar keepers + // Ulduar keepers case TYPE_KEEPER_HODIR: m_auiUlduarKeepers[0] = uiData; break; @@ -641,7 +911,7 @@ void instance_ulduar::SetData(uint32 uiType, uint32 uiData) m_auiUlduarKeepers[3] = uiData; break; - // Teleporters + // teleporters case TYPE_LEVIATHAN_TP: m_auiUlduarTeleporters[0] = uiData; break; @@ -651,38 +921,81 @@ void instance_ulduar::SetData(uint32 uiType, uint32 uiData) case TYPE_MIMIRON_TP: m_auiUlduarTeleporters[2] = uiData; break; - } - DoOpenMadnessDoorIfCan(); + // mini boss + case TYPE_RUNIC_COLOSSUS: + m_auiMiniBoss[0] = uiData; + if (uiData == DONE) + OpenDoor(m_uiHallwayDoorGUID); + else + CloseDoor(m_uiHallwayDoorGUID); + break; + case TYPE_RUNE_GIANT: + m_auiMiniBoss[1] = uiData; + if (uiData == DONE) + OpenDoor(m_uiThorimEnterDoorGUID); + else + CloseDoor(m_uiThorimEnterDoorGUID); + break; + case TYPE_LEVIATHAN_MK: + m_auiMiniBoss[2] = uiData; + break; + case TYPE_VX001: + m_auiMiniBoss[3] = uiData; + if (uiData == DONE) // just for animation :) + { + for(uint8 i = 0; i < 9; i++) + DoUseDoorOrButton(m_uiMimironTelGUID[i]); + } + break; + case TYPE_AERIAL_UNIT: + m_auiMiniBoss[4] = uiData; + break; + case TYPE_YOGG_BRAIN: + m_auiMiniBoss[5] = uiData; + break; + + //phases + case TYPE_MIMIRON_PHASE: + m_uiMimironPhase = uiData; + break; + case TYPE_YOGG_PHASE: + m_uiYoggPhase = uiData; + break; + case TYPE_VISION_PHASE: + m_uiVisionPhase = uiData; + break; + } - if (uiData == DONE || uiData == FAIL) - { - OUT_SAVE_INST_DATA; - - // Save all encounters, hard bosses, keepers and teleporters - std::ostringstream saveStream; - saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " - << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " - << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " - << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11] << " " - << m_auiEncounter[12] << " " << m_auiEncounter[13] << " " << m_auiHardBoss[0] << " " - << m_auiHardBoss[1] << " " << m_auiHardBoss[2] << " " << m_auiHardBoss[2] << " " - << m_auiHardBoss[4] << " " << m_auiHardBoss[5] << " " << m_auiHardBoss[6] << " " - << m_auiHardBoss[7] << " " << m_auiHardBoss[8] << " " << m_auiUlduarKeepers[0] << " " - << m_auiUlduarKeepers[1] << " " << m_auiUlduarKeepers[2] << " " << m_auiUlduarKeepers[3]; - - strInstData = saveStream.str(); - - SaveToDB(); - OUT_SAVE_INST_DATA_COMPLETE; + if (uiData == DONE || uiData == FAIL) + { + OUT_SAVE_INST_DATA; + + // save all encounters, hard bosses and keepers + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " " + << m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " + << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8] << " " + << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11] << " " + << m_auiEncounter[12] << " " << m_auiEncounter[13] << " " << m_auiHardBoss[0] << " " + << m_auiHardBoss[1] << " " << m_auiHardBoss[2] << " " << m_auiHardBoss[2] << " " + << m_auiHardBoss[4] << " " << m_auiHardBoss[5] << " " << m_auiHardBoss[6] << " " + << m_auiHardBoss[7] << " " << m_auiHardBoss[8] << " " << m_auiUlduarKeepers[0] << " " + << m_auiUlduarKeepers[1] << " " << m_auiUlduarKeepers[2] << " " << m_auiUlduarKeepers[3] << " " + << m_auiUlduarTeleporters[0] << " " << m_auiUlduarTeleporters[1] << " " << m_auiUlduarTeleporters[2]; + + m_strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; + } } -} -uint64 instance_ulduar::GetData64(uint32 uiData) -{ - switch (uiData) + uint64 GetData64(uint32 uiData) { - // Siege + switch(uiData) + { + // Siege case NPC_LEVIATHAN: return m_uiLeviathanGUID; case NPC_IGNIS: @@ -693,13 +1006,13 @@ uint64 instance_ulduar::GetData64(uint32 uiData) return m_uiCommanderGUID; case NPC_XT002: return m_uiXT002GUID; - // Antechamber + // Antechamber case NPC_STEELBREAKER: - return m_uiSteelbreakerGUID; + return m_auiAssemblyGUIDs[0]; case NPC_MOLGEIM: - return m_uiMolgeimGUID; + return m_auiAssemblyGUIDs[1]; case NPC_BRUNDIR: - return m_uiBrundirGUID; + return m_auiAssemblyGUIDs[2]; case NPC_KOLOGARN: return m_uiKologarnGUID; case NPC_LEFT_ARM: @@ -708,7 +1021,7 @@ uint64 instance_ulduar::GetData64(uint32 uiData) return m_uiRightArmGUID; case NPC_AURIAYA: return m_uiAuriayaGUID; - // Keepers + // Keepers case NPC_MIMIRON: return m_uiMimironGUID; case NPC_LEVIATHAN_MK: @@ -725,11 +1038,11 @@ uint64 instance_ulduar::GetData64(uint32 uiData) return m_uiJormungarGUID; case NPC_FREYA: return m_uiFreyaGUID; - case NPC_ELDER_BRIGHTLEAF: + case NPC_BRIGHTLEAF: return m_uiElderBrightleafGUID; - case NPC_ELDER_IRONBRACH: + case NPC_IRONBRACH: return m_uiElderIronbrachGUID; - case NPC_ELDER_STONEBARK: + case NPC_STONEBARK: return m_uiElderStonebarkGUID; case NPC_VEZAX: return m_uiVezaxGUID; @@ -742,35 +1055,47 @@ uint64 instance_ulduar::GetData64(uint32 uiData) case NPC_ALGALON: return m_uiAlgalonGUID; - // Mimiron hard mode button - case G0_MIMIRON_BUTTON: + // mimiron hard mode button + case GO_MIMIRON_BUTTON: return m_uiMimironButtonGUID; - // Celestial door + // thorim encounter starter lever + case GO_DOOR_LEVER: + return m_uiThorimLeverGUID; + // celestial door case GO_CELESTIAL_DOOR: return m_uiCelestialDoorGUID; - } + } - return 0; -} + return 0; + } -// TODO: implement all hard mode loot here! -bool instance_ulduar::CheckConditionCriteriaMeet(Player const* pSource, uint32 uiMapId, uint32 uiInstanceConditionId) -{ - if (uiMapId != instance->GetId()) + // TODO: implement all achievs here! + bool CheckAchievementCriteriaMeet(uint32 criteria_id, const Player *source) + { + switch(criteria_id) + { + case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET: + break; + } return false; + } - switch (uiInstanceConditionId) - { - case TYPE_XT002_HARD: - break; - } - return false; -} + // TODO: implement all hard mode loot here! + bool CheckConditionCriteriaMeet(Player const* source, uint32 map_id, uint32 instance_condition_id) + { + if (map_id != instance->GetId()) + return false; + switch (instance_condition_id) + { + case TYPE_XT002_HARD: + break; + } + } -uint32 instance_ulduar::GetData(uint32 uiType) -{ - switch (uiType) - { + uint32 GetData(uint32 uiType) + { + switch(uiType) + { case TYPE_LEVIATHAN: return m_auiEncounter[0]; case TYPE_IGNIS: @@ -800,7 +1125,7 @@ uint32 instance_ulduar::GetData(uint32 uiType) case TYPE_ALGALON: return m_auiEncounter[13]; - // Hard modes + // hard modes case TYPE_LEVIATHAN_HARD: return m_auiHardBoss[0]; case TYPE_XT002_HARD: @@ -820,7 +1145,7 @@ uint32 instance_ulduar::GetData(uint32 uiType) case TYPE_YOGGSARON_HARD: return m_auiHardBoss[8]; - // Ulduar Keepers + // ulduar keepers case TYPE_KEEPER_HODIR: return m_auiUlduarKeepers[0]; case TYPE_KEEPER_THORIM: @@ -830,61 +1155,91 @@ uint32 instance_ulduar::GetData(uint32 uiType) case TYPE_KEEPER_MIMIRON: return m_auiUlduarKeepers[3]; - // Teleporters + // teleporters case TYPE_LEVIATHAN_TP: return m_auiUlduarTeleporters[0]; case TYPE_XT002_TP: return m_auiUlduarTeleporters[1]; case TYPE_MIMIRON_TP: return m_auiUlduarTeleporters[2]; - } - return 0; -} + // mini boss + case TYPE_RUNE_GIANT: + return m_auiMiniBoss[1]; + case TYPE_RUNIC_COLOSSUS: + return m_auiMiniBoss[0]; + case TYPE_LEVIATHAN_MK: + return m_auiMiniBoss[2]; + case TYPE_VX001: + return m_auiMiniBoss[3]; + case TYPE_AERIAL_UNIT: + return m_auiMiniBoss[4]; + case TYPE_YOGG_BRAIN: + return m_auiMiniBoss[5]; -// Spawn the friendly keepers in the central chamber -void instance_ulduar::SpawnFriendlyKeeper(uint32 uiWho) -{ - Player* pPlayer = GetPlayerInMap(); - if (!pPlayer) - return; + case TYPE_MIMIRON_PHASE: + return m_uiMimironPhase; + case TYPE_YOGG_PHASE: + return m_uiYoggPhase; + case TYPE_VISION_PHASE: + return m_uiVisionPhase; + } - switch(uiWho) - { - case NPC_MIMIRON_IMAGE: pPlayer->SummonCreature(NPC_MIMIRON_IMAGE, m_aKeepersSpawnLocs[1].m_fX, m_aKeepersSpawnLocs[1].m_fY, m_aKeepersSpawnLocs[1].m_fZ, m_aKeepersSpawnLocs[1].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); break; - case NPC_HODIR_IMAGE: pPlayer->SummonCreature(NPC_HODIR_IMAGE, m_aKeepersSpawnLocs[2].m_fX, m_aKeepersSpawnLocs[2].m_fY, m_aKeepersSpawnLocs[2].m_fZ, m_aKeepersSpawnLocs[2].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); break; - case NPC_THORIM_IMAGE: pPlayer->SummonCreature(NPC_THORIM_IMAGE, m_aKeepersSpawnLocs[3].m_fX, m_aKeepersSpawnLocs[3].m_fY, m_aKeepersSpawnLocs[3].m_fZ, m_aKeepersSpawnLocs[3].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); break; - case NPC_FREYA_IMAGE: pPlayer->SummonCreature(NPC_FREYA_IMAGE, m_aKeepersSpawnLocs[0].m_fX, m_aKeepersSpawnLocs[0].m_fY, m_aKeepersSpawnLocs[0].m_fZ, m_aKeepersSpawnLocs[0].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000); break; + return 0; } -} -void instance_ulduar::Load(const char* strIn) -{ - if (!strIn) + const char* Save() { - OUT_LOAD_INST_DATA_FAIL; - return; + return m_strInstData.c_str(); } - OUT_LOAD_INST_DATA(strIn); + void Load(const char* strIn) + { + if (!strIn) + { + OUT_LOAD_INST_DATA_FAIL; + return; + } + + OUT_LOAD_INST_DATA(strIn); - std::istringstream loadStream(strIn); - loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] + std::istringstream loadStream(strIn); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11] >> m_auiEncounter[12] >> m_auiEncounter[13] >> m_auiHardBoss[0] >> m_auiHardBoss[1] >> m_auiHardBoss[2] >> m_auiHardBoss[3] >> m_auiHardBoss[4] >> m_auiHardBoss[5] >> m_auiHardBoss[6] >> m_auiHardBoss[7] >> m_auiHardBoss[8] >> m_auiUlduarKeepers[0] - >> m_auiUlduarKeepers[1] >> m_auiUlduarKeepers[2] >> m_auiUlduarKeepers[3]; + >> m_auiUlduarKeepers[1] >> m_auiUlduarKeepers[2] >> m_auiUlduarKeepers[3] >> m_auiUlduarTeleporters[0] + >> m_auiUlduarTeleporters[1] >> m_auiUlduarTeleporters[2]; + + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + { + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; + } + + OUT_LOAD_INST_DATA_COMPLETE; + } - for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) + // Hacky way of completing some achievs + // PLEASE REMOVE FOR REVISION! + void CheckIronCouncil() { - if (m_auiEncounter[i] == IN_PROGRESS) - m_auiEncounter[i] = NOT_STARTED; + // check if the other bosses in the antechamber are dead + // hacky way to complete achievements; use only if you have this function + if(m_auiEncounter[4] == DONE && m_auiEncounter[5] == DONE && m_auiEncounter[6] == DONE) + DoCompleteAchievement(instance->IsRegularDifficulty() ? ACHIEV_IRON_COUNCIL : ACHIEV_IRON_COUNCIL_H); } - OUT_LOAD_INST_DATA_COMPLETE; -} + void CheckKeepers() + { + // check if the other bosses in the antechamber are dead + // hacky way to complete achievements; use only if you have this function + if(m_auiEncounter[7] == DONE && m_auiEncounter[8] == DONE && m_auiEncounter[9] == DONE && m_auiEncounter[10] == DONE) + DoCompleteAchievement(instance->IsRegularDifficulty() ? ACHIEV_KEEPERS : ACHIEV_KEEPERS_H); + } +}; InstanceData* GetInstanceData_instance_ulduar(Map* pMap) { @@ -893,10 +1248,9 @@ InstanceData* GetInstanceData_instance_ulduar(Map* pMap) void AddSC_instance_ulduar() { - Script* pNewScript; - - pNewScript = new Script; - pNewScript->Name = "instance_ulduar"; - pNewScript->GetInstanceData = &GetInstanceData_instance_ulduar; - pNewScript->RegisterSelf(); + Script *newscript; + newscript = new Script; + newscript->Name = "instance_ulduar"; + newscript->GetInstanceData = &GetInstanceData_instance_ulduar; + newscript->RegisterSelf(); } diff --git a/scripts/northrend/ulduar/ulduar/ulduar.cpp b/scripts/northrend/ulduar/ulduar/ulduar.cpp index d7da144..96dd5c6 100644 --- a/scripts/northrend/ulduar/ulduar/ulduar.cpp +++ b/scripts/northrend/ulduar/ulduar/ulduar.cpp @@ -1,55 +1,201 @@ -/* Copyright (C) 2006 - 2010 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 - */ +/* 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: ulduar -SD%Complete: 0% +SDName: Ulduar teleport +SD%Complete: SDComment: SDCategory: Ulduar EndScriptData */ #include "precompiled.h" -#include "ulduar.h" - -/*##### -## Teleporters -#####*/ -enum TeleporterSpells -{ - SPELL_TELE_EXPEDITION_BASE_CAMP = 64014, - SPELL_TELE_FORMATION_GROUNDS = 64032, - SPELL_TELE_COLOSSAL_FORGE = 64028, - SPELL_TELE_SCRAPYARD = 64031, - SPELL_TELE_ANTECHAMBER_OF_ULDUAR = 64030, - SPELL_TELE_SHATTERED_WALKWAY = 64029, - SPELL_TELE_CONSERVATORY_OF_LIFE = 64024, - SPELL_TELE_SPARK_OF_IMAGINATION = 65061, - SPELL_TELE_PRISON_OF_YOGG = 65042, -}; - -// Teleporter Gossip handled by SD2 because depending on Instance Data -enum TeleporterGossipItems -{ - GOSSIP_ITEM_TELE_BASE_CAMP = -3603000, - GOSSIP_ITEM_TELE_FORMATION_GROUNDS = -3603001, - GOSSIP_ITEM_TELE_COLOSSAR_FORGE = -3603002, - GOSSIP_ITEM_TELE_SCRAPYARD = -3603003, - GOSSIP_ITEM_TELE_ANTECHAMBER = -3603004, - GOSSIP_ITEM_TELE_WALKWAY = -3603005, - GOSSIP_ITEM_TELE_CONSERVATORY = -3603006, - GOSSIP_ITEM_TELE_SPARK_IMAGINATION = -3603007, - GOSSIP_ITEM_TELE_YOGG_SARON = -3603008, -}; +#include "def_ulduar.h" + +#define REQUEST_HELP "Help me fight Yogg-Saron!" +#define DENY_HELP "I don't need your help." + +/* +* Here is the gossip for the keepers images +* Each image appears in the centra chamber after the corrupted keeper is defeated +* They should be spawned in script, but I added them into the DB by default as invisilbe +* After the players make theyr choice if the want help or not, this option is saved and there is no turning back, until raid reset +* If they are asked for help, at the beginning of the Yogg encounter each requested keeper will be summoned inside the chamber +* There should be more text in the gossip menu, I couldn't find it anywhere yet +*/ + +/*####### +*### Keepers images +#######*/ +// HODIR +bool GossipHello_hodir_image(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + + if(m_pInstance && m_pInstance->GetData(TYPE_KEEPER_HODIR) != DONE && m_pInstance->GetData(TYPE_KEEPER_HODIR) != FAIL) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, REQUEST_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, DENY_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_hodir_image(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + pPlayer->CLOSE_GOSSIP_MENU(); + + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_KEEPER_HODIR, DONE); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_KEEPER_HODIR, FAIL); + } + return true; +} + +// FREYA +bool GossipHello_freya_image(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + + if(m_pInstance && m_pInstance->GetData(TYPE_KEEPER_FREYA) != DONE && m_pInstance->GetData(TYPE_KEEPER_FREYA) != FAIL) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, REQUEST_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, DENY_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_freya_image(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + pPlayer->CLOSE_GOSSIP_MENU(); + + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_KEEPER_FREYA, DONE); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_KEEPER_FREYA, FAIL); + } + return true; +} +// MIMIRON +bool GossipHello_mimiron_image(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + + if(m_pInstance && m_pInstance->GetData(TYPE_KEEPER_MIMIRON) != DONE && m_pInstance->GetData(TYPE_KEEPER_MIMIRON) != FAIL) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, REQUEST_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, DENY_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_mimiron_image(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + pPlayer->CLOSE_GOSSIP_MENU(); + + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_KEEPER_MIMIRON, DONE); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_KEEPER_MIMIRON, FAIL); + } + return true; +} + +// THORIM +bool GossipHello_thorim_image(Player* pPlayer, Creature* pCreature) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + + if(m_pInstance && m_pInstance->GetData(TYPE_KEEPER_THORIM) != DONE && m_pInstance->GetData(TYPE_KEEPER_THORIM) != FAIL) + { + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, REQUEST_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1); + pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, DENY_HELP, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2); + } + + pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID()); + return true; +} + +bool GossipSelect_thorim_image(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction) +{ + ScriptedInstance *m_pInstance = (ScriptedInstance *) pCreature->GetInstanceData(); + pPlayer->CLOSE_GOSSIP_MENU(); + + if (uiAction == GOSSIP_ACTION_INFO_DEF+1) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_KEEPER_THORIM, DONE); + } + if (uiAction == GOSSIP_ACTION_INFO_DEF+2) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_KEEPER_THORIM, FAIL); + } + return true; +} + +void AddSC_ulduar() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "hodir_image"; + newscript->pGossipHello = &GossipHello_hodir_image; + newscript->pGossipSelect = &GossipSelect_hodir_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "freya_image"; + newscript->pGossipHello = &GossipHello_freya_image; + newscript->pGossipSelect = &GossipSelect_freya_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "thorim_image"; + newscript->pGossipHello = &GossipHello_thorim_image; + newscript->pGossipSelect = &GossipSelect_thorim_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "mimiron_image"; + newscript->pGossipHello = &GossipHello_mimiron_image; + newscript->pGossipSelect = &GossipSelect_mimiron_image; + newscript->RegisterSelf(); + +} diff --git a/scripts/northrend/ulduar/ulduar/ulduar_teleport.cpp b/scripts/northrend/ulduar/ulduar/ulduar_teleport.cpp new file mode 100644 index 0000000..bc6d903 --- /dev/null +++ b/scripts/northrend/ulduar/ulduar/ulduar_teleport.cpp @@ -0,0 +1,119 @@ +/* Copyright (C) 2006 - 2010 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: ulduar_teleport +SD%Complete: 95% +SDComment: by /dev/rsa +SDCategory: Ulduar instance +EndScriptData */ + +#include "precompiled.h" +#include "def_ulduar.h" + +enum +{ + PORTALS_COUNT = 9, + TELEPORT_GOSSIP_MESSAGE = 14424, + + // spells + SPELL_TELEPORT_BASE_CAMP = 64014, + SPELL_TELEPORT_GROUNDS = 64032, + SPELL_TELEPORT_FORGE = 64028, + SPELL_TELEPORT_SCRAPYARD = 64031, + SPELL_TELEPORT_ANTECHAMBER = 64030, + SPELL_TELEPORT_WALKWAY = 64029, + SPELL_TELEPORT_CONSERVATORY = 64024, + SPELL_TELEPORT_SPARK = 65061, + SPELL_TELEPORT_PRISON = 65042, +}; + +struct t_Locations +{ + int textNum; + uint32 map_num; + float x, y, z, o; + uint32 spellID; + bool state; + bool active; + uint32 encounter; +}; + +static t_Locations PortalLoc[]= +{ +{-3050001,603, -706.122f, -92.6024f, 430.176f, 4.19f, SPELL_TELEPORT_BASE_CAMP, true,true, TYPE_LEVIATHAN}, // base camp +{-3050002,603, 131.248f, -35.3802f, 410.104f, 0, SPELL_TELEPORT_GROUNDS, true,true, TYPE_LEVIATHAN_TP}, // formation ground +{-3050003,603, 553.233f, -12.3247f, 409.979f, 0, SPELL_TELEPORT_FORGE, false,true,TYPE_LEVIATHAN}, // +{-3050004,603, 926.292f, -11.4635f, 418.895f, 3.19f, SPELL_TELEPORT_SCRAPYARD, false,true,TYPE_XT002_TP}, // +{-3050005,603, 1498.09f, -24.246f, 421.267f, 0, SPELL_TELEPORT_ANTECHAMBER, false,true,TYPE_XT002}, // +{-3050006,603, 1859.45f, -24.1f, 449.2f, 0, SPELL_TELEPORT_WALKWAY, false,true,TYPE_KOLOGARN}, // +{-3050007,603, 2086.27f, -24.3134f, 421.539f, 0, SPELL_TELEPORT_CONSERVATORY,false,true,TYPE_AURIAYA}, // +{-3050008,603, 2517.3979f, 2568.89f, 412.99f, 6.17f, SPELL_TELEPORT_SPARK, false,true,TYPE_MIMIRON_TP}, // +{-3050009,603, 1854.782f, -11.3819f, 335.27f, 5.86f, SPELL_TELEPORT_PRISON, false,true,TYPE_VEZAX}, // +}; + + +bool GOGossipSelect_go_ulduar_teleporter(Player *pPlayer, GameObject* pGo, uint32 sender, uint32 action) +{ + int32 damage = 0; + if(sender != GOSSIP_SENDER_MAIN) return false; + + if(!pPlayer->getAttackers().empty()) return false; + + if(action >= 0 && action <= PORTALS_COUNT) + pPlayer->TeleportTo(PortalLoc[action].map_num, PortalLoc[action].x, PortalLoc[action].y, PortalLoc[action].z, PortalLoc[action].o); + if (PortalLoc[action].spellID != 0 ) + if (SpellEntry const* spell = (SpellEntry *)GetSpellStore()->LookupEntry(PortalLoc[action].spellID)) + { + SpellAuraHolder *holder = CreateSpellAuraHolder(spell, pPlayer, pPlayer); + Aura *aura = CreateAura(spell, EFFECT_INDEX_2, NULL, holder, pPlayer); + holder->AddAura(aura, EFFECT_INDEX_2); + pPlayer->AddSpellAuraHolder(holder); + } + + pPlayer->CLOSE_GOSSIP_MENU(); + return true; +} + +bool GOGossipHello_go_ulduar_teleporter(Player *pPlayer, GameObject* pGo) +{ + ScriptedInstance *pInstance = (ScriptedInstance *) pGo->GetInstanceData(); + + if (!pInstance || !pPlayer) return false; + if (pPlayer->isInCombat()) return true; + + for(uint8 i = 0; i < PORTALS_COUNT; i++) { + if ((PortalLoc[i].active == true && + (PortalLoc[i].state == true || + pInstance->GetData(PortalLoc[i].encounter) == DONE || + pInstance->GetData(PortalLoc[i].encounter) == IN_PROGRESS)) + || pPlayer->isGameMaster()) + pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_TAXI, PortalLoc[i].textNum, GOSSIP_SENDER_MAIN, i); + }; + pPlayer->SEND_GOSSIP_MENU(TELEPORT_GOSSIP_MESSAGE, pGo->GetGUID()); + return true; +} + +void AddSC_ulduar_teleport() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "go_ulduar_teleporter"; + newscript->pGOGossipHello = &GOGossipHello_go_ulduar_teleporter; + newscript->pGOGossipSelect = &GOGossipSelect_go_ulduar_teleporter; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/vault_of_archavon/boss_archavon.cpp b/scripts/northrend/vault_of_archavon/boss_archavon.cpp new file mode 100644 index 0000000..4410054 --- /dev/null +++ b/scripts/northrend/vault_of_archavon/boss_archavon.cpp @@ -0,0 +1,274 @@ +/* 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_Archavon_The_Stone_Watcher +SD%Complete: 0% +SDComment: +SDCategory: Vault of Archavon +EndScriptData */ + +#include "precompiled.h" +#include "vault_of_archavon.h" + +enum +{ + SPELL_ROCK_SHARDS_LEFT_N = 58695, + SPELL_ROCK_SHARDS_LEFT_H = 60883, + SPELL_ROCK_SHARDS_RIGHT_N = 58696, + SPELL_ROCK_SHARDS_RIGHT_H = 60884, + SPELL_CRUSHING_LEAP_N = 58963, + SPELL_CRUSHING_LEAP_H = 60895, + SPELL_STOMP_N = 58663, + SPELL_STOMP_H = 60880, + SPELL_IMPALE_DMG_N = 58666, + SPELL_IMPALE_DMG_H = 60882, + SPELL_IMPALE_STUN = 50839, + SPELL_BERSERK = 47008 +}; + +struct MANGOS_DLL_DECL boss_archavonAI : public ScriptedAI +{ + boss_archavonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + m_fDefaultMoveSpeed = pCreature->GetSpeedRate(MOVE_RUN); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + float m_fDefaultMoveSpeed; + uint32 m_uiEvadeCheckCooldown; + + uint32 m_uiBerserkTimer; + uint32 m_uiRockShardsTimer; + bool m_bRockShardsInProgress; + uint32 m_uiRockShardsProgressTimer; + uint32 m_uiRockShardTimer; + bool m_bRLRockShard; + Unit* m_pRockShardsTarget; + uint32 m_uiCrushingLeapTimer; + Unit* m_pCrushingLeapTarget; + bool m_bCrushingLeapInProgress; + uint32 m_uiCrushingLeapSecureTimer; + uint32 m_uiStompTimer; + uint32 m_uiImpaleAfterStompTimer; + bool m_bImpaleInProgress; + + void Reset() + { + m_uiEvadeCheckCooldown = 2000; + m_creature->SetSpeedRate(MOVE_RUN, m_fDefaultMoveSpeed); + m_uiBerserkTimer = 300000; + m_uiRockShardsTimer = 15000; + m_bRockShardsInProgress = false; + m_uiRockShardsProgressTimer = 3000; + m_uiRockShardTimer = 0; + m_bRLRockShard = true; + m_pRockShardsTarget = NULL; + m_uiCrushingLeapTimer = 30000; + m_pCrushingLeapTarget = NULL; + m_bCrushingLeapInProgress = false; + m_uiCrushingLeapSecureTimer = 2000; + m_uiStompTimer = 45000; + m_uiImpaleAfterStompTimer = 1000; + m_bImpaleInProgress = false; + + if(m_pInstance) + m_pInstance->SetData(TYPE_ARCHAVON, NOT_STARTED); + } + + void Aggro(Unit *pWho) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_ARCHAVON, IN_PROGRESS); + } + + void JustDied(Unit* pKiller) + { + if(m_pInstance) + m_pInstance->SetData(TYPE_ARCHAVON, DONE); + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiEvadeCheckCooldown < uiDiff) + { + if (m_creature->GetDistance2d(140.34f, -102.34f) > 80.0f) + EnterEvadeMode(); + m_uiEvadeCheckCooldown = 2000; + } + else + m_uiEvadeCheckCooldown -= uiDiff; + + if (m_bImpaleInProgress) + { + if (m_uiImpaleAfterStompTimer < uiDiff) + { + if (Unit* pTarget = m_creature->getVictim()) + { + DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_IMPALE_DMG_N : SPELL_IMPALE_DMG_H); + pTarget->CastSpell(pTarget, SPELL_IMPALE_STUN, true); + } + m_bImpaleInProgress = false; + } + else + { + m_uiImpaleAfterStompTimer -= uiDiff; + return; + } + } + + if (m_bCrushingLeapInProgress) + { + if (m_pCrushingLeapTarget) + { + if (m_pCrushingLeapTarget->isDead() || !m_pCrushingLeapTarget->IsInWorld() && !m_pCrushingLeapTarget->IsInMap(m_creature)) + { + m_bCrushingLeapInProgress = false; + return; + } + } + else + { + m_bCrushingLeapInProgress = false; + return; + } + if ((m_uiCrushingLeapSecureTimer < uiDiff) || (m_pCrushingLeapTarget && m_creature->IsWithinDist(m_pCrushingLeapTarget, 5.0f))) + { + m_creature->getThreatManager().addThreat(m_pCrushingLeapTarget, -100000000.0f); + m_creature->SetSpeedRate(MOVE_RUN, m_fDefaultMoveSpeed); + DoCastSpellIfCan(m_pCrushingLeapTarget, m_bIsRegularMode ? SPELL_CRUSHING_LEAP_N : SPELL_CRUSHING_LEAP_H, true); + m_bCrushingLeapInProgress = false; + } + else + m_uiCrushingLeapSecureTimer -= uiDiff; + + return; + } + + if (m_bRockShardsInProgress) + { + if (m_uiRockShardsProgressTimer < uiDiff) + { + m_bRockShardsInProgress = false; + if (m_pRockShardsTarget) + m_creature->getThreatManager().addThreat(m_pRockShardsTarget, -100000000.0f); + return; + } + else + m_uiRockShardsProgressTimer -= uiDiff; + + if (m_uiRockShardTimer < uiDiff) + { + if (m_pRockShardsTarget && m_pRockShardsTarget->isAlive()) + { + DoCast(m_pRockShardsTarget, m_bIsRegularMode ? (m_bRLRockShard ? SPELL_ROCK_SHARDS_LEFT_N : SPELL_ROCK_SHARDS_RIGHT_N) : (m_bRLRockShard ? SPELL_ROCK_SHARDS_LEFT_H : SPELL_ROCK_SHARDS_RIGHT_H)); + m_bRLRockShard = !m_bRLRockShard; + } + m_uiRockShardTimer = 100; + } + else + m_uiRockShardsTimer -= uiDiff; + + return; + } + + if (m_uiRockShardsTimer < uiDiff) + { + m_bRockShardsInProgress = true; + m_uiRockShardsProgressTimer = 3000; + m_bRLRockShard = true; + m_pRockShardsTarget = NULL; + if (m_pRockShardsTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + m_creature->getThreatManager().addThreat(m_pRockShardsTarget, 100000000.0f); + m_uiRockShardsTimer = 15000+rand()%15000; + return; + } + else + m_uiRockShardsTimer -= uiDiff; + + if (m_uiCrushingLeapTimer < uiDiff) + { + ThreatList const& tList = m_creature->getThreatManager().getThreatList(); + std::list lTargets; + for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr) + { + Unit *pTemp = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); + if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && !m_creature->IsWithinDist(pTemp, 10.0f) && m_creature->IsWithinDist(pTemp, 80.0f)) + lTargets.push_back(pTemp); + } + m_pCrushingLeapTarget = NULL; + if (!lTargets.empty()) + { + std::list::iterator pTarget = lTargets.begin(); + advance(pTarget, (rand() % lTargets.size())); + m_pCrushingLeapTarget = *pTarget; + if (m_pCrushingLeapTarget) + { + m_creature->MonsterSay(m_pCrushingLeapTarget->GetName(), LANG_UNIVERSAL); + m_creature->getThreatManager().addThreat(m_pCrushingLeapTarget, 100000000.0f); + m_creature->SetSpeedRate(MOVE_RUN, m_fDefaultMoveSpeed*10.0f); + m_bCrushingLeapInProgress = true; + m_uiCrushingLeapSecureTimer = 2000; + } + } + m_uiCrushingLeapTimer = 30000+rand()%15000; + return; + } + else + m_uiCrushingLeapTimer -= uiDiff; + + if (m_uiStompTimer < uiDiff) + { + DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_STOMP_N : SPELL_STOMP_H); + m_uiImpaleAfterStompTimer = 1000; + m_bImpaleInProgress = true; + m_uiStompTimer = 45000+rand()%15000; + } + else + m_uiStompTimer -= uiDiff; + + if (m_uiBerserkTimer < uiDiff) + { + DoCastSpellIfCan(m_creature, SPELL_BERSERK); + m_uiBerserkTimer = 60000; + } + else + m_uiBerserkTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_archavon(Creature *pCreature) +{ + return new boss_archavonAI (pCreature); +}; + +void AddSC_boss_archavon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_archavon"; + newscript->GetAI = &GetAI_boss_archavon; + newscript->RegisterSelf(); +}; diff --git a/scripts/northrend/vault_of_archavon/boss_emalon.cpp b/scripts/northrend/vault_of_archavon/boss_emalon.cpp new file mode 100644 index 0000000..4a0215b --- /dev/null +++ b/scripts/northrend/vault_of_archavon/boss_emalon.cpp @@ -0,0 +1,445 @@ +/* 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_Emalon_The_Storm_Watcher +SD%Complete: 0% +SDComment: +SDCategory: Vault of Archavon +EndScriptData */ + +#include "precompiled.h" +#include "vault_of_archavon.h" + +enum +{ + // Emalon spells + SPELL_CHAIN_LIGHTNING_N = 64213, + SPELL_CHAIN_LIGHTNING_H = 64215, + SPELL_LIGHTNING_NOVA_N = 64216, + SPELL_LIGHTNING_NOVA_H = 65279, + SPELL_OVERCHARGE = 64379, //This spell is used by Time Warder, and temporary by Emalon, because 64218 is bugged + SPELL_BERSERK = 26662, + + // Tempest Minion spells + SPELL_SHOCK = 64363, + SPELL_OVERCHARGED_BLAST = 64219, + SPELL_OVERCHARGED = 64217 +}; + +/*###### +## npc_tempest_minion +######*/ + +struct MANGOS_DLL_DECL npc_tempest_minionAI : public ScriptedAI +{ + npc_tempest_minionAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_fDefaultX = m_creature->GetPositionX(); + m_fDefaultY = m_creature->GetPositionY(); + m_fDefaultZ = m_creature->GetPositionZ(); + m_fDefaultO = m_creature->GetOrientation(); + Reset(); + } + + ScriptedInstance* m_pInstance; + uint32 m_uiEvadeCheckCooldown; + + uint32 m_uiShockTimer; + uint32 m_uiRespawnTimer; + uint32 m_uiOverchargedStacksCheckTimer; + bool m_bDead; + bool m_bTimeToDie; + float m_fDefaultX; + float m_fDefaultY; + float m_fDefaultZ; + float m_fDefaultO; + + void Init() + { + m_uiEvadeCheckCooldown = 2000; + m_uiShockTimer = 8000+rand()%4000; + m_bDead = false; + m_bTimeToDie = false; + m_uiRespawnTimer = 4000; + m_uiOverchargedStacksCheckTimer = 2000; + + m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->SetStandState(UNIT_STAND_STATE_STAND); + m_creature->SetVisibility(VISIBILITY_ON); + } + + void Reset() + { + Init(); + } + + void Aggro(Unit* pWho) + { + m_creature->CallForHelp(80.0f); + } + + void FakeDeath() + { + m_bDead = true; + m_bTimeToDie = false; + m_uiRespawnTimer = 4000; + m_creature->InterruptNonMeleeSpells(false); + m_creature->SetHealth(0); + m_creature->StopMoving(); + m_creature->ClearComboPointHolders(); + m_creature->RemoveAllAurasOnDeath(); + m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_20_PERCENT, false); + m_creature->ModifyAuraState(AURA_STATE_HEALTHLESS_35_PERCENT, false); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + m_creature->ClearAllReactives(); + m_creature->SetUInt64Value(UNIT_FIELD_TARGET,0); + m_creature->GetMotionMaster()->Clear(); + m_creature->GetMotionMaster()->MoveIdle(); + m_creature->SetStandState(UNIT_STAND_STATE_DEAD); + m_creature->GetMap()->CreatureRelocation(m_creature, m_fDefaultX, m_fDefaultY, m_fDefaultZ, m_fDefaultO); + } + + void DamageTaken(Unit* pDoneBy, uint32& uiDamage) + { + if (uiDamage < m_creature->GetHealth()) + return; + + if (m_pInstance && (m_pInstance->GetData(TYPE_EMALON) != DONE)) + { + uiDamage = 0; + FakeDeath(); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiEvadeCheckCooldown < uiDiff) + { + Creature* pEmalon = m_creature->GetMap()->GetCreature( m_pInstance->GetData64(DATA_EMALON)); + if ((pEmalon && pEmalon->IsInEvadeMode()) || (m_creature->GetDistance2d(-219.119f, -289.037f) > 80.0f)) + { + EnterEvadeMode(); + return; + } + m_uiEvadeCheckCooldown = 2000; + } + else + m_uiEvadeCheckCooldown -= uiDiff; + + if (m_bTimeToDie) + { + FakeDeath(); + return; + } + + if (m_bDead) + { + if (m_uiRespawnTimer < uiDiff) + { + m_creature->SetHealth(m_creature->GetMaxHealth()); + m_creature->SetVisibility(VISIBILITY_OFF); + Init(); + m_creature->MonsterTextEmote("%s appears to defend Emalon!", NULL, true); + m_creature->SetInCombatWithZone(); + DoResetThreat(); + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + m_creature->GetMotionMaster()->MoveChase(pTarget); + } + else + m_uiRespawnTimer -= uiDiff; + + return; + } + + if (m_uiOverchargedStacksCheckTimer < uiDiff) + { + m_uiOverchargedStacksCheckTimer = 2000; + Aura* pAuraOvercharged = m_creature->GetAura(SPELL_OVERCHARGED, EFFECT_INDEX_0); + if(pAuraOvercharged && pAuraOvercharged->GetStackAmount() >= 10) + { + DoCastSpellIfCan(m_creature, SPELL_OVERCHARGED_BLAST); + m_bTimeToDie = true; + return; + } + } + else + m_uiOverchargedStacksCheckTimer -= uiDiff; + + if (m_uiShockTimer < uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOCK); + m_uiShockTimer = 8000+rand()%4000; + } + else + m_uiShockTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## boss_emalon +######*/ + +struct MANGOS_DLL_DECL boss_emalonAI : public ScriptedAI +{ + boss_emalonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* m_pInstance; + bool m_bIsRegularMode; + uint32 m_uiEvadeCheckCooldown; + + uint64 m_auiTempestMinionGUID[4]; + uint32 m_uiChainLightningTimer; + uint32 m_uiChainLightningCount; + uint32 m_uiLightningNovaTimer; + uint32 m_uiOverchargeTimer; + uint32 m_uiEnrageTimer; + + void Reset() + { + m_uiEvadeCheckCooldown = 2000; + memset(&m_auiTempestMinionGUID, 0, sizeof(m_auiTempestMinionGUID)); + m_uiChainLightningTimer = 15000; + m_uiChainLightningCount = 0; + m_uiLightningNovaTimer = 20000; + m_uiOverchargeTimer = 45000; + m_uiEnrageTimer = 360000; + + if (m_pInstance) + { + m_auiTempestMinionGUID[0] = m_pInstance->GetData64(DATA_TEMPEST_MINION_1); + m_auiTempestMinionGUID[1] = m_pInstance->GetData64(DATA_TEMPEST_MINION_2); + m_auiTempestMinionGUID[2] = m_pInstance->GetData64(DATA_TEMPEST_MINION_3); + m_auiTempestMinionGUID[3] = m_pInstance->GetData64(DATA_TEMPEST_MINION_4); + } + + for (uint8 i=0; i<4; ++i) + { + Creature* pMinion = m_creature->GetMap()->GetCreature( m_auiTempestMinionGUID[i]); + if (pMinion && pMinion->isDead()) + pMinion->Respawn(); + } + + if (m_pInstance) + m_pInstance->SetData(TYPE_EMALON, NOT_STARTED); + } + + void Aggro(Unit* pWho) + { + if (m_pInstance) + { + m_auiTempestMinionGUID[0] = m_pInstance->GetData64(DATA_TEMPEST_MINION_1); + m_auiTempestMinionGUID[1] = m_pInstance->GetData64(DATA_TEMPEST_MINION_2); + m_auiTempestMinionGUID[2] = m_pInstance->GetData64(DATA_TEMPEST_MINION_3); + m_auiTempestMinionGUID[3] = m_pInstance->GetData64(DATA_TEMPEST_MINION_4); + } + + m_creature->CallForHelp(80.0f); + + if (m_pInstance) + m_pInstance->SetData(TYPE_EMALON, IN_PROGRESS); + } + + void JustDied(Unit* pKiller) + { + if (m_pInstance) + m_pInstance->SetData(TYPE_EMALON, DONE); + for (uint8 i=0; i<4; ++i) + { + Creature *pMinion = m_creature->GetMap()->GetCreature( m_auiTempestMinionGUID[i]); + if (pMinion) + pMinion->DealDamage(pMinion, pMinion->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + } + } + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_uiEvadeCheckCooldown < uiDiff) + { + if (m_creature->GetDistance2d(-219.119f, -289.037f) > 80.0f) + EnterEvadeMode(); + m_creature->CallForHelp(80.0f); + m_uiEvadeCheckCooldown = 2000; + } + else + m_uiEvadeCheckCooldown -= uiDiff; + + if (m_uiOverchargeTimer < uiDiff) + { + Creature* pMinion = m_creature->GetMap()->GetCreature( m_auiTempestMinionGUID[rand()%4]); + if(pMinion && pMinion->isAlive()) + { + m_creature->MonsterTextEmote("%s overcharges Tempest Minion!",NULL, true); + pMinion->SetHealth(pMinion->GetMaxHealth()); + pMinion->CastSpell(pMinion, SPELL_OVERCHARGE, false); + } + m_uiOverchargeTimer = 45000; + } + else + m_uiOverchargeTimer -= uiDiff; + + if (m_uiChainLightningTimer < uiDiff) + { + if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING_N : SPELL_CHAIN_LIGHTNING_H); + m_uiChainLightningTimer = 10000 + rand()%15000; + } + else + m_uiChainLightningTimer -= uiDiff; + + if (m_uiLightningNovaTimer < uiDiff) + { + DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_LIGHTNING_NOVA_N : SPELL_LIGHTNING_NOVA_H); + m_uiLightningNovaTimer = 45000; + } + else + m_uiLightningNovaTimer -= uiDiff; + + if (m_uiEnrageTimer < uiDiff) + { + DoCastSpellIfCan(m_creature, SPELL_BERSERK); + m_uiEnrageTimer = 30000; + } + else + m_uiEnrageTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +/*###### +## npc_tempest_warder +######*/ + +struct MANGOS_DLL_DECL npc_tempest_warderAI : public ScriptedAI +{ + npc_tempest_warderAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + ScriptedInstance* m_pInstance; + + uint32 m_uiShockTimer; + bool m_bOvercharged; + uint32 m_uiOverchargedStacksCheckTimer; + bool m_bTimeToDie; + + void Reset() + { + m_uiShockTimer = 8000+rand()%4000; + m_bOvercharged = false; + uint32 m_uiOverchargedStacksCheckTimer = 2000; + m_bTimeToDie = false; + } + + void Aggro(Unit* pWho) {} + + void UpdateAI(const uint32 uiDiff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if (m_bTimeToDie) + { + m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false); + return; + } + + if (!m_bOvercharged && ((m_creature->GetHealth()*100 / m_creature->GetMaxHealth()) < 37)) + { + DoCastSpellIfCan(m_creature, SPELL_OVERCHARGE); + m_bOvercharged = true; + } + + if (m_bOvercharged) + { + if (m_uiOverchargedStacksCheckTimer < uiDiff) + { + m_uiOverchargedStacksCheckTimer = 2000; + Aura* pAuraOvercharged = m_creature->GetAura(SPELL_OVERCHARGED, EFFECT_INDEX_0); + if(pAuraOvercharged && pAuraOvercharged->GetStackAmount() >= 10) + { + DoCastSpellIfCan(m_creature, SPELL_OVERCHARGED_BLAST); + m_bTimeToDie = true; + return; + } + } + else + m_uiOverchargedStacksCheckTimer -= uiDiff; + } + + if (m_uiShockTimer < uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOCK); + m_uiShockTimer = 8000+rand()%4000; + } + else + m_uiShockTimer -= uiDiff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_emalonAI(Creature* pCreature) +{ + return new boss_emalonAI(pCreature); +} + +CreatureAI* GetAI_npc_tempest_minionAI(Creature* pCreature) +{ + return new npc_tempest_minionAI(pCreature); +} + +CreatureAI* GetAI_npc_tempest_warderAI(Creature* pCreature) +{ + return new npc_tempest_warderAI(pCreature); +} + +void AddSC_boss_emalon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_emalon"; + newscript->GetAI = &GetAI_boss_emalonAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tempest_minion"; + newscript->GetAI = &GetAI_npc_tempest_minionAI; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_tempest_warder"; + newscript->GetAI = &GetAI_npc_tempest_warderAI; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/vault_of_archavon/boss_koralon.cpp b/scripts/northrend/vault_of_archavon/boss_koralon.cpp new file mode 100644 index 0000000..181d5fa --- /dev/null +++ b/scripts/northrend/vault_of_archavon/boss_koralon.cpp @@ -0,0 +1,117 @@ +#include "precompiled.h" +#include "vault_of_archavon.h" + +#define SP_BURNING_FURY_AURA 66895 +#define SP_BURNING_FURY_AURA2 68168 +#define SP_BURNING_FURY_EFFECT 66721 + +#define SP_BURNING_BREATH 66665 +#define H_SP_BURNING_BREATH 67328 //DBM +#define SP_BB_EFFECT 66670 +#define H_SP_BB_EFFECT 67329 + +#define SP_METEOR_FISTS 66725 //DBM +#define H_SP_METEOR_FISTS 68161 +#define SP_METEOR_FISTS_EFF 66765 +#define H_SP_METEOR_FISTS_EFF 67333 + +#define SP_CINDER 66684 +#define H_SP_CINDER 67332 + +struct MANGOS_DLL_DECL boss_koralonAI : public ScriptedAI +{ + boss_koralonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Regular = pCreature->GetMap()->IsRegularDifficulty(); + Reset(); + } + + ScriptedInstance* pInstance; + bool Regular; + uint32 BurningBreathTimer; + uint32 MeteorFistsTimer; + uint32 FlamesTimer; + + uint32 BBTickTimer; + uint32 BBTicks; + bool BB; + + void Reset() + { + BurningBreathTimer = 25000; + MeteorFistsTimer = 47000; + FlamesTimer = 15000; + + BB = false; + + if(pInstance) pInstance->SetData(TYPE_KORALON, NOT_STARTED); + } + + void Aggro(Unit *who) + { + DoCastSpellIfCan(m_creature, SP_BURNING_FURY_AURA); + + if(pInstance) pInstance->SetData(TYPE_KORALON, IN_PROGRESS); + }; + + void JustDied(Unit *killer) + { + if(pInstance) pInstance->SetData(TYPE_KORALON, DONE); + }; + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(BurningBreathTimer < diff) + { + DoCastSpellIfCan(m_creature, Regular ? SP_BURNING_BREATH : H_SP_BURNING_BREATH); + BurningBreathTimer = 45000; + + BB = true; + BBTickTimer = 1000; + BBTicks = 0; + } + else BurningBreathTimer -= diff; + + + if(FlamesTimer < diff) + { + int flames = Regular ? 3 : 5; + int i; + for(i=0; i< flames; ++i) + { + Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); + if(target) DoCastSpellIfCan(target, Regular ? SP_CINDER : H_SP_CINDER); + } + FlamesTimer = 20000; + } + else FlamesTimer -= diff; + + if(MeteorFistsTimer < diff) + { + DoCastSpellIfCan(m_creature->getVictim(), SP_METEOR_FISTS_EFF); + MeteorFistsTimer = 45000; + } + else MeteorFistsTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_koralonAI(Creature* pCreature) +{ + return new boss_koralonAI(pCreature); +} + +void AddSC_boss_koralon() +{ + Script *newscript; + + newscript = new Script; + newscript->Name = "boss_koralon"; + newscript->GetAI = &GetAI_boss_koralonAI; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/vault_of_archavon/boss_toravon.cpp b/scripts/northrend/vault_of_archavon/boss_toravon.cpp new file mode 100644 index 0000000..febca32 --- /dev/null +++ b/scripts/northrend/vault_of_archavon/boss_toravon.cpp @@ -0,0 +1,122 @@ +/* ScriptData +SDName: Toravon the Ice Watcher +SDAuthor: Lutik +SD%Complete: 0% +SDComment: +SDCategory: Vault of Archavon +EndScriptData */ + +#include "precompiled.h" +#include "vault_of_archavon.h" + +enum +{ + SP_WHITEOUT = 72034, + H_SP_WHITEOUT = 72096, + SP_FREEZING_GROUND = 72090, + H_SP_FREEZING_GROUND = 72104, + SP_FROZEN_MALLET = 71993, + FROZEN_ORB_AURA = 72081, + + CR_FROZEN_ORB = 38456 +}; + + +struct MANGOS_DLL_DECL boss_toravonAI : public ScriptedAI +{ + boss_toravonAI(Creature* pCreature) : ScriptedAI(pCreature) + { + m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty(); + orbsNum = m_bIsRegularMode ? 1 : 3; + pInstance = (ScriptedInstance*)pCreature->GetInstanceData(); + Reset(); + } + + bool m_bIsRegularMode; + ScriptedInstance *pInstance; + + int orbsNum; + uint32 WhiteoutTimer; + uint32 OrbsTimer; + uint32 FreezeTimer; + + void Reset() + { + WhiteoutTimer = 40000; + OrbsTimer = 15000; + FreezeTimer = 20000 + rand()%5000; + + if(pInstance) + pInstance->SetData(TYPE_TORAVON, NOT_STARTED); + } + + void Aggro(Unit *who) + { + DoCastSpellIfCan(m_creature, SP_FROZEN_MALLET); + + if(pInstance) + pInstance->SetData(TYPE_TORAVON, IN_PROGRESS); + } + + void JustDied(Unit *killer) + { + if(pInstance) + pInstance->SetData(TYPE_TORAVON, DONE); + } + + void JustSummoned(Creature *orb) + { + orb->CastSpell(orb, FROZEN_ORB_AURA, false); + orb->SetInCombatWithZone(); + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->SelectHostileTarget() || !m_creature->getVictim()) + return; + + if(WhiteoutTimer < diff) + { + DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SP_WHITEOUT : H_SP_WHITEOUT); + WhiteoutTimer = 40000; + } + else + WhiteoutTimer -= diff; + + if(OrbsTimer < diff) + { + for(int i=0; iSelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0)) + m_creature->SummonCreature(CR_FROZEN_ORB, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000); + } + OrbsTimer = 40000; + } + else + OrbsTimer -= diff; + + if(FreezeTimer < diff) + { + DoCastSpellIfCan(m_creature, SP_FREEZING_GROUND); + FreezeTimer = 20000 + rand()%5000; + } + else + FreezeTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_boss_toravon(Creature *pCreature) +{ + return new boss_toravonAI (pCreature); +}; + +void AddSC_boss_toravon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "boss_toravon"; + newscript->GetAI = &GetAI_boss_toravon; + newscript->RegisterSelf(); +}; diff --git a/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp b/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp new file mode 100644 index 0000000..f0db618 --- /dev/null +++ b/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp @@ -0,0 +1,210 @@ +/* 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_Vault_of_Archavon +SD%Complete: 0 +SDComment: +SDCategory: Vault of Archavon +EndScriptData */ + +#include "precompiled.h" +#include "vault_of_archavon.h" + +struct MANGOS_DLL_DECL instance_vault_of_archavon : public ScriptedInstance +{ + instance_vault_of_archavon(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string strInstData; + + uint64 m_uiArchavonGUID; + uint64 m_uiEmalonGUID; + uint64 m_uiKoralonGUID; + uint64 m_uiTempestMinion1GUID; + uint64 m_uiTempestMinion2GUID; + uint64 m_uiTempestMinion3GUID; + uint64 m_uiTempestMinion4GUID; + uint8 m_uiMinion; + + void Initialize() + { + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); + m_uiArchavonGUID = 0; + m_uiEmalonGUID = 0; + m_uiKoralonGUID = 0; + m_uiTempestMinion1GUID = 0; + m_uiTempestMinion2GUID = 0; + m_uiTempestMinion3GUID = 0; + m_uiTempestMinion4GUID = 0; + m_uiMinion = 0; + } + + void OnCreatureCreate(Creature* pCreature) + { + switch (pCreature->GetEntry()) + { + case NPC_ARCHAVON: + m_uiArchavonGUID = pCreature->GetGUID(); + break; + case NPC_EMALON: + m_uiEmalonGUID = pCreature->GetGUID(); + break; + case NPC_KORALON: + m_uiKoralonGUID = pCreature->GetGUID(); + break; + case NPC_TEMPEST_MINION: + ++m_uiMinion; + switch (m_uiMinion) + { + case 1: + m_uiTempestMinion1GUID = pCreature->GetGUID(); + break; + case 2: + m_uiTempestMinion2GUID = pCreature->GetGUID(); + break; + case 3: + m_uiTempestMinion3GUID = pCreature->GetGUID(); + break; + case 4: + m_uiTempestMinion4GUID = pCreature->GetGUID(); + break; + case 5: + m_uiMinion = 0; + break; + } + break; + } + } + + void SetData(uint32 uiType, uint32 uiData) + { + switch (uiType) + { + case TYPE_ARCHAVON: + m_auiEncounter[0] = uiData; + break; + case TYPE_EMALON: + m_auiEncounter[1] = uiData; + break; + case TYPE_KORALON: + m_auiEncounter[2] = uiData; + break; + case TYPE_TORAVON: + m_auiEncounter[3] = uiData; + break; + } + + if (uiData == 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; + } + } + + uint32 GetData(uint32 uiType) + { + switch (uiType) + { + case TYPE_ARCHAVON: + return m_auiEncounter[0]; + case TYPE_EMALON: + return m_auiEncounter[1]; + case TYPE_KORALON: + return m_auiEncounter[2]; + case TYPE_TORAVON: + return m_auiEncounter[3]; + } + return 0; + } + + uint64 GetData64(uint32 uiData) + { + switch (uiData) + { + case DATA_ARCHAVON: + return m_uiArchavonGUID; + case DATA_EMALON: + return m_uiEmalonGUID; + case DATA_KORALON: + return m_uiKoralonGUID; + case DATA_TEMPEST_MINION_1: + return m_uiTempestMinion1GUID; + case DATA_TEMPEST_MINION_2: + return m_uiTempestMinion2GUID; + case DATA_TEMPEST_MINION_3: + return m_uiTempestMinion3GUID; + case DATA_TEMPEST_MINION_4: + return m_uiTempestMinion4GUID; + } + return 0; + } + const char* Save() + { + return strInstData.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] >> 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; + } + + bool IsEncounterInProgress() const + { + for (uint8 i = 0; i < MAX_ENCOUNTER; ++i) + if (m_auiEncounter[i] == IN_PROGRESS) + return true; + return false; + } +}; + +InstanceData* GetInstanceData_instance_vault_of_archavon(Map* pMap) +{ + return new instance_vault_of_archavon(pMap); +} + +void AddSC_instance_vault_of_archavon() +{ + Script *newscript; + newscript = new Script; + newscript->Name = "instance_vault_of_archavon"; + newscript->GetInstanceData = &GetInstanceData_instance_vault_of_archavon; + newscript->RegisterSelf(); +} diff --git a/scripts/northrend/vault_of_archavon/vault_of_archavon.h b/scripts/northrend/vault_of_archavon/vault_of_archavon.h new file mode 100644 index 0000000..3267282 --- /dev/null +++ b/scripts/northrend/vault_of_archavon/vault_of_archavon.h @@ -0,0 +1,31 @@ +/* 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_VAULT_OF_ARCHAVON_H +#define DEF_VAULT_OF_ARCHAVON_H + +enum +{ + MAX_ENCOUNTER = 4, + + DATA_ARCHAVON = 1, + DATA_EMALON = 2, + DATA_KORALON = 3, + DATA_TEMPEST_MINION_1 = 4, + DATA_TEMPEST_MINION_2 = 5, + DATA_TEMPEST_MINION_3 = 6, + DATA_TEMPEST_MINION_4 = 7, + + TYPE_ARCHAVON = 8, + TYPE_EMALON = 9, + TYPE_KORALON = 10, + TYPE_TORAVON = 11, + + NPC_ARCHAVON = 31125, + NPC_EMALON = 33993, + NPC_KORALON = 35013, + NPC_TEMPEST_MINION = 33998 +}; + +#endif diff --git a/scripts/northrend/violet_hold/def_violet_hold.h b/scripts/northrend/violet_hold/def_violet_hold.h new file mode 100644 index 0000000..1ba5264 --- /dev/null +++ b/scripts/northrend/violet_hold/def_violet_hold.h @@ -0,0 +1,195 @@ +/* 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_VIOLET_HOLD_H +#define DEF_VIOLET_HOLD_H + +enum +{ + MAX_ENCOUNTER = 11, + + TYPE_EVENT = 0, + TYPE_RIFT = 1, + TYPE_EREKEM = 2, + TYPE_MORAGG = 3, + TYPE_ICHORON = 4, + TYPE_XEVOZZ = 5, + TYPE_LAVANTHOR = 6, + TYPE_ZURAMAT = 7, + TYPE_CYANIGOSA = 8, + TYPE_PORTAL6 = 9, + TYPE_PORTAL12 = 10, + + + WORLD_STATE_VH = 3816, + WORLD_STATE_VH_PRISON = 3815, + WORLD_STATE_VH_PORTALS = 3810, + + TYPE_LASTBOSS = 19, + TYPE_DOOR = 21, + TYPE_PORTAL_TIME = 22, + + TYPE_DISRUPTIONS = 101, + TYPE_LASTBOSS_ID = 102, + + DATA_EREKEM = 23, + DATA_MORAGG = 24, + DATA_ICHORON = 25, + DATA_XEVOZZ = 26, + DATA_LAVANTHOR = 27, + DATA_ZURAMAT = 28, + DATA_SINCLARI = 29, + DATA_BOSSTIME = 30, + DATA_NPC_SEAL_DOOR = 31, + + DATA_SEAL_DOOR = 32, + DATA_EREKEM_DOOR = 33, + DATA_MORAGG_DOOR = 34, + DATA_ICHORON_DOOR = 35, + DATA_XEVOZZ_DOOR = 36, + DATA_LAVANTHOR_DOOR = 37, + DATA_ZURAMAT_DOOR = 38, + DATA_EREKEM_DOOR_L = 39, + DATA_EREKEM_DOOR_R = 40, + + NPC_EREKEM = 29315, + NPC_EREKEM_GUARD = 29395, + NPC_MORAGG = 29316, + NPC_ICHORON = 29313, + NPC_XEVOZZ = 29266, + NPC_LAVANTHOR = 29312, + NPC_ZURAMAT = 29314, + NPC_CYANIGOSA = 31134, + + NPC_AZURE_SABOTEUR = 31079, // Open boss's cell + + NPC_AZURE_CAPTAIN = 30666, //Melee, 40k - 60k hp, 3 for 1-11, 4 for 13-17 + NPC_AZURE_RAIDER = 30668, //Melee, 40k - 60k hp + NPC_AZURE_SORCEROR = 30667, //Caster, 40k - 60k hp + NPC_AZURE_STALKER = 32191, //Melee, 40k - 60k hp + NPC_GUARDIAN = 30660, + NPC_KEEPER = 30695, + NPC_AZURE_BINDER = 30663, //Caster, 7k - 10k hp + NPC_AZURE_INVADER = 30661, //Melee, 8k - 12k hp + NPC_AZURE_MAGE_SLAYER = 30664, //Melee, 10k - 15k hp + NPC_AZURE_SPELLBREAKER = 30662, //Caster, 10k - 15k hp + + NPC_SINCLARI = 30658, + NPC_GUARD = 30659, + NPC_PORTAL = 31011, + NPC_DOOR_SEAL = 30896, + + GO_DOOR_SEAL = 191723, + GO_DOOR_EREKEM = 191564, + GO_DOOR_EREKEM_RIGHT = 191563, + GO_DOOR_EREKEM_LEFT = 191562, + GO_DOOR_MORAGG = 191606, + GO_DOOR_ICHORON = 191722, + GO_DOOR_XEVOZZ = 191556, + GO_DOOR_LAVANTHOR = 191566, + GO_DOOR_ZURAMAT = 191565, + + SPELL_PORTAL_CHANNEL = 58012, + SPELL_CORRUPT = 58040, + + EMOTE_GUARDIAN_PORTAL = -1608005, + EMOTE_DRAGONFLIGHT_PORTAL = -1608006, + EMOTE_KEEPER_PORTAL = -1608007 +}; + +struct Locations +{ + float x, y, z; + uint32 id; +}; + +struct WayPoints +{ + WayPoints(uint32 _id, float _x, float _y, float _z) + { + id = _id; + x = _x; + y = _y; + z = _z; + } + uint32 id; + float x, y, z; +}; + +static Locations SinclariWP[]= +{ + {1830.5f, 799.357f, 44.3418f}, // 0 use activation + {1832.46f, 800.431f, 44.3117f}, // 1 SAY_BEGIN call back guards + {1824.79f, 803.828f, 44.3634f}, // 2 SAY_LOCK_DOOR close door + {1807.25f, 803.904f, 44.3634f}, // 3 + {1808.07f, 804.259f, 44.3641f}, // 4 + +}; + +static Locations PortalLoc[]= +{ + {1888.271f, 810.781f, 38.441f}, // 0 center + {1857.125f, 763.295f, 38.654f}, // 1 Lavanthor + {1925.480f, 849.981f, 47.174f}, // 2 Zuramat + {1892.737f, 744.589f, 47.666f}, // 3 Moragg + {1878.198f, 850.005f, 43.333f}, // 4 Portal in front of Erekem + {1909.381f, 806.796f, 38.645f}, // 5 Portal outside of Ichoron + {1936.101f, 802.950f, 52.417f}, // 6 at the highest platform +}; + +static Locations BossLoc[]= +{ + {0,0,0}, + {0,0,0}, + {1876.100f, 857.079f, 43.333f}, // Erekem + {1892.737f, 744.589f, 47.666f}, // Moragg + {1908.863f, 785.647f, 37.435f}, // Ichoron + {1905.364f, 840.607f, 38.670f}, // Xevozz + {1857.125f, 763.295f, 38.654f}, // Lavanthor + {1925.480f, 849.981f, 47.174f}, // Zuramat +}; + +static Locations DragonsWP[]= +{ + //center, ichoron + {1869.393f, 803.902f, 38.768f}, // 0 + {1859.843f, 804.222f, 44.008f}, // 1 + {1829.64f, 804.194f, 44.355f}, // 2 + + //From left side (lavanthor) + {1861.016f, 789.717f, 38.908f}, // 3 + {1856.217f, 796.705f, 44.008f}, // 4 + {1829.64f, 804.194f, 44.355f}, // 5 + + //From Zuramat + {1931.446f, 826.734f, 47.556f}, // 6 + {1913.049f, 823.930f, 38.792f}, // 7 + {1827.960f, 804.208f, 44.364f}, // 8 + {1869.393f, 803.902f, 38.768f}, // 9 + {1859.843f, 804.222f, 44.008f}, // 10 + {1829.64f, 804.194f, 44.355f}, // 11 + + //From Morag + {1887.500f, 763.096f, 47.666f}, // 12 + {1880.837f, 775.769f, 38.796f}, // 13 + {1861.016f, 789.717f, 38.908f}, // 14 + {1856.217f, 796.705f, 44.008f}, // 15 + {1829.64f, 804.194f, 44.355f}, // 16 + + //From erekem + {1878.280f, 843.267f, 43.333f}, // 17 + {1872.311f, 835.531f, 38.780f}, // 18 + {1861.997f, 818.766f, 38.650f}, // 19 + {1857.348f, 811.230f, 44.008f}, // 20 + {1829.64f, 804.194f, 44.355f}, // 21 + + //From Highest platform + {1937.298f, 824.557f, 52.332f}, // 22 + {1913.049f, 823.930f, 38.792f}, // 23 + {1869.393f, 803.902f, 38.768f}, // 24 + {1859.843f, 804.222f, 44.008f}, // 25 + {1829.64f, 804.194f, 44.355f}, // 26 +}; + +#endif diff --git a/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak.cpp b/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak.cpp new file mode 100644 index 0000000..c7c32a2 --- /dev/null +++ b/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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_shirrak +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Auchindoun, Auchenai Crypts +EndScriptData */ + +#include "precompiled.h" + +void AddSC_boss_shirrak() +{ +} \ No newline at end of file diff --git a/scripts/outland/auchindoun/sethekk_halls/boss_anzu.cpp b/scripts/outland/auchindoun/sethekk_halls/boss_anzu.cpp new file mode 100644 index 0000000..bc59c27 --- /dev/null +++ b/scripts/outland/auchindoun/sethekk_halls/boss_anzu.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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_anzu +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Auchindoun, Sethekk Halls +EndScriptData */ + +#include "precompiled.h" + +void AddSC_boss_anzu() +{ +} diff --git a/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp b/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp index 5d331ad..e22a3a4 100644 --- a/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp +++ b/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp @@ -110,6 +110,9 @@ struct MANGOS_DLL_DECL boss_talon_king_ikissAI : public ScriptedAI case 1: DoScriptText(SAY_AGGRO_2, m_creature); break; case 2: DoScriptText(SAY_AGGRO_3, m_creature); break; } + + if (m_pInstance) + m_pInstance->SetData(TYPE_IKISS, IN_PROGRESS); } void JustDied(Unit* Killer) @@ -117,7 +120,13 @@ struct MANGOS_DLL_DECL boss_talon_king_ikissAI : public ScriptedAI DoScriptText(SAY_DEATH, m_creature); if (m_pInstance) - m_pInstance->SetData(DATA_IKISSDOOREVENT, DONE); + m_pInstance->SetData(TYPE_IKISS, DONE); + } + + void JustReachedHome() + { + if (m_pInstance) + m_pInstance->SetData(TYPE_IKISS, FAIL); } void KilledUnit(Unit* victim) @@ -184,8 +193,7 @@ struct MANGOS_DLL_DECL boss_talon_king_ikissAI : public ScriptedAI float Y = target->GetPositionY(); float Z = target->GetPositionZ(); - m_creature->GetMap()->CreatureRelocation(m_creature,X,Y,Z,0.0f); - m_creature->SendMonsterMove(X, Y, Z, SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, 1); + m_creature->MonsterMove(X, Y, Z, 1); DoCastSpellIfCan(target,SPELL_BLINK_TELEPORT); Blink = true; diff --git a/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp b/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp index 2a2d65b..e1f2110 100644 --- a/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp +++ b/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp @@ -24,36 +24,98 @@ EndScriptData */ #include "precompiled.h" #include "sethekk_halls.h" -#define IKISS_DOOR 177203 +instance_sethekk_halls::instance_sethekk_halls(Map* pMap) : ScriptedInstance(pMap), + m_uiIkissDoorGUID(0) +{ + Initialize(); +} +void instance_sethekk_halls::Initialize() +{ + memset(&m_auiEncounter, 0, sizeof(m_auiEncounter)); +} -struct MANGOS_DLL_DECL instance_sethekk_halls : public ScriptedInstance +void instance_sethekk_halls::OnObjectCreate(GameObject* pGo) { - instance_sethekk_halls(Map* pMap) : ScriptedInstance(pMap) {Initialize();}; + if (pGo->GetEntry() == GO_IKISS_DOOR) + { + m_uiIkissDoorGUID = pGo->GetGUID(); + if (m_auiEncounter[TYPE_IKISS] == DONE) + pGo->SetGoState(GO_STATE_ACTIVE); + } +} - uint64 m_uiIkissDoorGUID; +void instance_sethekk_halls::SetData(uint32 uiType, uint32 uiData) +{ + switch(uiType) + { + case TYPE_SYTH: + case TYPE_ANZU: + m_auiEncounter[uiType] = uiData; + break; + case TYPE_IKISS: + if (uiData == DONE) + DoUseDoorOrButton(m_uiIkissDoorGUID, DAY*IN_MILLISECONDS); + m_auiEncounter[uiType] = uiData; + break; + default: + return; + } - void Initialize() + if (uiData == DONE) { - m_uiIkissDoorGUID = 0; + OUT_SAVE_INST_DATA; + + std::ostringstream saveStream; + saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2]; + + m_strInstData = saveStream.str(); + + SaveToDB(); + OUT_SAVE_INST_DATA_COMPLETE; } +} - void OnObjectCreate(GameObject* pGo) +uint32 instance_sethekk_halls::GetData(uint32 uiType) +{ + if (uiType < MAX_ENCOUNTER) + return m_auiEncounter[uiType]; + + return 0; +} + +void instance_sethekk_halls::Load(const char* chrIn) +{ + if (!chrIn) { - if (pGo->GetEntry() == IKISS_DOOR) - m_uiIkissDoorGUID = pGo->GetGUID(); + OUT_LOAD_INST_DATA_FAIL; + return; } - void SetData(uint32 uiType, uint32 uiData) + OUT_LOAD_INST_DATA(chrIn); + + std::istringstream loadStream(chrIn); + loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2]; + + for(uint8 i = 0; i < MAX_ENCOUNTER; ++i) { - switch(uiType) - { - case DATA_IKISSDOOREVENT: - if (uiData == DONE) - DoUseDoorOrButton(m_uiIkissDoorGUID,DAY*IN_MILLISECONDS); - break; - } + if (m_auiEncounter[i] == IN_PROGRESS) + m_auiEncounter[i] = NOT_STARTED; } -}; + + OUT_LOAD_INST_DATA_COMPLETE; +} + +bool instance_sethekk_halls::CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/) +{ + if (uiCriteriaId != ACHIEV_CRITA_TURKEY_TIME) + return false; + + if (!pSource) + return false; + + return pSource->HasItemOrGemWithIdEquipped(ITEM_PILGRIMS_HAT, 1) && (pSource->HasItemOrGemWithIdEquipped(ITEM_PILGRIMS_DRESS, 1) + || pSource->HasItemOrGemWithIdEquipped(ITEM_PILGRIMS_ROBE, 1) || pSource->HasItemOrGemWithIdEquipped(ITEM_PILGRIMS_ATTIRE, 1)); +} InstanceData* GetInstanceData_instance_sethekk_halls(Map* pMap) { @@ -62,9 +124,10 @@ InstanceData* GetInstanceData_instance_sethekk_halls(Map* pMap) void AddSC_instance_sethekk_halls() { - Script *newscript; - newscript = new Script; - newscript->Name = "instance_sethekk_halls"; - newscript->GetInstanceData = &GetInstanceData_instance_sethekk_halls; - newscript->RegisterSelf(); + Script* pNewScript; + + pNewScript = new Script; + pNewScript->Name = "instance_sethekk_halls"; + pNewScript->GetInstanceData = &GetInstanceData_instance_sethekk_halls; + pNewScript->RegisterSelf(); } diff --git a/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h b/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h index e51ce8b..7cd8b8a 100644 --- a/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h +++ b/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h @@ -5,5 +5,45 @@ #ifndef DEF_SETHEKK_HALLS_H #define DEF_SETHEKK_HALLS_H -#define DATA_IKISSDOOREVENT 1 +enum +{ + MAX_ENCOUNTER = 3, + + TYPE_SYTH = 0, + TYPE_ANZU = 1, + TYPE_IKISS = 2, + + GO_IKISS_DOOR = 177203, + + ACHIEV_CRITA_TURKEY_TIME = 11142, + ITEM_PILGRIMS_HAT = 46723, + ITEM_PILGRIMS_DRESS = 44785, + ITEM_PILGRIMS_ROBE = 46824, + ITEM_PILGRIMS_ATTIRE = 46800, +}; + +class MANGOS_DLL_DECL instance_sethekk_halls : public ScriptedInstance +{ + public: + instance_sethekk_halls(Map* pMap); + ~instance_sethekk_halls() {} + + void Initialize(); + void OnObjectCreate(GameObject* pGo); + + void SetData(uint32 uiType, uint32 uiData); + uint32 GetData(uint32 uiType); + + bool CheckAchievementCriteriaMeet(uint32 uiCriteriaId, Player const* pSource, Unit const* pTarget, uint32 uiMiscValue1 /* = 0*/); + + const char* Save() { return m_strInstData.c_str(); } + void Load(const char* chrIn); + + private: + uint32 m_auiEncounter[MAX_ENCOUNTER]; + std::string m_strInstData; + + uint64 m_uiIkissDoorGUID; +}; + #endif diff --git a/scripts/outland/black_temple/boss_supremus.cpp b/scripts/outland/black_temple/boss_supremus.cpp index 64ee18c..ed2c694 100644 --- a/scripts/outland/black_temple/boss_supremus.cpp +++ b/scripts/outland/black_temple/boss_supremus.cpp @@ -120,7 +120,7 @@ struct MANGOS_DLL_DECL npc_volcanoAI : public ScriptedAI CheckTimer = 1000; SupremusGUID = 0; FireballTimer = 500; - GeyserTimer = 0; + GeyserTimer = 2000; } void AttackStart(Unit* who) {} diff --git a/scripts/outland/boss_doomlord_kazzak.cpp b/scripts/outland/boss_doomlord_kazzak.cpp index cdea9a4..0bb1edf 100644 --- a/scripts/outland/boss_doomlord_kazzak.cpp +++ b/scripts/outland/boss_doomlord_kazzak.cpp @@ -140,11 +140,12 @@ struct MANGOS_DLL_DECL boss_doomlordkazzakAI : public ScriptedAI if (MarkOfKazzak_Timer < diff) { Unit* victim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); - if (victim->GetPower(POWER_MANA)) - { - DoCastSpellIfCan(victim, SPELL_MARKOFKAZZAK); - MarkOfKazzak_Timer = 20000; - } + if (victim) + if (victim->GetPower(POWER_MANA)) + { + DoCastSpellIfCan(victim, SPELL_MARKOFKAZZAK); + MarkOfKazzak_Timer = 20000; + } }else MarkOfKazzak_Timer -= diff; //Enrage_Timer diff --git a/scripts/outland/coilfang_reservoir/serpent_shrine/boss_the_lurker_below.cpp b/scripts/outland/coilfang_reservoir/serpent_shrine/boss_the_lurker_below.cpp index 2618f7e..430e343 100644 --- a/scripts/outland/coilfang_reservoir/serpent_shrine/boss_the_lurker_below.cpp +++ b/scripts/outland/coilfang_reservoir/serpent_shrine/boss_the_lurker_below.cpp @@ -31,6 +31,7 @@ enum SPELL_GEYSER = 37478, SPELL_SPOUT = 37433, // TODO should sweep the room 360degrees, related spells 37429 37430 37431 SPELL_WATERBOLT = 37138, // TODO is used when no enemy in melee range (unknown if on random or top-most aggro holder in this case + ACHIEVEMENT_LURKER = 144, }; enum Phases @@ -42,6 +43,7 @@ enum Phases }; // TODO This boss should infact be a Scripted_NoMovementAI, but selecting only melee targets is not supported yet, change when implemented + struct MANGOS_DLL_DECL boss_the_lurker_belowAI : public ScriptedAI { boss_the_lurker_belowAI(Creature* pCreature) : ScriptedAI(pCreature) @@ -128,6 +130,7 @@ bool GOHello_go_strange_pool(Player* pPlayer, GameObject* pGo) if (pInstance->GetData(TYPE_THELURKER_EVENT) == NOT_STARTED) { pPlayer->CastSpell(pPlayer, SPELL_LURKER_SPAWN_TRIGGER, true); + pPlayer->CompletedAchievement(ACHIEVEMENT_LURKER); pInstance->SetData(TYPE_THELURKER_EVENT, IN_PROGRESS); return true; } diff --git a/scripts/outland/coilfang_reservoir/slave_pens/boss_ahune.cpp b/scripts/outland/coilfang_reservoir/slave_pens/boss_ahune.cpp new file mode 100644 index 0000000..d95b51f --- /dev/null +++ b/scripts/outland/coilfang_reservoir/slave_pens/boss_ahune.cpp @@ -0,0 +1,28 @@ +/* Copyright (C) 2006 - 2010 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_ahune +SD%Complete: 0 +SDComment: Placeholder +SDCategory: Slave Pens +EndScriptData */ + +#include "precompiled.h" + +void AddSC_boss_ahune() +{ +} diff --git a/scripts/outland/gruuls_lair/boss_gruul.cpp b/scripts/outland/gruuls_lair/boss_gruul.cpp index 3c9b648..0928527 100644 --- a/scripts/outland/gruuls_lair/boss_gruul.cpp +++ b/scripts/outland/gruuls_lair/boss_gruul.cpp @@ -197,7 +197,7 @@ struct MANGOS_DLL_DECL boss_gruulAI : public ScriptedAI if (m_uiHurtfulStrike_Timer < uiDiff) { // Find 2nd-aggro target within melee range. - Unit *pTarget = NULL; + Unit* pTarget = NULL; ThreatList const& tList = m_creature->getThreatManager().getThreatList(); ThreatList::const_iterator itr = tList.begin(); std::advance(itr, 1); @@ -206,7 +206,7 @@ struct MANGOS_DLL_DECL boss_gruulAI : public ScriptedAI pTarget = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()); // exclude pets, totems & player out of melee range - if (pTarget->GetTypeId() != TYPEID_PLAYER || !pTarget->IsWithinDist(m_creature, ATTACK_DISTANCE, false)) + if (!pTarget || pTarget->GetTypeId() != TYPEID_PLAYER || !pTarget->IsWithinDist(m_creature, ATTACK_DISTANCE, false)) { pTarget = NULL; continue; diff --git a/scripts/world/boss_lethon.cpp b/scripts/world/boss_lethon.cpp index 623a4ac..a46d917 100644 --- a/scripts/world/boss_lethon.cpp +++ b/scripts/world/boss_lethon.cpp @@ -22,3 +22,7 @@ SDCategory: Bosses EndScriptData */ #include "precompiled.h" + +void AddSC_boss_lethon() +{ +} diff --git a/scripts/world/go_scripts.cpp b/scripts/world/go_scripts.cpp index a06958f..a4ba5e8 100644 --- a/scripts/world/go_scripts.cpp +++ b/scripts/world/go_scripts.cpp @@ -17,7 +17,7 @@ /* ScriptData SDName: GO_Scripts SD%Complete: 100 -SDComment: Quest support: 4285,4287,4288(crystal pylons), 4296, 5088, 5097, 5098, 6481, 10990, 10991, 10992, 14092/14076. Field_Repair_Bot->Teaches spell 22704. Barov_journal->Teaches spell 26089 +SDComment: Quest support: 4285,4287,4288(crystal pylons), 4296, 5088, 5097, 5098, 6481, 10990, 10991, 10992, 12557, 14092/14076. Field_Repair_Bot->Teaches spell 22704. Barov_journal->Teaches spell 26089 SDCategory: Game Objects EndScriptData */ @@ -41,6 +41,7 @@ go_tele_to_dalaran_crystal go_tele_to_violet_stand go_andorhal_tower go_scourge_enclosure +go_lab_work_reagents EndContentData */ #include "precompiled.h" @@ -537,6 +538,45 @@ bool GOHello_go_scourge_enclosure(Player* pPlayer, GameObject* pGo) return true; } +/*###### +## go_lab_work_reagents +######*/ + +enum +{ + QUEST_LAB_WORK = 12557, + + SPELL_WIRHERED_BATWING_KILL_CREDIT = 51226, + SPELL_MUDDY_MIRE_MAGGOT_KILL_CREDIT = 51227, + SPELL_AMBERSEED_KILL_CREDIT = 51228, + SPELL_CHILLED_SERPENT_MUCUS_KILL_CREDIT = 51229, + + GO_AMBERSEED = 190459, + GO_CHILLED_SERPENT_MUCUS = 190462, + GO_WITHERED_BATWING = 190473, + GO_MUDDY_MIRE_MAGGOTS = 190478, +}; + +bool GOHello_go_lab_work_reagents(Player* pPlayer, GameObject* pGo) +{ + if (pPlayer->GetQuestStatus(QUEST_LAB_WORK) == QUEST_STATUS_INCOMPLETE) + { + uint32 uiCreditSpellId = 0; + switch (pGo->GetEntry()) + { + case GO_AMBERSEED: uiCreditSpellId = SPELL_AMBERSEED_KILL_CREDIT; break; + case GO_CHILLED_SERPENT_MUCUS: uiCreditSpellId = SPELL_CHILLED_SERPENT_MUCUS_KILL_CREDIT; break; + case GO_WITHERED_BATWING: uiCreditSpellId = SPELL_WIRHERED_BATWING_KILL_CREDIT; break; + case GO_MUDDY_MIRE_MAGGOTS: uiCreditSpellId = SPELL_MUDDY_MIRE_MAGGOT_KILL_CREDIT; break; + } + + if (uiCreditSpellId) + pPlayer->CastSpell(pPlayer, uiCreditSpellId, true); + } + + return false; +} + void AddSC_go_scripts() { Script* pNewScript; @@ -650,4 +690,10 @@ void AddSC_go_scripts() pNewScript->Name = "go_scourge_enclosure"; pNewScript->pGOHello = &GOHello_go_scourge_enclosure; pNewScript->RegisterSelf(); + + pNewScript = new Script; + pNewScript->Name = "go_lab_work_reagents"; + pNewScript->pGOHello = &GOHello_go_lab_work_reagents; + pNewScript->RegisterSelf(); + } diff --git a/scripts/world/npcs_special.cpp b/scripts/world/npcs_special.cpp index 926eea9..7962348 100644 --- a/scripts/world/npcs_special.cpp +++ b/scripts/world/npcs_special.cpp @@ -43,6 +43,7 @@ npc_rogue_trainer 80% Scripted trainers, so they are able to offer ite npc_sayge 100% Darkmoon event fortune teller, buff player based on answers given npc_tabard_vendor 50% allow recovering quest related tabards, achievement related ones need core support npc_locksmith 75% list of keys needs to be confirmed +npc_death_knight_gargoyle AI for summoned gargoyle of deathknights EndContentData */ /*######## @@ -1750,6 +1751,448 @@ bool GossipSelect_npc_locksmith(Player* pPlayer, Creature* pCreature, uint32 uiS return true; } +/*###### +## npc_mirror_image +######*/ + +enum MirrorImageSpells +{ + SPELL_CLONE_CASTER = 45204, + SPELL_CLONE_CASTER_1 = 69837, +// SPELL_CLONE_CASTER_1 = 58836, + SPELL_CLONE_THREAT = 58838, + SPELL_FIREBLAST = 59637, + SPELL_FROSTBOLT = 59638, + SPELL_FROSTSHIELD = 43008, + SPELL_FIRESHIELD = 43046, + SPELL_ICEBLOCK = 65802, + SPELL_ICERING = 42917, +}; + +struct MANGOS_DLL_DECL npc_mirror_imageAI : public ScriptedAI +{ + npc_mirror_imageAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + uint32 m_uiFrostboltTimer; + uint32 m_uiFrostringTimer; + uint32 m_uiFireblastTimer; + bool inCombat; + Unit *owner; + float angle; + bool blocked; + bool movement; + + void Reset() + { + owner = m_creature->GetOwner(); + if (!owner) + return; + + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_2,owner->GetUInt32Value(UNIT_FIELD_BYTES_2)); + m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + m_creature->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, DEFAULT_WORLD_OBJECT_SIZE); + m_creature->SetFloatValue(UNIT_FIELD_COMBATREACH, 1.5f); + + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, owner->GetUInt32Value(PLAYER_VISIBLE_ITEM_16_ENTRYID)); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, owner->GetUInt32Value(PLAYER_VISIBLE_ITEM_17_ENTRYID)); + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+2, owner->GetUInt32Value(PLAYER_VISIBLE_ITEM_18_ENTRYID)); + m_creature->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN), true); + + m_uiFrostboltTimer = urand(0,3000); + m_uiFrostringTimer = urand(2000,6000); + m_uiFireblastTimer = urand(0,3000); + inCombat = false; + blocked = false; + movement = false; + + + if (owner && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) + { + angle = m_creature->GetAngle(owner); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST + 3.0f, angle); + } + + if(owner->IsPvP()) + m_creature->SetPvP(true); + if(owner->IsFFAPvP()) + m_creature->SetFFAPvP(true); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) return; + + if (m_creature->Attack(pWho, true)) + { + if (owner) + m_creature->CastSpell(m_creature, SPELL_CLONE_THREAT, true, NULL, NULL, owner->GetGUID()); + m_creature->clearUnitState(UNIT_STAT_FOLLOW); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 100.0f); + DoStartMovement(pWho, 30.0f); + SetCombatMovement(true); + inCombat = true; + } + } + + void EnterEvadeMode() + { + if (m_creature->IsInEvadeMode() || !m_creature->isAlive()) + return; + + inCombat = false; + + m_creature->AttackStop(); + m_creature->CombatStop(true); + if (owner && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) + { + angle = m_creature->GetAngle(owner); + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST + 3.0f,angle); + } + } + + void UpdateAI(const uint32 diff) + { + if (!owner || !owner->isAlive()) + m_creature->ForcedDespawn(); + + if (owner && !m_creature->HasAura(SPELL_CLONE_CASTER)) + m_creature->CastSpell(m_creature, SPELL_CLONE_CASTER, true, NULL, NULL, owner->GetGUID()); + + if (owner && !m_creature->HasAura(SPELL_CLONE_CASTER_1)) + m_creature->CastSpell(m_creature, SPELL_CLONE_CASTER_1, true, NULL, NULL, owner->GetGUID()); + + if (owner && owner->HasAura(SPELL_FROSTSHIELD) && !m_creature->HasAura(SPELL_FROSTSHIELD)) + m_creature->CastSpell(m_creature, SPELL_FROSTSHIELD, false); + + if (owner && owner->HasAura(SPELL_FIRESHIELD) && !m_creature->HasAura(SPELL_FIRESHIELD)) + m_creature->CastSpell(m_creature, SPELL_FIRESHIELD, false); + + if (!m_creature->getVictim()) + if (owner && owner->getVictim()) + AttackStart(owner->getVictim()); + + if (m_creature->getVictim() && m_creature->getVictim() != owner->getVictim()) + AttackStart(owner->getVictim()); + + if (inCombat && !m_creature->getVictim()) + { + EnterEvadeMode(); + return; + } + + if (!inCombat) + return; + + if (m_creature->IsWithinDistInMap(m_creature->getVictim(),30.0f)) + { + movement = false; + if (m_uiFrostboltTimer <= diff) + { + DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROSTBOLT); + m_uiFrostboltTimer = urand(1000,6000); + } else m_uiFrostboltTimer -= diff; + + if (m_uiFireblastTimer <= diff) + { + DoCastSpellIfCan(m_creature->getVictim(),SPELL_FIREBLAST); + m_uiFireblastTimer = urand(1000,6000); + } else m_uiFireblastTimer -= diff; + + if (m_uiFrostringTimer <= diff && m_creature->IsWithinDistInMap(m_creature->getVictim(),5.0f)) + { + DoCastSpellIfCan(m_creature->getVictim(),SPELL_ICERING); + m_uiFrostringTimer = urand(4000,8000); + } else m_uiFrostringTimer -= diff; + + if (!blocked && m_creature->GetHealthPercent() < 10.0f) + { + DoCastSpellIfCan(m_creature,SPELL_ICEBLOCK); + blocked = true; + } + } + else + if (!movement) + { + DoStartMovement(m_creature->getVictim(), 20.0f); + movement = true; + } + +// DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_mirror_image(Creature* pCreature) +{ + return new npc_mirror_imageAI(pCreature); +}; + +/*#### + ## npc_snake_trap_serpents - Summonned snake id are 19921 and 19833 + ####*/ + +#define SPELL_MIND_NUMBING_POISON 25810 //Viper +#define SPELL_CRIPPLING_POISON 30981 //Viper +#define SPELL_DEADLY_POISON 34655 //Venomous Snake + +#define MOB_VIPER 19921 +#define MOB_VENOM_SNIKE 19833 + +struct MANGOS_DLL_DECL npc_snake_trap_serpentsAI : public ScriptedAI +{ + npc_snake_trap_serpentsAI(Creature *c) : ScriptedAI(c) {Reset();} + + uint32 SpellTimer; + Unit* Owner; + + void Reset() + { + SpellTimer = 500; + Owner = m_creature->GetCharmerOrOwner(); + if (!Owner) return; + + m_creature->SetLevel(Owner->getLevel()); + m_creature->setFaction(Owner->getFaction()); + } + + void AttackStart(Unit* pWho) + { + if (!pWho) return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->SetInCombatWith(pWho); + m_creature->AddThreat(pWho, 100.0f); + SetCombatMovement(true); + m_creature->GetMotionMaster()->MoveChase(pWho); + } + } + + void UpdateAI(const uint32 diff) + { + if (!m_creature->getVictim()) + { + if (Owner && Owner->getVictim()) + AttackStart(Owner->getVictim()); + return; + } + + if (SpellTimer <= diff) + { + if (m_creature->GetEntry() == MOB_VIPER ) //Viper - 19921 + { + if (!urand(0,2)) //33% chance to cast + { + uint32 spell; + if (urand(0,1)) + spell = SPELL_MIND_NUMBING_POISON; + else + spell = SPELL_CRIPPLING_POISON; + DoCast(m_creature->getVictim(), spell); + } + + SpellTimer = urand(3000, 5000); + } + else if (m_creature->GetEntry() == MOB_VENOM_SNIKE ) //Venomous Snake - 19833 + { + if (urand(0,1) == 0) //80% chance to cast + DoCast(m_creature->getVictim(), SPELL_DEADLY_POISON); + SpellTimer = urand(2500, 4500); + } + } + else SpellTimer -= diff; + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_snake_trap_serpents(Creature* pCreature) +{ + return new npc_snake_trap_serpentsAI(pCreature); +} + +struct MANGOS_DLL_DECL npc_rune_blade : public ScriptedAI +{ + npc_rune_blade(Creature* pCreature) : ScriptedAI(pCreature) {Reset();} + + Unit* owner; + + void Reset() + { + owner = m_creature->GetOwner(); + if (!owner || owner->GetTypeId() != TYPEID_PLAYER) + return; + + // Cannot be Selected or Attacked + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); + m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); + + m_creature->SetLevel(owner->getLevel()); + m_creature->setFaction(owner->getFaction()); + + // Add visible weapon + if (Item const * item = ((Player *)owner)->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND)) + m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, item->GetProto()->ItemId); + + // Add stats scaling + int32 damageDone=owner->CalculateDamage(BASE_ATTACK, true); // might be average damage instead ? + int32 meleeSpeed=owner->m_modAttackSpeedPct[BASE_ATTACK]; + m_creature->CastCustomSpell(m_creature, 51906, &damageDone, &meleeSpeed, NULL, true); + + // Visual Glow + m_creature->CastSpell(m_creature, 53160, true); + + SetCombatMovement(true); + } + + void UpdateAI(const uint32 diff) + { + if (!owner) return; + + if (!m_creature->getVictim()) + { + if (owner->getVictim()) + AttackStart(owner->getVictim()); + } + + DoMeleeAttackIfReady(); + } +}; + +CreatureAI* GetAI_npc_rune_blade(Creature* pCreature) +{ + return new npc_rune_blade(pCreature); +} +/*######## +# mob_death_knight_gargoyle AI +#########*/ + +// UPDATE `creature_template` SET `ScriptName` = 'mob_death_knight_gargoyle' WHERE `entry` = '27829'; + +enum GargoyleSpells +{ + SPELL_GARGOYLE_STRIKE = 51963 // Don't know if this is the correct spell, it does about 700-800 damage points +}; + +struct MANGOS_DLL_DECL npc_death_knight_gargoyle : public ScriptedAI +{ + npc_death_knight_gargoyle(Creature* pCreature) : ScriptedAI(pCreature) + { + Reset(); + } + uint32 m_uiGargoyleStrikeTimer; + bool inCombat; + Unit *owner; + + + void Reset() + { + owner = m_creature->GetOwner(); + if (!owner) return; + + m_creature->SetLevel(owner->getLevel()); + m_creature->setFaction(owner->getFaction()); + + m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE); + m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_0, 50331648); + m_creature->SetUInt32Value(UNIT_FIELD_BYTES_1, 50331648); + m_creature->AddSplineFlag(SPLINEFLAG_FLYING); + + inCombat = false; + m_uiGargoyleStrikeTimer = urand(3000, 5000); + + float fPosX, fPosY, fPosZ; + owner->GetPosition(fPosX, fPosY, fPosZ); + + m_creature->NearTeleportTo(fPosX, fPosY, fPosZ+10.0f, m_creature->GetAngle(owner)); + + + if (owner && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST + 3.0f, m_creature->GetAngle(owner)); + } + + if(owner->IsPvP()) + m_creature->SetPvP(true); + if(owner->IsFFAPvP()) + m_creature->SetFFAPvP(true); + } + + void EnterEvadeMode() + { + if (m_creature->IsInEvadeMode() || !m_creature->isAlive()) + return; + + inCombat = false; + + m_creature->AttackStop(); + m_creature->CombatStop(true); + if (owner && !m_creature->hasUnitState(UNIT_STAT_FOLLOW)) + { + m_creature->GetMotionMaster()->Clear(false); + m_creature->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST + 3.0f, m_creature->GetAngle(owner)); + } + } + + void AttackStart(Unit* pWho) + { + if (!pWho) return; + + if (m_creature->Attack(pWho, true)) + { + m_creature->clearUnitState(UNIT_STAT_FOLLOW); + m_creature->SetInCombatWith(pWho); + pWho->SetInCombatWith(m_creature); + m_creature->AddThreat(pWho, 100.0f); + DoStartMovement(pWho, 10.0f); + SetCombatMovement(true); + inCombat = true; + } + } + + void UpdateAI(const uint32 uiDiff) + { + + if (!owner || !owner->IsInWorld()) + { + m_creature->ForcedDespawn(); + return; + } + + if (!m_creature->getVictim()) + if (owner && owner->getVictim()) + AttackStart(owner->getVictim()); + + if (m_creature->getVictim() && m_creature->getVictim() != owner->getVictim()) + AttackStart(owner->getVictim()); + + if (inCombat && !m_creature->getVictim()) + { + EnterEvadeMode(); + return; + } + + if (!inCombat) return; + + if (m_uiGargoyleStrikeTimer <= uiDiff) + { + DoCastSpellIfCan(m_creature->getVictim(), SPELL_GARGOYLE_STRIKE); + m_uiGargoyleStrikeTimer = urand(3000, 5000); + } + else m_uiGargoyleStrikeTimer -= uiDiff; + } +}; + +CreatureAI* GetAI_npc_death_knight_gargoyle(Creature* pCreature) +{ + return new npc_death_knight_gargoyle(pCreature); +} /*###### ## npc_training_dummy ######*/ @@ -1897,6 +2340,21 @@ void AddSC_npcs_special() newscript->pGossipSelect = &GossipSelect_npc_locksmith; newscript->RegisterSelf(); + newscript = new Script; + newscript->Name = "npc_mirror_image"; + newscript->GetAI = &GetAI_npc_mirror_image; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_snake_trap_serpents"; + newscript->GetAI = &GetAI_npc_snake_trap_serpents; + newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_runeblade"; + newscript->GetAI = &GetAI_npc_rune_blade; + newscript->RegisterSelf(); + newscript = new Script; newscript->Name = "npc_training_dummy"; newscript->GetAI = &GetAI_npc_training_dummy; @@ -1906,4 +2364,9 @@ void AddSC_npcs_special() newscript->Name = "npc_lightwell"; newscript->pGossipHello = &GossipHello_npc_lightwell; newscript->RegisterSelf(); + + newscript = new Script; + newscript->Name = "npc_death_knight_gargoyle"; + newscript->GetAI = &GetAI_npc_death_knight_gargoyle; + newscript->RegisterSelf(); } diff --git a/sql/Updates/Makefile.am b/sql/Updates/Makefile.am index 384e2ba..cba782f 100644 --- a/sql/Updates/Makefile.am +++ b/sql/Updates/Makefile.am @@ -201,5 +201,8 @@ pkgdata_DATA = \ r1889_scriptdev2.sql \ r1890_mangos.sql \ r1890_scriptdev2.sql \ - r1891_mangos.sql - + r1891_mangos.sql \ + r1899_mangos.sql \ + r1899_scriptdev2.sql \ + r1908_scriptdev2.sql \ + r1913_mangos.sql diff --git a/sql/Updates/r1632_mangos.sql b/sql/Updates/r1632_mangos.sql index bc9112e..d493d2b 100644 --- a/sql/Updates/r1632_mangos.sql +++ b/sql/Updates/r1632_mangos.sql @@ -3,7 +3,7 @@ UPDATE creature_template SET ScriptName='boss_gormok' WHERE entry=34796; UPDATE creature_template SET ScriptName='boss_acidmaw' WHERE entry=35144; UPDATE creature_template SET ScriptName='boss_dreadscale' WHERE entry=34799; UPDATE creature_template SET ScriptName='boss_icehowl' WHERE entry=34797; -UPDATE creature_template SET ScriptName='boss_jaraxxis' WHERE entry=34780; +UPDATE creature_template SET ScriptName='boss_jaraxxus' WHERE entry=34780; UPDATE creature_template SET ScriptName='boss_anubarak_trial' WHERE entry=34564; UPDATE creature_template SET ScriptName='boss_fjola' WHERE entry=34497; UPDATE creature_template SET ScriptName='boss_eydis' WHERE entry=34496; diff --git a/sql/Updates/r1899_mangos.sql b/sql/Updates/r1899_mangos.sql new file mode 100644 index 0000000..6231b90 --- /dev/null +++ b/sql/Updates/r1899_mangos.sql @@ -0,0 +1 @@ +UPDATE creature_template SET ScriptName='npc_greer_orehammer' WHERE entry=23859; diff --git a/sql/Updates/r1899_scriptdev2.sql b/sql/Updates/r1899_scriptdev2.sql new file mode 100644 index 0000000..3ea1157 --- /dev/null +++ b/sql/Updates/r1899_scriptdev2.sql @@ -0,0 +1,5 @@ +DELETE FROM gossip_texts WHERE entry BETWEEN -3000108 AND -3000106; +INSERT INTO gossip_texts (entry,content_default,comment) VALUES +(-3000106,'Show me where I can fly.','greer orehammer GOSSIP_ITEM_TAXI'), +(-3000107,'[PH] Get Presicion Bombs','greer orehammer GOSSIP_ITEM_GET_BOMBS'), +(-3000108,'[PH] Start bombing mission','greer orehammer GOSSIP_ITEM_FLIGHT'); diff --git a/sql/Updates/r1908_scriptdev2.sql b/sql/Updates/r1908_scriptdev2.sql new file mode 100644 index 0000000..64e1cb1 --- /dev/null +++ b/sql/Updates/r1908_scriptdev2.sql @@ -0,0 +1,12 @@ +DELETE FROM script_texts WHERE entry BETWEEN -1554005 AND -1554000; +INSERT INTO script_texts (entry,content_default,sound,type,language,emote,comment) VALUES +(-1554000,'REUSE_ME',0,0,0,0,'REUSE_ME'), +(-1554001,'REUSE_ME',0,0,0,0,'REUSE_ME'), +(-1554002,'REUSE_ME',0,0,0,0,'REUSE_ME'), +(-1554003,'REUSE_ME',0,0,0,0,'REUSE_ME'), +(-1554004,'REUSE_ME',0,0,0,0,'REUSE_ME'), +(-1554005,'REUSE_ME',0,0,0,0,'REUSE_ME'); + +DELETE FROM gossip_texts WHERE entry=-3000102; +INSERT INTO gossip_texts (entry,content_default,comment) VALUES +(-3000102,'Pay up, Harry!','silvermoon harry GOSSIP_ITEM_PAYING'); diff --git a/sql/Updates/r1913_mangos.sql b/sql/Updates/r1913_mangos.sql new file mode 100644 index 0000000..cd04992 --- /dev/null +++ b/sql/Updates/r1913_mangos.sql @@ -0,0 +1 @@ +UPDATE gameobject_template SET ScriptName='go_lab_work_reagents' WHERE entry IN (190462, 190473, 190478, 190459); diff --git a/sql/mangos_scriptname_full.sql b/sql/mangos_scriptname_full.sql index bc614c9..359f264 100644 --- a/sql/mangos_scriptname_full.sql +++ b/sql/mangos_scriptname_full.sql @@ -79,6 +79,7 @@ UPDATE gameobject_template SET ScriptName='go_blood_filled_orb' WHERE entry=1820 UPDATE gameobject_template SET ScriptName='go_andorhal_tower' WHERE entry IN (176094,176095,176096,176097); UPDATE gameobject_template SET ScriptName='go_scourge_enclosure' WHERE entry=191548; UPDATE gameobject_template SET ScriptName='go_veil_skith_cage' WHERE entry IN (185202,185203,185204,185205); +UPDATE gameobject_template SET ScriptName='go_lab_work_reagents' WHERE entry IN (190462, 190473, 190478, 190459); /* GUARD */ UPDATE creature_template SET ScriptName='guard_azuremyst' WHERE entry=18038; @@ -655,6 +656,7 @@ UPDATE creature_template SET ScriptName='npc_rinji' WHERE entry=7780; UPDATE creature_template SET ScriptName='npc_daegarn' WHERE entry=24151; UPDATE creature_template SET ScriptName='npc_deathstalker_razael' WHERE entry=23998; UPDATE creature_template SET ScriptName='npc_dark_ranger_lyana' WHERE entry=23778; +UPDATE creature_template SET ScriptName='npc_greer_orehammer' WHERE entry=23859; UPDATE creature_template SET ScriptName='npc_mcgoyver' WHERE entry=24040; UPDATE creature_template SET ScriptName='npc_silvermoon_harry' WHERE entry=24539; diff --git a/sql/scriptdev2_script_full.sql b/sql/scriptdev2_script_full.sql index af7e088..adeb5f0 100644 --- a/sql/scriptdev2_script_full.sql +++ b/sql/scriptdev2_script_full.sql @@ -3354,10 +3354,13 @@ INSERT INTO gossip_texts (entry,content_default,comment) VALUES -- -3 000 100 GENERAL MAPS (not instance maps) INSERT INTO gossip_texts (entry,content_default,comment) VALUES (-3000101,'Taruk send me to collect what you owe.','silvermoon harry GOSSIP_ITEM_GAMBLING_DEBT'), -(-3000102,'Here\'s the money.','silvermoon harry GOSSIP_ITEM_PAYING'), +(-3000102,'Pay up, Harry!','silvermoon harry GOSSIP_ITEM_PAYING'), (-3000103,'I am ready to travel to you village now.','rainspeaker GOSSIP_ITEM_READY'), (-3000104,'','mosswalker victim GOSSIP_ITEM_PULSE'), -(-3000105,'Ezekiel said that you might have a certain book...','dirty larry GOSSIP_ITEM_BOOK'); +(-3000105,'Ezekiel said that you might have a certain book...','dirty larry GOSSIP_ITEM_BOOK'), +(-3000106,'Show me where I can fly.','greer orehammer GOSSIP_ITEM_TAXI'), +(-3000107,'[PH] Get Presicion Bombs','greer orehammer GOSSIP_ITEM_GET_BOMBS'), +(-3000108,'[PH] Start bombing mission','greer orehammer GOSSIP_ITEM_FLIGHT'); -- -3 090 000 GNOMEREGAN INSERT INTO gossip_texts (entry,content_default,comment) VALUES diff --git a/system/ScriptLoader.cpp b/system/ScriptLoader.cpp index c21bb0c..7ece369 100644 --- a/system/ScriptLoader.cpp +++ b/system/ScriptLoader.cpp @@ -11,6 +11,8 @@ extern void AddSC_battleground(); extern void AddSC_boss_pusillin(); extern void AddSC_instance_dire_maul(); extern void AddSC_custom_cybernetic(); +extern void AddSC_npc_arena_honor(); +extern void AddSC_mob_teleguy(); //examples extern void AddSC_example_creature(); @@ -214,8 +216,6 @@ extern void AddSC_boss_epoch_hunter(); extern void AddSC_boss_lieutenant_drake(); extern void AddSC_instance_old_hillsbrad(); extern void AddSC_old_hillsbrad(); -extern void AddSC_culling_of_stratholme(); //Culling of Stratholme -extern void AddSC_instance_culling_of_stratholme(); extern void AddSC_boss_celebras_the_cursed(); //maraudon extern void AddSC_boss_landslide(); extern void AddSC_boss_noxxion(); @@ -242,6 +242,17 @@ extern void AddSC_instance_wailing_caverns(); // Wailing Caverns extern void AddSC_zulfarrak(); //zulfarrak extern void AddSC_instance_zulfarrak(); +// culling of stratholme +extern void AddSC_boss_lord_epoch(); +extern void AddSC_boss_malganis(); +extern void AddSC_boss_meathook(); +extern void AddSC_boss_salramm(); +extern void AddSC_boss_infinite_corruptor(); +extern void AddSC_culling_of_stratholme(); +extern void AddSC_culling_of_stratholmeAI(); +extern void AddSC_instance_culling_of_stratholme(); +extern void AddSC_trash_culling_of_stratholme(); + extern void AddSC_ashenvale(); extern void AddSC_azshara(); extern void AddSC_azuremyst_isle(); @@ -266,23 +277,34 @@ extern void AddSC_ungoro_crater(); extern void AddSC_winterspring(); //northrend + +extern void AddSC_trial_of_the_champion(); //trial_of_the_champion +extern void AddSC_boss_argent_challenge(); +extern void AddSC_boss_black_knight(); +extern void AddSC_boss_grand_champions(); +extern void AddSC_instance_trial_of_the_champion(); + extern void AddSC_boss_jedoga(); //ahnkahet +extern void AddSC_boss_amanitar(); extern void AddSC_boss_nadox(); extern void AddSC_boss_taldaram(); extern void AddSC_boss_volazj(); -extern void AddSC_boss_amanitar(); extern void AddSC_instance_ahnkahet(); extern void AddSC_boss_anubarak(); //azjol-nerub extern void AddSC_boss_hadronox(); extern void AddSC_boss_krikthir(); extern void AddSC_instance_azjol_nerub(); -extern void AddSC_boss_anubarak_trial(); //trial_of_the_crusader + +extern void AddSC_northrend_beasts(); //Crusaders' Coliseum, trial_of_the_crusader extern void AddSC_boss_jaraxxus(); +extern void AddSC_boss_anubarak_trial(); +extern void AddSC_boss_faction_champions(); +extern void AddSC_twin_valkyr(); extern void AddSC_instance_trial_of_the_crusader(); -extern void AddSC_northrend_beasts(); extern void AddSC_trial_of_the_crusader(); -extern void AddSC_twin_valkyr(); + extern void AddSC_boss_novos(); //draktharon_keep +extern void AddSC_boss_dred(); extern void AddSC_boss_tharonja(); extern void AddSC_boss_trollgore(); extern void AddSC_instance_draktharon_keep(); @@ -292,20 +314,19 @@ extern void AddSC_boss_galdarah(); extern void AddSC_boss_moorabi(); extern void AddSC_boss_sladran(); extern void AddSC_instance_gundrak(); -extern void AddSC_boss_bronjahm(); // ICC, forge_of_souls -extern void AddSC_boss_devourer_of_souls(); -extern void AddSC_instance_forge_of_souls(); + extern void AddSC_boss_gafrost(); // ICC, pit_of_saron extern void AddSC_boss_krick_and_ick(); extern void AddSC_boss_tyrannus(); extern void AddSC_instance_pit_of_saron(); extern void AddSC_pit_of_saron(); + extern void AddSC_boss_anubrekhan(); //naxxramas extern void AddSC_boss_four_horsemen(); extern void AddSC_boss_faerlina(); +extern void AddSC_boss_grobbulus(); extern void AddSC_boss_gluth(); extern void AddSC_boss_gothik(); -extern void AddSC_boss_grobbulus(); extern void AddSC_boss_kelthuzad(); extern void AddSC_boss_loatheb(); extern void AddSC_boss_maexxna(); @@ -316,13 +337,27 @@ extern void AddSC_boss_razuvious(); extern void AddSC_boss_sapphiron(); extern void AddSC_boss_thaddius(); extern void AddSC_instance_naxxramas(); + extern void AddSC_boss_anomalus(); //nexus extern void AddSC_boss_keristrasza(); extern void AddSC_boss_ormorok(); extern void AddSC_boss_telestra(); extern void AddSC_instance_nexus(); + +extern void AddSC_oculus(); //Oculus +extern void AddSC_instance_oculus(); +extern void AddSC_boss_drakos(); +extern void AddSC_boss_varos(); +extern void AddSC_boss_urom(); +extern void AddSC_boss_eregos(); + extern void AddSC_boss_sartharion(); //obsidian_sanctum extern void AddSC_instance_obsidian_sanctum(); +extern void AddSC_instance_vault_of_archavon(); //vault_of_archavon +extern void AddSC_boss_toravon(); +extern void AddSC_boss_koralon(); +extern void AddSC_boss_emalon(); +extern void AddSC_boss_archavon(); extern void AddSC_boss_bjarngrim(); //Ulduar, halls_of_lightning extern void AddSC_boss_ionar(); extern void AddSC_boss_loken(); @@ -330,23 +365,26 @@ extern void AddSC_boss_volkhan(); extern void AddSC_instance_halls_of_lightning(); extern void AddSC_boss_maiden_of_grief(); //Ulduar, halls_of_stone extern void AddSC_boss_sjonnir(); +extern void AddSC_boss_krystallus(); extern void AddSC_halls_of_stone(); extern void AddSC_instance_halls_of_stone(); -extern void AddSC_boss_assembly_of_iron(); //ulduar -extern void AddSC_boss_algalon(); +extern void AddSC_boss_algalon(); //Ulduar raid extern void AddSC_boss_auriaya(); -extern void AddSC_boss_flame_leviathan(); extern void AddSC_boss_freya(); -extern void AddSC_boss_general_vezax(); extern void AddSC_boss_hodir(); extern void AddSC_boss_ignis(); +extern void AddSC_boss_iron_council(); extern void AddSC_boss_kologarn(); +extern void AddSC_boss_leviathan(); extern void AddSC_boss_mimiron(); extern void AddSC_boss_razorscale(); extern void AddSC_boss_thorim(); -extern void AddSC_boss_xt_002(); +extern void AddSC_boss_vezax(); +extern void AddSC_boss_xt002(); extern void AddSC_boss_yogg_saron(); extern void AddSC_instance_ulduar(); +extern void AddSC_ulduar(); +extern void AddSC_ulduar_teleport(); extern void AddSC_boss_ingvar(); //utgarde_keep extern void AddSC_boss_keleseth(); extern void AddSC_boss_skarvald_and_dalronn(); @@ -357,15 +395,6 @@ extern void AddSC_boss_skadi(); extern void AddSC_boss_svala(); extern void AddSC_boss_ymiron(); extern void AddSC_instance_pinnacle(); -extern void AddSC_boss_erekem(); //violet_hold -extern void AddSC_boss_ichoron(); -extern void AddSC_boss_lavanthor(); -extern void AddSC_boss_moragg(); -extern void AddSC_boss_xevozz(); -extern void AddSC_boss_zuramat(); -extern void AddSC_boss_cyanigosa(); -extern void AddSC_instance_violet_hold(); -extern void AddSC_violet_hold(); extern void AddSC_borean_tundra(); extern void AddSC_dalaran(); @@ -377,6 +406,50 @@ extern void AddSC_sholazar_basin(); extern void AddSC_storm_peaks(); extern void AddSC_zuldrak(); +extern void AddSC_instance_violet_hold(); +extern void AddSC_violet_hold(); +extern void AddSC_boss_cyanigosa(); +extern void AddSC_boss_moragg(); +extern void AddSC_boss_erekem(); +extern void AddSC_boss_xevozz(); +extern void AddSC_boss_ichoron(); +extern void AddSC_boss_zuramat(); +extern void AddSC_boss_lavanthor(); +//IceCrown Citadel +extern void AddSC_instance_icecrown_spire(); +extern void AddSC_icecrown_spire(); +extern void AddSC_icecrown_teleporter(); +extern void AddSC_boss_lord_marrowgar(); +extern void AddSC_boss_lady_deathwhisper(); +extern void AddSC_boss_deathbringer_saurfang(); +extern void AddSC_boss_rotface(); +extern void AddSC_boss_festergut(); +extern void AddSC_boss_proffesor_putricide(); +extern void AddSC_blood_prince_council(); +extern void AddSC_boss_blood_queen_lanathel(); +extern void AddSC_boss_valithria_dreamwalker(); +extern void AddSC_boss_sindragosa(); +extern void AddSC_boss_lich_king_icc(); + +extern void AddSC_instance_forge_of_souls(); +extern void AddSC_boss_devourer_of_souls(); +extern void AddSC_boss_bronjahm(); +extern void AddSC_trash_forge_of_souls(); +extern void AddSC_forge_of_souls(); + +extern void AddSC_instance_halls_of_reflection(); +extern void AddSC_halls_of_reflection(); +extern void AddSC_boss_falric(); +extern void AddSC_boss_marwyn(); +extern void AddSC_boss_lich_king_hr(); + +extern void AddSC_instance_ruby_sanctum(); // Ruby Sanctum +extern void AddSC_ruby_sanctum(); +extern void AddSC_boss_halion(); +extern void AddSC_boss_ragefire(); +extern void AddSC_boss_zarithrian(); +extern void AddSC_boss_baltharus(); + //outland extern void AddSC_boss_exarch_maladaar(); //auchindoun, auchenai_crypts extern void AddSC_boss_nexusprince_shaffar(); //auchindoun, mana_tombs @@ -465,6 +538,9 @@ void AddScripts() AddSC_boss_pusillin(); AddSC_instance_dire_maul(); AddSC_custom_cybernetic(); + AddSC_npc_arena_honor(); + AddSC_mob_teleguy(); + //examples AddSC_example_creature(); AddSC_example_escort(); @@ -667,8 +743,6 @@ void AddScripts() AddSC_boss_lieutenant_drake(); AddSC_instance_old_hillsbrad(); AddSC_old_hillsbrad(); - AddSC_culling_of_stratholme(); // Culling of Stratholme - AddSC_instance_culling_of_stratholme(); AddSC_boss_celebras_the_cursed(); //maraudon AddSC_boss_landslide(); AddSC_boss_noxxion(); @@ -719,23 +793,33 @@ void AddScripts() AddSC_winterspring(); //northrend + AddSC_trial_of_the_champion(); //trial_of_the_champion + AddSC_boss_argent_challenge(); + AddSC_boss_black_knight(); + AddSC_boss_grand_champions(); + AddSC_instance_trial_of_the_champion(); + AddSC_boss_jedoga(); //ahnkahet + AddSC_boss_amanitar(); AddSC_boss_nadox(); AddSC_boss_taldaram(); AddSC_boss_volazj(); - AddSC_boss_amanitar(); AddSC_instance_ahnkahet(); AddSC_boss_anubarak(); //azjol-nerub AddSC_boss_hadronox(); AddSC_boss_krikthir(); AddSC_instance_azjol_nerub(); - AddSC_boss_anubarak_trial(); //trial_of_the_crusader + + AddSC_northrend_beasts(); //Crusaders' Coliseum, trial_of_the_crusader AddSC_boss_jaraxxus(); + AddSC_boss_anubarak_trial(); + AddSC_boss_faction_champions(); + AddSC_twin_valkyr(); AddSC_instance_trial_of_the_crusader(); - AddSC_northrend_beasts(); AddSC_trial_of_the_crusader(); - AddSC_twin_valkyr(); + AddSC_boss_novos(); //draktharon_keep + AddSC_boss_dred(); AddSC_boss_tharonja(); AddSC_boss_trollgore(); AddSC_instance_draktharon_keep(); @@ -745,37 +829,50 @@ void AddScripts() AddSC_boss_moorabi(); AddSC_boss_sladran(); AddSC_instance_gundrak(); - AddSC_boss_bronjahm(); // ICC, forge_of_souls - AddSC_boss_devourer_of_souls(); - AddSC_instance_forge_of_souls(); + AddSC_boss_gafrost(); // ICC, pit_of_saron AddSC_boss_krick_and_ick(); AddSC_boss_tyrannus(); AddSC_instance_pit_of_saron(); AddSC_pit_of_saron(); + AddSC_boss_anubrekhan(); //naxxramas AddSC_boss_four_horsemen(); AddSC_boss_faerlina(); AddSC_boss_gluth(); AddSC_boss_gothik(); - AddSC_boss_grobbulus(); AddSC_boss_kelthuzad(); AddSC_boss_loatheb(); AddSC_boss_maexxna(); AddSC_boss_noth(); + AddSC_boss_grobbulus(); AddSC_boss_heigan(); AddSC_boss_patchwerk(); AddSC_boss_razuvious(); AddSC_boss_sapphiron(); AddSC_boss_thaddius(); AddSC_instance_naxxramas(); + AddSC_boss_anomalus(); //nexus AddSC_boss_keristrasza(); AddSC_boss_ormorok(); AddSC_boss_telestra(); AddSC_instance_nexus(); + + AddSC_oculus(); //Oculus + AddSC_instance_oculus(); + AddSC_boss_drakos(); + AddSC_boss_varos(); + AddSC_boss_urom(); + AddSC_boss_eregos(); + AddSC_boss_sartharion(); //obsidian_sanctum AddSC_instance_obsidian_sanctum(); + AddSC_instance_vault_of_archavon(); //vault_of_archavon + AddSC_boss_toravon(); + AddSC_boss_koralon(); + AddSC_boss_emalon(); + AddSC_boss_archavon(); AddSC_boss_bjarngrim(); //Ulduar, halls_of_lightning AddSC_boss_ionar(); AddSC_boss_loken(); @@ -783,23 +880,26 @@ void AddScripts() AddSC_instance_halls_of_lightning(); AddSC_boss_maiden_of_grief(); //Ulduar, halls_of_stone AddSC_boss_sjonnir(); + AddSC_boss_krystallus(); AddSC_halls_of_stone(); AddSC_instance_halls_of_stone(); - AddSC_boss_assembly_of_iron(); //ulduar - AddSC_boss_algalon(); + AddSC_boss_algalon(); //Ulduar AddSC_boss_auriaya(); - AddSC_boss_flame_leviathan(); AddSC_boss_freya(); - AddSC_boss_general_vezax(); AddSC_boss_hodir(); AddSC_boss_ignis(); + AddSC_boss_iron_council(); AddSC_boss_kologarn(); + AddSC_boss_leviathan(); AddSC_boss_mimiron(); AddSC_boss_razorscale(); AddSC_boss_thorim(); - AddSC_boss_xt_002(); + AddSC_boss_vezax(); + AddSC_boss_xt002(); AddSC_boss_yogg_saron(); AddSC_instance_ulduar(); + AddSC_ulduar(); + AddSC_ulduar_teleport(); AddSC_boss_ingvar(); //utgarde_keep AddSC_boss_keleseth(); AddSC_boss_skarvald_and_dalronn(); @@ -810,15 +910,6 @@ void AddScripts() AddSC_boss_svala(); AddSC_boss_ymiron(); AddSC_instance_pinnacle(); - AddSC_boss_erekem(); //violet_hold - AddSC_boss_ichoron(); - AddSC_boss_lavanthor(); - AddSC_boss_moragg(); - AddSC_boss_xevozz(); - AddSC_boss_zuramat(); - AddSC_boss_cyanigosa(); - AddSC_instance_violet_hold(); - AddSC_violet_hold(); AddSC_borean_tundra(); AddSC_dalaran(); @@ -830,6 +921,50 @@ void AddScripts() AddSC_storm_peaks(); AddSC_zuldrak(); + AddSC_instance_violet_hold(); + AddSC_boss_cyanigosa(); + AddSC_boss_moragg(); + AddSC_boss_erekem(); + AddSC_boss_xevozz(); + AddSC_boss_ichoron(); + AddSC_boss_zuramat(); + AddSC_boss_lavanthor(); + AddSC_violet_hold(); + + AddSC_instance_icecrown_spire(); + AddSC_icecrown_spire(); + AddSC_icecrown_teleporter(); + AddSC_boss_lord_marrowgar(); + AddSC_boss_lady_deathwhisper(); + AddSC_boss_deathbringer_saurfang(); + AddSC_boss_rotface(); + AddSC_boss_festergut(); + AddSC_boss_proffesor_putricide(); + AddSC_blood_prince_council(); + AddSC_boss_blood_queen_lanathel(); + AddSC_boss_valithria_dreamwalker(); + AddSC_boss_sindragosa(); + AddSC_boss_lich_king_icc(); + + AddSC_instance_forge_of_souls(); + AddSC_boss_devourer_of_souls(); + AddSC_boss_bronjahm(); + AddSC_trash_forge_of_souls(); + AddSC_forge_of_souls(); + + AddSC_instance_halls_of_reflection(); + AddSC_halls_of_reflection(); + AddSC_boss_falric(); + AddSC_boss_marwyn(); + AddSC_boss_lich_king_hr(); + + AddSC_instance_ruby_sanctum(); // Ruby Sanctum + AddSC_ruby_sanctum(); + AddSC_boss_halion(); + AddSC_boss_ragefire(); + AddSC_boss_zarithrian(); + AddSC_boss_baltharus(); + //outland AddSC_boss_exarch_maladaar(); //auchindoun, auchenai_crypts AddSC_boss_nexusprince_shaffar(); //auchindoun, mana_tombs @@ -898,6 +1033,16 @@ void AddScripts() AddSC_boss_pathaleon_the_calculator(); AddSC_instance_mechanar(); + AddSC_boss_lord_epoch(); //culling of stratholme + AddSC_boss_malganis(); + AddSC_boss_meathook(); + AddSC_boss_salramm(); + AddSC_boss_infinite_corruptor(); + AddSC_culling_of_stratholme(); + AddSC_culling_of_stratholmeAI(); + AddSC_instance_culling_of_stratholme(); + AddSC_trash_culling_of_stratholme(); + AddSC_blades_edge_mountains(); AddSC_boss_doomlordkazzak(); AddSC_boss_doomwalker();