diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..1f05b58
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..957df71
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,599 @@
+# Copyright (C) 2005-2009 MaNGOS
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+## Process this file with automake to produce Makefile.in
+
+## Sub-directories to parse
+SUBDIRS = sql
+
+BUILT_SOURCES = revision.h
+CLEANFILES = revision.h
+## CPP flags for includes, defines, etc.
+AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../shared/ -I$(srcdir)/../../framework/ -I$(srcdir)/../../game/ -I$(srcdir)/include/ -I$(srcdir)/base/ -DSYSCONFDIR=\"$(sysconfdir)/\"
+
+## Build MaNGOS script library as shared library.
+# libmangosscript shared library will later be reused by world server daemon.
+lib_LTLIBRARIES = libmangosscript.la
+libmangosscript_la_SOURCES = \
+ScriptMgr.cpp \
+ScriptMgr.h \
+config.h \
+base/escort_ai.cpp \
+base/escort_ai.h \
+base/follower_ai.cpp \
+base/follower_ai.h \
+base/guard_ai.cpp \
+base/guard_ai.h \
+include/precompiled.cpp \
+include/precompiled.h \
+include/sc_creature.cpp \
+include/sc_creature.h \
+include/sc_gossip.h \
+include/sc_grid_searchers.cpp \
+include/sc_grid_searchers.h \
+include/sc_instance.cpp \
+include/sc_instance.h \
+scripts/battlegrounds/battleground.cpp \
+scripts/eastern_kingdoms/alterac_mountains.cpp \
+scripts/eastern_kingdoms/arathi_highlands.cpp \
+scripts/eastern_kingdoms/blasted_lands.cpp \
+scripts/eastern_kingdoms/boss_kruul.cpp \
+scripts/eastern_kingdoms/burning_steppes.cpp \
+scripts/eastern_kingdoms/dun_morogh.cpp \
+scripts/eastern_kingdoms/eastern_plaguelands.cpp \
+scripts/eastern_kingdoms/elwynn_forest.cpp \
+scripts/eastern_kingdoms/eversong_woods.cpp \
+scripts/eastern_kingdoms/ghostlands.cpp \
+scripts/eastern_kingdoms/hinterlands.cpp \
+scripts/eastern_kingdoms/ironforge.cpp \
+scripts/eastern_kingdoms/isle_of_queldanas.cpp \
+scripts/eastern_kingdoms/loch_modan.cpp \
+scripts/eastern_kingdoms/redridge_mountains.cpp \
+scripts/eastern_kingdoms/searing_gorge.cpp \
+scripts/eastern_kingdoms/silvermoon_city.cpp \
+scripts/eastern_kingdoms/silverpine_forest.cpp \
+scripts/eastern_kingdoms/stormwind_city.cpp \
+scripts/eastern_kingdoms/stranglethorn_vale.cpp \
+scripts/eastern_kingdoms/swamp_of_sorrows.cpp \
+scripts/eastern_kingdoms/tirisfal_glades.cpp \
+scripts/eastern_kingdoms/undercity.cpp \
+scripts/eastern_kingdoms/western_plaguelands.cpp \
+scripts/eastern_kingdoms/westfall.cpp \
+scripts/eastern_kingdoms/wetlands.cpp \
+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_emperor_dagran_thaurissan.cpp \
+scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp \
+scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp \
+scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp \
+scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp \
+scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp \
+scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp \
+scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp \
+scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h \
+scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp \
+scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp \
+scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp \
+scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp \
+scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp \
+scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp \
+scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp \
+scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp \
+scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp \
+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/boss_broodlord_lashlayer.cpp \
+scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp \
+scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp \
+scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp \
+scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp \
+scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp \
+scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp \
+scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp \
+scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp \
+scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp \
+scripts/eastern_kingdoms/deadmines/deadmines.cpp \
+scripts/eastern_kingdoms/deadmines/deadmines.h \
+scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp \
+scripts/eastern_kingdoms/gnomeregan/boss_thermaplugg.cpp \
+scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp \
+scripts/eastern_kingdoms/gnomeregan/gnomeregan.h \
+scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp \
+scripts/eastern_kingdoms/karazhan/boss_curator.cpp \
+scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp \
+scripts/eastern_kingdoms/karazhan/boss_midnight.cpp \
+scripts/eastern_kingdoms/karazhan/boss_moroes.cpp \
+scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp \
+scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp \
+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/instance_karazhan.cpp \
+scripts/eastern_kingdoms/karazhan/karazhan.cpp \
+scripts/eastern_kingdoms/karazhan/karazhan.h \
+scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp \
+scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp \
+scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp \
+scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp \
+scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp \
+scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp \
+scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h \
+scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp \
+scripts/eastern_kingdoms/molten_core/boss_garr.cpp \
+scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp \
+scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp \
+scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp \
+scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp \
+scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp \
+scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp \
+scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp \
+scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp \
+scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp \
+scripts/eastern_kingdoms/molten_core/molten_core.cpp \
+scripts/eastern_kingdoms/molten_core/molten_core.h \
+scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp \
+scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h \
+scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp \
+scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp \
+scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp \
+scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp \
+scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp \
+scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp \
+scripts/eastern_kingdoms/scholomance/boss_kormok.cpp \
+scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp \
+scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp \
+scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp \
+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/instance_shadowfang_keep.cpp \
+scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp \
+scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h \
+scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp \
+scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp \
+scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp \
+scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp \
+scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp \
+scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp \
+scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp \
+scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp \
+scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp \
+scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp \
+scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp \
+scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp \
+scripts/eastern_kingdoms/stratholme/stratholme.cpp \
+scripts/eastern_kingdoms/stratholme/stratholme.h \
+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_kalecgos.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 \
+scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp \
+scripts/eastern_kingdoms/uldaman/uldaman.cpp \
+scripts/eastern_kingdoms/uldaman/uldaman.h \
+scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp \
+scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp \
+scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp \
+scripts/eastern_kingdoms/zulaman/boss_janalai.cpp \
+scripts/eastern_kingdoms/zulaman/boss_malacrass.cpp \
+scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp \
+scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp \
+scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp \
+scripts/eastern_kingdoms/zulaman/zulaman.cpp \
+scripts/eastern_kingdoms/zulaman/zulaman.h \
+scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_marli.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp \
+scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp \
+scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp \
+scripts/eastern_kingdoms/zulgurub/zulgurub.h \
+scripts/examples/example_creature.cpp \
+scripts/examples/example_escort.cpp \
+scripts/examples/example_gossip_codebox.cpp \
+scripts/examples/example_misc.cpp \
+scripts/kalimdor/ashenvale.cpp \
+scripts/kalimdor/azshara.cpp \
+scripts/kalimdor/azuremyst_isle.cpp \
+scripts/kalimdor/bloodmyst_isle.cpp \
+scripts/kalimdor/boss_azuregos.cpp \
+scripts/kalimdor/darkshore.cpp \
+scripts/kalimdor/desolace.cpp \
+scripts/kalimdor/dustwallow_marsh.cpp \
+scripts/kalimdor/felwood.cpp \
+scripts/kalimdor/feralas.cpp \
+scripts/kalimdor/moonglade.cpp \
+scripts/kalimdor/mulgore.cpp \
+scripts/kalimdor/orgrimmar.cpp \
+scripts/kalimdor/silithus.cpp \
+scripts/kalimdor/stonetalon_mountains.cpp \
+scripts/kalimdor/tanaris.cpp \
+scripts/kalimdor/teldrassil.cpp \
+scripts/kalimdor/the_barrens.cpp \
+scripts/kalimdor/thousand_needles.cpp \
+scripts/kalimdor/thunder_bluff.cpp \
+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 \
+scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp \
+scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h \
+scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp \
+scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp \
+scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp \
+scripts/kalimdor/caverns_of_time/hyjal/hyjal.h \
+scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp \
+scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h \
+scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp \
+scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp \
+scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp \
+scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp \
+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/maraudon/boss_celebras_the_cursed.cpp \
+scripts/kalimdor/maraudon/boss_landslide.cpp \
+scripts/kalimdor/maraudon/boss_noxxion.cpp \
+scripts/kalimdor/maraudon/boss_princess_theradras.cpp \
+scripts/kalimdor/onyxias_lair/boss_onyxia.cpp \
+scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp \
+scripts/kalimdor/onyxias_lair/onyxias_lair.h \
+scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp \
+scripts/kalimdor/razorfen_downs/razorfen_downs.cpp \
+scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp \
+scripts/kalimdor/razorfen_kraul/razorfen_kraul.h \
+scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp \
+scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp \
+scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp \
+scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp \
+scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp \
+scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp \
+scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp \
+scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.cpp \
+scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h \
+scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp \
+scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h \
+scripts/kalimdor/wailing_caverns/instance_wailing_caverns.cpp \
+scripts/kalimdor/wailing_caverns/wailing_caverns.h \
+scripts/kalimdor/zulfarrak/zulfarrak.cpp \
+scripts/northrend/borean_tundra.cpp \
+scripts/northrend/dalaran.cpp \
+scripts/northrend/dragonblight.cpp \
+scripts/northrend/grizzly_hills.cpp \
+scripts/northrend/icecrown.cpp \
+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_jedoga.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 \
+scripts/northrend/azjol-nerub/ahnkahet/ahnkahet.h \
+scripts/northrend/azjol-nerub/ahnkahet/instance_ahnkahet.cpp \
+scripts/northrend/azjol-nerub/azjol-nerub/azjol-nerub.h \
+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_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/boss_novos.cpp \
+scripts/northrend/draktharon_keep/boss_tharonja.cpp \
+scripts/northrend/draktharon_keep/boss_trollgore.cpp \
+scripts/northrend/gundrak/boss_colossus.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/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/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/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/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/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/gunship_battle.cpp \
+scripts/northrend/naxxramas/boss_anubrekhan.cpp \
+scripts/northrend/naxxramas/boss_faerlina.cpp \
+scripts/northrend/naxxramas/boss_four_horsemen.cpp \
+scripts/northrend/naxxramas/boss_gluth.cpp \
+scripts/northrend/naxxramas/boss_gothik.cpp \
+scripts/northrend/naxxramas/boss_grobbulus.cpp \
+scripts/northrend/naxxramas/boss_heigan.cpp \
+scripts/northrend/naxxramas/boss_kelthuzad.cpp \
+scripts/northrend/naxxramas/boss_loatheb.cpp \
+scripts/northrend/naxxramas/boss_maexxna.cpp \
+scripts/northrend/naxxramas/boss_noth.cpp \
+scripts/northrend/naxxramas/boss_patchwerk.cpp \
+scripts/northrend/naxxramas/boss_razuvious.cpp \
+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/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/obsidian_sanctum/boss_sartharion.cpp \
+scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp \
+scripts/northrend/obsidian_sanctum/obsidian_sanctum.h \
+scripts/northrend/ruby_sanctum/boss_halion.cpp \
+scripts/northrend/ruby_sanctum/boss_baltharus.cpp \
+scripts/northrend/ruby_sanctum/boss_saviana.cpp \
+scripts/northrend/ruby_sanctum/boss_zarithian.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 \
+scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp \
+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/halls_of_stone.cpp \
+scripts/northrend/ulduar/halls_of_stone/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/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_kologarn.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_yogg_saron.cpp \
+scripts/northrend/ulduar/ulduar/instance_ulduar.cpp \
+scripts/northrend/ulduar/ulduar/ulduar.cpp \
+scripts/northrend/ulduar/ulduar/ulduar.h \
+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 \
+scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp \
+scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp \
+scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.h \
+scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_gortok.cpp \
+scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp \
+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/instance_violet_hold.cpp \
+scripts/northrend/violet_hold/violet_hold.cpp \
+scripts/northrend/violet_hold/violet_hold.h \
+scripts/outland/blades_edge_mountains.cpp \
+scripts/outland/boss_doomlord_kazzak.cpp \
+scripts/outland/boss_doomwalker.cpp \
+scripts/outland/hellfire_peninsula.cpp \
+scripts/outland/nagrand.cpp \
+scripts/outland/netherstorm.cpp \
+scripts/outland/shadowmoon_valley.cpp \
+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/mana_tombs/boss_nexusprince_shaffar.cpp \
+scripts/outland/auchindoun/mana_tombs/boss_pandemonius.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 \
+scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h \
+scripts/outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp \
+scripts/outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp \
+scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp \
+scripts/outland/auchindoun/shadow_labyrinth/boss_murmur.cpp \
+scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp \
+scripts/outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h \
+scripts/outland/black_temple/black_temple.cpp \
+scripts/outland/black_temple/black_temple.h \
+scripts/outland/black_temple/boss_bloodboil.cpp \
+scripts/outland/black_temple/boss_illidan.cpp \
+scripts/outland/black_temple/boss_mother_shahraz.cpp \
+scripts/outland/black_temple/boss_reliquary_of_souls.cpp \
+scripts/outland/black_temple/boss_shade_of_akama.cpp \
+scripts/outland/black_temple/boss_supremus.cpp \
+scripts/outland/black_temple/boss_teron_gorefiend.cpp \
+scripts/outland/black_temple/boss_warlord_najentus.cpp \
+scripts/outland/black_temple/illidari_council.cpp \
+scripts/outland/black_temple/instance_black_temple.cpp \
+scripts/outland/coilfang_reservoir/serpent_shrine/boss_fathomlord_karathress.cpp \
+scripts/outland/coilfang_reservoir/serpent_shrine/boss_hydross_the_unstable.cpp \
+scripts/outland/coilfang_reservoir/serpent_shrine/boss_lady_vashj.cpp \
+scripts/outland/coilfang_reservoir/serpent_shrine/boss_leotheras_the_blind.cpp \
+scripts/outland/coilfang_reservoir/serpent_shrine/boss_morogrim_tidewalker.cpp \
+scripts/outland/coilfang_reservoir/serpent_shrine/instance_serpent_shrine.cpp \
+scripts/outland/coilfang_reservoir/serpent_shrine/serpent_shrine.h \
+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 \
+scripts/outland/coilfang_reservoir/steam_vault/instance_steam_vault.cpp \
+scripts/outland/coilfang_reservoir/steam_vault/steam_vault.h \
+scripts/outland/coilfang_reservoir/underbog/boss_hungarfen.cpp \
+scripts/outland/gruuls_lair/boss_gruul.cpp \
+scripts/outland/gruuls_lair/boss_high_king_maulgar.cpp \
+scripts/outland/gruuls_lair/gruuls_lair.h \
+scripts/outland/gruuls_lair/instance_gruuls_lair.cpp \
+scripts/outland/hellfire_citadel/blood_furnace/blood_furnace.h \
+scripts/outland/hellfire_citadel/blood_furnace/boss_broggok.cpp \
+scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp \
+scripts/outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp \
+scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp \
+scripts/outland/hellfire_citadel/hellfire_ramparts/boss_nazan_and_vazruden.cpp \
+scripts/outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp \
+scripts/outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp \
+scripts/outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h \
+scripts/outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp \
+scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp \
+scripts/outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp \
+scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h \
+scripts/outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp \
+scripts/outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp \
+scripts/outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp \
+scripts/outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp \
+scripts/outland/hellfire_citadel/shattered_halls/shattered_halls.h \
+scripts/outland/tempest_keep/arcatraz/arcatraz.cpp \
+scripts/outland/tempest_keep/arcatraz/arcatraz.h \
+scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp \
+scripts/outland/tempest_keep/arcatraz/instance_arcatraz.cpp \
+scripts/outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp \
+scripts/outland/tempest_keep/botanica/boss_laj.cpp \
+scripts/outland/tempest_keep/botanica/boss_warp_splinter.cpp \
+scripts/outland/tempest_keep/the_eye/boss_astromancer.cpp \
+scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp \
+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/world/areatrigger_scripts.cpp \
+scripts/world/boss_emeriss.cpp \
+scripts/world/boss_lethon.cpp \
+scripts/world/boss_taerar.cpp \
+scripts/world/boss_ysondre.cpp \
+scripts/world/go_scripts.cpp \
+scripts/world/guards.cpp \
+scripts/world/item_scripts.cpp \
+scripts/world/mob_generic_creature.cpp \
+scripts/world/npc_professions.cpp \
+scripts/world/npcs_special.cpp \
+scripts/world/spell_scripts.cpp \
+system/ScriptLoader.cpp \
+system/ScriptLoader.h \
+system/system.cpp \
+system/system.h \
+revision.h
+
+
+## magic to include revision data in SD2 version string
+revision.h: FORCE
+ $(top_builddir)/src/tools/genrevision/genrevision $(srcdir)
+
+FORCE:
+
+## libtool settings
+# API versioning
+# Link against dependencies
+# How to increase version info:
+# - only bug fixes implemented:
+# bump the version to LTMANGOS_CURRENT:LTMANGOS_REVISION+1:LTMANGOS_AGE
+# - augmented the interface:
+# bump the version to LTMANGOS_CURRENT+1:0:LTMANGOS_AGE+1
+# - broken old interface:
+# bump the version to LTMANGOS_CURRENT+1:0:0
+LTMANGOS_CURRENT = 0
+LTMANGOS_REVISION = 0
+LTMANGOS_AGE = 0
+libmangosscript_la_LIBFLAGS = -version-info $(LTMANGOS_CURRENT):$(LTMANGOS_REVISION):$(LTMANGOS_AGE)
+
+## Additional files to include when running 'make dist'
+# Scripts defaults.
+EXTRA_DIST = \
+ Scripts/sc_default.cpp \
+ Scripts/sc_defines.cpp \
+ Scripts/sc_defines.h \
+ scriptdev2.conf.dist
+
+## Additional files to install
+sysconf_DATA = \
+ scriptdev2.conf.dist
+
+install-data-hook:
+ @list='$(sysconf_DATA)'; for p in $$list; do \
+ dest=`echo $$p | sed -e s/.dist//`; \
+ if test -f $(DESTDIR)$(sysconfdir)/$$dest; then \
+ echo "$@ will not overwrite existing $(DESTDIR)$(sysconfdir)/$$dest"; \
+ else \
+ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest"; \
+ $(INSTALL_DATA) $$p $(DESTDIR)$(sysconfdir)/$$dest; \
+ fi; \
+ done
+
+clean-local:
+ rm -f $(sysconf_DATA)
diff --git a/ScriptMgr.cpp b/ScriptMgr.cpp
new file mode 100644
index 0000000..33984b5
--- /dev/null
+++ b/ScriptMgr.cpp
@@ -0,0 +1,563 @@
+/* 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 */
+
+#include "precompiled.h"
+#include "Config/Config.h"
+#include "config.h"
+#include "Database/DatabaseEnv.h"
+#include "DBCStores.h"
+#include "ObjectMgr.h"
+#include "ProgressBar.h"
+#include "../system/ScriptLoader.h"
+#include "../system/system.h"
+
+int num_sc_scripts;
+Script *m_scripts[MAX_SCRIPTS];
+
+Config SD2Config;
+
+void FillSpellSummary();
+
+void LoadDatabase()
+{
+ std::string strSD2DBinfo = SD2Config.GetStringDefault("ScriptDev2DatabaseInfo", "");
+
+ if (strSD2DBinfo.empty())
+ {
+ error_log("SD2: Missing Scriptdev2 database info from configuration file. Load database aborted.");
+ return;
+ }
+
+ //Initialize connection to DB
+ if (SD2Database.Initialize(strSD2DBinfo.c_str()))
+ {
+ outstring_log("SD2: ScriptDev2 database at %s initialized.", strSD2DBinfo.c_str());
+ outstring_log("");
+
+ pSystemMgr.LoadVersion();
+ pSystemMgr.LoadScriptTexts();
+ pSystemMgr.LoadScriptTextsCustom();
+ pSystemMgr.LoadScriptGossipTexts();
+ pSystemMgr.LoadScriptWaypoints();
+ }
+ else
+ {
+ error_log("SD2: Unable to connect to Database. Load database aborted.");
+ return;
+ }
+
+ SD2Database.HaltDelayThread();
+
+}
+
+struct TSpellSummary {
+ uint8 Targets; // set of enum SelectTarget
+ uint8 Effects; // set of enum SelectEffect
+}extern *SpellSummary;
+
+MANGOS_DLL_EXPORT
+void ScriptsFree()
+{
+ // Free Spell Summary
+ delete []SpellSummary;
+
+ // Free resources before library unload
+ for(int i=0; i> Loaded %i C++ Scripts.", num_sc_scripts);
+}
+
+//*********************************
+//*** Functions used globally ***
+
+void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget)
+{
+ if (!pSource)
+ {
+ error_log("SD2: DoScriptText entry %i, invalid Source pointer.", iTextEntry);
+ return;
+ }
+
+ if (iTextEntry >= 0)
+ {
+ error_log("SD2: DoScriptText with source entry %u (TypeId=%u, guid=%u) attempts to process text entry %i, but text entry must be negative.",
+ pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry);
+
+ return;
+ }
+
+ const StringTextData* pData = pSystemMgr.GetTextData(iTextEntry);
+
+ if (!pData)
+ {
+ error_log("SD2: DoScriptText with source entry %u (TypeId=%u, guid=%u) could not find text entry %i.",
+ pSource->GetEntry(), pSource->GetTypeId(), pSource->GetGUIDLow(), iTextEntry);
+
+ return;
+ }
+
+ debug_log("SD2: DoScriptText: text entry=%i, Sound=%u, Type=%u, Language=%u, Emote=%u",
+ iTextEntry, pData->uiSoundId, pData->uiType, pData->uiLanguage, pData->uiEmote);
+
+ if (pData->uiSoundId)
+ {
+ if (GetSoundEntriesStore()->LookupEntry(pData->uiSoundId))
+ pSource->PlayDirectSound(pData->uiSoundId);
+ else
+ error_log("SD2: DoScriptText entry %i tried to process invalid sound id %u.", iTextEntry, pData->uiSoundId);
+ }
+
+ if (pData->uiEmote)
+ {
+ if (pSource->GetTypeId() == TYPEID_UNIT || pSource->GetTypeId() == TYPEID_PLAYER)
+ ((Unit*)pSource)->HandleEmote(pData->uiEmote);
+ else
+ error_log("SD2: DoScriptText entry %i tried to process emote for invalid TypeId (%u).", iTextEntry, pSource->GetTypeId());
+ }
+
+ switch(pData->uiType)
+ {
+ case CHAT_TYPE_SAY:
+ pSource->MonsterSay(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0);
+ break;
+ case CHAT_TYPE_YELL:
+ pSource->MonsterYell(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0);
+ break;
+ case CHAT_TYPE_TEXT_EMOTE:
+ pSource->MonsterTextEmote(iTextEntry, pTarget ? pTarget->GetGUID() : 0);
+ break;
+ case CHAT_TYPE_BOSS_EMOTE:
+ pSource->MonsterTextEmote(iTextEntry, pTarget ? pTarget->GetGUID() : 0, true);
+ break;
+ case CHAT_TYPE_WHISPER:
+ {
+ if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
+ pSource->MonsterWhisper(iTextEntry, pTarget->GetGUID());
+ else
+ error_log("SD2: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry);
+
+ break;
+ }
+ case CHAT_TYPE_BOSS_WHISPER:
+ {
+ if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
+ pSource->MonsterWhisper(iTextEntry, pTarget->GetGUID(), true);
+ else
+ error_log("SD2: DoScriptText entry %i cannot whisper without target unit (TYPEID_PLAYER).", iTextEntry);
+
+ break;
+ }
+ case CHAT_TYPE_ZONE_YELL:
+ pSource->MonsterYellToZone(iTextEntry, pData->uiLanguage, pTarget ? pTarget->GetGUID() : 0);
+ break;
+ }
+}
+
+//*********************************
+//*** Functions used internally ***
+
+void Script::RegisterSelf(bool bReportError)
+{
+ int id = GetScriptId(Name.c_str());
+ if (id != 0)
+ {
+ m_scripts[id] = this;
+ ++num_sc_scripts;
+ }
+ else
+ {
+ if (bReportError)
+ error_log("SD2: Script registering but ScriptName %s is not assigned in database. Script will not be used.", (this)->Name.c_str());
+
+ delete this;
+ }
+}
+
+//********************************
+//*** Functions to be Exported ***
+
+MANGOS_DLL_EXPORT
+char const* ScriptsVersion()
+{
+ if (!strSD2Version.empty())
+ {
+ strSD2Version.append(_FULLVERSION);
+ return strSD2Version.c_str();
+ }
+
+ return _FULLVERSION;
+}
+
+MANGOS_DLL_EXPORT
+bool GossipHello(Player* pPlayer, Creature* pCreature)
+{
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pGossipHello)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGossipHello(pPlayer, pCreature);
+}
+
+MANGOS_DLL_EXPORT
+bool GOGossipHello(Player *pPlayer, GameObject *pGo)
+{
+ Script *tmpscript = m_scripts[pGo->GetGOInfo()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pGOGossipHello)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGOGossipHello(pPlayer, pGo);
+}
+
+MANGOS_DLL_EXPORT
+bool GossipSelect(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ debug_log("SD2: Gossip selection, sender: %u, action: %u", uiSender, uiAction);
+
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pGossipSelect)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGossipSelect(pPlayer, pCreature, uiSender, uiAction);
+}
+
+MANGOS_DLL_EXPORT
+bool GOGossipSelect(Player *pPlayer, GameObject *pGo, uint32 sender, uint32 action)
+{
+ debug_log("SD2: GO Gossip selection, sender: %u, action: %u", sender, action);
+
+ Script *tmpscript = m_scripts[pGo->GetGOInfo()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pGOGossipSelect)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGOGossipSelect(pPlayer, pGo, sender, action);
+}
+
+MANGOS_DLL_EXPORT
+bool GossipSelectWithCode(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode)
+{
+ debug_log("SD2: Gossip selection with code, sender: %u, action: %u", uiSender, uiAction);
+
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pGossipSelectWithCode)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGossipSelectWithCode(pPlayer, pCreature, uiSender, uiAction, sCode);
+}
+
+MANGOS_DLL_EXPORT
+bool GOGossipSelectWithCode(Player *pPlayer, GameObject *pGo, uint32 sender, uint32 action, const char* sCode)
+{
+ debug_log("SD2: GO Gossip selection with code, sender: %u, action: %u", sender, action);
+
+ Script *tmpscript = m_scripts[pGo->GetGOInfo()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pGOGossipSelectWithCode)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGOGossipSelectWithCode(pPlayer, pGo, sender, action, sCode);
+}
+
+MANGOS_DLL_EXPORT
+bool QuestAccept(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pQuestAccept)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pQuestAccept(pPlayer, pCreature, pQuest);
+}
+
+MANGOS_DLL_EXPORT
+bool QuestSelect(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pQuestSelect)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pQuestSelect(pPlayer, pCreature, pQuest);
+}
+
+MANGOS_DLL_EXPORT
+bool QuestComplete(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pQuestComplete)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pQuestComplete(pPlayer, pCreature, pQuest);
+}
+
+MANGOS_DLL_EXPORT
+bool ChooseReward(Player* pPlayer, Creature* pCreature, const Quest* pQuest, uint32 opt)
+{
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pChooseReward)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pChooseReward(pPlayer, pCreature, pQuest, opt);
+}
+
+MANGOS_DLL_EXPORT
+uint32 NPCDialogStatus(Player* pPlayer, Creature* pCreature)
+{
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pNPCDialogStatus)
+ return 100;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pNPCDialogStatus(pPlayer, pCreature);
+}
+
+MANGOS_DLL_EXPORT
+uint32 GODialogStatus(Player* pPlayer, GameObject* pGo)
+{
+ Script *tmpscript = m_scripts[pGo->GetGOInfo()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pGODialogStatus)
+ return 100;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGODialogStatus(pPlayer, pGo);
+}
+
+MANGOS_DLL_EXPORT
+bool ItemHello(Player* pPlayer, Item *_Item, const Quest* pQuest)
+{
+ Script *tmpscript = m_scripts[_Item->GetProto()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pItemHello)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pItemHello(pPlayer,_Item, pQuest);
+}
+
+MANGOS_DLL_EXPORT
+bool ItemQuestAccept(Player* pPlayer, Item *_Item, const Quest* pQuest)
+{
+ Script *tmpscript = m_scripts[_Item->GetProto()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pItemQuestAccept)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pItemQuestAccept(pPlayer,_Item, pQuest);
+}
+
+MANGOS_DLL_EXPORT
+bool GOHello(Player* pPlayer, GameObject* pGo)
+{
+ Script *tmpscript = m_scripts[pGo->GetGOInfo()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pGOHello)
+ return false;
+
+ return tmpscript->pGOHello(pPlayer, pGo);
+}
+
+MANGOS_DLL_EXPORT
+bool GOQuestAccept(Player* pPlayer, GameObject* pGo, const Quest* pQuest)
+{
+ Script *tmpscript = m_scripts[pGo->GetGOInfo()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pGOQuestAccept)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGOQuestAccept(pPlayer, pGo, pQuest);
+}
+
+MANGOS_DLL_EXPORT
+bool GOChooseReward(Player* pPlayer, GameObject* pGo, const Quest* pQuest, uint32 opt)
+{
+ Script *tmpscript = m_scripts[pGo->GetGOInfo()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pGOChooseReward)
+ return false;
+
+ pPlayer->PlayerTalkClass->ClearMenus();
+
+ return tmpscript->pGOChooseReward(pPlayer, pGo, pQuest,opt);
+}
+
+MANGOS_DLL_EXPORT
+bool AreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry)
+{
+ Script *tmpscript = m_scripts[GetAreaTriggerScriptId(atEntry->id)];
+
+ if (!tmpscript || !tmpscript->pAreaTrigger)
+ return false;
+
+ return tmpscript->pAreaTrigger(pPlayer, atEntry);
+}
+
+MANGOS_DLL_EXPORT
+bool ProcessEventId(uint32 uiEventId, Object* pSource, Object* pTarget, bool bIsStart)
+{
+ Script *tmpscript = m_scripts[GetEventIdScriptId(uiEventId)];
+ if (!tmpscript || !tmpscript->pProcessEventId)
+ return false;
+
+ // bIsStart may be false, when event is from taxi node events (arrival=false, departure=true)
+ return tmpscript->pProcessEventId(uiEventId, pSource, pTarget, bIsStart);
+}
+
+MANGOS_DLL_EXPORT
+CreatureAI* GetAI(Creature* pCreature)
+{
+ Script *tmpscript = m_scripts[pCreature->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->GetAI)
+ return NULL;
+
+ return tmpscript->GetAI(pCreature);
+}
+
+MANGOS_DLL_EXPORT
+bool ItemUse(Player* pPlayer, Item* _Item, SpellCastTargets const& targets)
+{
+ Script *tmpscript = m_scripts[_Item->GetProto()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pItemUse)
+ return false;
+
+ return tmpscript->pItemUse(pPlayer,_Item,targets);
+}
+
+MANGOS_DLL_EXPORT
+bool EffectDummyCreature(Unit *pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature *pCreatureTarget)
+{
+ Script *tmpscript = m_scripts[pCreatureTarget->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pEffectDummyCreature)
+ return false;
+
+ return tmpscript->pEffectDummyCreature(pCaster, spellId, effIndex, pCreatureTarget);
+}
+
+MANGOS_DLL_EXPORT
+bool EffectDummyGameObj(Unit *pCaster, uint32 spellId, SpellEffectIndex effIndex, GameObject *pGameObjTarget)
+{
+ Script *tmpscript = m_scripts[pGameObjTarget->GetGOInfo()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pEffectDummyGameObj)
+ return false;
+
+ return tmpscript->pEffectDummyGameObj(pCaster, spellId, effIndex, pGameObjTarget);
+}
+
+MANGOS_DLL_EXPORT
+bool EffectDummyItem(Unit *pCaster, uint32 spellId, SpellEffectIndex effIndex, Item *pItemTarget)
+{
+ Script *tmpscript = m_scripts[pItemTarget->GetProto()->ScriptId];
+
+ if (!tmpscript || !tmpscript->pEffectDummyItem)
+ return false;
+
+ return tmpscript->pEffectDummyItem(pCaster, spellId, effIndex, pItemTarget);
+}
+
+MANGOS_DLL_EXPORT
+bool EffectAuraDummy(const Aura* pAura, bool apply)
+{
+ Script *tmpscript = m_scripts[((Creature*)pAura->GetTarget())->GetScriptId()];
+
+ if (!tmpscript || !tmpscript->pEffectAuraDummy)
+ return false;
+
+ return tmpscript->pEffectAuraDummy(pAura, apply);
+}
+
+MANGOS_DLL_EXPORT
+InstanceData* CreateInstanceData(Map *map)
+{
+ if (!map->IsDungeon())
+ return NULL;
+
+ Script *tmpscript = m_scripts[((InstanceMap*)map)->GetScriptId()];
+ if (!tmpscript || !tmpscript->GetInstanceData)
+ return NULL;
+
+ return tmpscript->GetInstanceData(map);
+}
diff --git a/ScriptMgr.h b/ScriptMgr.h
new file mode 100644
index 0000000..66d7685
--- /dev/null
+++ b/ScriptMgr.h
@@ -0,0 +1,84 @@
+/* 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 */
+
+#ifndef SC_SCRIPTMGR_H
+#define SC_SCRIPTMGR_H
+
+#include "Common.h"
+#include "DBCStructure.h"
+
+class Player;
+class Creature;
+class CreatureAI;
+class InstanceData;
+class Quest;
+class Item;
+class GameObject;
+class SpellCastTargets;
+class Map;
+class Unit;
+class WorldObject;
+class Aura;
+class Object;
+
+#define MAX_SCRIPTS 5000 //72 bytes each (approx 351kb)
+#define VISIBLE_RANGE (166.0f) //MAX visible range (size of grid)
+#define DEFAULT_TEXT ""
+
+struct Script
+{
+ Script() :
+ pGossipHello(NULL), pGOGossipHello(NULL), pGossipSelect(NULL), pGOGossipSelect(NULL),
+ pGossipSelectWithCode(NULL), pGOGossipSelectWithCode(NULL),
+ pQuestSelect(NULL), pQuestComplete(NULL), pNPCDialogStatus(NULL), pGODialogStatus(NULL),
+ pChooseReward(NULL), pItemHello(NULL), pGOHello(NULL), pAreaTrigger(NULL), pProcessEventId(NULL), pItemQuestAccept(NULL),
+ pQuestAccept(NULL), pGOQuestAccept(NULL), pGOChooseReward(NULL), pItemUse(NULL),
+ pEffectDummyCreature(NULL), pEffectDummyGameObj(NULL), pEffectDummyItem(NULL), pEffectAuraDummy(NULL),
+ GetAI(NULL), GetInstanceData(NULL)
+ {}
+
+ std::string Name;
+
+ //Methods to be scripted
+ bool (*pGossipHello )(Player*, Creature*);
+ bool (*pGOGossipHello )(Player*, GameObject*);
+ bool (*pQuestAccept )(Player*, Creature*, const Quest*);
+ bool (*pGossipSelect )(Player*, Creature*, uint32, uint32);
+ bool (*pGOGossipSelect )(Player*, GameObject*, uint32, uint32);
+ bool (*pGossipSelectWithCode )(Player*, Creature*, uint32, uint32, const char*);
+ bool (*pGOGossipSelectWithCode )(Player*, GameObject*, uint32, uint32, const char*);
+ bool (*pQuestSelect )(Player*, Creature*, const Quest*);
+ bool (*pQuestComplete )(Player*, Creature*, const Quest*);
+ uint32 (*pNPCDialogStatus )(Player*, Creature*);
+ uint32 (*pGODialogStatus )(Player*, GameObject*);
+ bool (*pChooseReward )(Player*, Creature*, const Quest*, uint32);
+ bool (*pItemHello )(Player*, Item*, const Quest*);
+ bool (*pGOHello )(Player*, GameObject*);
+ bool (*pAreaTrigger )(Player*, AreaTriggerEntry const*);
+ bool (*pProcessEventId )(uint32, Object*, Object*, bool);
+ bool (*pItemQuestAccept )(Player*, Item*, const Quest*);
+ bool (*pGOQuestAccept )(Player*, GameObject*, const Quest*);
+ bool (*pGOChooseReward )(Player*, GameObject*, const Quest*, uint32);
+ bool (*pItemUse )(Player*, Item*, SpellCastTargets const&);
+ bool (*pEffectDummyCreature )(Unit*, uint32, SpellEffectIndex, Creature*);
+ bool (*pEffectDummyGameObj )(Unit*, uint32, SpellEffectIndex, GameObject*);
+ bool (*pEffectDummyItem )(Unit*, uint32, SpellEffectIndex, Item*);
+ bool (*pEffectAuraDummy )(const Aura*, bool);
+
+ CreatureAI* (*GetAI)(Creature*);
+ InstanceData* (*GetInstanceData)(Map*);
+
+ void RegisterSelf(bool bReportError = true);
+};
+
+//Generic scripting text function
+void DoScriptText(int32 iTextEntry, WorldObject* pSource, Unit* pTarget = NULL);
+
+#if COMPILER == COMPILER_GNU
+#define FUNC_PTR(name,callconvention,returntype,parameters) typedef returntype(*name)parameters __attribute__ ((callconvention));
+#else
+#define FUNC_PTR(name, callconvention, returntype, parameters) typedef returntype(callconvention *name)parameters;
+#endif
+
+#endif
diff --git a/VC100/100ScriptDev2.vcxproj b/VC100/100ScriptDev2.vcxproj
new file mode 100644
index 0000000..a7eabb3
--- /dev/null
+++ b/VC100/100ScriptDev2.vcxproj
@@ -0,0 +1,772 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Debug
+ x64
+
+
+ Release
+ Win32
+
+
+ Release
+ x64
+
+
+
+ ScriptDev2
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}
+ ScriptDev2
+ Win32Proj
+
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+ DynamicLibrary
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFileVersion>10.0.30319.1
+ ..\..\..\..\bin\win32_debug\
+ .\ScriptDev2__$(Platform)_$(Configuration)\
+ true
+ ..\..\..\..\bin\x64_debug\
+ .\ScriptDev2__$(Platform)_$(Configuration)\
+ true
+ ..\..\..\..\bin\win32_release\
+ .\ScriptDev2__$(Platform)_$(Configuration)\
+ false
+ ..\..\..\..\bin\x64_release\
+ .\ScriptDev2__$(Platform)_$(Configuration)\
+ false
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ AllRules.ruleset
+
+
+ mangosscript
+ mangosscript
+ mangosscript
+ mangosscript
+
+
+
+ Disabled
+ ..\..\..\..\dep\include\;..\..\..\shared\;..\..\..\framework\;..\..\..\game\;..\include\;..\base\;..\..\..\..\dep\ACE_wrappers\;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;MANGOS_DEBUG;_WINDOWS;_USRDLL;SCRIPT;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ Use
+ precompiled.h
+ Level3
+ ProgramDatabase
+ true
+ true
+ true
+
+
+ mangosd.lib;ACEd.lib;framework.lib;%(AdditionalDependencies)
+ ..\..\..\..\win\VC100\mangosd__Win32_Debug;..\..\..\..\win\VC100\framework__Win32_Debug;..\..\..\..\dep\lib\win32_debug\;%(AdditionalLibraryDirectories)
+ true
+ Windows
+ false
+
+
+ $(OutDir)mangosscript.lib
+ MachineX86
+
+
+
+
+ X64
+
+
+ Disabled
+ ..\..\..\..\dep\include\;..\..\..\shared\;..\..\..\framework\;..\..\..\game\;..\include\;..\base\;..\..\..\..\dep\ACE_wrappers\;%(AdditionalIncludeDirectories)
+ WIN32;_DEBUG;MANGOS_DEBUG;_WINDOWS;_USRDLL;SCRIPT;%(PreprocessorDefinitions)
+ true
+ EnableFastChecks
+ MultiThreadedDebugDLL
+ Use
+ precompiled.h
+ Level3
+ ProgramDatabase
+ true
+ true
+ true
+
+
+ mangosd.lib;ACEd.lib;framework.lib;%(AdditionalDependencies)
+ ..\..\..\..\win\VC100\mangosd__x64_Debug;..\..\..\..\win\VC100\framework__x64_Debug;..\..\..\..\dep\lib\x64_Debug\;%(AdditionalLibraryDirectories)
+ true
+ Windows
+ false
+
+
+ $(OutDir)mangosscript.lib
+ MachineX64
+
+
+
+
+ /MP %(AdditionalOptions)
+ ..\..\..\..\dep\include\;..\..\..\shared\;..\..\..\framework\;..\..\..\game\;..\include\;..\base\;..\..\..\..\dep\ACE_wrappers\;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;SCRIPT;_SECURE_SCL=0;%(PreprocessorDefinitions)
+ false
+ MultiThreadedDLL
+ Use
+ precompiled.h
+ Level3
+ ProgramDatabase
+ true
+ true
+ true
+
+
+ mangosd.lib;ACE.lib;framework.lib;%(AdditionalDependencies)
+ ..\..\..\..\win\VC100\mangosd__Win32_Release;..\..\..\..\win\VC100\framework__Win32_Release;..\..\..\..\dep\lib\win32_release\;%(AdditionalLibraryDirectories)
+ true
+ Windows
+ true
+ true
+ false
+
+
+ $(OutDir)mangosscript.lib
+
+
+
+
+ X64
+
+
+ /MP %(AdditionalOptions)
+ ..\..\..\..\dep\include\;..\..\..\shared\;..\..\..\framework\;..\..\..\game\;..\include\;..\base\;..\..\..\..\dep\ACE_wrappers\;%(AdditionalIncludeDirectories)
+ WIN32;NDEBUG;_WINDOWS;_USRDLL;SCRIPT;_SECURE_SCL=0;%(PreprocessorDefinitions)
+ MultiThreadedDLL
+ Use
+ precompiled.h
+ Level3
+ ProgramDatabase
+ true
+ true
+ true
+
+
+ mangosd.lib;ACE.lib;framework.lib;%(AdditionalDependencies)
+ ..\..\..\..\win\VC100\mangosd__x64_Release;..\..\..\..\win\VC100\framework__x64_Release;..\..\..\..\dep\lib\x64_release\;%(AdditionalLibraryDirectories)
+ true
+ Windows
+ true
+ true
+ false
+
+
+ $(OutDir)mangosscript.lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Create
+ Create
+ Create
+ Create
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Extracting revision
+ cd "$(SolutionDir)"
+"$(SolutionDir)..\..\..\win\VC100\genrevision__Win32_$(Configuration)\genrevision.exe"
+
+ .svn/entries;%(AdditionalInputs)
+ revision.h;%(Outputs)
+ Extracting revision
+ cd "$(SolutionDir)"
+"$(SolutionDir)..\..\..\win\VC100\genrevision__Win32_$(Configuration)\genrevision.exe"
+
+ .svn/entries;%(AdditionalInputs)
+ revision.h;%(Outputs)
+ Extracting revision
+ cd "$(SolutionDir)"
+"$(SolutionDir)..\..\..\win\VC100\genrevision__Win32_$(Configuration)\genrevision.exe"
+
+ .svn/entries;%(AdditionalInputs)
+ revision.h;%(Outputs)
+ Extracting revision
+ cd "$(SolutionDir)"
+"$(SolutionDir)..\..\..\win\VC100\genrevision__Win32_$(Configuration)\genrevision.exe"
+
+ .svn/entries;%(AdditionalInputs)
+ revision.h;%(Outputs)
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VC100/100ScriptDev2.vcxproj.filters b/VC100/100ScriptDev2.vcxproj.filters
new file mode 100644
index 0000000..53595c0
--- /dev/null
+++ b/VC100/100ScriptDev2.vcxproj.filters
@@ -0,0 +1,1869 @@
+
+
+
+
+ {3b1307a9-bc58-4773-9a93-0e9ceff55c82}
+
+
+ {b7b35df3-4231-4370-aed5-5859ab4c312e}
+
+
+ {ced0a1e2-6867-4f01-a762-390a3d1f01d3}
+
+
+ {af3d4b4d-a585-41c4-ba95-79669a614ea8}
+
+
+ {ca2551e0-68d0-4331-88f3-ab0cdaa2bf9a}
+
+
+ {45c59280-02fb-482f-859b-bd47cc230f0f}
+
+
+ {5631f38e-66c8-4efd-ad3a-2834fbb49a6e}
+
+
+ {31605090-12b9-4d42-a5e9-1cbfac8ab384}
+
+
+ {08fb5b22-710d-46d6-9893-f567aa75a5e6}
+
+
+ {cef5c3c5-f434-4b9f-9bad-8c106d46c755}
+
+
+ {66bc2cec-8372-4191-991c-1c23275fa13c}
+
+
+ {af465469-5a16-4908-aa08-39c77d02cd88}
+
+
+ {920d1832-b347-4afd-bd05-4c943e5555f0}
+
+
+ {6ffd42e5-ac49-4635-8087-77ad2b7b0866}
+
+
+ {dd4995a8-6d86-4f21-82bc-a18acc2c688f}
+
+
+ {2a3a25e5-51f1-4ab3-a1a0-1b9ec9c45d1a}
+
+
+ {7a028ad9-afa1-42ea-b147-20a40c5e716c}
+
+
+ {66401dac-d94c-4ed6-b912-229dda0906d6}
+
+
+ {385f26dc-dcaf-4022-921d-3a562617bf93}
+
+
+ {25be39dd-536d-450d-ac94-6372d37a4fae}
+
+
+ {1d718eaa-2a8d-4cb9-9abf-17fcf0d91f83}
+
+
+ {c929f54b-22dd-49b4-862c-92dfa9a2d1f7}
+
+
+ {60b91cfe-7dff-40de-9957-41f8d03144cc}
+
+
+ {22eca3e6-662f-4c53-9344-6e749c09c86b}
+
+
+ {070541ef-a813-43f5-a8a6-e6674fe1a47e}
+
+
+ {5cda7bda-399b-46b7-8bc2-5786f0202fa2}
+
+
+ {226d4dc8-830b-4249-b28a-313ac21080a9}
+
+
+ {404b30fd-bdaa-44d1-ab3a-384886ebb8ec}
+
+
+ {5833dbce-1fa8-49eb-b678-145a2d58a067}
+
+
+ {dc38d3fe-d1fe-49f2-bd8f-758cd270dd62}
+
+
+ {2552ab59-1f73-4778-a6db-6f03e405622d}
+
+
+ {8206776b-4d43-431d-bca5-5f6cff157ea4}
+
+
+ {02135a7c-33cc-444e-af90-48a5193e5a6f}
+
+
+ {014ada9a-13bf-4540-a0ce-5132bdc36fcf}
+
+
+ {9feb59d0-e6bd-4328-9a50-7ddb9852936e}
+
+
+ {00f03f8d-4af1-40d9-a95a-e2dc1a81ca7d}
+
+
+ {de2e959a-1ef4-41ef-9235-15a1f3f8a19d}
+
+
+ {8f8a60e0-223e-4517-918c-243e523a7892}
+
+
+ {416ccfc8-a1bb-43a5-b202-d7656981094a}
+
+
+ {ba031a13-787e-41da-bcaf-1986fdea8069}
+
+
+ {0412262e-b05b-4827-adef-97507204cb69}
+
+
+ {e775610e-fa3c-4355-9c4c-473a6a5e57d5}
+
+
+ {6c5f7fd4-671b-4cba-aa95-7758b93dc844}
+
+
+ {71e87e58-3b30-41e7-8f8a-16886508a4d9}
+
+
+ {3cf8e088-da94-4561-993f-2970908d6642}
+
+
+ {bc0156b2-6544-4ebc-9ed6-fe45ac1902a4}
+
+
+ {b59c73a8-c480-43b2-8a2e-65f5a54978eb}
+
+
+ {5eb6a84a-97e6-477e-97e3-23681f29f675}
+
+
+ {d7e0e45a-fd89-48a6-8d24-f4922058160e}
+
+
+ {71617682-fe62-4d7c-a2de-7181fb3f46f6}
+
+
+ {9c5d9a0f-8967-4cf6-a047-3b724f81dc29}
+
+
+ {42501e94-f91e-40be-a02a-472b5ca1e22c}
+
+
+ {aac6b8be-6055-4d7d-a50a-41650b8d464e}
+
+
+ {e7ee3113-f4d0-4e28-acc7-dc80f42d41df}
+
+
+ {e603d4b3-3c2f-4011-aa2b-040243163d3f}
+
+
+ {36c79ad7-420c-4909-8da3-c90d3cc83b31}
+
+
+ {d47410b0-3184-40e2-8704-cea9b97e20ed}
+
+
+ {1b2f0d99-82b0-4a96-aaac-c485830eb1b3}
+
+
+ {fd594031-4dc2-40de-b37b-93063ee6e3e9}
+
+
+ {ef27a557-e12d-4b02-9e86-c258329f201e}
+
+
+ {b7e4ad7d-8515-4981-ae27-9e542c223618}
+
+
+ {04b1d59c-38b6-4b5c-a50d-b9ff1d39bb30}
+
+
+ {ee364414-732a-4aad-820f-a5b73cb8b093}
+
+
+ {638d5426-652e-4d1f-9abe-3ed95d7e7e69}
+
+
+ {a21893a5-0f34-4a73-b0aa-49b175822834}
+
+
+ {728148f8-18a0-4606-a2ec-2c9eae4e5e7e}
+
+
+ {88c327d5-0768-465f-b954-30eca0d31f45}
+
+
+ {b20efa19-1e16-42e4-bc29-a9c8e282d17c}
+
+
+ {fec1fbfa-5119-4bb0-98bc-f8d4583521f7}
+
+
+ {1cb43523-dc33-4c49-a5b7-6e700fe0ecd6}
+
+
+ {7289cc07-6956-4b09-8dc5-753c82abe8c9}
+
+
+ {e834cf7b-88ad-4bae-9fc8-8e027136c63b}
+
+
+ {cfb08e82-63e6-49ca-bff2-533f8647797b}
+
+
+ {2be3084e-c5c0-4e2f-bbb4-2ebb22bfff19}
+
+
+ {6dc08e92-3e86-4a7f-bab9-9a8cec6a201b}
+
+
+ {01da56d1-ee04-455c-846c-4e53869314f6}
+
+
+ {5e79ca74-cd29-47ff-a08e-3fada858ddd7}
+
+
+ {32b92545-4821-4cc8-ae39-f631b0176d46}
+
+
+ {044e4dbc-e2fc-437c-b359-b6fb5a3439ff}
+
+
+ {4cbcf193-4d98-4518-a9c4-6c8b4bedbf44}
+
+
+ {5c32221e-3532-4c32-bdba-9a85213006af}
+
+
+ {2df99085-aee2-4202-b4d1-38a5cc35f3e2}
+
+
+ {0a109c31-6dd3-4030-8d6c-6c0e147481be}
+
+
+ {ddada980-2eed-4f2b-a9f7-dbb9cca7ca3d}
+
+
+ {d6843352-6425-48da-85b6-6b26f6217ba8}
+
+
+ {6a68396b-343f-4c79-938c-93741acdeb41}
+
+
+ {974fc97c-e585-442c-b35e-b21a17804619}
+
+
+ {ba709b56-d5db-4730-9591-79b8f9788ca1}
+
+
+ {1fa90250-9c5b-450c-be64-d9eee910c4a8}
+
+
+ {7b3c1c18-03e9-493e-a364-5beb1a6936eb}
+
+
+ {575420cc-581f-4d08-a9da-7814f221ab47}
+
+
+ {9c5997ee-accc-4737-815f-b031d422577b}
+
+
+ {579f2f5c-acf1-410a-bce6-d353d6912546}
+
+
+ {04e4571d-55ee-4f2e-ac4e-46fc2610341f}
+
+
+ {79a3e62b-bd96-4d16-8c23-bda17f968d19}
+
+
+ {ca7213e9-56c1-4084-a48b-19ff57dee433}
+
+
+ {2fd46769-c050-4e47-9533-461ef8695d6a}
+
+
+ {90f3df6a-a1d0-4a6e-b8d7-d1d993fc795b}
+
+
+ {e35abead-2389-4eb9-88bd-70e6fe5636b5}
+
+
+
+
+ base
+
+
+ base
+
+
+ base
+
+
+ scripts\battlegrounds
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackrock_spire
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\blackwing_lair
+
+
+ scripts\eastern_kingdoms\deadmines
+
+
+ scripts\eastern_kingdoms\deadmines
+
+
+ scripts\eastern_kingdoms\gnomeregan
+
+
+ scripts\eastern_kingdoms\gnomeregan
+
+
+ scripts\eastern_kingdoms\gnomeregan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\magisters_terrace
+
+
+ scripts\eastern_kingdoms\magisters_terrace
+
+
+ scripts\eastern_kingdoms\magisters_terrace
+
+
+ scripts\eastern_kingdoms\magisters_terrace
+
+
+ scripts\eastern_kingdoms\magisters_terrace
+
+
+ scripts\eastern_kingdoms\magisters_terrace
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\scarlet_enclave
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\shadowfang_keep
+
+
+ scripts\eastern_kingdoms\shadowfang_keep
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\sunken_temple
+
+
+ scripts\eastern_kingdoms\sunken_temple
+
+
+ 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
+
+
+ scripts\eastern_kingdoms\uldaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\examples
+
+
+ scripts\examples
+
+
+ scripts\examples
+
+
+ scripts\examples
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor
+
+
+ scripts\kalimdor\blackfathom_deeps
+
+
+ scripts\kalimdor\caverns_of_time\culling_of_stratholme
+
+
+ scripts\kalimdor\caverns_of_time\culling_of_stratholme
+
+
+ scripts\kalimdor\caverns_of_time\dark_portal
+
+
+ scripts\kalimdor\caverns_of_time\dark_portal
+
+
+ scripts\kalimdor\caverns_of_time\dark_portal
+
+
+ scripts\kalimdor\caverns_of_time\dark_portal
+
+
+ scripts\kalimdor\caverns_of_time\dark_portal
+
+
+ scripts\kalimdor\caverns_of_time\hyjal
+
+
+ scripts\kalimdor\caverns_of_time\hyjal
+
+
+ scripts\kalimdor\caverns_of_time\hyjal
+
+
+ scripts\kalimdor\caverns_of_time\hyjal
+
+
+ scripts\kalimdor\caverns_of_time\old_hillsbrad
+
+
+ scripts\kalimdor\caverns_of_time\old_hillsbrad
+
+
+ scripts\kalimdor\caverns_of_time\old_hillsbrad
+
+
+ scripts\kalimdor\caverns_of_time\old_hillsbrad
+
+
+ scripts\kalimdor\caverns_of_time\old_hillsbrad
+
+
+ scripts\kalimdor\maraudon
+
+
+ scripts\kalimdor\maraudon
+
+
+ scripts\kalimdor\maraudon
+
+
+ scripts\kalimdor\maraudon
+
+
+ scripts\kalimdor\onyxias_lair
+
+
+ scripts\kalimdor\onyxias_lair
+
+
+ scripts\kalimdor\razorfen_downs
+
+
+ scripts\kalimdor\razorfen_downs
+
+
+ scripts\kalimdor\razorfen_kraul
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\wailing_caverns
+
+
+ scripts\kalimdor\zulfarrak
+
+
+ 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\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_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\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\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
+
+
+ scripts\northrend\ulduar\halls_of_lightning
+
+
+ scripts\northrend\ulduar\halls_of_stone
+
+
+ scripts\northrend\ulduar\halls_of_stone
+
+
+ scripts\northrend\ulduar\halls_of_stone
+
+
+ scripts\northrend\ulduar\halls_of_stone
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\ulduar\ulduar
+
+
+ scripts\northrend\utgarde_keep\utgarde_keep
+
+
+ scripts\northrend\utgarde_keep\utgarde_keep
+
+
+ scripts\northrend\utgarde_keep\utgarde_keep
+
+
+ scripts\northrend\utgarde_keep\utgarde_keep
+
+
+ scripts\northrend\utgarde_keep\utgarde_keep
+
+
+ scripts\northrend\utgarde_keep\utgarde_pinnacle
+
+
+ scripts\northrend\utgarde_keep\utgarde_pinnacle
+
+
+ scripts\northrend\utgarde_keep\utgarde_pinnacle
+
+
+ scripts\northrend\utgarde_keep\utgarde_pinnacle
+
+
+ scripts\northrend\utgarde_keep\utgarde_pinnacle
+
+
+ scripts\northrend\violet_hold
+
+
+ scripts\northrend\violet_hold
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\icecrown_citadel
+
+
+ scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron
+
+
+ scripts\northrend\icecrown_citadel\frozen_halls\pit_of_saron
+
+
+ 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\halls_of_reflection
+
+
+ scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls
+
+
+ scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls
+
+
+ scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland
+
+
+ scripts\outland\auchindoun\auchenai_crypts
+
+
+ scripts\outland\auchindoun\mana_tombs
+
+
+ scripts\outland\auchindoun\mana_tombs
+
+
+ scripts\outland\auchindoun\sethekk_halls
+
+
+ scripts\outland\auchindoun\sethekk_halls
+
+
+ scripts\outland\auchindoun\sethekk_halls
+
+
+ scripts\outland\auchindoun\shadow_labyrinth
+
+
+ scripts\outland\auchindoun\shadow_labyrinth
+
+
+ scripts\outland\auchindoun\shadow_labyrinth
+
+
+ scripts\outland\auchindoun\shadow_labyrinth
+
+
+ scripts\outland\auchindoun\shadow_labyrinth
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\coilfang_reservoir\serpent_shrine
+
+
+ scripts\outland\coilfang_reservoir\serpent_shrine
+
+
+ scripts\outland\coilfang_reservoir\serpent_shrine
+
+
+ scripts\outland\coilfang_reservoir\serpent_shrine
+
+
+ scripts\outland\coilfang_reservoir\serpent_shrine
+
+
+ scripts\outland\coilfang_reservoir\serpent_shrine
+
+
+ scripts\outland\coilfang_reservoir\steam_vault
+
+
+ scripts\outland\coilfang_reservoir\steam_vault
+
+
+ scripts\outland\coilfang_reservoir\steam_vault
+
+
+ scripts\outland\coilfang_reservoir\steam_vault
+
+
+ scripts\outland\coilfang_reservoir\underbog
+
+
+ scripts\outland\gruuls_lair
+
+
+ scripts\outland\gruuls_lair
+
+
+ scripts\outland\gruuls_lair
+
+
+ scripts\outland\hellfire_citadel\blood_furnace
+
+
+ scripts\outland\hellfire_citadel\blood_furnace
+
+
+ scripts\outland\hellfire_citadel\blood_furnace
+
+
+ scripts\outland\hellfire_citadel\blood_furnace
+
+
+ scripts\outland\hellfire_citadel\hellfire_ramparts
+
+
+ scripts\outland\hellfire_citadel\hellfire_ramparts
+
+
+ scripts\outland\hellfire_citadel\hellfire_ramparts
+
+
+ scripts\outland\hellfire_citadel\hellfire_ramparts
+
+
+ scripts\outland\hellfire_citadel\magtheridons_lair
+
+
+ scripts\outland\hellfire_citadel\magtheridons_lair
+
+
+ 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\ruby_sanctum
+
+
+ scripts\northrend\ruby_sanctum
+
+
+ scripts\northrend\ruby_sanctum
+
+
+ scripts\northrend\ruby_sanctum
+
+
+
+
+ base
+
+
+ base
+
+
+ base
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\blackrock_depths
+
+
+ scripts\eastern_kingdoms\deadmines
+
+
+ scripts\eastern_kingdoms\gnomeregan
+
+
+ scripts\eastern_kingdoms\karazhan
+
+
+ scripts\eastern_kingdoms\magisters_terrace
+
+
+ scripts\eastern_kingdoms\molten_core
+
+
+ scripts\eastern_kingdoms\scarlet_monastery
+
+
+ scripts\eastern_kingdoms\scholomance
+
+
+ scripts\eastern_kingdoms\shadowfang_keep
+
+
+ scripts\eastern_kingdoms\stratholme
+
+
+ scripts\eastern_kingdoms\sunken_temple
+
+
+ scripts\eastern_kingdoms\sunwell_plateau
+
+
+ scripts\eastern_kingdoms\uldaman
+
+
+ scripts\eastern_kingdoms\zulaman
+
+
+ scripts\eastern_kingdoms\zulgurub
+
+
+ scripts\kalimdor\blackfathom_deeps
+
+
+ scripts\kalimdor\caverns_of_time\culling_of_stratholme
+
+
+ scripts\kalimdor\caverns_of_time\dark_portal
+
+
+ scripts\kalimdor\caverns_of_time\hyjal
+
+
+ scripts\kalimdor\caverns_of_time\hyjal
+
+
+ scripts\kalimdor\caverns_of_time\old_hillsbrad
+
+
+ scripts\kalimdor\onyxias_lair
+
+
+ scripts\kalimdor\razorfen_kraul
+
+
+ scripts\kalimdor\ruins_of_ahnqiraj
+
+
+ scripts\kalimdor\temple_of_ahnqiraj
+
+
+ scripts\kalimdor\wailing_caverns
+
+
+ scripts\northrend\azjol-nerub\ahnkahet
+
+
+ scripts\northrend\azjol-nerub\azjol-nerub
+
+
+ scripts\northrend\crusaders_coliseum\trial_of_the_crusader
+
+
+ scripts\northrend\gundrak
+
+
+ scripts\northrend\icecrown_citadel\frozen_halls\forge_of_souls
+
+
+ scripts\northrend\naxxramas
+
+
+ scripts\northrend\nexus\nexus
+
+
+ scripts\northrend\obsidian_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\violet_hold
+
+
+ scripts\outland\auchindoun\sethekk_halls
+
+
+ scripts\outland\auchindoun\shadow_labyrinth
+
+
+ scripts\outland\black_temple
+
+
+ scripts\outland\coilfang_reservoir\serpent_shrine
+
+
+ scripts\outland\coilfang_reservoir\steam_vault
+
+
+ scripts\outland\gruuls_lair
+
+
+ scripts\outland\hellfire_citadel\blood_furnace
+
+
+ scripts\outland\hellfire_citadel\hellfire_ramparts
+
+
+ scripts\outland\hellfire_citadel\magtheridons_lair
+
+
+ scripts\outland\hellfire_citadel\shattered_halls
+
+
+ scripts\outland\tempest_keep\arcatraz
+
+
+ scripts\outland\tempest_keep\the_eye
+
+
+ scripts\outland\tempest_keep\the_mechanar
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ include
+
+
+ system
+
+
+ system
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/VC80/80ScriptDev2.vcproj b/VC80/80ScriptDev2.vcproj
new file mode 100644
index 0000000..79f33f6
--- /dev/null
+++ b/VC80/80ScriptDev2.vcproj
@@ -0,0 +1,2924 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/VC90/90ScriptDev2.vcproj b/VC90/90ScriptDev2.vcproj
new file mode 100644
index 0000000..d701a13
--- /dev/null
+++ b/VC90/90ScriptDev2.vcproj
@@ -0,0 +1,2967 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/base/escort_ai.cpp b/base/escort_ai.cpp
new file mode 100644
index 0000000..ecc4a62
--- /dev/null
+++ b/base/escort_ai.cpp
@@ -0,0 +1,519 @@
+/* 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 */
+
+/* ScriptData
+SDName: EscortAI
+SD%Complete: 100
+SDComment:
+SDCategory: Npc
+EndScriptData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+const float MAX_PLAYER_DISTANCE = 66.0f;
+
+enum
+{
+ POINT_LAST_POINT = 0xFFFFFF,
+ POINT_HOME = 0xFFFFFE
+};
+
+npc_escortAI::npc_escortAI(Creature* pCreature) : ScriptedAI(pCreature),
+ m_uiPlayerGUID(0),
+ m_uiPlayerCheckTimer(1000),
+ m_uiWPWaitTimer(2500),
+ m_uiEscortState(STATE_ESCORT_NONE),
+ m_bIsRunning(false),
+ m_pQuestForEscort(NULL),
+ m_bCanInstantRespawn(false),
+ m_bCanReturnToStart(false)
+{}
+
+bool npc_escortAI::IsVisible(Unit* pWho) const
+{
+ if (!pWho)
+ return false;
+
+ return m_creature->IsWithinDist(pWho, VISIBLE_RANGE) && pWho->isVisibleForOrDetect(m_creature, m_creature, true);
+}
+
+void npc_escortAI::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 (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
+ m_creature->GetMotionMaster()->MovementExpired();
+
+ if (IsCombatMovement())
+ m_creature->GetMotionMaster()->MoveChase(pWho);
+ }
+}
+
+void npc_escortAI::EnterCombat(Unit* pEnemy)
+{
+ if (!pEnemy)
+ return;
+
+ Aggro(pEnemy);
+}
+
+void npc_escortAI::Aggro(Unit* pEnemy)
+{
+}
+
+//see followerAI
+bool npc_escortAI::AssistPlayerInCombat(Unit* pWho)
+{
+ if (!pWho->getVictim())
+ return false;
+
+ // experimental (unknown) flag not present
+ if (!(m_creature->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_CAN_ASSIST))
+ return false;
+
+ // unit state prevents (similar check is done in CanInitiateAttack which also include checking unit_flags. We skip those here)
+ if (m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED))
+ return false;
+
+ // victim of pWho is not a player
+ if (!pWho->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
+ return false;
+
+ // never attack friendly
+ if (m_creature->IsFriendlyTo(pWho))
+ return false;
+
+ // too far away and no free sight?
+ if (m_creature->IsWithinDistInMap(pWho, MAX_PLAYER_DISTANCE) && m_creature->IsWithinLOSInMap(pWho))
+ {
+ // already fighting someone?
+ if (!m_creature->getVictim())
+ {
+ AttackStart(pWho);
+ return true;
+ }
+ else
+ {
+ pWho->SetInCombatWith(m_creature);
+ m_creature->AddThreat(pWho);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void npc_escortAI::MoveInLineOfSight(Unit* pWho)
+{
+ if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature))
+ {
+ // AssistPlayerInCombat can start attack, so return if true
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombat(pWho))
+ return;
+
+ if (!m_creature->CanInitiateAttack())
+ return;
+
+ if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
+ return;
+
+ if (m_creature->IsHostileTo(pWho))
+ {
+ float fAttackRadius = m_creature->GetAttackDistance(pWho);
+ if (m_creature->IsWithinDistInMap(pWho, fAttackRadius) && 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);
+ }
+ }
+ }
+ }
+}
+
+void npc_escortAI::JustDied(Unit* pKiller)
+{
+ if (!HasEscortState(STATE_ESCORT_ESCORTING) || !m_uiPlayerGUID || !m_pQuestForEscort)
+ return;
+
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ if (Group* pGroup = pPlayer->GetGroup())
+ {
+ for(GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
+ {
+ if (Player* pMember = pRef->getSource())
+ {
+ if (pMember->GetQuestStatus(m_pQuestForEscort->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
+ pMember->FailQuest(m_pQuestForEscort->GetQuestId());
+ }
+ }
+ }
+ else
+ {
+ if (pPlayer->GetQuestStatus(m_pQuestForEscort->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->FailQuest(m_pQuestForEscort->GetQuestId());
+ }
+ }
+}
+
+void npc_escortAI::JustRespawned()
+{
+ m_uiEscortState = STATE_ESCORT_NONE;
+
+ if (!IsCombatMovement())
+ SetCombatMovement(true);
+
+ //add a small delay before going to first waypoint, normal in near all cases
+ m_uiWPWaitTimer = 2500;
+
+ if (m_creature->getFaction() != m_creature->GetCreatureInfo()->faction_A)
+ m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A);
+
+ Reset();
+}
+
+void npc_escortAI::EnterEvadeMode()
+{
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(true);
+ m_creature->SetLootRecipient(NULL);
+
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ debug_log("SD2: EscortAI has left combat and is now returning to CombatStartPosition.");
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
+ {
+ AddEscortState(STATE_ESCORT_RETURNING);
+
+ float fPosX, fPosY, fPosZ;
+ m_creature->GetCombatStartPosition(fPosX, fPosY, fPosZ);
+ m_creature->GetMotionMaster()->MovePoint(POINT_LAST_POINT, fPosX, fPosY, fPosZ);
+ }
+ }
+ else
+ {
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
+ m_creature->GetMotionMaster()->MoveTargetedHome();
+ }
+
+ Reset();
+}
+
+bool npc_escortAI::IsPlayerOrGroupInRange()
+{
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ if (Group* pGroup = pPlayer->GetGroup())
+ {
+ for(GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
+ {
+ Player* pMember = pRef->getSource();
+
+ if (pMember && m_creature->IsWithinDistInMap(pMember, MAX_PLAYER_DISTANCE))
+ {
+ return true;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (m_creature->IsWithinDistInMap(pPlayer, MAX_PLAYER_DISTANCE))
+ return true;
+ }
+ }
+ return false;
+}
+
+void npc_escortAI::UpdateAI(const uint32 uiDiff)
+{
+ //Waypoint Updating
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && !m_creature->getVictim() && m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_RETURNING))
+ {
+ if (m_uiWPWaitTimer <= uiDiff)
+ {
+ //End of the line
+ if (CurrentWP == WaypointList.end())
+ {
+ debug_log("SD2: EscortAI reached end of waypoints");
+
+ if (m_bCanReturnToStart)
+ {
+ float fRetX, fRetY, fRetZ;
+ m_creature->GetRespawnCoord(fRetX, fRetY, fRetZ);
+
+ m_creature->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ);
+
+ m_uiWPWaitTimer = 0;
+
+ debug_log("SD2: EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
+ return;
+ }
+
+ if (m_bCanInstantRespawn)
+ {
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->Respawn();
+ }
+ else
+ m_creature->ForcedDespawn();
+
+ return;
+ }
+
+ if (!HasEscortState(STATE_ESCORT_PAUSED))
+ {
+ m_creature->GetMotionMaster()->MovePoint(CurrentWP->uiId, CurrentWP->fX, CurrentWP->fY, CurrentWP->fZ);
+ debug_log("SD2: EscortAI start waypoint %u (%f, %f, %f).", CurrentWP->uiId, CurrentWP->fX, CurrentWP->fY, CurrentWP->fZ);
+
+ WaypointStart(CurrentWP->uiId);
+
+ m_uiWPWaitTimer = 0;
+ }
+ }
+ else
+ m_uiWPWaitTimer -= uiDiff;
+ }
+
+ //Check if player or any member of his group is within range
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPlayerGUID && !m_creature->getVictim() && !HasEscortState(STATE_ESCORT_RETURNING))
+ {
+ if (m_uiPlayerCheckTimer < uiDiff)
+ {
+ if (!HasEscortState(STATE_ESCORT_PAUSED) && !IsPlayerOrGroupInRange())
+ {
+ debug_log("SD2: EscortAI failed because player/group was to far away or not found");
+
+ if (m_bCanInstantRespawn)
+ {
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->Respawn();
+ }
+ else
+ m_creature->ForcedDespawn();
+
+ return;
+ }
+
+ m_uiPlayerCheckTimer = 1000;
+ }
+ else
+ m_uiPlayerCheckTimer -= uiDiff;
+ }
+
+ UpdateEscortAI(uiDiff);
+}
+
+void npc_escortAI::UpdateEscortAI(const uint32 uiDiff)
+{
+ //Check if we have a current target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+}
+
+void npc_escortAI::MovementInform(uint32 uiMoveType, uint32 uiPointId)
+{
+ if (uiMoveType != POINT_MOTION_TYPE || !HasEscortState(STATE_ESCORT_ESCORTING))
+ return;
+
+ //Combat start position reached, continue waypoint movement
+ if (uiPointId == POINT_LAST_POINT)
+ {
+ debug_log("SD2: EscortAI has returned to original position before combat");
+
+ if (m_bIsRunning && m_creature->HasSplineFlag(SPLINEFLAG_WALKMODE))
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ else if (!m_bIsRunning && !m_creature->HasSplineFlag(SPLINEFLAG_WALKMODE))
+ m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE);
+
+ RemoveEscortState(STATE_ESCORT_RETURNING);
+
+ if (!m_uiWPWaitTimer)
+ m_uiWPWaitTimer = 1;
+ }
+ else if (uiPointId == POINT_HOME)
+ {
+ debug_log("SD2: EscortAI has returned to original home location and will continue from beginning of waypoint list.");
+
+ CurrentWP = WaypointList.begin();
+ m_uiWPWaitTimer = 1;
+ }
+ else
+ {
+ //Make sure that we are still on the right waypoint
+ if (CurrentWP->uiId != uiPointId)
+ {
+ error_log("SD2: EscortAI reached waypoint out of order %u, expected %u.", uiPointId, CurrentWP->uiId);
+ return;
+ }
+
+ debug_log("SD2: EscortAI waypoint %u reached.", CurrentWP->uiId);
+
+ //Call WP function
+ WaypointReached(CurrentWP->uiId);
+
+ m_uiWPWaitTimer = CurrentWP->uiWaitTime + 1;
+
+ ++CurrentWP;
+ }
+}
+
+/*void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 WaitTimeMs)
+{
+ Escort_Waypoint t(id, x, y, z, WaitTimeMs);
+
+ WaypointList.push_back(t);
+}*/
+
+void npc_escortAI::FillPointMovementListForCreature()
+{
+ std::vector const &pPointsEntries = pSystemMgr.GetPointMoveList(m_creature->GetEntry());
+
+ if (pPointsEntries.empty())
+ return;
+
+ std::vector::const_iterator itr;
+
+ for (itr = pPointsEntries.begin(); itr != pPointsEntries.end(); ++itr)
+ {
+ Escort_Waypoint pPoint(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime);
+ WaypointList.push_back(pPoint);
+ }
+}
+
+void npc_escortAI::SetCurrentWaypoint(uint32 uiPointId)
+{
+ if (!(HasEscortState(STATE_ESCORT_PAUSED))) // only when paused
+ return;
+
+ if (uiPointId >= WaypointList.size()) // too high number
+ return;
+
+ if (uiPointId == CurrentWP->uiId) // already here
+ return;
+
+ CurrentWP = WaypointList.begin(); // set to begin (can't -- backwards in itr list)
+
+ while(uiPointId != CurrentWP->uiId)
+ {
+ ++CurrentWP;
+
+ if (CurrentWP == WaypointList.end())
+ break;
+ }
+
+ m_uiWPWaitTimer = 1;
+
+ debug_log("SD2: EscortAI current waypoint set to id %u", CurrentWP->uiId);
+}
+
+void npc_escortAI::SetRun(bool bRun)
+{
+ if (bRun)
+ {
+ if (!m_bIsRunning)
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ else
+ debug_log("SD2: EscortAI attempt to set run mode, but is already running.");
+ }
+ else
+ {
+ if (m_bIsRunning)
+ m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE);
+ else
+ debug_log("SD2: EscortAI attempt to set walk mode, but is already walking.");
+ }
+ m_bIsRunning = bRun;
+}
+
+//TODO: get rid of this many variables passed in function.
+void npc_escortAI::Start(bool bRun, uint64 uiPlayerGUID, const Quest* pQuest, bool bInstantRespawn, bool bCanLoopPath)
+{
+ if (m_creature->getVictim())
+ {
+ error_log("SD2: EscortAI attempt to Start while in combat.");
+ return;
+ }
+
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ error_log("SD2: EscortAI attempt to Start while already escorting.");
+ return;
+ }
+
+ if (!WaypointList.empty())
+ WaypointList.clear();
+
+ FillPointMovementListForCreature();
+
+ if (WaypointList.empty())
+ {
+ error_db_log("SD2: EscortAI Start with 0 waypoints (possible missing entry in script_waypoint).");
+ return;
+ }
+
+ //set variables
+ m_bIsRunning = bRun;
+
+ m_uiPlayerGUID = uiPlayerGUID;
+ m_pQuestForEscort = pQuest;
+
+ m_bCanInstantRespawn = bInstantRespawn;
+ m_bCanReturnToStart = bCanLoopPath;
+
+ if (m_bCanReturnToStart && m_bCanInstantRespawn)
+ debug_log("SD2: EscortAI is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.");
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
+ {
+ m_creature->GetMotionMaster()->MovementExpired();
+ m_creature->GetMotionMaster()->MoveIdle();
+ debug_log("SD2: EscortAI start with WAYPOINT_MOTION_TYPE, changed to MoveIdle.");
+ }
+
+ //disable npcflags
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+
+ debug_log("SD2: EscortAI started with " SIZEFMTD " waypoints. Run = %d, PlayerGUID = " UI64FMTD, WaypointList.size(), m_bIsRunning, m_uiPlayerGUID);
+
+ CurrentWP = WaypointList.begin();
+
+ //Set initial speed
+ if (m_bIsRunning)
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+
+ AddEscortState(STATE_ESCORT_ESCORTING);
+
+ JustStartedEscort();
+}
+
+void npc_escortAI::SetEscortPaused(bool bPaused)
+{
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ return;
+
+ if (bPaused)
+ AddEscortState(STATE_ESCORT_PAUSED);
+ else
+ RemoveEscortState(STATE_ESCORT_PAUSED);
+}
diff --git a/base/escort_ai.h b/base/escort_ai.h
new file mode 100644
index 0000000..0d1b6f4
--- /dev/null
+++ b/base/escort_ai.h
@@ -0,0 +1,107 @@
+/* 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 */
+
+#ifndef SC_ESCORTAI_H
+#define SC_ESCORTAI_H
+
+#include "../system/system.h"
+
+struct Escort_Waypoint
+{
+ Escort_Waypoint(uint32 uiId, float fX, float fY, float fZ, uint32 uiWaitTime) :
+ uiId(uiId),
+ fX(fX),
+ fY(fY),
+ fZ(fZ),
+ uiWaitTime(uiWaitTime)
+ {}
+
+ uint32 uiId;
+ float fX;
+ float fY;
+ float fZ;
+ uint32 uiWaitTime;
+};
+
+enum eEscortState
+{
+ STATE_ESCORT_NONE = 0x000, //nothing in progress
+ STATE_ESCORT_ESCORTING = 0x001, //escort are in progress
+ STATE_ESCORT_RETURNING = 0x002, //escort is returning after being in combat
+ STATE_ESCORT_PAUSED = 0x004 //will not proceed with waypoints before state is removed
+};
+
+struct MANGOS_DLL_DECL npc_escortAI : public ScriptedAI
+{
+ public:
+ explicit npc_escortAI(Creature* pCreature);
+ ~npc_escortAI() {}
+
+ virtual void Aggro(Unit*);
+
+ virtual void Reset() = 0;
+
+ // CreatureAI functions
+ bool IsVisible(Unit*) const;
+
+ void AttackStart(Unit*);
+
+ void EnterCombat(Unit*);
+
+ void MoveInLineOfSight(Unit*);
+
+ void JustDied(Unit*);
+
+ void JustRespawned();
+
+ void EnterEvadeMode();
+
+ void UpdateAI(const uint32); //the "internal" update, calls UpdateEscortAI()
+ virtual void UpdateEscortAI(const uint32); //used when it's needed to add code in update (abilities, scripted events, etc)
+
+ void MovementInform(uint32, uint32);
+
+ // EscortAI functions
+ //void AddWaypoint(uint32 id, float x, float y, float z, uint32 WaitTimeMs = 0);
+
+ virtual void WaypointReached(uint32 uiPointId) = 0;
+ virtual void WaypointStart(uint32 uiPointId) {}
+
+ void Start(bool bRun = false, uint64 uiPlayerGUID = 0, const Quest* pQuest = NULL, bool bInstantRespawn = false, bool bCanLoopPath = false);
+
+ void SetRun(bool bRun = true);
+ void SetEscortPaused(bool uPaused);
+
+ bool HasEscortState(uint32 uiEscortState) { return (m_uiEscortState & uiEscortState); }
+
+ // update current point
+ void SetCurrentWaypoint(uint32 uiPointId);
+
+ protected:
+ Player* GetPlayerForEscort() { return m_creature->GetMap()->GetPlayer(m_uiPlayerGUID); }
+ virtual void JustStartedEscort() {}
+
+ private:
+ bool AssistPlayerInCombat(Unit* pWho);
+ bool IsPlayerOrGroupInRange();
+ void FillPointMovementListForCreature();
+
+ void AddEscortState(uint32 uiEscortState) { m_uiEscortState |= uiEscortState; }
+ void RemoveEscortState(uint32 uiEscortState) { m_uiEscortState &= ~uiEscortState; }
+
+ uint64 m_uiPlayerGUID;
+ uint32 m_uiWPWaitTimer;
+ uint32 m_uiPlayerCheckTimer;
+ uint32 m_uiEscortState;
+
+ const Quest* m_pQuestForEscort; //generally passed in Start() when regular escort script.
+
+ std::list WaypointList;
+ std::list::iterator CurrentWP;
+
+ bool m_bIsRunning; //all creatures are walking by default (has flag SPLINEFLAG_WALKMODE)
+ bool m_bCanInstantRespawn; //if creature should respawn instantly after escort over (if not, database respawntime are used)
+ bool m_bCanReturnToStart; //if creature can walk same path (loop) without despawn. Not for regular escort quests.
+};
+#endif
diff --git a/base/follower_ai.cpp b/base/follower_ai.cpp
new file mode 100644
index 0000000..f19ab72
--- /dev/null
+++ b/base/follower_ai.cpp
@@ -0,0 +1,387 @@
+/* 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 */
+
+/* ScriptData
+SDName: FollowerAI
+SD%Complete: 60
+SDComment: This AI is under development
+SDCategory: Npc
+EndScriptData */
+
+#include "precompiled.h"
+#include "follower_ai.h"
+
+const float MAX_PLAYER_DISTANCE = 100.0f;
+
+enum
+{
+ POINT_COMBAT_START = 0xFFFFFF
+};
+
+FollowerAI::FollowerAI(Creature* pCreature) : ScriptedAI(pCreature),
+ m_uiLeaderGUID(0),
+ m_pQuestForFollow(NULL),
+ m_uiUpdateFollowTimer(2500),
+ m_uiFollowState(STATE_FOLLOW_NONE)
+{}
+
+void FollowerAI::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);
+ }
+}
+
+//This part provides assistance to a player that are attacked by pWho, even if out of normal aggro range
+//It will cause m_creature to attack pWho that are attacking _any_ player (which has been confirmed may happen also on offi)
+bool FollowerAI::AssistPlayerInCombat(Unit* pWho)
+{
+ if (!pWho->getVictim())
+ return false;
+
+ // experimental (unknown) flag not present
+ if (!(m_creature->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_CAN_ASSIST))
+ return false;
+
+ // unit state prevents (similar check is done in CanInitiateAttack which also include checking unit_flags. We skip those here)
+ if (m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED))
+ return false;
+
+ // victim of pWho is not a player
+ if (!pWho->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
+ return false;
+
+ // never attack friendly
+ if (m_creature->IsFriendlyTo(pWho))
+ return false;
+
+ // too far away and no free sight?
+ if (m_creature->IsWithinDistInMap(pWho, MAX_PLAYER_DISTANCE) && m_creature->IsWithinLOSInMap(pWho))
+ {
+ // already fighting someone?
+ if (!m_creature->getVictim())
+ {
+ AttackStart(pWho);
+ return true;
+ }
+ else
+ {
+ pWho->SetInCombatWith(m_creature);
+ m_creature->AddThreat(pWho);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void FollowerAI::MoveInLineOfSight(Unit* pWho)
+{
+ if (pWho->isTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature))
+ {
+ // AssistPlayerInCombat can start attack, so return if true
+ if (HasFollowState(STATE_FOLLOW_INPROGRESS) && AssistPlayerInCombat(pWho))
+ return;
+
+ if (!m_creature->CanInitiateAttack())
+ return;
+
+ if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
+ return;
+
+ if (m_creature->IsHostileTo(pWho))
+ {
+ float fAttackRadius = m_creature->GetAttackDistance(pWho);
+ if (m_creature->IsWithinDistInMap(pWho, fAttackRadius) && 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);
+ }
+ }
+ }
+ }
+}
+
+void FollowerAI::JustDied(Unit* pKiller)
+{
+ if (!HasFollowState(STATE_FOLLOW_INPROGRESS) || !m_uiLeaderGUID || !m_pQuestForFollow)
+ return;
+
+ //TODO: need a better check for quests with time limit.
+ if (Player* pPlayer = GetLeaderForFollower())
+ {
+ if (Group* pGroup = pPlayer->GetGroup())
+ {
+ for(GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
+ {
+ if (Player* pMember = pRef->getSource())
+ {
+ if (pMember->GetQuestStatus(m_pQuestForFollow->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
+ pMember->FailQuest(m_pQuestForFollow->GetQuestId());
+ }
+ }
+ }
+ else
+ {
+ if (pPlayer->GetQuestStatus(m_pQuestForFollow->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->FailQuest(m_pQuestForFollow->GetQuestId());
+ }
+ }
+}
+
+void FollowerAI::JustRespawned()
+{
+ m_uiFollowState = STATE_FOLLOW_NONE;
+
+ if (!IsCombatMovement())
+ SetCombatMovement(true);
+
+ if (m_creature->getFaction() != m_creature->GetCreatureInfo()->faction_A)
+ m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A);
+
+ Reset();
+}
+
+void FollowerAI::EnterEvadeMode()
+{
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(true);
+ m_creature->SetLootRecipient(NULL);
+
+ if (HasFollowState(STATE_FOLLOW_INPROGRESS))
+ {
+ debug_log("SD2: FollowerAI left combat, returning to CombatStartPosition.");
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
+ {
+ float fPosX, fPosY, fPosZ;
+ m_creature->GetCombatStartPosition(fPosX, fPosY, fPosZ);
+ m_creature->GetMotionMaster()->MovePoint(POINT_COMBAT_START, fPosX, fPosY, fPosZ);
+ }
+ }
+ else
+ {
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
+ m_creature->GetMotionMaster()->MoveTargetedHome();
+ }
+
+ Reset();
+}
+
+void FollowerAI::UpdateAI(const uint32 uiDiff)
+{
+ if (HasFollowState(STATE_FOLLOW_INPROGRESS) && !m_creature->getVictim())
+ {
+ if (m_uiUpdateFollowTimer < uiDiff)
+ {
+ if (HasFollowState(STATE_FOLLOW_COMPLETE) && !HasFollowState(STATE_FOLLOW_POSTEVENT))
+ {
+ debug_log("SD2: FollowerAI is set completed, despawns.");
+ m_creature->ForcedDespawn();
+ return;
+ }
+
+ bool bIsMaxRangeExceeded = true;
+
+ if (Player* pPlayer = GetLeaderForFollower())
+ {
+ if (HasFollowState(STATE_FOLLOW_RETURNING))
+ {
+ debug_log("SD2: FollowerAI is returning to leader.");
+
+ RemoveFollowState(STATE_FOLLOW_RETURNING);
+ m_creature->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ return;
+ }
+
+ if (Group* pGroup = pPlayer->GetGroup())
+ {
+ for(GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
+ {
+ Player* pMember = pRef->getSource();
+
+ if (pMember && m_creature->IsWithinDistInMap(pMember, MAX_PLAYER_DISTANCE))
+ {
+ bIsMaxRangeExceeded = false;
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (m_creature->IsWithinDistInMap(pPlayer, MAX_PLAYER_DISTANCE))
+ bIsMaxRangeExceeded = false;
+ }
+ }
+
+ if (bIsMaxRangeExceeded)
+ {
+ debug_log("SD2: FollowerAI failed because player/group was to far away or not found");
+ m_creature->ForcedDespawn();
+ return;
+ }
+
+ m_uiUpdateFollowTimer = 1000;
+ }
+ else
+ m_uiUpdateFollowTimer -= uiDiff;
+ }
+
+ UpdateFollowerAI(uiDiff);
+}
+
+void FollowerAI::UpdateFollowerAI(const uint32 uiDiff)
+{
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+}
+
+void FollowerAI::MovementInform(uint32 uiMotionType, uint32 uiPointId)
+{
+ if (uiMotionType != POINT_MOTION_TYPE || !HasFollowState(STATE_FOLLOW_INPROGRESS))
+ return;
+
+ if (uiPointId == POINT_COMBAT_START)
+ {
+ if (GetLeaderForFollower())
+ {
+ if (!HasFollowState(STATE_FOLLOW_PAUSED))
+ AddFollowState(STATE_FOLLOW_RETURNING);
+ }
+ else
+ m_creature->ForcedDespawn();
+ }
+}
+
+void FollowerAI::StartFollow(Player* pLeader, uint32 uiFactionForFollower, const Quest* pQuest)
+{
+ if (m_creature->getVictim())
+ {
+ debug_log("SD2: FollowerAI attempt to StartFollow while in combat.");
+ return;
+ }
+
+ if (HasFollowState(STATE_FOLLOW_INPROGRESS))
+ {
+ error_log("SD2: FollowerAI attempt to StartFollow while already following.");
+ return;
+ }
+
+ //set variables
+ m_uiLeaderGUID = pLeader->GetGUID();
+
+ if (uiFactionForFollower)
+ m_creature->setFaction(uiFactionForFollower);
+
+ m_pQuestForFollow = pQuest;
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
+ {
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MoveIdle();
+ debug_log("SD2: FollowerAI start with WAYPOINT_MOTION_TYPE, set to MoveIdle.");
+ }
+
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+
+ AddFollowState(STATE_FOLLOW_INPROGRESS);
+
+ m_creature->GetMotionMaster()->MoveFollow(pLeader, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+
+ debug_log("SD2: FollowerAI start follow %s (GUID " UI64FMTD ")", pLeader->GetName(), m_uiLeaderGUID);
+}
+
+Player* FollowerAI::GetLeaderForFollower()
+{
+ if (Player* pLeader = m_creature->GetMap()->GetPlayer(m_uiLeaderGUID))
+ {
+ if (pLeader->isAlive())
+ return pLeader;
+ else
+ {
+ if (Group* pGroup = pLeader->GetGroup())
+ {
+ for(GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
+ {
+ Player* pMember = pRef->getSource();
+
+ if (pMember && pMember->isAlive() && m_creature->IsWithinDistInMap(pMember, MAX_PLAYER_DISTANCE))
+ {
+ debug_log("SD2: FollowerAI GetLeader changed and returned new leader.");
+ m_uiLeaderGUID = pMember->GetGUID();
+ return pMember;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ debug_log("SD2: FollowerAI GetLeader can not find suitable leader.");
+ return NULL;
+}
+
+void FollowerAI::SetFollowComplete(bool bWithEndEvent)
+{
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE)
+ {
+ m_creature->StopMoving();
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MoveIdle();
+ }
+
+ if (bWithEndEvent)
+ AddFollowState(STATE_FOLLOW_POSTEVENT);
+ else
+ {
+ if (HasFollowState(STATE_FOLLOW_POSTEVENT))
+ RemoveFollowState(STATE_FOLLOW_POSTEVENT);
+ }
+
+ AddFollowState(STATE_FOLLOW_COMPLETE);
+}
+
+void FollowerAI::SetFollowPaused(bool bPaused)
+{
+ if (!HasFollowState(STATE_FOLLOW_INPROGRESS) || HasFollowState(STATE_FOLLOW_COMPLETE))
+ return;
+
+ if (bPaused)
+ {
+ AddFollowState(STATE_FOLLOW_PAUSED);
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE)
+ {
+ m_creature->StopMoving();
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MoveIdle();
+ }
+ }
+ else
+ {
+ RemoveFollowState(STATE_FOLLOW_PAUSED);
+
+ if (Player* pLeader = GetLeaderForFollower())
+ m_creature->GetMotionMaster()->MoveFollow(pLeader, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ }
+}
diff --git a/base/follower_ai.h b/base/follower_ai.h
new file mode 100644
index 0000000..7fa28cc
--- /dev/null
+++ b/base/follower_ai.h
@@ -0,0 +1,67 @@
+/* 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 */
+
+#ifndef SC_FOLLOWERAI_H
+#define SC_FOLLOWERAI_H
+
+#include "../system/system.h"
+
+enum eFollowState
+{
+ STATE_FOLLOW_NONE = 0x000,
+ STATE_FOLLOW_INPROGRESS = 0x001, //must always have this state for any follow
+ STATE_FOLLOW_RETURNING = 0x002, //when returning to combat start after being in combat
+ STATE_FOLLOW_PAUSED = 0x004, //disables following
+ STATE_FOLLOW_COMPLETE = 0x008, //follow is completed and may end
+ STATE_FOLLOW_PREEVENT = 0x010, //not implemented (allow pre event to run, before follow is initiated)
+ STATE_FOLLOW_POSTEVENT = 0x020 //can be set at complete and allow post event to run
+};
+
+class MANGOS_DLL_DECL FollowerAI : public ScriptedAI
+{
+ public:
+ explicit FollowerAI(Creature* pCreature);
+ ~FollowerAI() {}
+
+ //virtual void WaypointReached(uint32 uiPointId) = 0;
+
+ void MovementInform(uint32 uiMotionType, uint32 uiPointId);
+
+ void AttackStart(Unit*);
+
+ void MoveInLineOfSight(Unit*);
+
+ void EnterEvadeMode();
+
+ void JustDied(Unit*);
+
+ void JustRespawned();
+
+ void UpdateAI(const uint32); //the "internal" update, calls UpdateFollowerAI()
+ virtual void UpdateFollowerAI(const uint32); //used when it's needed to add code in update (abilities, scripted events, etc)
+
+ void StartFollow(Player* pPlayer, uint32 uiFactionForFollower = 0, const Quest* pQuest = NULL);
+
+ void SetFollowPaused(bool bPaused); //if special event require follow mode to hold/resume during the follow
+ void SetFollowComplete(bool bWithEndEvent = false);
+
+ bool HasFollowState(uint32 uiFollowState) { return (m_uiFollowState & uiFollowState); }
+
+ protected:
+ Player* GetLeaderForFollower();
+
+ private:
+ void AddFollowState(uint32 uiFollowState) { m_uiFollowState |= uiFollowState; }
+ void RemoveFollowState(uint32 uiFollowState) { m_uiFollowState &= ~uiFollowState; }
+
+ bool AssistPlayerInCombat(Unit* pWho);
+
+ uint64 m_uiLeaderGUID;
+ uint32 m_uiUpdateFollowTimer;
+ uint32 m_uiFollowState;
+
+ const Quest* m_pQuestForFollow; //normally we have a quest
+};
+
+#endif
diff --git a/base/guard_ai.cpp b/base/guard_ai.cpp
new file mode 100644
index 0000000..d531baf
--- /dev/null
+++ b/base/guard_ai.cpp
@@ -0,0 +1,210 @@
+/* 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: Guard_AI
+SD%Complete: 90
+SDComment:
+SDCategory: Guards
+EndScriptData */
+
+#include "precompiled.h"
+#include "guard_ai.h"
+
+// This script is for use within every single guard to save coding time
+
+guardAI::guardAI(Creature* pCreature) : ScriptedAI(pCreature),
+ m_uiGlobalCooldown(0),
+ m_uiBuffTimer(0)
+{}
+
+void guardAI::Reset()
+{
+ m_uiGlobalCooldown = 0;
+ m_uiBuffTimer = 0; //Rebuff as soon as we can
+}
+
+void guardAI::Aggro(Unit *pWho)
+{
+ if (m_creature->GetEntry() == NPC_CENARION_INFANTRY)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_GUARD_SIL_AGGRO1, m_creature, pWho); break;
+ case 1: DoScriptText(SAY_GUARD_SIL_AGGRO2, m_creature, pWho); break;
+ case 2: DoScriptText(SAY_GUARD_SIL_AGGRO3, m_creature, pWho); break;
+ }
+ }
+
+ if (const SpellEntry *pSpellInfo = m_creature->ReachWithSpellAttack(pWho))
+ DoCastSpell(pWho, pSpellInfo);
+}
+
+void guardAI::JustDied(Unit *pKiller)
+{
+ //Send Zone Under Attack message to the LocalDefense and WorldDefense Channels
+ if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself())
+ m_creature->SendZoneUnderAttackMessage(pPlayer);
+}
+
+void guardAI::UpdateAI(const uint32 uiDiff)
+{
+ //Always decrease our global cooldown first
+ if (m_uiGlobalCooldown > uiDiff)
+ m_uiGlobalCooldown -= uiDiff;
+ else
+ m_uiGlobalCooldown = 0;
+
+ //Buff timer (only buff when we are alive and not in combat
+ if (m_creature->isAlive() && !m_creature->isInCombat())
+ {
+ if (m_uiBuffTimer < uiDiff)
+ {
+ //Find a spell that targets friendly and applies an aura (these are generally buffs)
+ const SpellEntry *pSpellInfo = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_AURA);
+
+ if (pSpellInfo && !m_uiGlobalCooldown)
+ {
+ //Cast the buff spell
+ DoCastSpell(m_creature, pSpellInfo);
+
+ //Set our global cooldown
+ m_uiGlobalCooldown = GENERIC_CREATURE_COOLDOWN;
+
+ //Set our timer to 10 minutes before rebuff
+ m_uiBuffTimer = 600000;
+ } //Try again in 30 seconds
+ else
+ m_uiBuffTimer = 30000;
+ }
+ else
+ m_uiBuffTimer -= uiDiff;
+ }
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Make sure our attack is ready and we arn't currently casting
+ if (m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false))
+ {
+ //If we are within range melee the target
+ if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
+ {
+ bool bHealing = false;
+ const SpellEntry *pSpellInfo = NULL;
+
+ //Select a healing spell if less than 30% hp
+ if (m_creature->GetHealthPercent() < 30.0f)
+ pSpellInfo = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING);
+
+ //No healing spell available, select a hostile spell
+ if (pSpellInfo)
+ bHealing = true;
+ else
+ pSpellInfo = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, 0, 0, SELECT_EFFECT_DONTCARE);
+
+ //20% chance to replace our white hit with a spell
+ if (pSpellInfo && !urand(0, 4) && !m_uiGlobalCooldown)
+ {
+ //Cast the spell
+ if (bHealing)
+ DoCastSpell(m_creature, pSpellInfo);
+ else
+ DoCastSpell(m_creature->getVictim(), pSpellInfo);
+
+ //Set our global cooldown
+ m_uiGlobalCooldown = GENERIC_CREATURE_COOLDOWN;
+ }
+ else
+ m_creature->AttackerStateUpdate(m_creature->getVictim());
+
+ m_creature->resetAttackTimer();
+ }
+ }
+ else
+ {
+ //Only run this code if we arn't already casting
+ if (!m_creature->IsNonMeleeSpellCasted(false))
+ {
+ bool bHealing = false;
+ const SpellEntry *pSpellInfo = NULL;
+
+ //Select a healing spell if less than 30% hp ONLY 33% of the time
+ if (m_creature->GetHealthPercent() < 30.0f && !urand(0, 2))
+ pSpellInfo = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING);
+
+ //No healing spell available, See if we can cast a ranged spell (Range must be greater than ATTACK_DISTANCE)
+ if (pSpellInfo)
+ bHealing = true;
+ else
+ pSpellInfo = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, ATTACK_DISTANCE, 0, SELECT_EFFECT_DONTCARE);
+
+ //Found a spell, check if we arn't on cooldown
+ if (pSpellInfo && !m_uiGlobalCooldown)
+ {
+ //If we are currently moving stop us and set the movement generator
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE)
+ {
+ m_creature->GetMotionMaster()->Clear(false);
+ m_creature->GetMotionMaster()->MoveIdle();
+ }
+
+ //Cast spell
+ if (bHealing)
+ DoCastSpell(m_creature, pSpellInfo);
+ else
+ DoCastSpell(m_creature->getVictim(), pSpellInfo);
+
+ //Set our global cooldown
+ m_uiGlobalCooldown = GENERIC_CREATURE_COOLDOWN;
+
+ } //If no spells available and we arn't moving run to target
+ else if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
+ {
+ //Cancel our current spell and then mutate new movement generator
+ m_creature->InterruptNonMeleeSpells(false);
+ m_creature->GetMotionMaster()->Clear(false);
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ }
+ }
+ }
+}
+
+void guardAI::DoReplyToTextEmote(uint32 uiTextEmote)
+{
+ switch(uiTextEmote)
+ {
+ case TEXTEMOTE_KISS: m_creature->HandleEmote(EMOTE_ONESHOT_BOW); break;
+ case TEXTEMOTE_WAVE: m_creature->HandleEmote(EMOTE_ONESHOT_WAVE); break;
+ case TEXTEMOTE_SALUTE: m_creature->HandleEmote(EMOTE_ONESHOT_SALUTE); break;
+ case TEXTEMOTE_SHY: m_creature->HandleEmote(EMOTE_ONESHOT_FLEX); break;
+ case TEXTEMOTE_RUDE:
+ case TEXTEMOTE_CHICKEN: m_creature->HandleEmote(EMOTE_ONESHOT_POINT); break;
+ }
+}
+
+void guardAI_orgrimmar::ReceiveEmote(Player* pPlayer, uint32 uiTextEmote)
+{
+ if (pPlayer->GetTeam() == HORDE)
+ DoReplyToTextEmote(uiTextEmote);
+}
+
+void guardAI_stormwind::ReceiveEmote(Player* pPlayer, uint32 uiTextEmote)
+{
+ if (pPlayer->GetTeam() == ALLIANCE)
+ DoReplyToTextEmote(uiTextEmote);
+}
diff --git a/base/guard_ai.h b/base/guard_ai.h
new file mode 100644
index 0000000..b8077c0
--- /dev/null
+++ b/base/guard_ai.h
@@ -0,0 +1,63 @@
+/* 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 */
+
+#ifndef SC_GUARDAI_H
+#define SC_GUARDAI_H
+
+enum
+{
+ GENERIC_CREATURE_COOLDOWN = 5000,
+
+ SAY_GUARD_SIL_AGGRO1 = -1000198,
+ SAY_GUARD_SIL_AGGRO2 = -1000199,
+ SAY_GUARD_SIL_AGGRO3 = -1000200,
+
+ NPC_CENARION_INFANTRY = 15184
+};
+
+enum eShattrathGuard
+{
+ SPELL_BANISHED_SHATTRATH_A = 36642,
+ SPELL_BANISHED_SHATTRATH_S = 36671,
+ SPELL_BANISH_TELEPORT = 36643,
+ SPELL_EXILE = 39533
+};
+
+struct MANGOS_DLL_DECL guardAI : public ScriptedAI
+{
+ public:
+ explicit guardAI(Creature* pCreature);
+ ~guardAI() {}
+
+ uint32 m_uiGlobalCooldown; //This variable acts like the global cooldown that players have (1.5 seconds)
+ uint32 m_uiBuffTimer; //This variable keeps track of buffs
+
+ void Reset();
+
+ void Aggro(Unit *pWho);
+
+ void JustDied(Unit *pKiller);
+
+ void UpdateAI(const uint32 uiDiff);
+
+ //common used for guards in main cities
+ void DoReplyToTextEmote(uint32 uiTextEmote);
+
+};
+
+struct MANGOS_DLL_DECL guardAI_orgrimmar : public guardAI
+{
+ guardAI_orgrimmar(Creature* pCreature) : guardAI(pCreature) {}
+
+ void ReceiveEmote(Player* pPlayer, uint32 uiTextEmote);
+};
+
+struct MANGOS_DLL_DECL guardAI_stormwind : public guardAI
+{
+ guardAI_stormwind(Creature* pCreature) : guardAI(pCreature) {}
+
+ void ReceiveEmote(Player* pPlayer, uint32 uiTextEmote);
+};
+
+#endif
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..06e016e
--- /dev/null
+++ b/config.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SC_CONFIG_H
+#define SC_CONFIG_H
+
+#include "Platform/CompilerDefs.h"
+#include "revision.h"
+
+// Format is YYYYMMDDRR where RR is the change in the conf file
+// for that day.
+#define SD2_CONF_VERSION 2010062001
+
+#ifdef WIN32
+ #define MANGOS_DLL_EXPORT extern "C" __declspec(dllexport)
+#elif defined( __GNUC__ )
+ #define MANGOS_DLL_EXPORT extern "C"
+#else
+ #define MANGOS_DLL_EXPORT extern "C" export
+#endif
+
+#ifndef _VERSION
+ #define _VERSION "Revision [" REVISION_ID "] " REVISION_DATE " " REVISION_TIME
+#endif
+
+// The path to config files
+#ifndef SYSCONFDIR
+ #define SYSCONFDIR ""
+#endif
+
+#if PLATFORM == PLATFORM_WINDOWS
+ #ifdef _WIN64
+ #define _FULLVERSION _VERSION " (Win64)"
+ #else
+ #define _FULLVERSION _VERSION " (Win32)"
+ #endif
+ #define _SCRIPTDEV2_CONFIG "scriptdev2.conf"
+#else
+ #define _FULLVERSION _VERSION " (Unix)"
+ #define _SCRIPTDEV2_CONFIG SYSCONFDIR"scriptdev2.conf"
+#endif
+
+#endif
diff --git a/config.h.in b/config.h.in
new file mode 100644
index 0000000..daa4279
--- /dev/null
+++ b/config.h.in
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SC_CONFIG_H
+#define SC_CONFIG_H
+
+#include "Platform/CompilerDefs.h"
+#include "revision.h"
+
+// Format is YYYYMMDDRR where RR is the change in the conf file
+// for that day.
+#define SD2_CONF_VERSION 2009040501
+
+#ifdef WIN32
+ #define MANGOS_DLL_EXPORT extern "C" __declspec(dllexport)
+#elif defined( __GNUC__ )
+ #define MANGOS_DLL_EXPORT extern "C"
+#else
+ #define MANGOS_DLL_EXPORT extern "C" export
+#endif
+
+#ifndef _VERSION
+ #define _VERSION "Revision [" REVISION_ID "] " REVISION_DATE " " REVISION_TIME
+#endif
+
+// The path to config files
+#ifndef SYSCONFDIR
+ #define SYSCONFDIR ""
+#endif
+
+#if PLATFORM == PLATFORM_WINDOWS
+ #ifdef _WIN64
+ #define _FULLVERSION _VERSION " (Win64)"
+ #else
+ #define _FULLVERSION _VERSION " (Win32)"
+ #endif
+ #define _SCRIPTDEV2_CONFIG "scriptdev2.conf"
+#else
+ #define _FULLVERSION _VERSION " (Unix)"
+ #define _SCRIPTDEV2_CONFIG SYSCONFDIR"scriptdev2.conf"
+#endif
+
+#endif
diff --git a/docs/How to install.txt b/docs/How to install.txt
new file mode 100644
index 0000000..dfe1251
--- /dev/null
+++ b/docs/How to install.txt
@@ -0,0 +1,53 @@
+
+--- How to install ScriptDev2 ---
+
+1) Download MaNGOS (using git clone)
+
+2) Do the source stuff:
+
+MS Windows:
+- Create a new folder under "src\bindings\" within the MaNGOS source called "ScriptDev2"
+- Checkout the ScriptDev2 trunk from "https://scriptdev2.svn.sourceforge.net/svnroot/scriptdev2"
+- Apply the Git patch to Mangos - "git am src/bindings/ScriptDev2/patches/MaNGOS-XXXX-ScriptDev2.patch" ('XXXX' is revision number for Mangos). (Note this is not required for compile, but needed to avoid deletion of untracked folders/files in GIT-directory when using certain GIT commands (example: git clean -f -d))
+- Compile MaNGOS
+- Compile ScriptDev2 using the ScriptVC80 or ScriptVC90 Solution within the ScriptDev2 folder (this will overwrite the Mangoscript dll in the output directory)
+
+GNU/Linux:
+- Checkout the ScriptDev2 to "src/bindings/ScriptDev2" - "svn co https://scriptdev2.svn.sourceforge.net/svnroot/scriptdev2 src/bindings/ScriptDev2"
+SVN:
+- Apply MaNGOS-XXXX-ScriptDev2.patch to Mangos, where XXXX is the highest version to that of your MaNGOS revision.
+GIT:
+- Apply the Git patch to Mangos - "git am src/bindings/ScriptDev2/patches/MaNGOS-XXXX-ScriptDev2.patch"
+
+- Compile MaNGOS (ScriptDev2 will automatically be built when compiling Mangos from here on)
+
+3) Create the default ScriptDev2 database using
+"sql\scriptdev2_create_database.sql", then execute
+"sql\scriptdev2_create_structure.sql" on that database.
+
+4) Execute the following on your ScriptDev2 database.
+- sql\scriptdev2_script_full.sql
+
+5) Execute the following file on your MaNGOS database.
+- sql\mangos_scriptname_full.sql
+
+6) Place the included "scriptdev2.conf" file within the directory containing your "mangosd.conf" and "realmd.conf" files. You may need to change this file to match the database you created and any custom settings you wish to use. Note this file will be different created for Unix based systems.
+
+7) Run mangosd from your output directory
+
+
+To update ScriptDev2:
+
+MS Windows:
+- All you have to do is open src\bindings\ and right click on the ScriptDev2 folder and click "Update" and then follow steps 4, 6, and 7 again. You must still compile MaNGOS before ScriptDev2 when on the Windows platform.
+
+GNU/Linux:
+- Go to the src/bindings/ScriptDev2 directory - "cd src/bindings/ScriptDev2"
+- Update ScriptDev2 - "svn up"
+
+To update your Database with new Scriptdev2 SQL changes you can either:
+a) apply only the changes that were made during that revision by looking in the sql\update folder or (files named rXXX_scriptdev2.sql should be executed on the scriptdev2 db while rXXX_mangos.sql should be executed on your mangos db)
+b) reapply "mangos_scriptname_full.sql" to your MaNGOS database.
+
+You can view the ScriptDev2 Change Log at:
+http://scriptdev2.svn.sourceforge.net/viewvc/scriptdev2/?view=log
diff --git a/docs/LICENSE.txt b/docs/LICENSE.txt
new file mode 100644
index 0000000..1f05b58
--- /dev/null
+++ b/docs/LICENSE.txt
@@ -0,0 +1,280 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
\ No newline at end of file
diff --git a/docs/Script Layout.txt b/docs/Script Layout.txt
new file mode 100644
index 0000000..b519352
--- /dev/null
+++ b/docs/Script Layout.txt
@@ -0,0 +1,32 @@
+--- Script Layout ---
+A quick explanation of the layout I hope everyone will follow for scriptdev2.
+
+--- Sub Folders ---
+
+Area - Contains scripts used solely by area triggers
+
+Boss - Boss scripts for bosses that are not zone specific
+
+Mob - Generic Creature scripts for creatures that are not zone specific
+
+Custom - Intentionally empty folder from SVN. If you make a custom script please put it here.
+
+GO - Contains scripts used solely by Game Objects (GOs) that do not have a specific zone
+
+Guard - Scripts for Guard NPCs
+
+Honor - Honor npcs (currently a blank script as these npcs do nothing special)
+
+Item - Item scripts
+
+NPC - Scripts for individual NPCs who do not have a specific zone
+
+Servers - Generic NPC servers script for things such as flightmasters and guildmasters.
+
+Zone - ALL zone specific scripts should be written within these folders. This includes creature scripts, boss scripts, go scripts, area scripts, and npc scripts.
+
+--- Naming Conventions ---
+
+Please keep file names to "type_objectname.cpp" where type is replaced by the type of object and objectname is replaced by the name of the object, creature, item, or area that this script will be used by.
+
+AddSC functions should follow "void AddSC_creaturename(void);" format. Do not append AI or anything else.
diff --git a/docs/Text-tables.txt b/docs/Text-tables.txt
new file mode 100644
index 0000000..3c02832
--- /dev/null
+++ b/docs/Text-tables.txt
@@ -0,0 +1,86 @@
+=========================================
+Texts Documentation
+=========================================
+
+Scriptdev2 Revision 695 introduces a new format for using texts in EventAI and SD2 Scripts.
+This information relates to the *_texts tables located in the ScriptDev Database.
+
+Any script can at any time access and use text from any of the three text tables, as long as the entry does in fact exist.
+Custom scripters are advised to store their text data in custom_texts.
+
+The different tables has ranges of entries allowed for that table.
+Reserved EventAI in Mangos entry -1 -> -999999
+script_texts: entry -1000000 -> -1999999
+custom_texts: entry -2000000 -> -2999999
+Any entry out of range for that table will display a start-up error.
+
+
+=========================================
+Basic Structure of script_texts and custom_texts
+=========================================
+Below is a the list of current fields within the texts tables.
+
+Field_Name Description
+-----------------------------------------------------------
+entry This value is mearly an NEGATIVE identifier of the current text number. Required for sql queries.
+content_default This is the actual text presented in the default language (English).
+
+content_loc1 This is the actual text presented in the Localization #1 Clients (Korean)
+content_loc2 This is the actual text presented in the Localization #2 Clients (French)
+content_loc3 This is the actual text presented in the Localization #3 Clients (German)
+content_loc4 This is the actual text presented in the Localization #4 Clients (Chinese)
+content_loc5 This is the actual text presented in the Localization #5 Clients (Taiwanese)
+content_loc6 This is the actual text presented in the Localization #6 Clients (Spanish)
+content_loc7 This is the actual text presented in the Localization #7 Clients (Spanish Mexico)
+content_loc8 This is the actual text presented in the Localization #8 Clients (Russian)
+
+sound This value is the Sound ID that corresponds to the actual text used (Defined in SoundEntries.dbc).
+type Variables used to define type of text (Say/Yell/Textemote/Whisper).
+language This value is the Language that the text is native in (Defined in Languages.dbc).
+emote Value from enum Emote (defined in Emotes.dbc). Only source of text will play this emote (not target, if target are defined in DoScriptText)
+comment This is a comment regarding the text entry (For ACID, accepted format is to use Creature ID of NPC using it).
+
+Note: Fields `content_loc1` to `content_loc8` are NULL values by default and are handled by separate localization projects.
+
+
+=========================================
+Text Types (type)
+=========================================
+Below is the list of current Text types that texts tables can handle. These were previously separate Actions in ACID.
+
+# Internal Name Description
+-----------------------------------------------------------
+0 CHAT_TYPE_SAY This type sets the text to be displayed as a Say (Speech Bubble).
+1 CHAT_TYPE_YELL This type sets the text to be displayed as a Yell (Red Speech Bubble) and usually has a matching Sound ID.
+2 CHAT_TYPE_TEXT_EMOTE This type sets the text to be displayed as a text emote in orange in the chat log.
+3 CHAT_TYPE_BOSS_EMOTE This type sets the text to be displayed as a text emote in orange in the chat log (Used only for specific Bosses).
+4 CHAT_TYPE_WHISPER This type sets the text to be displayed as a whisper to the player in the chat log.
+5 CHAT_TYPE_BOSS_WHISPER This type sets the text to be displayed as a whisper to the player in the chat log (Used only for specific Bosses).
+6 CHAT_TYPE_ZONE_YELL Same as CHAT_TYPE_YELL but will display to all players in current zone.
+
+=========================================
+Language Types (language)
+=========================================
+Below is the list of current Language types that are allowed.
+This is the Race Language that the text is native to (So it will display properly)
+
+# Internal Name Description
+-----------------------------------------------------------
+0 UNIVERSAL Text in this language is understood by ALL Races.
+1 ORCISH Text in this language is understood ONLY by Horde Races.
+2 DARNASSIAN Text in this language is understood ONLY by the Night Elf Race.
+3 TAURAHE Text in this language is understood ONLY by the Tauren Race.
+6 DWARVISH Text in this language is understood ONLY by the Dwarf Race.
+7 COMMON Text in this language is understood ONLY by Alliance Races.
+8 DEMONIC Text in this language is understood ONLY by the Demon Race (Not Implemented).
+9 TITAN This language was used by Sargeras to speak with other Titians (Not Implemented).
+10 THALASSIAN Text in this language is understood ONLY by the Blood Elf Race.
+11 DRACONIC Text in this language is understood ONLY by the Dragon Race.
+12 KALIMAG Text will display as Kalimag (not readable by players, language of all elementals)
+13 GNOMISH Text in this language is understood ONLY by the Gnome Race.
+14 TROLL Text in this language is understood ONLY by the Troll Race.
+33 GUTTERSPEAK Text in this language is understood ONLY by the Undead Race.
+35 DRAENEI Text in this language is understood ONLY by the Draenai Race.
+36 ZOMBIE (not currently used?)
+37 GNOMISH BINARY Binary language used by Alliance when drinking Binary Brew
+38 GOBLIN BINARY Binary language used by Horde when drinking Binary Brew
diff --git a/docs/ToDo.txt b/docs/ToDo.txt
new file mode 100644
index 0000000..f4cad66
--- /dev/null
+++ b/docs/ToDo.txt
@@ -0,0 +1,14 @@
+--- TO DO ---
+Simple list of things we need to do.
+
+--- ScriptDev2 Framework ---
+Move all text out of C++ code and into SD2 database.
+
+--- Scripting with Priorities ---
+1) Boss AI and Boss Event scripts
+2) Specific NPC AI, Gossip, Quest, Event scripts
+3) Spell and Item scripts
+
+--- Core Problems ---
+
+- Spell scripts are only scriptable within the core. Spell scripts should be done in SD2 since they are very specialized.
\ No newline at end of file
diff --git a/include/precompiled.cpp b/include/precompiled.cpp
new file mode 100644
index 0000000..babe1eb
--- /dev/null
+++ b/include/precompiled.cpp
@@ -0,0 +1,5 @@
+/* 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 */
+
+#include "precompiled.h"
diff --git a/include/precompiled.h b/include/precompiled.h
new file mode 100644
index 0000000..ae85e85
--- /dev/null
+++ b/include/precompiled.h
@@ -0,0 +1,22 @@
+/* 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 */
+
+#ifndef SC_PRECOMPILED_H
+#define SC_PRECOMPILED_H
+
+#include "../ScriptMgr.h"
+#include "sc_creature.h"
+#include "sc_gossip.h"
+#include "sc_grid_searchers.h"
+#include "sc_instance.h"
+
+#ifdef WIN32
+# include
+ BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+ {
+ return true;
+ }
+#endif
+
+#endif
diff --git a/include/sc_creature.cpp b/include/sc_creature.cpp
new file mode 100644
index 0000000..f0526c8
--- /dev/null
+++ b/include/sc_creature.cpp
@@ -0,0 +1,550 @@
+/* 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 */
+
+#include "precompiled.h"
+#include "Item.h"
+#include "Spell.h"
+#include "WorldPacket.h"
+#include "ObjectMgr.h"
+
+// Spell summary for ScriptedAI::SelectSpell
+struct TSpellSummary
+{
+ uint8 Targets; // set of enum SelectTarget
+ uint8 Effects; // set of enum SelectEffect
+} *SpellSummary;
+
+ScriptedAI::ScriptedAI(Creature* pCreature) : CreatureAI(pCreature),
+ m_bCombatMovement(true),
+ m_uiEvadeCheckCooldown(2500)
+{}
+
+bool ScriptedAI::IsVisible(Unit* pWho) const
+{
+ if (!pWho)
+ return false;
+
+ return m_creature->IsWithinDist(pWho, VISIBLE_RANGE) && pWho->isVisibleForOrDetect(m_creature, m_creature, true);
+}
+
+void ScriptedAI::MoveInLineOfSight(Unit* pWho)
+{
+ if (m_creature->CanInitiateAttack() && pWho->isTargetableForAttack() &&
+ m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature))
+ {
+ if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
+ return;
+
+ 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);
+ }
+ }
+ }
+}
+
+void ScriptedAI::AttackStart(Unit* pWho)
+{
+ if (pWho && 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 ScriptedAI::EnterCombat(Unit* pEnemy)
+{
+ if (pEnemy)
+ Aggro(pEnemy);
+}
+
+void ScriptedAI::Aggro(Unit* pEnemy)
+{
+}
+
+void ScriptedAI::UpdateAI(const uint32 uiDiff)
+{
+ //Check if we have a current target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_creature->isAttackReady())
+ {
+ //If we are within range melee the target
+ if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
+ {
+ m_creature->AttackerStateUpdate(m_creature->getVictim());
+ m_creature->resetAttackTimer();
+ }
+ }
+}
+
+void ScriptedAI::EnterEvadeMode()
+{
+ 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 ScriptedAI::JustRespawned()
+{
+ Reset();
+}
+
+void ScriptedAI::DoStartMovement(Unit* pVictim, float fDistance, float fAngle)
+{
+ if (pVictim)
+ m_creature->GetMotionMaster()->MoveChase(pVictim, fDistance, fAngle);
+}
+
+void ScriptedAI::DoStartNoMovement(Unit* pVictim)
+{
+ if (!pVictim)
+ return;
+
+ m_creature->GetMotionMaster()->MoveIdle();
+ m_creature->StopMoving();
+}
+
+void ScriptedAI::DoMeleeAttackIfReady()
+{
+ //Make sure our attack is ready before checking distance
+ if (m_creature->isAttackReady())
+ {
+ //If we are within range melee the target
+ if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
+ {
+ m_creature->AttackerStateUpdate(m_creature->getVictim());
+ m_creature->resetAttackTimer();
+ }
+ }
+}
+
+void ScriptedAI::DoStopAttack()
+{
+ if (m_creature->getVictim())
+ m_creature->AttackStop();
+}
+
+void ScriptedAI::DoCast(Unit* pTarget, uint32 uiSpellId, bool bTriggered)
+{
+ if (m_creature->IsNonMeleeSpellCasted(false) && !bTriggered)
+ return;
+
+ m_creature->CastSpell(pTarget, uiSpellId, bTriggered);
+}
+
+void ScriptedAI::DoCastSpell(Unit* pTarget, SpellEntry const* pSpellInfo, bool bTriggered)
+{
+ if (m_creature->IsNonMeleeSpellCasted(false) && !bTriggered)
+ return;
+
+ m_creature->CastSpell(pTarget, pSpellInfo, bTriggered);
+}
+
+void ScriptedAI::DoPlaySoundToSet(WorldObject* pSource, uint32 uiSoundId)
+{
+ if (!pSource)
+ return;
+
+ if (!GetSoundEntriesStore()->LookupEntry(uiSoundId))
+ {
+ error_log("SD2: Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)", uiSoundId, pSource->GetTypeId(), pSource->GetGUIDLow());
+ return;
+ }
+
+ pSource->PlayDirectSound(uiSoundId);
+}
+
+Creature* ScriptedAI::DoSpawnCreature(uint32 uiId, float fX, float fY, float fZ, float fAngle, uint32 uiType, uint32 uiDespawntime)
+{
+ return m_creature->SummonCreature(uiId,m_creature->GetPositionX()+fX, m_creature->GetPositionY()+fY, m_creature->GetPositionZ()+fZ, fAngle, (TempSummonType)uiType, uiDespawntime);
+}
+
+SpellEntry const* ScriptedAI::SelectSpell(Unit* pTarget, int32 uiSchool, int32 uiMechanic, SelectTarget selectTargets, uint32 uiPowerCostMin, uint32 uiPowerCostMax, float fRangeMin, float fRangeMax, SelectEffect selectEffects)
+{
+ //No target so we can't cast
+ if (!pTarget)
+ return false;
+
+ //Silenced so we can't cast
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
+ return false;
+
+ //Using the extended script system we first create a list of viable spells
+ SpellEntry const* apSpell[4];
+ memset(apSpell, 0, sizeof(SpellEntry*)*4);
+
+ uint32 uiSpellCount = 0;
+
+ SpellEntry const* pTempSpell;
+ SpellRangeEntry const* pTempRange;
+
+ //Check if each spell is viable(set it to null if not)
+ for (uint8 i = 0; i < 4; ++i)
+ {
+ pTempSpell = GetSpellStore()->LookupEntry(m_creature->m_spells[i]);
+
+ //This spell doesn't exist
+ if (!pTempSpell)
+ continue;
+
+ // Targets and Effects checked first as most used restrictions
+ //Check the spell targets if specified
+ if (selectTargets && !(SpellSummary[m_creature->m_spells[i]].Targets & (1 << (selectTargets-1))))
+ continue;
+
+ //Check the type of spell if we are looking for a specific spell type
+ if (selectEffects && !(SpellSummary[m_creature->m_spells[i]].Effects & (1 << (selectEffects-1))))
+ continue;
+
+ //Check for school if specified
+ if (uiSchool >= 0 && pTempSpell->SchoolMask & uiSchool)
+ continue;
+
+ //Check for spell mechanic if specified
+ if (uiMechanic >= 0 && pTempSpell->Mechanic != uiMechanic)
+ continue;
+
+ //Make sure that the spell uses the requested amount of power
+ if (uiPowerCostMin && pTempSpell->manaCost < uiPowerCostMin)
+ continue;
+
+ if (uiPowerCostMax && pTempSpell->manaCost > uiPowerCostMax)
+ continue;
+
+ //Continue if we don't have the mana to actually cast this spell
+ if (pTempSpell->manaCost > m_creature->GetPower((Powers)pTempSpell->powerType))
+ continue;
+
+ //Get the Range
+ pTempRange = GetSpellRangeStore()->LookupEntry(pTempSpell->rangeIndex);
+
+ //Spell has invalid range store so we can't use it
+ if (!pTempRange)
+ continue;
+
+ //Check if the spell meets our range requirements
+ if (fRangeMin && pTempRange->maxRange < fRangeMin)
+ continue;
+
+ if (fRangeMax && pTempRange->maxRange > fRangeMax)
+ continue;
+
+ //Check if our target is in range
+ if (m_creature->IsWithinDistInMap(pTarget, pTempRange->minRange) || !m_creature->IsWithinDistInMap(pTarget, pTempRange->maxRange))
+ continue;
+
+ //All good so lets add it to the spell list
+ apSpell[uiSpellCount] = pTempSpell;
+ ++uiSpellCount;
+ }
+
+ //We got our usable spells so now lets randomly pick one
+ if (!uiSpellCount)
+ return NULL;
+
+ return apSpell[urand(0, uiSpellCount -1)];
+}
+
+bool ScriptedAI::CanCast(Unit* pTarget, SpellEntry const* pSpellEntry, bool bTriggered)
+{
+ //No target so we can't cast
+ if (!pTarget || !pSpellEntry)
+ return false;
+
+ //Silenced so we can't cast
+ if (!bTriggered && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
+ return false;
+
+ //Check for power
+ if (!bTriggered && m_creature->GetPower((Powers)pSpellEntry->powerType) < pSpellEntry->manaCost)
+ return false;
+
+ SpellRangeEntry const* pTempRange = GetSpellRangeStore()->LookupEntry(pSpellEntry->rangeIndex);
+
+ //Spell has invalid range store so we can't use it
+ if (!pTempRange)
+ return false;
+
+ //Unit is out of range of this spell
+ if (!m_creature->IsInRange(pTarget, pTempRange->minRange, pTempRange->maxRange))
+ return false;
+
+ return true;
+}
+
+void FillSpellSummary()
+{
+ SpellSummary = new TSpellSummary[GetSpellStore()->GetNumRows()];
+
+ SpellEntry const* pTempSpell;
+
+ for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
+ {
+ SpellSummary[i].Effects = 0;
+ SpellSummary[i].Targets = 0;
+
+ pTempSpell = GetSpellStore()->LookupEntry(i);
+ //This spell doesn't exist
+ if (!pTempSpell)
+ continue;
+
+ for (uint8 j = 0; j < 3; ++j)
+ {
+ //Spell targets self
+ if (pTempSpell->EffectImplicitTargetA[j] == TARGET_SELF)
+ SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF-1);
+
+ //Spell targets a single enemy
+ if (pTempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES)
+ SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY-1);
+
+ //Spell targets AoE at enemy
+ if (pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
+ SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY-1);
+
+ //Spell targets an enemy
+ if (pTempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
+ SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY-1);
+
+ //Spell targets a single friend(or self)
+ if (pTempSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY)
+ SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND-1);
+
+ //Spell targets aoe friends
+ if (pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES)
+ SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND-1);
+
+ //Spell targets any friend(or self)
+ if (pTempSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY ||
+ pTempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES)
+ SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND-1);
+
+ //Make sure that this spell includes a damage effect
+ if (pTempSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE ||
+ pTempSpell->Effect[j] == SPELL_EFFECT_INSTAKILL ||
+ pTempSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
+ pTempSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH)
+ SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE-1);
+
+ //Make sure that this spell includes a healing effect (or an apply aura with a periodic heal)
+ if (pTempSpell->Effect[j] == SPELL_EFFECT_HEAL ||
+ pTempSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH ||
+ pTempSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL ||
+ (pTempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA && pTempSpell->EffectApplyAuraName[j]== 8))
+ SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING-1);
+
+ //Make sure that this spell applies an aura
+ if (pTempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA)
+ SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA-1);
+ }
+ }
+}
+
+void ScriptedAI::DoResetThreat()
+{
+ if (!m_creature->CanHaveThreatList() || m_creature->getThreatManager().isThreatListEmpty())
+ {
+ error_log("SD2: DoResetThreat called for creature that either cannot have threat list or has empty threat list (m_creature entry = %d)", m_creature->GetEntry());
+ return;
+ }
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
+
+ if (pUnit && m_creature->getThreatManager().getThreat(pUnit))
+ m_creature->getThreatManager().modifyThreatPercent(pUnit, -100);
+ }
+}
+
+void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float fX, float fY, float fZ, float fO)
+{
+ if (!pUnit)
+ return;
+
+ if (pUnit->GetTypeId() != TYPEID_PLAYER)
+ {
+ error_log("SD2: Creature " UI64FMTD " (Entry: %u) Tried to teleport non-player unit (Type: %u GUID: " UI64FMTD ") to x: %f y:%f z: %f o: %f. Aborted.", m_creature->GetGUID(), m_creature->GetEntry(), pUnit->GetTypeId(), pUnit->GetGUID(), fX, fY, fZ, fO);
+ return;
+ }
+
+ ((Player*)pUnit)->TeleportTo(pUnit->GetMapId(), fX, fY, fZ, fO, TELE_TO_NOT_LEAVE_COMBAT);
+}
+
+Unit* ScriptedAI::DoSelectLowestHpFriendly(float fRange, uint32 uiMinHPDiff)
+{
+ Unit* pUnit = NULL;
+
+ MaNGOS::MostHPMissingInRangeCheck u_check(m_creature, fRange, uiMinHPDiff);
+ MaNGOS::UnitLastSearcher searcher(pUnit, u_check);
+
+ Cell::VisitGridObjects(m_creature, searcher, fRange);
+
+ return pUnit;
+}
+
+std::list ScriptedAI::DoFindFriendlyCC(float fRange)
+{
+ std::list pList;
+
+ MaNGOS::FriendlyCCedInRangeCheck u_check(m_creature, fRange);
+ MaNGOS::CreatureListSearcher searcher(pList, u_check);
+
+ Cell::VisitGridObjects(m_creature, searcher, fRange);
+
+ return pList;
+}
+
+std::list ScriptedAI::DoFindFriendlyMissingBuff(float fRange, uint32 uiSpellId)
+{
+ std::list pList;
+
+ MaNGOS::FriendlyMissingBuffInRangeCheck u_check(m_creature, fRange, uiSpellId);
+ MaNGOS::CreatureListSearcher searcher(pList, u_check);
+
+ Cell::VisitGridObjects(m_creature, searcher, fRange);
+
+ return pList;
+}
+
+Player* ScriptedAI::GetPlayerAtMinimumRange(float fMinimumRange)
+{
+ Player* pPlayer = NULL;
+
+ MaNGOS::AnyPlayerInObjectRangeCheck check(m_creature, fMinimumRange);
+ MaNGOS::PlayerSearcher searcher(pPlayer, check);
+
+ Cell::VisitWorldObjects(m_creature, searcher, fMinimumRange);
+
+ return pPlayer;
+}
+
+void ScriptedAI::SetEquipmentSlots(bool bLoadDefault, int32 uiMainHand, int32 uiOffHand, int32 uiRanged)
+{
+ if (bLoadDefault)
+ {
+ m_creature->LoadEquipment(m_creature->GetCreatureInfo()->equipmentId,true);
+ return;
+ }
+
+ if (uiMainHand >= 0)
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(uiMainHand));
+
+ if (uiOffHand >= 0)
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, uint32(uiOffHand));
+
+ if (uiRanged >= 0)
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 2, uint32(uiRanged));
+}
+
+void ScriptedAI::SetCombatMovement(bool bCombatMove)
+{
+ m_bCombatMovement = bCombatMove;
+}
+
+// Hacklike storage used for misc creatures that are expected to evade of outside of a certain area.
+// It is assumed the information is found elswehere and can be handled by mangos. So far no luck finding such information/way to extract it.
+enum
+{
+ NPC_BROODLORD = 12017,
+ NPC_VOID_REAVER = 19516,
+ NPC_JAN_ALAI = 23578,
+ NPC_SARTHARION = 28860
+};
+
+bool ScriptedAI::EnterEvadeIfOutOfCombatArea(const uint32 uiDiff)
+{
+ if (m_uiEvadeCheckCooldown < uiDiff)
+ m_uiEvadeCheckCooldown = 2500;
+ else
+ {
+ m_uiEvadeCheckCooldown -= uiDiff;
+ return false;
+ }
+
+ if (m_creature->IsInEvadeMode() || !m_creature->getVictim())
+ return false;
+
+ float fX = m_creature->GetPositionX();
+ float fY = m_creature->GetPositionY();
+ float fZ = m_creature->GetPositionZ();
+
+ switch(m_creature->GetEntry())
+ {
+ case NPC_BROODLORD: // broodlord (not move down stairs)
+ if (fZ > 448.60f)
+ return false;
+ break;
+ case NPC_VOID_REAVER: // void reaver (calculate from center of room)
+ if (m_creature->GetDistance2d(432.59f, 371.93f) < 105.0f)
+ return false;
+ break;
+ case NPC_JAN_ALAI: // jan'alai (calculate by Z)
+ if (fZ > 12.0f)
+ return false;
+ break;
+ case NPC_SARTHARION: // sartharion (calculate box)
+ if (fX > 3218.86f && fX < 3275.69f && fY < 572.40f && fY > 484.68f)
+ return false;
+ break;
+ default:
+ error_log("SD2: EnterEvadeIfOutOfCombatArea used for creature entry %u, but does not have any definition.", m_creature->GetEntry());
+ return false;
+ }
+
+ EnterEvadeMode();
+ return true;
+}
+
+void Scripted_NoMovementAI::AttackStart(Unit* pWho)
+{
+ if (pWho && m_creature->Attack(pWho, true))
+ {
+ m_creature->AddThreat(pWho);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ DoStartNoMovement(pWho);
+ }
+}
diff --git a/include/sc_creature.h b/include/sc_creature.h
new file mode 100644
index 0000000..b960506
--- /dev/null
+++ b/include/sc_creature.h
@@ -0,0 +1,186 @@
+/* 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 */
+
+#ifndef SC_CREATURE_H
+#define SC_CREATURE_H
+
+#include "CreatureAI.h"
+#include "Creature.h"
+
+//Spell targets used by SelectSpell
+enum SelectTarget
+{
+ SELECT_TARGET_DONTCARE = 0, //All target types allowed
+
+ SELECT_TARGET_SELF, //Only Self casting
+
+ SELECT_TARGET_SINGLE_ENEMY, //Only Single Enemy
+ SELECT_TARGET_AOE_ENEMY, //Only AoE Enemy
+ SELECT_TARGET_ANY_ENEMY, //AoE or Single Enemy
+
+ SELECT_TARGET_SINGLE_FRIEND, //Only Single Friend
+ SELECT_TARGET_AOE_FRIEND, //Only AoE Friend
+ SELECT_TARGET_ANY_FRIEND, //AoE or Single Friend
+};
+
+//Spell Effects used by SelectSpell
+enum SelectEffect
+{
+ SELECT_EFFECT_DONTCARE = 0, //All spell effects allowed
+ SELECT_EFFECT_DAMAGE, //Spell does damage
+ SELECT_EFFECT_HEALING, //Spell does healing
+ SELECT_EFFECT_AURA, //Spell applies an aura
+};
+
+enum SCEquip
+{
+ EQUIP_NO_CHANGE = -1,
+ EQUIP_UNEQUIP = 0
+};
+
+struct MANGOS_DLL_DECL ScriptedAI : public CreatureAI
+{
+ explicit ScriptedAI(Creature* pCreature);
+ ~ScriptedAI() {}
+
+ //*************
+ //CreatureAI Functions
+ //*************
+
+ //Called if IsVisible(Unit *who) is true at each *who move
+ void MoveInLineOfSight(Unit*);
+
+ //Called at each attack of m_creature by any victim
+ void AttackStart(Unit*);
+
+ // Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
+ void EnterCombat(Unit*);
+
+ //Called at stoping attack by any attacker
+ void EnterEvadeMode();
+
+ //Called at any heal cast/item used (call non implemented in mangos)
+ void HealBy(Unit* pHealer, uint32 uiAmountHealed) {}
+
+ // Called at any Damage to any victim (before damage apply)
+ void DamageDeal(Unit* pDoneTo, uint32& uiDamage) {}
+
+ // Called at any Damage from any attacker (before damage apply)
+ void DamageTaken(Unit* pDoneBy, uint32& uiDamage) {}
+
+ //Is unit visible for MoveInLineOfSight
+ bool IsVisible(Unit* pWho) const;
+
+ //Called at World update tick
+ void UpdateAI(const uint32);
+
+ //Called at creature death
+ void JustDied(Unit*) {}
+
+ //Called at creature killing another unit
+ void KilledUnit(Unit*) {}
+
+ // Called when the creature summon successfully other creature
+ void JustSummoned(Creature*) {}
+
+ // Called when a summoned creature is despawned
+ void SummonedCreatureDespawn(Creature*) {}
+
+ // Called when hit by a spell
+ void SpellHit(Unit*, const SpellEntry*) {}
+
+ // Called when creature is spawned or respawned (for reseting variables)
+ void JustRespawned();
+
+ //Called at waypoint reached or PointMovement end
+ void MovementInform(uint32, uint32) {}
+
+ //*************
+ // Variables
+ //*************
+
+ //*************
+ //Pure virtual functions
+ //*************
+
+ //Called at creature reset either by death or evade
+ virtual void Reset() = 0;
+
+ //Called at creature EnterCombat
+ virtual void Aggro(Unit*);
+
+ //*************
+ //AI Helper Functions
+ //*************
+
+ //Start movement toward victim
+ void DoStartMovement(Unit* pVictim, float fDistance = 0, float fAngle = 0);
+
+ //Start no movement on victim
+ void DoStartNoMovement(Unit* pVictim);
+
+ //Do melee swing of current victim if in rnage and ready and not casting
+ void DoMeleeAttackIfReady();
+
+ //Stop attack of current victim
+ void DoStopAttack();
+
+ //Cast spell by Id
+ void DoCast(Unit* pTarget, uint32 uiSpellId, bool bTriggered = false);
+
+ //Cast spell by spell info
+ void DoCastSpell(Unit* pTarget, SpellEntry const* pSpellInfo, bool bTriggered = false);
+
+ //Plays a sound to all nearby players
+ void DoPlaySoundToSet(WorldObject* pSource, uint32 uiSoundId);
+
+ //Drops all threat to 0%. Does not remove players from the threat list
+ void DoResetThreat();
+
+ //Teleports a player without dropping threat (only teleports to same map)
+ void DoTeleportPlayer(Unit* pUnit, float fX, float fY, float fZ, float fO);
+
+ //Returns friendly unit with the most amount of hp missing from max hp
+ Unit* DoSelectLowestHpFriendly(float fRange, uint32 uiMinHPDiff = 1);
+
+ //Returns a list of friendly CC'd units within range
+ std::list DoFindFriendlyCC(float fRange);
+
+ //Returns a list of all friendly units missing a specific buff within range
+ std::list DoFindFriendlyMissingBuff(float fRange, uint32 uiSpellId);
+
+ //Return a player with at least minimumRange from m_creature
+ Player* GetPlayerAtMinimumRange(float fMinimumRange);
+
+ //Spawns a creature relative to m_creature
+ Creature* DoSpawnCreature(uint32 uiId, float fX, float fY, float fZ, float fAngle, uint32 uiType, uint32 uiDespawntime);
+
+ //Returns spells that meet the specified criteria from the creatures spell list
+ SpellEntry const* SelectSpell(Unit* pTarget, int32 uiSchool, int32 uiMechanic, SelectTarget selectTargets, uint32 uiPowerCostMin, uint32 uiPowerCostMax, float fRangeMin, float fRangeMax, SelectEffect selectEffect);
+
+ //Checks if you can cast the specified spell
+ bool CanCast(Unit* pTarget, SpellEntry const* pSpell, bool bTriggered = false);
+
+ void SetEquipmentSlots(bool bLoadDefault, int32 uiMainHand = EQUIP_NO_CHANGE, int32 uiOffHand = EQUIP_NO_CHANGE, int32 uiRanged = EQUIP_NO_CHANGE);
+
+ //Generally used to control if MoveChase() is to be used or not in AttackStart(). Some creatures does not chase victims
+ void SetCombatMovement(bool bCombatMove);
+ bool IsCombatMovement() { return m_bCombatMovement; }
+
+ bool EnterEvadeIfOutOfCombatArea(const uint32 uiDiff);
+
+ private:
+ bool m_bCombatMovement;
+ uint32 m_uiEvadeCheckCooldown;
+};
+
+struct MANGOS_DLL_DECL Scripted_NoMovementAI : public ScriptedAI
+{
+ Scripted_NoMovementAI(Creature* pCreature) : ScriptedAI(pCreature) {}
+
+ //Called at each attack of m_creature by any victim
+ void AttackStart(Unit*);
+};
+
+#endif
diff --git a/include/sc_gossip.h b/include/sc_gossip.h
new file mode 100644
index 0000000..d9916c0
--- /dev/null
+++ b/include/sc_gossip.h
@@ -0,0 +1,188 @@
+/* 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 */
+
+#ifndef SC_GOSSIP_H
+#define SC_GOSSIP_H
+
+#include "Player.h"
+#include "GossipDef.h"
+#include "QuestDef.h"
+
+// Gossip Item Text
+#define GOSSIP_TEXT_BROWSE_GOODS "I'd like to browse your goods."
+#define GOSSIP_TEXT_TRAIN "Train me!"
+
+#define GOSSIP_TEXT_BANK "The bank"
+#define GOSSIP_TEXT_IRONFORGE_BANK "The bank of Ironforge"
+#define GOSSIP_TEXT_STORMWIND_BANK "The bank of Stormwind"
+#define GOSSIP_TEXT_WINDRIDER "The wind rider master"
+#define GOSSIP_TEXT_GRYPHON "The gryphon master"
+#define GOSSIP_TEXT_BATHANDLER "The bat handler"
+#define GOSSIP_TEXT_HIPPOGRYPH "The hippogryph master"
+#define GOSSIP_TEXT_ZEPPLINMASTER "The zeppelin master"
+#define GOSSIP_TEXT_DEEPRUNTRAM "The Deeprun Tram"
+#define GOSSIP_TEXT_FERRY "The Rut'theran Ferry"
+#define GOSSIP_TEXT_FLIGHTMASTER "The flight master"
+#define GOSSIP_TEXT_AUCTIONHOUSE "The auction house"
+#define GOSSIP_TEXT_GUILDMASTER "The guild master"
+#define GOSSIP_TEXT_INN "The inn"
+#define GOSSIP_TEXT_MAILBOX "The mailbox"
+#define GOSSIP_TEXT_STABLEMASTER "The stable master"
+#define GOSSIP_TEXT_WEAPONMASTER "The weapon master"
+#define GOSSIP_TEXT_OFFICERS "The officers' lounge"
+#define GOSSIP_TEXT_BATTLEMASTER "The battlemaster"
+#define GOSSIP_TEXT_BARBER "Barber"
+#define GOSSIP_TEXT_CLASSTRAINER "A class trainer"
+#define GOSSIP_TEXT_PROFTRAINER "A profession trainer"
+#define GOSSIP_TEXT_LEXICON "Lexicon of Power"
+
+#define GOSSIP_TEXT_ALTERACVALLEY "Alterac Valley"
+#define GOSSIP_TEXT_ARATHIBASIN "Arathi Basin"
+#define GOSSIP_TEXT_WARSONGULCH "Warsong Gulch"
+#define GOSSIP_TEXT_ARENA "Arena"
+#define GOSSIP_TEXT_EYEOFTHESTORM "Eye of The Storm"
+#define GOSSIP_TEXT_STRANDOFANCIENT "Strand of the Ancients"
+
+#define GOSSIP_TEXT_DEATH_KNIGHT "Death Knight"
+#define GOSSIP_TEXT_DRUID "Druid"
+#define GOSSIP_TEXT_HUNTER "Hunter"
+#define GOSSIP_TEXT_PRIEST "Priest"
+#define GOSSIP_TEXT_ROGUE "Rogue"
+#define GOSSIP_TEXT_WARRIOR "Warrior"
+#define GOSSIP_TEXT_PALADIN "Paladin"
+#define GOSSIP_TEXT_SHAMAN "Shaman"
+#define GOSSIP_TEXT_MAGE "Mage"
+#define GOSSIP_TEXT_WARLOCK "Warlock"
+
+#define GOSSIP_TEXT_ALCHEMY "Alchemy"
+#define GOSSIP_TEXT_BLACKSMITHING "Blacksmithing"
+#define GOSSIP_TEXT_COOKING "Cooking"
+#define GOSSIP_TEXT_ENCHANTING "Enchanting"
+#define GOSSIP_TEXT_ENGINEERING "Engineering"
+#define GOSSIP_TEXT_FIRSTAID "First Aid"
+#define GOSSIP_TEXT_HERBALISM "Herbalism"
+#define GOSSIP_TEXT_LEATHERWORKING "Leatherworking"
+#define GOSSIP_TEXT_TAILORING "Tailoring"
+#define GOSSIP_TEXT_MINING "Mining"
+#define GOSSIP_TEXT_FISHING "Fishing"
+#define GOSSIP_TEXT_SKINNING "Skinning"
+#define GOSSIP_TEXT_JEWELCRAFTING "Jewelcrafting"
+#define GOSSIP_TEXT_INSCRIPTION "Inscription"
+
+enum
+{
+ // Skill defines
+ TRADESKILL_ALCHEMY = 1,
+ TRADESKILL_BLACKSMITHING = 2,
+ TRADESKILL_COOKING = 3,
+ TRADESKILL_ENCHANTING = 4,
+ TRADESKILL_ENGINEERING = 5,
+ TRADESKILL_FIRSTAID = 6,
+ TRADESKILL_HERBALISM = 7,
+ TRADESKILL_LEATHERWORKING = 8,
+ TRADESKILL_POISONS = 9,
+ TRADESKILL_TAILORING = 10,
+ TRADESKILL_MINING = 11,
+ TRADESKILL_FISHING = 12,
+ TRADESKILL_SKINNING = 13,
+ TRADESKILL_JEWLCRAFTING = 14,
+ TRADESKILL_INSCRIPTION = 15,
+
+ TRADESKILL_LEVEL_NONE = 0,
+ TRADESKILL_LEVEL_APPRENTICE = 1,
+ TRADESKILL_LEVEL_JOURNEYMAN = 2,
+ TRADESKILL_LEVEL_EXPERT = 3,
+ TRADESKILL_LEVEL_ARTISAN = 4,
+ TRADESKILL_LEVEL_MASTER = 5,
+ TRADESKILL_LEVEL_GRAND_MASTER = 6,
+
+ // Gossip defines
+ GOSSIP_ACTION_TRADE = 1,
+ GOSSIP_ACTION_TRAIN = 2,
+ GOSSIP_ACTION_TAXI = 3,
+ GOSSIP_ACTION_GUILD = 4,
+ GOSSIP_ACTION_BATTLE = 5,
+ GOSSIP_ACTION_BANK = 6,
+ GOSSIP_ACTION_INN = 7,
+ GOSSIP_ACTION_HEAL = 8,
+ GOSSIP_ACTION_TABARD = 9,
+ GOSSIP_ACTION_AUCTION = 10,
+ GOSSIP_ACTION_INN_INFO = 11,
+ GOSSIP_ACTION_UNLEARN = 12,
+ GOSSIP_ACTION_INFO_DEF = 1000,
+
+ GOSSIP_SENDER_MAIN = 1,
+ GOSSIP_SENDER_INN_INFO = 2,
+ GOSSIP_SENDER_INFO = 3,
+ GOSSIP_SENDER_SEC_PROFTRAIN = 4,
+ GOSSIP_SENDER_SEC_CLASSTRAIN = 5,
+ GOSSIP_SENDER_SEC_BATTLEINFO = 6,
+ GOSSIP_SENDER_SEC_BANK = 7,
+ GOSSIP_SENDER_SEC_INN = 8,
+ GOSSIP_SENDER_SEC_MAILBOX = 9,
+ GOSSIP_SENDER_SEC_STABLEMASTER = 10
+};
+
+extern uint32 GetSkillLevel(Player* pPlayer, uint32 uiSkill);
+
+// Defined fuctions to use with player.
+
+// This fuction add's a menu item,
+// Icon Id
+// Text
+// Sender(this is to identify the current Menu with this item)
+// Option id (identifies this Menu Item)
+// Text to be displayed in pop up box
+// Money value in pop up box
+// Coded
+#define ADD_GOSSIP_ITEM(uiIcon, chrText, uiSender, uiOptionId) PlayerTalkClass->GetGossipMenu().AddMenuItem(uiIcon, chrText, uiSender, uiOptionId, "", 0)
+#define ADD_GOSSIP_ITEM_ID(uiIcon, iTextId, uiSender, uiOptionId) PlayerTalkClass->GetGossipMenu().AddMenuItem(uiIcon, iTextId, uiSender, uiOptionId, 0, 0)
+#define ADD_GOSSIP_ITEM_EXTENDED(uiIcon, chrText, uiSender, uiOptionId, chrBoxMessage, uiBoxMoney, bCode) PlayerTalkClass->GetGossipMenu().AddMenuItem(uiIcon, chrText, uiSender, uiOptionId, chrBoxMessage, uiBoxMoney, bCode)
+
+// This fuction Sends the current menu to show to client, uiTextId - NPCTEXTID(uint32) , uiGuid - npc guid(uint64)
+#define SEND_GOSSIP_MENU(uiTextId, uiGuid) PlayerTalkClass->SendGossipMenu(uiTextId, uiGuid)
+
+// This fuction shows POI(point of interest) to client.
+// a - position X
+// b - position Y
+// c - Icon Id
+// d - Flags
+// e - Data
+// f - Location Name
+#define SEND_POI(a, b, c, d, e, f) PlayerTalkClass->SendPointOfInterest(a, b, c, d, e, f)
+
+// Closes the Menu
+#define CLOSE_GOSSIP_MENU() PlayerTalkClass->CloseGossip()
+
+// Fuction to tell to client the details
+// a - quest object
+// b - npc guid(uint64)
+// c - Activate accept(bool)
+#define SEND_QUEST_DETAILS(a, b, c) PlayerTalkClass->SendQuestDetails(a, b, c)
+
+// Fuction to tell to client the requested items to complete quest
+// a - quest object
+// b - npc guid(uint64)
+// c - Iscompletable(bool)
+// d - close at cancel(bool) - in case single incomplite ques
+#define SEND_REQUESTEDITEMS(a, b, c, d) PlayerTalkClass->SendRequestedItems(a, b, c, d)
+
+// Fuctions to send NPC lists, a - is always the npc guid(uint64)
+#define SEND_VENDORLIST(a) GetSession()->SendListInventory(a)
+#define SEND_TRAINERLIST(a) GetSession()->SendTrainerList(a)
+#define SEND_BANKERLIST(a) GetSession()->SendShowBank(a)
+#define SEND_TABARDLIST(a) GetSession()->SendTabardVendorActivate(a)
+#define SEND_TAXILIST(a) GetSession()->SendTaxiStatus(a)
+
+// Function to send the Auction List, a - npc guid(uint64), b - pointer to npc(Creature*)
+#define SEND_AUCTIONLIST(a, b) GetSession()->SendAuctionHello(a, b)
+
+// Ressurect's the player if is dead.
+#define SEND_SPRESURRECT() GetSession()->SendSpiritResurrect()
+// -----------------------------------
+
+// defined fuctions to use with Creature
+
+#define QUEST_DIALOG_STATUS(a, b, c) GetSession()->getDialogStatus(a, b, c)
+#endif
diff --git a/include/sc_grid_searchers.cpp b/include/sc_grid_searchers.cpp
new file mode 100644
index 0000000..535c0c4
--- /dev/null
+++ b/include/sc_grid_searchers.cpp
@@ -0,0 +1,47 @@
+/* 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 */
+
+#include "precompiled.h"
+
+//return closest GO in grid, with range from pSource
+GameObject* GetClosestGameObjectWithEntry(WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange)
+{
+ GameObject* pGo = NULL;
+
+ MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*pSource, uiEntry, fMaxSearchRange);
+ MaNGOS::GameObjectLastSearcher searcher(pGo, go_check);
+
+ Cell::VisitGridObjects(pSource, searcher, fMaxSearchRange);
+
+ return pGo;
+}
+
+//return closest creature alive in grid, with range from pSource
+Creature* GetClosestCreatureWithEntry(WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange)
+{
+ Creature* pCreature = NULL;
+
+ MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check(*pSource, uiEntry, true, fMaxSearchRange);
+ MaNGOS::CreatureLastSearcher searcher(pCreature, creature_check);
+
+ Cell::VisitGridObjects(pSource, searcher, fMaxSearchRange);
+
+ return pCreature;
+}
+
+void GetGameObjectListWithEntryInGrid(std::list& lList , WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange)
+{
+ AllGameObjectsWithEntryInRangeCheck check(pSource, uiEntry, fMaxSearchRange);
+ MaNGOS::GameObjectListSearcher searcher(lList, check);
+
+ Cell::VisitGridObjects(pSource, searcher, fMaxSearchRange);
+}
+
+void GetCreatureListWithEntryInGrid(std::list& lList, WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange)
+{
+ AllCreaturesOfEntryInRangeCheck check(pSource, uiEntry, fMaxSearchRange);
+ MaNGOS::CreatureListSearcher searcher(lList, check);
+
+ Cell::VisitGridObjects(pSource, searcher, fMaxSearchRange);
+}
diff --git a/include/sc_grid_searchers.h b/include/sc_grid_searchers.h
new file mode 100644
index 0000000..a5c635d
--- /dev/null
+++ b/include/sc_grid_searchers.h
@@ -0,0 +1,103 @@
+/* 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 */
+
+#ifndef SC_GRIDSEARCH_H
+#define SC_GRIDSEARCH_H
+
+#include "Unit.h"
+#include "GameObject.h"
+
+#include "Cell.h"
+#include "CellImpl.h"
+#include "GridNotifiers.h"
+#include "GridNotifiersImpl.h"
+
+struct ObjectDistanceOrder : public std::binary_function
+{
+ const Unit* m_pSource;
+
+ ObjectDistanceOrder(const Unit* pSource) : m_pSource(pSource) {};
+
+ bool operator()(const WorldObject* pLeft, const WorldObject* pRight) const
+ {
+ return m_pSource->GetDistanceOrder(pLeft, pRight);
+ }
+};
+
+struct ObjectDistanceOrderReversed : public std::binary_function
+{
+ const Unit* m_pSource;
+
+ ObjectDistanceOrderReversed(const Unit* pSource) : m_pSource(pSource) {};
+
+ bool operator()(const WorldObject* pLeft, const WorldObject* pRight) const
+ {
+ return !m_pSource->GetDistanceOrder(pLeft, pRight);
+ }
+};
+
+GameObject* GetClosestGameObjectWithEntry(WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange);
+Creature* GetClosestCreatureWithEntry(WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange);
+
+void GetGameObjectListWithEntryInGrid(std::list& lList , WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange);
+void GetCreatureListWithEntryInGrid(std::list& lList, WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange);
+
+class AllGameObjectsWithEntryInRangeCheck
+{
+ public:
+ AllGameObjectsWithEntryInRangeCheck(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {}
+ WorldObject const& GetFocusObject() const { return *m_pObject; }
+ bool operator() (GameObject* pGo)
+ {
+ if (pGo->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pGo,m_fRange,false))
+ return true;
+
+ return false;
+ }
+
+ private:
+ const WorldObject* m_pObject;
+ uint32 m_uiEntry;
+ float m_fRange;
+};
+
+class AllCreaturesOfEntryInRangeCheck
+{
+ public:
+ AllCreaturesOfEntryInRangeCheck(const WorldObject* pObject, uint32 uiEntry, float fMaxRange) : m_pObject(pObject), m_uiEntry(uiEntry), m_fRange(fMaxRange) {}
+ WorldObject const& GetFocusObject() const { return *m_pObject; }
+ bool operator() (Unit* pUnit)
+ {
+ if (pUnit->GetEntry() == m_uiEntry && m_pObject->IsWithinDist(pUnit,m_fRange,false))
+ return true;
+
+ return false;
+ }
+
+ private:
+ const WorldObject* m_pObject;
+ uint32 m_uiEntry;
+ float m_fRange;
+};
+
+//Used in: hyjalAI.cpp
+/*
+class AllFriendlyCreaturesInGrid
+{
+ public:
+ AllFriendlyCreaturesInGrid(Unit const* obj) : pUnit(obj) {}
+ bool operator() (Unit* u)
+ {
+ if (u->isAlive() && u->GetVisibility() == VISIBILITY_ON && u->IsFriendlyTo(pUnit))
+ return true;
+
+ return false;
+ }
+
+ private:
+ Unit const* pUnit;
+};
+*/
+
+#endif
diff --git a/include/sc_instance.cpp b/include/sc_instance.cpp
new file mode 100644
index 0000000..f91b8a0
--- /dev/null
+++ b/include/sc_instance.cpp
@@ -0,0 +1,58 @@
+/* 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 */
+
+#include "precompiled.h"
+
+//Optional uiWithRestoreTime. If not defined, autoCloseTime will be used (if not 0 by default in *_template)
+void ScriptedInstance::DoUseDoorOrButton(uint64 uiGuid, uint32 uiWithRestoreTime, bool bUseAlternativeState)
+{
+ if (!uiGuid)
+ return;
+
+ if (GameObject* pGo = instance->GetGameObject(uiGuid))
+ {
+ if (pGo->GetGoType() == GAMEOBJECT_TYPE_DOOR || pGo->GetGoType() == GAMEOBJECT_TYPE_BUTTON)
+ {
+ if (pGo->getLootState() == GO_READY)
+ pGo->UseDoorOrButton(uiWithRestoreTime, bUseAlternativeState);
+ else if (pGo->getLootState() == GO_ACTIVATED)
+ pGo->ResetDoorOrButton();
+ }
+ else
+ error_log("SD2: Script call DoUseDoorOrButton, but gameobject entry %u is type %u.",pGo->GetEntry(),pGo->GetGoType());
+ }
+}
+
+void ScriptedInstance::DoRespawnGameObject(uint64 uiGuid, uint32 uiTimeToDespawn)
+{
+ if (GameObject* pGo = instance->GetGameObject(uiGuid))
+ {
+ //not expect any of these should ever be handled
+ if (pGo->GetGoType()==GAMEOBJECT_TYPE_FISHINGNODE || pGo->GetGoType()==GAMEOBJECT_TYPE_DOOR ||
+ pGo->GetGoType()==GAMEOBJECT_TYPE_BUTTON || pGo->GetGoType()==GAMEOBJECT_TYPE_TRAP)
+ return;
+
+ if (pGo->isSpawned())
+ return;
+
+ pGo->SetRespawnTime(uiTimeToDespawn);
+ pGo->Refresh();
+ }
+}
+
+void ScriptedInstance::DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData)
+{
+ 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->SendUpdateWorldState(uiStateId, uiStateData);
+ }
+ }
+ else
+ debug_log("SD2: DoUpdateWorldState attempt send data but no players in map.");
+}
diff --git a/include/sc_instance.h b/include/sc_instance.h
new file mode 100644
index 0000000..3b44167
--- /dev/null
+++ b/include/sc_instance.h
@@ -0,0 +1,42 @@
+/* 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 */
+
+#ifndef SC_INSTANCE_H
+#define SC_INSTANCE_H
+
+#include "InstanceData.h"
+#include "Map.h"
+
+enum EncounterState
+{
+ NOT_STARTED = 0,
+ IN_PROGRESS = 1,
+ FAIL = 2,
+ DONE = 3,
+ SPECIAL = 4
+};
+
+#define OUT_SAVE_INST_DATA debug_log("SD2: Saving Instance Data for Instance %s (Map %d, Instance Id %d)", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
+#define OUT_SAVE_INST_DATA_COMPLETE debug_log("SD2: Saving Instance Data for Instance %s (Map %d, Instance Id %d) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
+#define OUT_LOAD_INST_DATA(a) debug_log("SD2: Loading Instance Data for Instance %s (Map %d, Instance Id %d). Input is '%s'", instance->GetMapName(), instance->GetId(), instance->GetInstanceId(), a)
+#define OUT_LOAD_INST_DATA_COMPLETE debug_log("SD2: Instance Data Load for Instance %s (Map %d, Instance Id: %d) is complete.",instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
+#define OUT_LOAD_INST_DATA_FAIL error_log("SD2: Unable to load Instance Data for Instance %s (Map %d, Instance Id: %d).",instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
+
+class MANGOS_DLL_DECL ScriptedInstance : public InstanceData
+{
+ public:
+
+ ScriptedInstance(Map* pMap) : InstanceData(pMap) {}
+ ~ScriptedInstance() {}
+
+ //change active state of doors or buttons
+ void DoUseDoorOrButton(uint64 uiGuid, uint32 uiWithRestoreTime = 0, bool bUseAlternativeState = false);
+
+ //Respawns a GO having negative spawntimesecs in gameobject-table
+ void DoRespawnGameObject(uint64 uiGuid, uint32 uiTimeToDespawn = MINUTE);
+
+ //sends world state update to all players in instance
+ void DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData);
+};
+#endif
diff --git a/patches/MaNGOS-9519-ScriptDev2.patch b/patches/MaNGOS-9519-ScriptDev2.patch
new file mode 100644
index 0000000..e5e5dca
--- /dev/null
+++ b/patches/MaNGOS-9519-ScriptDev2.patch
@@ -0,0 +1,63 @@
+From 3a3dda6636d81c33c3c9b143f64b5a518bfadb56 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 90b332a..c31ff26 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -308,7 +308,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 fe1ace1..40b6fdd 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 \
+ ../shared/Database/libmangosdatabase.a \
+ ../shared/Config/libmangosconfig.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/patches/custom/ScriptDev2_1835_to_MaNGOS_0.12.patch b/patches/custom/ScriptDev2_1835_to_MaNGOS_0.12.patch
new file mode 100644
index 0000000..9eb4462
--- /dev/null
+++ b/patches/custom/ScriptDev2_1835_to_MaNGOS_0.12.patch
@@ -0,0 +1,284 @@
+Index: include/precompiled.h
+===================================================================
+--- include/precompiled.h (revision 1838)
++++ include/precompiled.h (working copy)
+@@ -11,6 +11,11 @@
+ #include "sc_grid_searchers.h"
+ #include "sc_instance.h"
+
++enum backports
++{
++ UNIT_VIRTUAL_ITEM_SLOT_ID = UNIT_VIRTUAL_ITEM_SLOT_DISPLAY
++};
++
+ #ifdef WIN32
+ # include
+ BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+Index: scripts/kalimdor/azuremyst_isle.cpp
+===================================================================
+--- scripts/kalimdor/azuremyst_isle.cpp (revision 1838)
++++ scripts/kalimdor/azuremyst_isle.cpp (working copy)
+@@ -103,7 +103,7 @@
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+- if (pSpell->SpellFamilyFlags2 & 0x080000000)
++ if (pSpell->Id == 28880)
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+Index: scripts/kalimdor/onyxias_lair/boss_onyxia.cpp
+===================================================================
+--- scripts/kalimdor/onyxias_lair/boss_onyxia.cpp (revision 1838)
++++ scripts/kalimdor/onyxias_lair/boss_onyxia.cpp (working copy)
+@@ -299,7 +299,7 @@
+ DoScriptText(SAY_PHASE_2_TRANS, m_creature);
+
+ // sort of a hack, it is unclear how this really work but the values appear to be valid
+- m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2);
++ m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND/* | UNIT_BYTE1_FLAG_UNK_2*/);
+ m_creature->AddSplineFlag(SPLINEFLAG_FLYING);
+
+ if (m_pPointData)
+Index: scripts/northrend/dragonblight.cpp
+===================================================================
+--- scripts/northrend/dragonblight.cpp (revision 1838)
++++ scripts/northrend/dragonblight.cpp (working copy)
+@@ -101,7 +101,7 @@
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+- pPlayer->SendMovieStart(MOVIE_ID_GATES);
++// pPlayer->SendMovieStart(MOVIE_ID_GATES);
+ }
+
+ return true;
+Index: scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp
+===================================================================
+--- scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp (revision 1838)
++++ scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp (working copy)
+@@ -107,10 +107,10 @@
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MOONFIRE);
+ m_uiSpellTimer = 10000;
+ break;
+- case CLASS_DEATH_KNIGHT:
+- DoCastSpellIfCan(m_creature->getVictim(), SPELL_PLAGUE_STRIKE);
+- m_uiSpellTimer = 10000;
+- break;
++// case CLASS_DEATH_KNIGHT:
++// DoCastSpellIfCan(m_creature->getVictim(), SPELL_PLAGUE_STRIKE);
++// m_uiSpellTimer = 10000;
++// break;
+ }
+ }
+ else
+Index: scripts/world/item_scripts.cpp
+===================================================================
+--- scripts/world/item_scripts.cpp (revision 1838)
++++ scripts/world/item_scripts.cpp (working copy)
+@@ -47,7 +47,7 @@
+ pPlayer->SendEquipError(EQUIP_ERR_NONE, pItem, NULL);
+
+ if (const SpellEntry* pSpellInfo = GetSpellStore()->LookupEntry(SPELL_ARCANE_CHARGES))
+- Spell::SendCastResult(pPlayer, pSpellInfo, 1, SPELL_FAILED_NOT_ON_GROUND);
++ Spell::SendCastResult(pPlayer, pSpellInfo, 1, SPELL_FAILED_ERROR);
+
+ return true;
+ }
+Index: scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp
+===================================================================
+--- scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp (revision 1838)
++++ scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp (working copy)
+@@ -91,10 +91,10 @@
+ else
+ DoScriptText(EMOTE_UNLOCK_DOOR_AD, m_creature);
+ break;
+- case 12:
+- if (m_uiNpcEntry != NPC_ASH)
+- m_creature->HandleEmote(EMOTE_ONESHOT_USESTANDING);
+- break;
++// case 12:
++// if (m_uiNpcEntry != NPC_ASH)
++// m_creature->HandleEmote(EMOTE_ONESHOT_USESTANDING);
++// break;
+ case 13:
+ if (m_uiNpcEntry == NPC_ASH)
+ DoScriptText(SAY_POST_DOOR_AS, m_creature);
+Index: system/ScriptLoader.cpp
+===================================================================
+--- system/ScriptLoader.cpp (revision 1838)
++++ system/ScriptLoader.cpp (working copy)
+@@ -263,85 +263,8 @@
+ extern void AddSC_winterspring();
+
+ //northrend
+-extern void AddSC_boss_jedoga(); //ahnkahet
+-extern void AddSC_boss_nadox();
+-extern void AddSC_boss_taldaram();
+-extern void AddSC_boss_volazj();
+-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_boss_jaraxxus();
+-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_tharonja();
+-extern void AddSC_boss_trollgore();
+-extern void AddSC_boss_colossus(); //gundrak
+-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_anubrekhan(); //naxxramas
+-extern void AddSC_boss_four_horsemen();
+-extern void AddSC_boss_faerlina();
+-extern void AddSC_boss_gluth();
+-extern void AddSC_boss_gothik();
+-extern void AddSC_boss_kelthuzad();
+-extern void AddSC_boss_loatheb();
+-extern void AddSC_boss_maexxna();
+-extern void AddSC_boss_noth();
+-extern void AddSC_boss_heigan();
+-extern void AddSC_boss_patchwerk();
+-extern void AddSC_boss_razuvious();
+-extern void AddSC_boss_sapphiron();
+-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_boss_sartharion(); //obsidian_sanctum
+-extern void AddSC_instance_obsidian_sanctum();
+-extern void AddSC_boss_bjarngrim(); //Ulduar, halls_of_lightning
+-extern void AddSC_boss_ionar();
+-extern void AddSC_boss_loken();
+-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_halls_of_stone();
+-extern void AddSC_instance_halls_of_stone();
+-extern void AddSC_instance_ulduar(); //ulduar
+-extern void AddSC_boss_ingvar(); //utgarde_keep
+-extern void AddSC_boss_keleseth();
+-extern void AddSC_boss_skarvald_and_dalronn();
+-extern void AddSC_instance_utgarde_keep();
+-extern void AddSC_utgarde_keep();
+-extern void AddSC_boss_gortok(); //utgarde_pinnacle
+-extern void AddSC_boss_skadi();
+-extern void AddSC_boss_svala();
+-extern void AddSC_boss_ymiron();
+-extern void AddSC_instance_pinnacle();
+-extern void AddSC_instance_violet_hold(); //violet_hold
+-extern void AddSC_violet_hold();
++// removed
+
+-extern void AddSC_borean_tundra();
+-extern void AddSC_dalaran();
+-extern void AddSC_dragonblight();
+-extern void AddSC_howling_fjord();
+-extern void AddSC_icecrown();
+-extern void AddSC_sholazar_basin();
+-extern void AddSC_storm_peaks();
+-extern void AddSC_zuldrak();
+-
+ //outland
+ extern void AddSC_boss_exarch_maladaar(); //auchindoun, auchenai_crypts
+ extern void AddSC_boss_nexusprince_shaffar(); //auchindoun, mana_tombs
+@@ -681,85 +604,8 @@
+ AddSC_winterspring();
+
+ //northrend
+- AddSC_boss_jedoga(); //ahnkahet
+- AddSC_boss_nadox();
+- AddSC_boss_taldaram();
+- AddSC_boss_volazj();
+- 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_boss_jaraxxus();
+- AddSC_instance_trial_of_the_crusader();
+- AddSC_northrend_beasts();
+- AddSC_trial_of_the_crusader();
+- AddSC_twin_valkyr();
+- AddSC_boss_novos(); //draktharon_keep
+- AddSC_boss_tharonja();
+- AddSC_boss_trollgore();
+- AddSC_boss_colossus(); //gundrak
+- AddSC_boss_galdarah();
+- 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_anubrekhan(); //naxxramas
+- AddSC_boss_four_horsemen();
+- AddSC_boss_faerlina();
+- AddSC_boss_gluth();
+- AddSC_boss_gothik();
+- AddSC_boss_kelthuzad();
+- AddSC_boss_loatheb();
+- AddSC_boss_maexxna();
+- AddSC_boss_noth();
+- AddSC_boss_heigan();
+- AddSC_boss_patchwerk();
+- AddSC_boss_razuvious();
+- AddSC_boss_sapphiron();
+- AddSC_instance_naxxramas();
+- AddSC_boss_anomalus(); //nexus
+- AddSC_boss_keristrasza();
+- AddSC_boss_ormorok();
+- AddSC_boss_telestra();
+- AddSC_instance_nexus();
+- AddSC_boss_sartharion(); //obsidian_sanctum
+- AddSC_instance_obsidian_sanctum();
+- AddSC_boss_bjarngrim(); //Ulduar, halls_of_lightning
+- AddSC_boss_ionar();
+- AddSC_boss_loken();
+- AddSC_boss_volkhan();
+- AddSC_instance_halls_of_lightning();
+- AddSC_boss_maiden_of_grief(); //Ulduar, halls_of_stone
+- AddSC_boss_sjonnir();
+- AddSC_halls_of_stone();
+- AddSC_instance_halls_of_stone();
+- AddSC_instance_ulduar(); //ulduar
+- AddSC_boss_ingvar(); //utgarde_keep
+- AddSC_boss_keleseth();
+- AddSC_boss_skarvald_and_dalronn();
+- AddSC_instance_utgarde_keep();
+- AddSC_utgarde_keep();
+- AddSC_boss_gortok(); //utgarde_pinnacle
+- AddSC_boss_skadi();
+- AddSC_boss_svala();
+- AddSC_boss_ymiron();
+- AddSC_instance_pinnacle();
+- AddSC_instance_violet_hold(); //violet_hold
+- AddSC_violet_hold();
++ // removed
+
+- AddSC_borean_tundra();
+- AddSC_dalaran();
+- AddSC_dragonblight();
+- AddSC_howling_fjord();
+- AddSC_icecrown();
+- AddSC_sholazar_basin();
+- AddSC_storm_peaks();
+- AddSC_zuldrak();
+-
+ //outland
+ AddSC_boss_exarch_maladaar(); //auchindoun, auchenai_crypts
+ AddSC_boss_nexusprince_shaffar(); //auchindoun, mana_tombs
diff --git a/scriptVC100.sln b/scriptVC100.sln
new file mode 100644
index 0000000..3860230
--- /dev/null
+++ b/scriptVC100.sln
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScriptDev2", "VC100\100ScriptDev2.vcxproj", "{4295C8A9-79B7-4354-8064-F05FB9CA0C96}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|Win32.Build.0 = Debug|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|x64.ActiveCfg = Debug|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|x64.Build.0 = Debug|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|Win32.ActiveCfg = Release|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|Win32.Build.0 = Release|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|x64.ActiveCfg = Release|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/scriptVC80.sln b/scriptVC80.sln
new file mode 100644
index 0000000..ea245ac
--- /dev/null
+++ b/scriptVC80.sln
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScriptDev2", "VC80\80ScriptDev2.vcproj", "{4295C8A9-79B7-4354-8064-F05FB9CA0C96}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|Win32.Build.0 = Debug|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|x64.ActiveCfg = Debug|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|x64.Build.0 = Debug|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|Win32.ActiveCfg = Release|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|Win32.Build.0 = Release|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|x64.ActiveCfg = Release|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/scriptVC90.sln b/scriptVC90.sln
new file mode 100644
index 0000000..05b24d7
--- /dev/null
+++ b/scriptVC90.sln
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ScriptDev2", "VC90\90ScriptDev2.vcproj", "{4295C8A9-79B7-4354-8064-F05FB9CA0C96}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|Win32.ActiveCfg = Debug|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|Win32.Build.0 = Debug|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|x64.ActiveCfg = Debug|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Debug|x64.Build.0 = Debug|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|Win32.ActiveCfg = Release|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|Win32.Build.0 = Release|Win32
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|x64.ActiveCfg = Release|x64
+ {4295C8A9-79B7-4354-8064-F05FB9CA0C96}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/scriptdev2.conf.dist.in b/scriptdev2.conf.dist.in
new file mode 100644
index 0000000..486c85c
--- /dev/null
+++ b/scriptdev2.conf.dist.in
@@ -0,0 +1,13 @@
+# ScriptDev2 Configuration file
+# This file must be placed within the directory which holds mangosd.conf and realmd.conf
+
+[ScriptDev2Conf]
+ConfVersion=2010062001
+
+# Database connection settings for the world server.
+# Default: hostname;port;username;password;database
+# .;somenumber;username;password;database - use named pipes at Windows
+# Named pipes: mySQL required adding "enable-named-pipe" to [mysqld] section my.ini
+# .;/path/to/unix_socket;username;password;database - use Unix sockets at Unix/Linux
+# Unix sockets: experimental, not tested
+ScriptDev2DatabaseInfo = "127.0.0.1;3306;mangos;mangos;scriptdev2"
diff --git a/scripts/battlegrounds/battleground.cpp b/scripts/battlegrounds/battleground.cpp
new file mode 100644
index 0000000..dcb1b21
--- /dev/null
+++ b/scripts/battlegrounds/battleground.cpp
@@ -0,0 +1,112 @@
+/* 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: Battleground
+SD%Complete: 100
+SDComment: Spirit guides in battlegrounds will revive all players every 30 sec
+SDCategory: Battlegrounds
+EndScriptData */
+
+#include "precompiled.h"
+
+// **** Script Info ****
+// Spiritguides in battlegrounds resurrecting many players at once
+// every 30 seconds - through a channeled spell, which gets autocasted
+// the whole time
+// if spiritguide despawns all players around him will get teleported
+// to the next spiritguide
+// here i'm not sure, if a dummyspell exist for it
+
+// **** Quick Info ****
+// battleground spiritguides - this script handles gossipHello
+// and JustDied also it let autocast the channel-spell
+
+enum
+{
+ SPELL_SPIRIT_HEAL_CHANNEL = 22011, // Spirit Heal Channel
+
+ SPELL_SPIRIT_HEAL = 22012, // Spirit Heal
+ SPELL_SPIRIT_HEAL_MANA = 44535, // in battlegrounds player get this no-mana-cost-buff
+
+ SPELL_WAITING_TO_RESURRECT = 2584 // players who cancel this aura don't want a resurrection
+};
+
+struct MANGOS_DLL_DECL npc_spirit_guideAI : public ScriptedAI
+{
+ npc_spirit_guideAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // auto cast the whole time this spell
+ if (!m_creature->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
+ m_creature->CastSpell(m_creature, SPELL_SPIRIT_HEAL_CHANNEL, false);
+ }
+
+ void CorpseRemoved(uint32 &)
+ {
+ // TODO: would be better to cast a dummy spell
+ Map* pMap = m_creature->GetMap();
+
+ if (!pMap || !pMap->IsBattleGround())
+ return;
+
+ Map::PlayerList const &PlayerList = pMap->GetPlayers();
+
+ for(Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
+ {
+ Player* pPlayer = itr->getSource();
+ if (!pPlayer || !pPlayer->IsWithinDistInMap(m_creature, 20.0f) || !pPlayer->HasAura(SPELL_WAITING_TO_RESURRECT))
+ continue;
+
+ // repop player again - now this node won't be counted and another node is searched
+ pPlayer->RepopAtGraveyard();
+ }
+ }
+
+ void SpellHitTarget (Unit* pUnit, const SpellEntry* pSpellEntry)
+ {
+ if (pSpellEntry->Id == SPELL_SPIRIT_HEAL && pUnit->GetTypeId() == TYPEID_PLAYER
+ && pUnit->HasAura(SPELL_WAITING_TO_RESURRECT))
+ pUnit->CastSpell(pUnit, SPELL_SPIRIT_HEAL_MANA, true);
+ }
+};
+
+bool GossipHello_npc_spirit_guide(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->CastSpell(pPlayer, SPELL_WAITING_TO_RESURRECT, true);
+ return true;
+}
+
+CreatureAI* GetAI_npc_spirit_guide(Creature* pCreature)
+{
+ return new npc_spirit_guideAI(pCreature);
+}
+
+void AddSC_battleground()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_spirit_guide";
+ newscript->GetAI = &GetAI_npc_spirit_guide;
+ newscript->pGossipHello = &GossipHello_npc_spirit_guide;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/alterac_mountains.cpp b/scripts/eastern_kingdoms/alterac_mountains.cpp
new file mode 100644
index 0000000..22dbc23
--- /dev/null
+++ b/scripts/eastern_kingdoms/alterac_mountains.cpp
@@ -0,0 +1,32 @@
+/* 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: Alterac_Mountains
+SD%Complete: 0
+SDComment: Placeholder
+SDCategory: Alterac Mountains
+EndScriptData */
+
+/* ContentData
+EndContentData */
+
+#include "precompiled.h"
+
+/*void AddSC_alterac_mountains()
+{
+ Script *newscript;
+}*/
diff --git a/scripts/eastern_kingdoms/arathi_highlands.cpp b/scripts/eastern_kingdoms/arathi_highlands.cpp
new file mode 100644
index 0000000..88122a1
--- /dev/null
+++ b/scripts/eastern_kingdoms/arathi_highlands.cpp
@@ -0,0 +1,126 @@
+/* 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: Arathi Highlands
+SD%Complete: 100
+SDComment: Quest support: 665
+SDCategory: Arathi Highlands
+EndScriptData */
+
+/* ContentData
+npc_professor_phizzlethorpe
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_professor_phizzlethorpe
+######*/
+
+enum
+{
+ SAY_PROGRESS_1 = -1000264,
+ SAY_PROGRESS_2 = -1000265,
+ SAY_PROGRESS_3 = -1000266,
+ EMOTE_PROGRESS_4 = -1000267,
+ SAY_AGGRO = -1000268,
+ SAY_PROGRESS_5 = -1000269,
+ SAY_PROGRESS_6 = -1000270,
+ SAY_PROGRESS_7 = -1000271,
+ EMOTE_PROGRESS_8 = -1000272,
+ SAY_PROGRESS_9 = -1000273,
+
+ QUEST_SUNKEN_TREASURE = 665,
+ ENTRY_VENGEFUL_SURGE = 2776
+};
+
+struct MANGOS_DLL_DECL npc_professor_phizzlethorpeAI : public npc_escortAI
+{
+ npc_professor_phizzlethorpeAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void Reset() { }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch(uiPointId)
+ {
+ case 4: DoScriptText(SAY_PROGRESS_2, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_PROGRESS_3, m_creature, pPlayer); break;
+ case 8: DoScriptText(EMOTE_PROGRESS_4, m_creature); break;
+ case 9:
+ m_creature->SummonCreature(ENTRY_VENGEFUL_SURGE, -2056.41f, -2144.01f, 20.59f, 5.70f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000);
+ m_creature->SummonCreature(ENTRY_VENGEFUL_SURGE, -2050.17f, -2140.02f, 19.54f, 5.17f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000);
+ break;
+ case 10: DoScriptText(SAY_PROGRESS_5, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(SAY_PROGRESS_6, m_creature, pPlayer);
+ SetRun();
+ break;
+ case 19: DoScriptText(SAY_PROGRESS_7, m_creature, pPlayer); break;
+ case 20:
+ DoScriptText(EMOTE_PROGRESS_8, m_creature);
+ DoScriptText(SAY_PROGRESS_9, m_creature, pPlayer);
+ pPlayer->GroupEventHappens(QUEST_SUNKEN_TREASURE, m_creature);
+ break;
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->AI()->AttackStart(m_creature);
+ }
+};
+
+bool QuestAccept_npc_professor_phizzlethorpe(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_SUNKEN_TREASURE)
+ {
+ pCreature->setFaction(FACTION_ESCORT_N_NEUTRAL_PASSIVE);
+ DoScriptText(SAY_PROGRESS_1, pCreature, pPlayer);
+
+ if (npc_professor_phizzlethorpeAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest, true);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_professor_phizzlethorpe(Creature* pCreature)
+{
+ return new npc_professor_phizzlethorpeAI(pCreature);
+}
+
+void AddSC_arathi_highlands()
+{
+ Script * newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_professor_phizzlethorpe";
+ newscript->GetAI = &GetAI_npc_professor_phizzlethorpe;
+ newscript->pQuestAccept = &QuestAccept_npc_professor_phizzlethorpe;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp b/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp
new file mode 100644
index 0000000..cd1d39d
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp
@@ -0,0 +1,754 @@
+/* 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: Blackrock_Depths
+SD%Complete: 50
+SDComment: Quest support: 4001, 4342, 7604. Vendor Lokhtos Darkbargainer.
+SDCategory: Blackrock Depths
+EndScriptData */
+
+/* ContentData
+go_shadowforge_brazier
+at_ring_of_law
+npc_grimstone
+mob_phalanx
+npc_kharan_mighthammer
+npc_lokhtos_darkbargainer
+EndContentData */
+
+#include "precompiled.h"
+#include "blackrock_depths.h"
+#include "escort_ai.h"
+
+/*######
+## go_shadowforge_brazier
+######*/
+
+bool GOHello_go_shadowforge_brazier(Player* pPlayer, GameObject* pGo)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData())
+ {
+ if (pInstance->GetData(TYPE_LYCEUM) == IN_PROGRESS)
+ pInstance->SetData(TYPE_LYCEUM, DONE);
+ else
+ pInstance->SetData(TYPE_LYCEUM, IN_PROGRESS);
+ }
+ return false;
+}
+
+/*######
+## npc_grimstone
+######*/
+
+enum
+{
+ SAY_START_1 = -1230004,
+ SAY_START_2 = -1230005,
+ SAY_OPEN_EAST_GATE = -1230006,
+ SAY_SUMMON_BOSS_1 = -1230007,
+ SAY_SUMMON_BOSS_2 = -1230008,
+ SAY_OPEN_NORTH_GATE = -1230009,
+
+ NPC_GRIMSTONE = 10096,
+ NPC_THELDREN = 16059,
+
+ //4 or 6 in total? 1+2+1 / 2+2+2 / 3+3. Depending on this, code should be changed.
+ MAX_MOB_AMOUNT = 4
+};
+
+static uint32 RingMob[]=
+{
+ 8925, // Dredge Worm
+ 8926, // Deep Stinger
+ 8927, // Dark Screecher
+ 8928, // Burrowing Thundersnout
+ 8933, // Cave Creeper
+ 8932, // Borer Beetle
+};
+
+static uint32 RingBoss[]=
+{
+ 9027, // Gorosh
+ 9028, // Grizzle
+ 9029, // Eviscerator
+ 9030, // Ok'thor
+ 9031, // Anub'shiah
+ 9032, // Hedrum
+};
+
+bool AreaTrigger_at_ring_of_law(Player* pPlayer, AreaTriggerEntry const* pAt)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pPlayer->GetInstanceData())
+ {
+ if (pInstance->GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || pInstance->GetData(TYPE_RING_OF_LAW) == DONE)
+ return false;
+
+ pInstance->SetData(TYPE_RING_OF_LAW, IN_PROGRESS);
+ pPlayer->SummonCreature(NPC_GRIMSTONE, 625.559f, -205.618f, -52.735f, 2.609f, TEMPSUMMON_DEAD_DESPAWN, 0);
+
+ return false;
+ }
+ return false;
+}
+
+/*######
+## npc_grimstone
+######*/
+
+//TODO: implement quest part of event (different end boss)
+struct MANGOS_DLL_DECL npc_grimstoneAI : public npc_escortAI
+{
+ npc_grimstoneAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_uiMobSpawnId = urand(0, 5);
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint8 m_uiEventPhase;
+ uint32 m_uiEventTimer;
+
+ uint8 m_uiMobSpawnId;
+ uint8 m_uiMobCount;
+ uint32 m_uiMobDeathTimer;
+
+ uint64 m_auiRingMobGUID[MAX_MOB_AMOUNT];
+ uint64 m_uiRingBossGUID;
+
+ bool m_bCanWalk;
+
+ void Reset()
+ {
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ memset(&m_auiRingMobGUID, 0, sizeof(m_auiRingMobGUID));
+
+ m_uiEventTimer = 1000;
+ m_uiEventPhase = 0;
+ m_uiMobCount = 0;
+ m_uiMobDeathTimer = 0;
+ m_uiRingBossGUID = 0;
+
+ m_bCanWalk = false;
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+
+ }
+
+ void SummonedCreatureJustDied(Creature* pSummoned)
+ {
+
+ }
+
+ void DoGate(uint32 id, uint32 state)
+ {
+ if (GameObject* pGo = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(id)))
+ pGo->SetGoState(GOState(state));
+
+ debug_log("SD2: npc_grimstone, arena gate update state.");
+ }
+
+ //TODO: move them to center
+ void SummonRingMob()
+ {
+ if (Creature* pTmp = m_creature->SummonCreature(RingMob[m_uiMobSpawnId], 608.960f, -235.322f, -53.907f, 1.857f, TEMPSUMMON_DEAD_DESPAWN, 0))
+ m_auiRingMobGUID[m_uiMobCount] = pTmp->GetGUID();
+
+ ++m_uiMobCount;
+
+ if (m_uiMobCount == MAX_MOB_AMOUNT)
+ m_uiMobDeathTimer = 2500;
+ }
+
+ //TODO: move them to center
+ void SummonRingBoss()
+ {
+ if (Creature* pTmp = m_creature->SummonCreature(RingBoss[urand(0, 5)], 644.300f, -175.989f, -53.739f, 3.418f, TEMPSUMMON_DEAD_DESPAWN, 0))
+ m_uiRingBossGUID = pTmp->GetGUID();
+
+ m_uiMobDeathTimer = 2500;
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 0: // Middle reached first time
+ DoScriptText(urand(0, 1) ? SAY_START_1 : SAY_START_2, m_creature);
+ m_bCanWalk = false;
+ m_uiEventTimer = 5000;
+ break;
+ case 1: // Reached wall again
+ DoScriptText(SAY_OPEN_EAST_GATE, m_creature);
+ m_bCanWalk = false;
+ m_uiEventTimer = 5000;
+ break;
+ case 2: // walking along the wall, while door opened
+ m_bCanWalk = false;
+ break;
+ case 3: // Middle reached second time
+ DoScriptText(urand(0, 1) ? SAY_SUMMON_BOSS_1 : SAY_SUMMON_BOSS_2, m_creature);
+ break;
+ case 4: // Reached North Gate
+ DoScriptText(SAY_OPEN_NORTH_GATE, m_creature);//6
+ m_bCanWalk = false;
+ m_uiEventTimer = 5000;
+ break;
+ case 5:
+ if (m_pInstance)
+ {
+ m_pInstance->SetData(TYPE_RING_OF_LAW, DONE);
+ debug_log("SD2: npc_grimstone: event reached end and set complete.");
+ }
+ break;
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (m_uiMobDeathTimer)
+ {
+ if (m_uiMobDeathTimer <= uiDiff)
+ {
+ m_uiMobDeathTimer = 2500;
+
+ if (m_uiRingBossGUID)
+ {
+ Creature* pBoss = m_creature->GetMap()->GetCreature(m_uiRingBossGUID);
+ if (pBoss && !pBoss->isAlive() && pBoss->isDead())
+ {
+ m_uiRingBossGUID = 0;
+ m_uiEventTimer = 5000;
+ m_uiMobDeathTimer = 0;
+ return;
+ }
+ return;
+ }
+
+ for(uint8 i = 0; i < MAX_MOB_AMOUNT; ++i)
+ {
+ Creature* pMob = m_creature->GetMap()->GetCreature(m_auiRingMobGUID[i]);
+ if (pMob && !pMob->isAlive() && pMob->isDead())
+ {
+ m_auiRingMobGUID[i] = 0;
+ --m_uiMobCount;
+
+ //seems all are gone, so set timer to continue and discontinue this
+ if (!m_uiMobCount)
+ {
+ m_uiEventTimer = 5000;
+ m_uiMobDeathTimer = 0;
+ }
+ }
+ }
+ }
+ else
+ m_uiMobDeathTimer -= uiDiff;
+ }
+
+ if (m_uiEventTimer)
+ {
+ if (m_uiEventTimer <= uiDiff)
+ {
+ switch(m_uiEventPhase)
+ {
+ case 0:
+ // Shortly after spawn, start walking
+ //DoScriptText(-1000000, m_creature); // no more text on spawn
+ DoGate(DATA_ARENA4, GO_STATE_READY);
+ Start(false);
+ m_bCanWalk = true;
+ m_uiEventTimer = 0;
+ break;
+ case 1:
+ // Start walking towards wall
+ m_bCanWalk = true;
+ m_uiEventTimer = 0;
+ break;
+ case 2:
+ m_uiEventTimer = 2000;
+ break;
+ case 3:
+ // Open East Gate
+ DoGate(DATA_ARENA1, GO_STATE_ACTIVE);
+ m_uiEventTimer = 3000;
+ break;
+ case 4:
+ m_bCanWalk = true;
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ SummonRingMob();
+ m_uiEventTimer = 8000;
+ break;
+ case 5:
+ SummonRingMob();
+ SummonRingMob();
+ m_uiEventTimer = 8000;
+ break;
+ case 6:
+ SummonRingMob();
+ m_uiEventTimer = 0;
+ break;
+ case 7:
+ // Summoned Mobs are dead, continue event
+ m_creature->SetVisibility(VISIBILITY_ON);
+ DoGate(DATA_ARENA1, GO_STATE_READY);
+ //DoScriptText(-1000000, m_creature); // after killed the mobs, no say here
+ m_bCanWalk = true;
+ m_uiEventTimer = 0;
+ break;
+ case 8:
+ // Open North Gate
+ DoGate(DATA_ARENA2, GO_STATE_ACTIVE);
+ m_uiEventTimer = 5000;
+ break;
+ case 9:
+ // Summon Boss
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ SummonRingBoss();
+ m_uiEventTimer = 0;
+ break;
+ case 10:
+ // Boss dead
+ //if quest, complete
+ DoGate(DATA_ARENA2, GO_STATE_READY);
+ DoGate(DATA_ARENA3, GO_STATE_ACTIVE);
+ DoGate(DATA_ARENA4, GO_STATE_ACTIVE);
+ m_bCanWalk = true;
+ m_uiEventTimer = 0;
+ break;
+ }
+ ++m_uiEventPhase;
+ }
+ else
+ m_uiEventTimer -= uiDiff;
+ }
+
+ if (m_bCanWalk)
+ npc_escortAI::UpdateAI(uiDiff);
+ }
+};
+
+CreatureAI* GetAI_npc_grimstone(Creature* pCreature)
+{
+ return new npc_grimstoneAI(pCreature);
+}
+
+/*######
+## mob_phalanx
+######*/
+
+enum
+{
+ SPELL_THUNDERCLAP = 15588,
+ SPELL_FIREBALLVOLLEY = 15285,
+ SPELL_MIGHTYBLOW = 14099
+};
+
+struct MANGOS_DLL_DECL mob_phalanxAI : public ScriptedAI
+{
+ mob_phalanxAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiThunderClapTimer;
+ uint32 m_uiFireballVolleyTimer;
+ uint32 m_uiMightyBlowTimer;
+
+ void Reset()
+ {
+ m_uiThunderClapTimer = 12000;
+ m_uiFireballVolleyTimer = 0;
+ m_uiMightyBlowTimer = 15000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // ThunderClap
+ if (m_uiThunderClapTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_THUNDERCLAP);
+ m_uiThunderClapTimer = 10000;
+ }
+ else
+ m_uiThunderClapTimer -= uiDiff;
+
+ // FireballVolley
+ if (m_creature->GetHealthPercent() < 51.0f)
+ {
+ if (m_uiFireballVolleyTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FIREBALLVOLLEY);
+ m_uiFireballVolleyTimer = 15000;
+ }
+ else
+ m_uiFireballVolleyTimer -= uiDiff;
+ }
+
+ // MightyBlow
+ if (m_uiMightyBlowTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIGHTYBLOW);
+ m_uiMightyBlowTimer = 10000;
+ }
+ else
+ m_uiMightyBlowTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_phalanx(Creature* pCreature)
+{
+ return new mob_phalanxAI(pCreature);
+}
+
+/*######
+## npc_kharan_mighthammer
+######*/
+enum
+{
+ QUEST_WHAT_IS_GOING_ON = 4001,
+ QUEST_KHARANS_TALE = 4342
+};
+
+#define GOSSIP_ITEM_KHARAN_1 "I need to know where the princess are, Kharan!"
+#define GOSSIP_ITEM_KHARAN_2 "All is not lost, Kharan!"
+
+#define GOSSIP_ITEM_KHARAN_3 "Gor'shak is my friend, you can trust me."
+#define GOSSIP_ITEM_KHARAN_4 "Not enough, you need to tell me more."
+#define GOSSIP_ITEM_KHARAN_5 "So what happened?"
+#define GOSSIP_ITEM_KHARAN_6 "Continue..."
+#define GOSSIP_ITEM_KHARAN_7 "So you suspect that someone on the inside was involved? That they were tipped off?"
+#define GOSSIP_ITEM_KHARAN_8 "Continue with your story please."
+#define GOSSIP_ITEM_KHARAN_9 "Indeed."
+#define GOSSIP_ITEM_KHARAN_10 "The door is open, Kharan. You are a free man."
+
+bool GossipHello_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(QUEST_WHAT_IS_GOING_ON) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ if (pPlayer->GetQuestStatus(QUEST_KHARANS_TALE) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+
+ if (pPlayer->GetTeam() == HORDE)
+ pPlayer->SEND_GOSSIP_MENU(2473, pCreature->GetGUID());
+ else
+ pPlayer->SEND_GOSSIP_MENU(2474, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_kharan_mighthammer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(2475, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->SEND_GOSSIP_MENU(2476, pCreature->GetGUID());
+ break;
+
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
+ pPlayer->SEND_GOSSIP_MENU(2477, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(2478, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
+ pPlayer->SEND_GOSSIP_MENU(2479, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+6:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_8, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7);
+ pPlayer->SEND_GOSSIP_MENU(2480, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+7:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_9, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8);
+ pPlayer->SEND_GOSSIP_MENU(2481, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+8:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KHARAN_10, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9);
+ pPlayer->SEND_GOSSIP_MENU(2482, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+9:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ if (pPlayer->GetTeam() == HORDE)
+ pPlayer->AreaExploredOrEventHappens(QUEST_WHAT_IS_GOING_ON);
+ else
+ pPlayer->AreaExploredOrEventHappens(QUEST_KHARANS_TALE);
+ break;
+ }
+ return true;
+}
+
+/*######
+## npc_lokhtos_darkbargainer
+######*/
+
+enum
+{
+ FACTION_THORIUM_BROTHERHOOD = 59,
+
+ ITEM_THRORIUM_BROTHERHOOD_CONTRACT = 18628,
+ ITEM_SULFURON_INGOT = 17203,
+
+ QUEST_A_BINDING_CONTRACT = 7604,
+
+ SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT = 23059
+};
+
+#define GOSSIP_ITEM_SHOW_ACCESS "Show me what I have access to, Lothos."
+#define GOSSIP_ITEM_GET_CONTRACT "Get Thorium Brotherhood Contract"
+
+bool GossipHello_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pCreature->isVendor() && pPlayer->GetReputationRank(FACTION_THORIUM_BROTHERHOOD) >= REP_FRIENDLY)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_ITEM_SHOW_ACCESS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+
+ if (!pPlayer->GetQuestRewardStatus(QUEST_A_BINDING_CONTRACT) &&
+ !pPlayer->HasItemCount(ITEM_THRORIUM_BROTHERHOOD_CONTRACT, 1, true) &&
+ pPlayer->HasItemCount(ITEM_SULFURON_INGOT, 1))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_GET_CONTRACT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ }
+
+ if (pPlayer->GetReputationRank(FACTION_THORIUM_BROTHERHOOD) < REP_FRIENDLY)
+ pPlayer->SEND_GOSSIP_MENU(3673, pCreature->GetGUID());
+ else
+ pPlayer->SEND_GOSSIP_MENU(3677, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_lokhtos_darkbargainer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->CastSpell(pPlayer, SPELL_CREATE_THORIUM_BROTHERHOOD_CONTRACT, false);
+ }
+
+ if (uiAction == GOSSIP_ACTION_TRADE)
+ pPlayer->SEND_VENDORLIST(pCreature->GetGUID());
+
+ return true;
+}
+
+/*######
+## npc_rocknot
+######*/
+
+enum
+{
+ SAY_GOT_BEER = -1230000,
+
+ SPELL_DRUNKEN_RAGE = 14872,
+
+ QUEST_ALE = 4295
+};
+
+struct MANGOS_DLL_DECL npc_rocknotAI : public npc_escortAI
+{
+ npc_rocknotAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiBreakKegTimer;
+ uint32 m_uiBreakDoorTimer;
+
+ void Reset()
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ return;
+
+ m_uiBreakKegTimer = 0;
+ m_uiBreakDoorTimer = 0;
+ }
+
+ void DoGo(uint32 id, uint32 state)
+ {
+ if (GameObject* pGo = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(id)))
+ pGo->SetGoState(GOState(state));
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ if (!m_pInstance)
+ return;
+
+ switch(uiPointId)
+ {
+ case 1:
+ m_creature->HandleEmote(EMOTE_ONESHOT_KICK);
+ break;
+ case 2:
+ m_creature->HandleEmote(EMOTE_ONESHOT_ATTACKUNARMED);
+ break;
+ case 3:
+ m_creature->HandleEmote(EMOTE_ONESHOT_ATTACKUNARMED);
+ break;
+ case 4:
+ m_creature->HandleEmote(EMOTE_ONESHOT_KICK);
+ break;
+ case 5:
+ m_creature->HandleEmote(EMOTE_ONESHOT_KICK);
+ m_uiBreakKegTimer = 2000;
+ break;
+ }
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (m_uiBreakKegTimer)
+ {
+ if (m_uiBreakKegTimer <= uiDiff)
+ {
+ DoGo(DATA_GO_BAR_KEG,0);
+ m_uiBreakKegTimer = 0;
+ m_uiBreakDoorTimer = 1000;
+ }
+ else
+ m_uiBreakKegTimer -= uiDiff;
+ }
+
+ if (m_uiBreakDoorTimer)
+ {
+ if (m_uiBreakDoorTimer <= uiDiff)
+ {
+ DoGo(DATA_GO_BAR_DOOR, 2);
+ DoGo(DATA_GO_BAR_KEG_TRAP, 0); //doesn't work very well, leaving code here for future
+ //spell by trap has effect61, this indicate the bar go hostile
+
+ if (Creature* pTmp = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_PHALANX)))
+ pTmp->setFaction(14);
+
+ // for later, this event(s) has alot more to it.
+ // optionally, DONE can trigger bar to go hostile.
+ m_pInstance->SetData(TYPE_BAR, DONE);
+
+ m_uiBreakDoorTimer = 0;
+ }
+ else
+ m_uiBreakDoorTimer -= uiDiff;
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_rocknot(Creature* pCreature)
+{
+ return new npc_rocknotAI(pCreature);
+}
+
+bool ChooseReward_npc_rocknot(Player* pPlayer, Creature* pCreature, const Quest* pQuest, uint32 item)
+{
+ ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+
+ if (!pInstance)
+ return true;
+
+ if (pInstance->GetData(TYPE_BAR) == DONE || pInstance->GetData(TYPE_BAR) == SPECIAL)
+ return true;
+
+ if (pQuest->GetQuestId() == QUEST_ALE)
+ {
+ if (pInstance->GetData(TYPE_BAR) != IN_PROGRESS)
+ pInstance->SetData(TYPE_BAR,IN_PROGRESS);
+
+ pInstance->SetData(TYPE_BAR,SPECIAL);
+
+ // keep track of amount in instance script, returns SPECIAL if amount ok and event in progress
+ if (pInstance->GetData(TYPE_BAR) == SPECIAL)
+ {
+ DoScriptText(SAY_GOT_BEER, pCreature);
+ pCreature->CastSpell(pCreature, SPELL_DRUNKEN_RAGE, false);
+
+ if (npc_rocknotAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, 0, NULL, true);
+ }
+ }
+
+ return true;
+}
+
+void AddSC_blackrock_depths()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "go_shadowforge_brazier";
+ pNewScript->pGOHello = &GOHello_go_shadowforge_brazier;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "at_ring_of_law";
+ pNewScript->pAreaTrigger = &AreaTrigger_at_ring_of_law;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_grimstone";
+ pNewScript->GetAI = &GetAI_npc_grimstone;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "mob_phalanx";
+ pNewScript->GetAI = &GetAI_mob_phalanx;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_kharan_mighthammer";
+ pNewScript->pGossipHello = &GossipHello_npc_kharan_mighthammer;
+ pNewScript->pGossipSelect = &GossipSelect_npc_kharan_mighthammer;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_lokhtos_darkbargainer";
+ pNewScript->pGossipHello = &GossipHello_npc_lokhtos_darkbargainer;
+ pNewScript->pGossipSelect = &GossipSelect_npc_lokhtos_darkbargainer;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_rocknot";
+ pNewScript->GetAI = &GetAI_npc_rocknot;
+ pNewScript->pChooseReward = &ChooseReward_npc_rocknot;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h b/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h
new file mode 100644
index 0000000..e17e274
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h
@@ -0,0 +1,40 @@
+/* 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 */
+
+#ifndef DEF_BRD_H
+#define DEF_BRD_H
+
+enum
+{
+ TYPE_RING_OF_LAW = 1,
+ TYPE_VAULT = 2,
+ TYPE_BAR = 3,
+ TYPE_TOMB_OF_SEVEN = 4,
+ TYPE_LYCEUM = 5,
+ TYPE_IRON_HALL = 6,
+
+ DATA_EMPEROR = 10,
+ DATA_PRINCESS = 11,
+ DATA_PHALANX = 12,
+ DATA_HATEREL = 13,
+ DATA_ANGERREL = 14,
+ DATA_VILEREL = 15,
+ DATA_GLOOMREL = 16,
+ DATA_SEETHREL = 17,
+ DATA_DOOMREL = 18,
+ DATA_DOPEREL = 19,
+
+ DATA_ARENA1 = 20,
+ DATA_ARENA2 = 21,
+ DATA_ARENA3 = 22,
+ DATA_ARENA4 = 23,
+
+ DATA_GO_BAR_KEG = 24,
+ DATA_GO_BAR_KEG_TRAP = 25,
+ DATA_GO_BAR_DOOR = 26,
+ DATA_GO_CHALICE = 27,
+ DATA_GO_TOMB_EXIT = 28
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp
new file mode 100644
index 0000000..ff47a96
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp
@@ -0,0 +1,104 @@
+/* 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_Ambassador_Flamelash
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_FIREBLAST 15573
+
+struct MANGOS_DLL_DECL boss_ambassador_flamelashAI : public ScriptedAI
+{
+ boss_ambassador_flamelashAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 FireBlast_Timer;
+ uint32 Spirit_Timer;
+ int Rand;
+ int RandX;
+ int RandY;
+ Creature* Summoned;
+
+ void Reset()
+ {
+ FireBlast_Timer = 2000;
+ Spirit_Timer = 24000;
+ }
+
+ void SummonSpirits(Unit* victim)
+ {
+ Rand = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: RandX -= Rand; break;
+ case 1: RandX += Rand; break;
+ }
+ Rand = 0;
+ Rand = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: RandY -= Rand; break;
+ case 1: RandY += Rand; break;
+ }
+ Summoned = DoSpawnCreature(9178, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(victim);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //FireBlast_Timer
+ if (FireBlast_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FIREBLAST);
+ FireBlast_Timer = 7000;
+ }else FireBlast_Timer -= diff;
+
+ //Spirit_Timer
+ if (Spirit_Timer < diff)
+ {
+ SummonSpirits(m_creature->getVictim());
+ SummonSpirits(m_creature->getVictim());
+ SummonSpirits(m_creature->getVictim());
+ SummonSpirits(m_creature->getVictim());
+
+ Spirit_Timer = 30000;
+ }else Spirit_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_ambassador_flamelash(Creature* pCreature)
+{
+ return new boss_ambassador_flamelashAI(pCreature);
+}
+
+void AddSC_boss_ambassador_flamelash()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_ambassador_flamelash";
+ newscript->GetAI = &GetAI_boss_ambassador_flamelash;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp
new file mode 100644
index 0000000..1b18a0c
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp
@@ -0,0 +1,111 @@
+/* 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_Anubshiah
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_SHADOWBOLT 17228
+#define SPELL_CURSEOFTONGUES 15470
+#define SPELL_CURSEOFWEAKNESS 17227
+#define SPELL_DEMONARMOR 11735
+#define SPELL_ENVELOPINGWEB 15471
+
+struct MANGOS_DLL_DECL boss_anubshiahAI : public ScriptedAI
+{
+ boss_anubshiahAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ShadowBolt_Timer;
+ uint32 CurseOfTongues_Timer;
+ uint32 CurseOfWeakness_Timer;
+ uint32 DemonArmor_Timer;
+ uint32 EnvelopingWeb_Timer;
+
+ void Reset()
+ {
+ ShadowBolt_Timer = 7000;
+ CurseOfTongues_Timer = 24000;
+ CurseOfWeakness_Timer = 12000;
+ DemonArmor_Timer = 3000;
+ EnvelopingWeb_Timer = 16000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowBolt_Timer
+ if (ShadowBolt_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWBOLT);
+ ShadowBolt_Timer = 7000;
+ }else ShadowBolt_Timer -= diff;
+
+ //CurseOfTongues_Timer
+ if (CurseOfTongues_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_CURSEOFTONGUES);
+ CurseOfTongues_Timer = 18000;
+ }else CurseOfTongues_Timer -= diff;
+
+ //CurseOfWeakness_Timer
+ if (CurseOfWeakness_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CURSEOFWEAKNESS);
+ CurseOfWeakness_Timer = 45000;
+ }else CurseOfWeakness_Timer -= diff;
+
+ //DemonArmor_Timer
+ if (DemonArmor_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_DEMONARMOR);
+ DemonArmor_Timer = 300000;
+ }else DemonArmor_Timer -= diff;
+
+ //EnvelopingWeb_Timer
+ if (EnvelopingWeb_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_ENVELOPINGWEB);
+ EnvelopingWeb_Timer = 12000;
+ }else EnvelopingWeb_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_anubshiah(Creature* pCreature)
+{
+ return new boss_anubshiahAI(pCreature);
+}
+
+void AddSC_boss_anubshiah()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_anubshiah";
+ newscript->GetAI = &GetAI_boss_anubshiah;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp
new file mode 100644
index 0000000..5ab26b8
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp
@@ -0,0 +1,260 @@
+/* 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_Emperor_Dagran_Thaurissan
+SD%Complete: 90
+SDComment: With script for Moria
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+#include "blackrock_depths.h"
+
+enum eEmperor
+{
+ FACTION_NEUTRAL = 734,
+ SAY_AGGRO = -1230001,
+ SAY_SLAY = -1230002,
+
+ SPELL_HANDOFTHAURISSAN = 17492,
+ SPELL_AVATAROFFLAME = 15636
+};
+
+struct MANGOS_DLL_DECL boss_emperor_dagran_thaurissanAI : public ScriptedAI
+{
+ boss_emperor_dagran_thaurissanAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiHandOfThaurissan_Timer;
+ uint32 m_uiAvatarOfFlame_Timer;
+ //uint32 m_uiCounter;
+
+ void Reset()
+ {
+ m_uiHandOfThaurissan_Timer = 4000;
+ m_uiAvatarOfFlame_Timer = 25000;
+ //m_uiCounter = 0;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ m_creature->CallForHelp(VISIBLE_RANGE);
+ }
+
+ void JustDied(Unit* pVictim)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pPrincess = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_PRINCESS)))
+ {
+ if (pPrincess->isAlive())
+ {
+ pPrincess->setFaction(FACTION_NEUTRAL);
+ pPrincess->AI()->EnterEvadeMode();
+ }
+ }
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(SAY_SLAY, m_creature);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiHandOfThaurissan_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget,SPELL_HANDOFTHAURISSAN);
+
+ //3 Hands of Thaurissan will be casted
+ //if (m_uiCounter < 3)
+ //{
+ // m_uiHandOfThaurissan_Timer = 1000;
+ // ++m_uiCounter;
+ //}
+ //else
+ //{
+ m_uiHandOfThaurissan_Timer = 5000;
+ //m_uiCounter = 0;
+ //}
+ }
+ else
+ m_uiHandOfThaurissan_Timer -= uiDiff;
+
+ //AvatarOfFlame_Timer
+ if (m_uiAvatarOfFlame_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_AVATAROFFLAME);
+ m_uiAvatarOfFlame_Timer = 18000;
+ }
+ else
+ m_uiAvatarOfFlame_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_emperor_dagran_thaurissan(Creature* pCreature)
+{
+ return new boss_emperor_dagran_thaurissanAI(pCreature);
+}
+
+/*######
+## boss_moira_bronzebeard
+######*/
+
+enum ePrincess
+{
+ SPELL_HEAL = 15586,
+ SPELL_RENEW = 10929,
+ SPELL_SHIELD = 10901,
+ SPELL_MINDBLAST = 15587,
+ SPELL_SHADOWWORDPAIN = 15654,
+ SPELL_SMITE = 10934,
+ SPELL_SHADOW_BOLT = 15537,
+ SPELL_OPEN_PORTAL = 13912
+};
+
+struct MANGOS_DLL_DECL boss_moira_bronzebeardAI : public ScriptedAI
+{
+ boss_moira_bronzebeardAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiHeal_Timer;
+ uint32 m_uiMindBlast_Timer;
+ uint32 m_uiShadowWordPain_Timer;
+ uint32 m_uiSmite_Timer;
+
+ void Reset()
+ {
+ m_uiHeal_Timer = 12000; //These times are probably wrong
+ m_uiMindBlast_Timer = 16000;
+ m_uiShadowWordPain_Timer = 2000;
+ m_uiSmite_Timer = 8000;
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (m_creature->Attack(pWho, false))
+ {
+ m_creature->AddThreat(pWho);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ m_creature->GetMotionMaster()->MoveChase(pWho, 25.0f);
+ }
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ {
+ if (Creature* pEmperor = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_EMPEROR)))
+ {
+ // if evade, then check if he is alive. If not, start make portal
+ if (!pEmperor->isAlive())
+ m_creature->CastSpell(m_creature, SPELL_OPEN_PORTAL, false);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //MindBlast_Timer
+ if (m_uiMindBlast_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MINDBLAST);
+ m_uiMindBlast_Timer = 14000;
+ }
+ else
+ m_uiMindBlast_Timer -= uiDiff;
+
+ //ShadowWordPain_Timer
+ if (m_uiShadowWordPain_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWWORDPAIN);
+ m_uiShadowWordPain_Timer = 18000;
+ }
+ else
+ m_uiShadowWordPain_Timer -= uiDiff;
+
+ //Smite_Timer
+ if (m_uiSmite_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SMITE);
+ m_uiSmite_Timer = 10000;
+ }
+ else
+ m_uiSmite_Timer -= uiDiff;
+
+ //Heal_Timer
+ if (m_uiHeal_Timer < uiDiff)
+ {
+ if (Creature* pEmperor = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_EMPEROR)))
+ {
+ if (pEmperor->isAlive() && pEmperor->GetHealthPercent() != 100.0f)
+ DoCastSpellIfCan(pEmperor, SPELL_HEAL);
+ }
+
+ m_uiHeal_Timer = 10000;
+ }
+ else
+ m_uiHeal_Timer -= uiDiff;
+
+ //No meele?
+ }
+};
+
+CreatureAI* GetAI_boss_moira_bronzebeard(Creature* pCreature)
+{
+ return new boss_moira_bronzebeardAI(pCreature);
+}
+
+void AddSC_boss_draganthaurissan()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_emperor_dagran_thaurissan";
+ newscript->GetAI = &GetAI_boss_emperor_dagran_thaurissan;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_moira_bronzebeard";
+ newscript->GetAI = &GetAI_boss_moira_bronzebeard;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp
new file mode 100644
index 0000000..c35606f
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp
@@ -0,0 +1,163 @@
+/* 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_General_Angerforge
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_MIGHTYBLOW 14099
+#define SPELL_HAMSTRING 9080
+#define SPELL_CLEAVE 20691
+
+struct MANGOS_DLL_DECL boss_general_angerforgeAI : public ScriptedAI
+{
+ boss_general_angerforgeAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 MightyBlow_Timer;
+ uint32 HamString_Timer;
+ uint32 Cleave_Timer;
+ uint32 Adds_Timer;
+ bool Medics;
+ int Rand1;
+ int Rand1X;
+ int Rand1Y;
+ int Rand2;
+ int Rand2X;
+ int Rand2Y;
+ Creature* SummonedAdds;
+ Creature* SummonedMedics;
+
+ void Reset()
+ {
+ MightyBlow_Timer = 8000;
+ HamString_Timer = 12000;
+ Cleave_Timer = 16000;
+ Adds_Timer = 0;
+ Medics = false;
+ }
+
+ void SummonAdds(Unit* victim)
+ {
+ Rand1 = rand()%15;
+ switch(urand(0, 1))
+ {
+ case 0: Rand1X = 0 - Rand1; break;
+ case 1: Rand1X = 0 + Rand1; break;
+ }
+ Rand1 = 0;
+ Rand1 = rand()%15;
+ switch(urand(0, 1))
+ {
+ case 0: Rand1Y = 0 - Rand1; break;
+ case 1: Rand1Y = 0 + Rand1; break;
+ }
+ Rand1 = 0;
+ SummonedAdds = DoSpawnCreature(8901, Rand1X, Rand1Y, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000);
+ if (SummonedAdds)
+ SummonedAdds->AI()->AttackStart(victim);
+ }
+
+ void SummonMedics(Unit* victim)
+ {
+ Rand2 = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: Rand2X = 0 - Rand2; break;
+ case 1: Rand2X = 0 + Rand2; break;
+ }
+ Rand2 = 0;
+ Rand2 = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: Rand2Y = 0 - Rand2; break;
+ case 1: Rand2Y = 0 + Rand2; break;
+ }
+ Rand2 = 0;
+ SummonedMedics = DoSpawnCreature(8894, Rand2X, Rand2Y, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000);
+ if (SummonedMedics)
+ SummonedMedics->AI()->AttackStart(victim);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //MightyBlow_Timer
+ if (MightyBlow_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MIGHTYBLOW);
+ MightyBlow_Timer = 18000;
+ }else MightyBlow_Timer -= diff;
+
+ //HamString_Timer
+ if (HamString_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_HAMSTRING);
+ HamString_Timer = 15000;
+ }else HamString_Timer -= diff;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = 9000;
+ }else Cleave_Timer -= diff;
+
+ //Adds_Timer
+ if (m_creature->GetHealthPercent() < 21.0f)
+ {
+ if (Adds_Timer < diff)
+ {
+ // summon 3 Adds every 25s
+ SummonAdds(m_creature->getVictim());
+ SummonAdds(m_creature->getVictim());
+ SummonAdds(m_creature->getVictim());
+
+ Adds_Timer = 25000;
+ } else Adds_Timer -= diff;
+ }
+
+ //Summon Medics
+ if (!Medics && m_creature->GetHealthPercent() < 21.0f)
+ {
+ SummonMedics(m_creature->getVictim());
+ SummonMedics(m_creature->getVictim());
+ Medics = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_general_angerforge(Creature* pCreature)
+{
+ return new boss_general_angerforgeAI(pCreature);
+}
+
+void AddSC_boss_general_angerforge()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_general_angerforge";
+ newscript->GetAI = &GetAI_boss_general_angerforge;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp
new file mode 100644
index 0000000..b46316d
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp
@@ -0,0 +1,77 @@
+/* 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_Gorosh_the_Dervish
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_WHIRLWIND 15589
+#define SPELL_MORTALSTRIKE 24573
+
+struct MANGOS_DLL_DECL boss_gorosh_the_dervishAI : public ScriptedAI
+{
+ boss_gorosh_the_dervishAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 WhirlWind_Timer;
+ uint32 MortalStrike_Timer;
+
+ void Reset()
+ {
+ WhirlWind_Timer = 12000;
+ MortalStrike_Timer = 22000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //WhirlWind_Timer
+ if (WhirlWind_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_WHIRLWIND);
+ WhirlWind_Timer = 15000;
+ }else WhirlWind_Timer -= diff;
+
+ //MortalStrike_Timer
+ if (MortalStrike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MORTALSTRIKE);
+ MortalStrike_Timer = 15000;
+ }else MortalStrike_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_gorosh_the_dervish(Creature* pCreature)
+{
+ return new boss_gorosh_the_dervishAI(pCreature);
+}
+
+void AddSC_boss_gorosh_the_dervish()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_gorosh_the_dervish";
+ newscript->GetAI = &GetAI_boss_gorosh_the_dervish;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp
new file mode 100644
index 0000000..a2a9d25
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp
@@ -0,0 +1,85 @@
+/* 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_Grizzle
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+
+#define EMOTE_GENERIC_FRENZY_KILL -1000001
+
+#define SPELL_GROUNDTREMOR 6524
+#define SPELL_FRENZY 28371
+
+struct MANGOS_DLL_DECL boss_grizzleAI : public ScriptedAI
+{
+ boss_grizzleAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 GroundTremor_Timer;
+ uint32 Frenzy_Timer;
+
+ void Reset()
+ {
+ GroundTremor_Timer = 12000;
+ Frenzy_Timer =0;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //GroundTremor_Timer
+ if (GroundTremor_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_GROUNDTREMOR);
+ GroundTremor_Timer = 8000;
+ }else GroundTremor_Timer -= diff;
+
+ //Frenzy_Timer
+ if (m_creature->GetHealthPercent() < 51.0f)
+ {
+ if (Frenzy_Timer < diff)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK)
+ {
+ DoScriptText(EMOTE_GENERIC_FRENZY_KILL, m_creature);
+ Frenzy_Timer = 15000;
+ }
+ }else Frenzy_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_grizzle(Creature* pCreature)
+{
+ return new boss_grizzleAI(pCreature);
+}
+
+void AddSC_boss_grizzle()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_grizzle";
+ newscript->GetAI = &GetAI_boss_grizzle;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp
new file mode 100644
index 0000000..2cb75de
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp
@@ -0,0 +1,113 @@
+/* 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_High_Interrogator_Gerstahn
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_SHADOWWORDPAIN = 14032,
+ SPELL_MANABURN = 14033,
+ SPELL_PSYCHICSCREAM = 13704,
+ SPELL_SHADOWSHIELD = 12040
+};
+
+struct MANGOS_DLL_DECL boss_high_interrogator_gerstahnAI : public ScriptedAI
+{
+ boss_high_interrogator_gerstahnAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiShadowWordPain_Timer;
+ uint32 m_uiManaBurn_Timer;
+ uint32 m_uiPsychicScream_Timer;
+ uint32 m_uiShadowShield_Timer;
+
+ void Reset()
+ {
+ m_uiShadowWordPain_Timer = 4000;
+ m_uiManaBurn_Timer = 14000;
+ m_uiPsychicScream_Timer = 32000;
+ m_uiShadowShield_Timer = 8000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowWordPain_Timer
+ if (m_uiShadowWordPain_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget, SPELL_SHADOWWORDPAIN);
+
+ m_uiShadowWordPain_Timer = 7000;
+ }
+ else
+ m_uiShadowWordPain_Timer -= uiDiff;
+
+ //ManaBurn_Timer
+ if (m_uiManaBurn_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget, SPELL_MANABURN);
+
+ m_uiManaBurn_Timer = 10000;
+ }
+ else
+ m_uiManaBurn_Timer -= uiDiff;
+
+ //PsychicScream_Timer
+ if (m_uiPsychicScream_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_PSYCHICSCREAM);
+ m_uiPsychicScream_Timer = 30000;
+ }
+ else
+ m_uiPsychicScream_Timer -= uiDiff;
+
+ //ShadowShield_Timer
+ if (m_uiShadowShield_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_SHADOWSHIELD);
+ m_uiShadowShield_Timer = 25000;
+ }
+ else
+ m_uiShadowShield_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_high_interrogator_gerstahn(Creature* pCreature)
+{
+ return new boss_high_interrogator_gerstahnAI(pCreature);
+}
+
+void AddSC_boss_high_interrogator_gerstahn()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_high_interrogator_gerstahn";
+ newscript->GetAI = &GetAI_boss_high_interrogator_gerstahn;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp
new file mode 100644
index 0000000..3fbbee9
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp
@@ -0,0 +1,113 @@
+/* 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_Magmus
+SD%Complete: 80
+SDComment: Missing pre-event to open doors
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+#include "blackrock_depths.h"
+
+enum
+{
+ SPELL_FIERYBURST = 13900,
+ SPELL_WARSTOMP = 24375
+};
+
+struct MANGOS_DLL_DECL boss_magmusAI : public ScriptedAI
+{
+ boss_magmusAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiFieryBurst_Timer;
+ uint32 m_uiWarStomp_Timer;
+
+ void Reset()
+ {
+ m_uiFieryBurst_Timer = 5000;
+ m_uiWarStomp_Timer = 0;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_IRON_HALL, IN_PROGRESS);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_IRON_HALL, FAIL);
+ }
+
+ void JustDied(Unit* pVictim)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_IRON_HALL, DONE);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //FieryBurst_Timer
+ if (m_uiFieryBurst_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FIERYBURST);
+ m_uiFieryBurst_Timer = 6000;
+ }
+ else
+ m_uiFieryBurst_Timer -= uiDiff;
+
+ //WarStomp_Timer
+ if (m_creature->GetHealthPercent() < 51.0f)
+ {
+ if (m_uiWarStomp_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_WARSTOMP);
+ m_uiWarStomp_Timer = 8000;
+ }
+ else
+ m_uiWarStomp_Timer -= uiDiff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_magmus(Creature* pCreature)
+{
+ return new boss_magmusAI(pCreature);
+}
+
+void AddSC_boss_magmus()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_magmus";
+ newscript->GetAI = &GetAI_boss_magmus;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp b/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp
new file mode 100644
index 0000000..e80efe2
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp
@@ -0,0 +1,325 @@
+/* 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_Tomb_Of_Seven
+SD%Complete: 90
+SDComment: Learning Smelt Dark Iron if tribute quest rewarded. Basic event implemented. Correct order and timing of event is unknown.
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+#include "blackrock_depths.h"
+
+enum
+{
+ FACTION_NEUTRAL = 734,
+ FACTION_HOSTILE = 754,
+
+ SPELL_SMELT_DARK_IRON = 14891,
+ SPELL_LEARN_SMELT = 14894,
+ QUEST_SPECTRAL_CHALICE = 4083,
+ SKILLPOINT_MIN = 230
+};
+
+#define GOSSIP_ITEM_TEACH_1 "Teach me the art of smelting dark iron"
+#define GOSSIP_ITEM_TEACH_2 "Continue..."
+#define GOSSIP_ITEM_TRIBUTE "I want to pay tribute"
+
+bool GossipHello_boss_gloomrel(Player* pPlayer, Creature* pCreature)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ {
+ if (pInstance->GetData(TYPE_TOMB_OF_SEVEN) == NOT_STARTED)
+ {
+ if (pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) &&
+ pPlayer->GetSkillValue(SKILL_MINING) >= SKILLPOINT_MIN &&
+ !pPlayer->HasSpell(SPELL_SMELT_DARK_IRON))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+
+ if (!pPlayer->GetQuestRewardStatus(QUEST_SPECTRAL_CHALICE) &&
+ pPlayer->GetSkillValue(SKILL_MINING) >= SKILLPOINT_MIN)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TRIBUTE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ }
+ }
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_boss_gloomrel(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEACH_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
+ pPlayer->SEND_GOSSIP_MENU(2606, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+11:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer, SPELL_LEARN_SMELT, false);
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] Continue...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
+ pPlayer->SEND_GOSSIP_MENU(2604, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+22:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ {
+ //are 5 minutes expected? go template may have data to despawn when used at quest
+ pInstance->DoRespawnGameObject(pInstance->GetData64(DATA_GO_CHALICE),MINUTE*5);
+ }
+ break;
+ }
+ return true;
+}
+
+enum
+{
+ SPELL_SHADOWBOLTVOLLEY = 15245,
+ SPELL_IMMOLATE = 12742,
+ SPELL_CURSEOFWEAKNESS = 12493,
+ SPELL_DEMONARMOR = 13787,
+ SPELL_SUMMON_VOIDWALKERS = 15092,
+
+ SAY_DOOMREL_START_EVENT = -1230003,
+
+ MAX_DWARF = 7
+};
+
+#define GOSSIP_ITEM_CHALLENGE "Your bondage is at an end, Doom'rel. I challenge you!"
+
+struct MANGOS_DLL_DECL boss_doomrelAI : public ScriptedAI
+{
+ boss_doomrelAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiShadowVolley_Timer;
+ uint32 m_uiImmolate_Timer;
+ uint32 m_uiCurseOfWeakness_Timer;
+ uint32 m_uiDemonArmor_Timer;
+ uint32 m_uiCallToFight_Timer;
+ uint8 m_uiDwarfRound;
+ bool m_bHasSummoned;
+
+ void Reset()
+ {
+ m_uiShadowVolley_Timer = 10000;
+ m_uiImmolate_Timer = 18000;
+ m_uiCurseOfWeakness_Timer = 5000;
+ m_uiDemonArmor_Timer = 16000;
+ m_uiCallToFight_Timer = 0;
+ m_uiDwarfRound = 0;
+ m_bHasSummoned = false;
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_TOMB_OF_SEVEN, FAIL);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_TOMB_OF_SEVEN, DONE);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ pSummoned->AI()->AttackStart(pTarget);
+ }
+
+ Creature* GetDwarfForPhase(uint8 uiPhase)
+ {
+ switch(uiPhase)
+ {
+ case 0:
+ return m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_ANGERREL));
+ case 1:
+ return m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_SEETHREL));
+ case 2:
+ return m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_DOPEREL));
+ case 3:
+ return m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_GLOOMREL));
+ case 4:
+ return m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_VILEREL));
+ case 5:
+ return m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_HATEREL));
+ case 6:
+ return m_creature;
+ }
+ return NULL;
+ }
+
+ void CallToFight(bool bStartFight)
+ {
+ if (Creature* pDwarf = GetDwarfForPhase(m_uiDwarfRound))
+ {
+ if (bStartFight && pDwarf->isAlive())
+ {
+ pDwarf->setFaction(FACTION_HOSTILE);
+ pDwarf->SetInCombatWithZone(); // attackstart
+ }
+ else
+ {
+ if (!pDwarf->isAlive() || pDwarf->isDead())
+ pDwarf->Respawn();
+
+ pDwarf->setFaction(FACTION_NEUTRAL);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_TOMB_OF_SEVEN) == IN_PROGRESS)
+ {
+ if (m_uiDwarfRound < MAX_DWARF)
+ {
+ if (m_uiCallToFight_Timer < diff)
+ {
+ CallToFight(true);
+ ++m_uiDwarfRound;
+ m_uiCallToFight_Timer = 30000;
+ }
+ else
+ m_uiCallToFight_Timer -= diff;
+ }
+ }
+ else if (m_pInstance->GetData(TYPE_TOMB_OF_SEVEN) == FAIL)
+ {
+ for (m_uiDwarfRound = 0; m_uiDwarfRound < MAX_DWARF; ++m_uiDwarfRound)
+ CallToFight(false);
+
+ m_uiDwarfRound = 0;
+ m_uiCallToFight_Timer = 0;
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_TOMB_OF_SEVEN, NOT_STARTED);
+ }
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowVolley_Timer
+ if (m_uiShadowVolley_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWBOLTVOLLEY);
+ m_uiShadowVolley_Timer = 12000;
+ }
+ else
+ m_uiShadowVolley_Timer -= diff;
+
+ //Immolate_Timer
+ if (m_uiImmolate_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_IMMOLATE);
+
+ m_uiImmolate_Timer = 25000;
+ }
+ else
+ m_uiImmolate_Timer -= diff;
+
+ //CurseOfWeakness_Timer
+ if (m_uiCurseOfWeakness_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CURSEOFWEAKNESS);
+ m_uiCurseOfWeakness_Timer = 45000;
+ }
+ else
+ m_uiCurseOfWeakness_Timer -= diff;
+
+ //DemonArmor_Timer
+ if (m_uiDemonArmor_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_DEMONARMOR);
+ m_uiDemonArmor_Timer = 300000;
+ }
+ else
+ m_uiDemonArmor_Timer -= diff;
+
+ //Summon Voidwalkers
+ if (!m_bHasSummoned && m_creature->GetHealthPercent() <= 50.0f)
+ {
+ m_creature->CastSpell(m_creature, SPELL_SUMMON_VOIDWALKERS, true);
+ m_bHasSummoned = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_doomrel(Creature* pCreature)
+{
+ return new boss_doomrelAI(pCreature);
+}
+
+bool GossipHello_boss_doomrel(Player* pPlayer, Creature* pCreature)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ {
+ if (pInstance->GetData(TYPE_TOMB_OF_SEVEN) == NOT_STARTED)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_CHALLENGE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(2601, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_boss_doomrel(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ DoScriptText(SAY_DOOMREL_START_EVENT, pCreature, pPlayer);
+ // start event
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ pInstance->SetData(TYPE_TOMB_OF_SEVEN, IN_PROGRESS);
+
+ break;
+ }
+ return true;
+}
+
+void AddSC_boss_tomb_of_seven()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_gloomrel";
+ newscript->pGossipHello = &GossipHello_boss_gloomrel;
+ newscript->pGossipSelect = &GossipSelect_boss_gloomrel;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_doomrel";
+ newscript->GetAI = &GetAI_boss_doomrel;
+ newscript->pGossipHello = &GossipHello_boss_doomrel;
+ newscript->pGossipSelect = &GossipSelect_boss_doomrel;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp b/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp
new file mode 100644
index 0000000..4c5bade
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp
@@ -0,0 +1,377 @@
+/* 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_Blackrock_Depths
+SD%Complete: 20
+SDComment: events: ring of law
+SDCategory: Blackrock Depths
+EndScriptData */
+
+#include "precompiled.h"
+#include "blackrock_depths.h"
+
+enum
+{
+ MAX_ENCOUNTER = 6,
+
+ NPC_EMPEROR = 9019,
+ NPC_PRINCESS = 8929,
+ NPC_PHALANX = 9502,
+ NPC_HATEREL = 9034,
+ NPC_ANGERREL = 9035,
+ NPC_VILEREL = 9036,
+ NPC_GLOOMREL = 9037,
+ NPC_SEETHREL = 9038,
+ NPC_DOOMREL = 9039,
+ NPC_DOPEREL = 9040,
+
+ GO_ARENA1 = 161525,
+ GO_ARENA2 = 161522,
+ GO_ARENA3 = 161524,
+ GO_ARENA4 = 161523,
+ GO_SHADOW_LOCK = 161460,
+ GO_SHADOW_MECHANISM = 161461,
+ GO_SHADOW_GIANT_DOOR = 157923,
+ GO_SHADOW_DUMMY = 161516,
+ GO_BAR_KEG_SHOT = 170607,
+ GO_BAR_KEG_TRAP = 171941,
+ GO_BAR_DOOR = 170571,
+ GO_TOMB_ENTER = 170576,
+ GO_TOMB_EXIT = 170577,
+ GO_LYCEUM = 170558,
+ GO_GOLEM_ROOM_N = 170573,
+ GO_GOLEM_ROOM_S = 170574,
+ GO_THRONE_ROOM = 170575,
+
+ GO_SPECTRAL_CHALICE = 164869,
+ GO_CHEST_SEVEN = 169243
+};
+
+struct MANGOS_DLL_DECL instance_blackrock_depths : public ScriptedInstance
+{
+ instance_blackrock_depths(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint64 m_uiEmperorGUID;
+ uint64 m_uiPrincessGUID;
+ uint64 m_uiPhalanxGUID;
+ uint64 m_uiHaterelGUID;
+ uint64 m_uiAngerrelGUID;
+ uint64 m_uiVilerelGUID;
+ uint64 m_uiGloomrelGUID;
+ uint64 m_uiSeethrelGUID;
+ uint64 m_uiDoomrelGUID;
+ uint64 m_uiDoperelGUID;
+
+ uint64 m_uiGoArena1GUID;
+ uint64 m_uiGoArena2GUID;
+ uint64 m_uiGoArena3GUID;
+ uint64 m_uiGoArena4GUID;
+ uint64 m_uiGoShadowLockGUID;
+ uint64 m_uiGoShadowMechGUID;
+ uint64 m_uiGoShadowGiantGUID;
+ uint64 m_uiGoShadowDummyGUID;
+ uint64 m_uiGoBarKegGUID;
+ uint64 m_uiGoBarKegTrapGUID;
+ uint64 m_uiGoBarDoorGUID;
+ uint64 m_uiGoTombEnterGUID;
+ uint64 m_uiGoTombExitGUID;
+ uint64 m_uiGoLyceumGUID;
+ uint64 m_uiGoGolemNGUID;
+ uint64 m_uiGoGolemSGUID;
+ uint64 m_uiGoThroneGUID;
+
+ uint64 m_uiSpectralChaliceGUID;
+ uint64 m_uiSevensChestGUID;
+
+ uint32 m_uiBarAleCount;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiEmperorGUID = 0;
+ m_uiPrincessGUID = 0;
+ m_uiPhalanxGUID = 0;
+ m_uiHaterelGUID = 0;
+ m_uiAngerrelGUID = 0;
+ m_uiVilerelGUID = 0;
+ m_uiGloomrelGUID = 0;
+ m_uiSeethrelGUID = 0;
+ m_uiDoomrelGUID = 0;
+ m_uiDoperelGUID = 0;
+
+ m_uiGoArena1GUID = 0;
+ m_uiGoArena2GUID = 0;
+ m_uiGoArena3GUID = 0;
+ m_uiGoArena4GUID = 0;
+ m_uiGoShadowLockGUID = 0;
+ m_uiGoShadowMechGUID = 0;
+ m_uiGoShadowGiantGUID = 0;
+ m_uiGoShadowDummyGUID = 0;
+ m_uiGoBarKegGUID = 0;
+ m_uiGoBarKegTrapGUID = 0;
+ m_uiGoBarDoorGUID = 0;
+ m_uiGoTombEnterGUID = 0;
+ m_uiGoTombExitGUID = 0;
+ m_uiGoLyceumGUID = 0;
+ m_uiGoGolemNGUID = 0;
+ m_uiGoGolemSGUID = 0;
+ m_uiGoThroneGUID = 0;
+
+ m_uiSpectralChaliceGUID = 0;
+ m_uiSevensChestGUID = 0;
+
+ m_uiBarAleCount = 0;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case NPC_EMPEROR: m_uiEmperorGUID = pCreature->GetGUID(); break;
+ case NPC_PRINCESS: m_uiPrincessGUID = pCreature->GetGUID(); break;
+ case NPC_PHALANX: m_uiPhalanxGUID = pCreature->GetGUID(); break;
+ case NPC_HATEREL: m_uiHaterelGUID = pCreature->GetGUID(); break;
+ case NPC_ANGERREL: m_uiAngerrelGUID = pCreature->GetGUID(); break;
+ case NPC_VILEREL: m_uiVilerelGUID = pCreature->GetGUID(); break;
+ case NPC_GLOOMREL: m_uiGloomrelGUID = pCreature->GetGUID(); break;
+ case NPC_SEETHREL: m_uiSeethrelGUID = pCreature->GetGUID(); break;
+ case NPC_DOOMREL: m_uiDoomrelGUID = pCreature->GetGUID(); break;
+ case NPC_DOPEREL: m_uiDoperelGUID = pCreature->GetGUID(); break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case GO_ARENA1: m_uiGoArena1GUID = pGo->GetGUID(); break;
+ case GO_ARENA2: m_uiGoArena2GUID = pGo->GetGUID(); break;
+ case GO_ARENA3: m_uiGoArena3GUID = pGo->GetGUID(); break;
+ case GO_ARENA4: m_uiGoArena4GUID = pGo->GetGUID(); break;
+ case GO_SHADOW_LOCK: m_uiGoShadowLockGUID = pGo->GetGUID(); break;
+ case GO_SHADOW_MECHANISM: m_uiGoShadowMechGUID = pGo->GetGUID(); break;
+ case GO_SHADOW_GIANT_DOOR: m_uiGoShadowGiantGUID = pGo->GetGUID(); break;
+ case GO_SHADOW_DUMMY: m_uiGoShadowDummyGUID = pGo->GetGUID(); break;
+ case GO_BAR_KEG_SHOT: m_uiGoBarKegGUID = pGo->GetGUID(); break;
+ case GO_BAR_KEG_TRAP: m_uiGoBarKegTrapGUID = pGo->GetGUID(); break;
+ case GO_BAR_DOOR: m_uiGoBarDoorGUID = pGo->GetGUID(); break;
+ case GO_TOMB_ENTER: m_uiGoTombEnterGUID = pGo->GetGUID(); break;
+ case GO_TOMB_EXIT: m_uiGoTombExitGUID = pGo->GetGUID(); break;
+ case GO_LYCEUM: m_uiGoLyceumGUID = pGo->GetGUID(); break;
+ case GO_GOLEM_ROOM_N: m_uiGoGolemNGUID = pGo->GetGUID(); break;
+ case GO_GOLEM_ROOM_S: m_uiGoGolemSGUID = pGo->GetGUID(); break;
+ case GO_THRONE_ROOM: m_uiGoThroneGUID = pGo->GetGUID(); break;
+ case GO_SPECTRAL_CHALICE: m_uiSpectralChaliceGUID = pGo->GetGUID(); break;
+ case GO_CHEST_SEVEN: m_uiSevensChestGUID = pGo->GetGUID(); break;
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ debug_log("SD2: Instance Blackrock Depths: SetData update (Type: %u Data %u)", uiType, uiData);
+
+ switch(uiType)
+ {
+ case TYPE_RING_OF_LAW:
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_VAULT:
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_BAR:
+ if (uiData == SPECIAL)
+ ++m_uiBarAleCount;
+ else
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_TOMB_OF_SEVEN:
+ switch(uiData)
+ {
+ case IN_PROGRESS:
+ DoUseDoorOrButton(m_uiGoTombEnterGUID);
+ break;
+ case FAIL:
+ if (m_auiEncounter[3] == IN_PROGRESS)//prevent use more than one time
+ DoUseDoorOrButton(m_uiGoTombEnterGUID);
+ break;
+ case DONE:
+ DoRespawnGameObject(m_uiSevensChestGUID, HOUR*IN_MILLISECONDS);
+ DoUseDoorOrButton(m_uiGoTombExitGUID);
+ DoUseDoorOrButton(m_uiGoTombEnterGUID);
+ break;
+ }
+ m_auiEncounter[3] = uiData;
+ break;
+ case TYPE_LYCEUM:
+ if (uiData == DONE)
+ {
+ DoUseDoorOrButton(m_uiGoGolemNGUID);
+ DoUseDoorOrButton(m_uiGoGolemSGUID);
+ }
+ m_auiEncounter[4] = uiData;
+ break;
+ case TYPE_IRON_HALL:
+ switch(uiData)
+ {
+ case IN_PROGRESS:
+ DoUseDoorOrButton(m_uiGoGolemNGUID);
+ DoUseDoorOrButton(m_uiGoGolemSGUID);
+ break;
+ case FAIL:
+ DoUseDoorOrButton(m_uiGoGolemNGUID);
+ DoUseDoorOrButton(m_uiGoGolemSGUID);
+ break;
+ case DONE:
+ DoUseDoorOrButton(m_uiGoGolemNGUID);
+ DoUseDoorOrButton(m_uiGoGolemSGUID);
+ DoUseDoorOrButton(m_uiGoThroneGUID);
+ break;
+ }
+ m_auiEncounter[5] = 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] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_RING_OF_LAW:
+ return m_auiEncounter[0];
+ case TYPE_VAULT:
+ return m_auiEncounter[1];
+ case TYPE_BAR:
+ if (m_auiEncounter[2] == IN_PROGRESS && m_uiBarAleCount == 3)
+ return SPECIAL;
+ else
+ return m_auiEncounter[2];
+ case TYPE_TOMB_OF_SEVEN:
+ return m_auiEncounter[3];
+ case TYPE_LYCEUM:
+ return m_auiEncounter[4];
+ case TYPE_IRON_HALL:
+ return m_auiEncounter[5];
+ }
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_EMPEROR:
+ return m_uiEmperorGUID;
+ case DATA_PRINCESS:
+ return m_uiPrincessGUID;
+ case DATA_PHALANX:
+ return m_uiPhalanxGUID;
+ case DATA_HATEREL:
+ return m_uiHaterelGUID;
+ case DATA_ANGERREL:
+ return m_uiAngerrelGUID;
+ case DATA_VILEREL:
+ return m_uiVilerelGUID;
+ case DATA_GLOOMREL:
+ return m_uiGloomrelGUID;
+ case DATA_SEETHREL:
+ return m_uiSeethrelGUID;
+ case DATA_DOOMREL:
+ return m_uiDoomrelGUID;
+ case DATA_DOPEREL:
+ return m_uiDoperelGUID;
+
+ case DATA_ARENA1:
+ return m_uiGoArena1GUID;
+ case DATA_ARENA2:
+ return m_uiGoArena2GUID;
+ case DATA_ARENA3:
+ return m_uiGoArena3GUID;
+ case DATA_ARENA4:
+ return m_uiGoArena4GUID;
+
+ case DATA_GO_BAR_KEG:
+ return m_uiGoBarKegGUID;
+ case DATA_GO_BAR_KEG_TRAP:
+ return m_uiGoBarKegTrapGUID;
+ case DATA_GO_BAR_DOOR:
+ return m_uiGoBarDoorGUID;
+ case DATA_GO_CHALICE:
+ return m_uiSpectralChaliceGUID;
+ case DATA_GO_TOMB_EXIT:
+ return m_uiGoTombExitGUID;
+ }
+ 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]
+ >> m_auiEncounter[4] >> m_auiEncounter[5];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstanceData_instance_blackrock_depths(Map* pMap)
+{
+ return new instance_blackrock_depths(pMap);
+}
+
+void AddSC_instance_blackrock_depths()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_blackrock_depths";
+ newscript->GetInstanceData = &GetInstanceData_instance_blackrock_depths;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h b/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h
new file mode 100644
index 0000000..40daa55
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h
@@ -0,0 +1,93 @@
+/* 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 */
+
+#ifndef DEF_BLACKROCK_SPIRE_H
+#define DEF_BLACKROCK_SPIRE_H
+
+enum
+{
+ MAX_ENCOUNTER = 5,
+ MAX_ROOMS = 7,
+
+ TYPE_ROOM_EVENT = 1,
+ TYPE_EMBERSEER = 2,
+ TYPE_FLAMEWREATH = 3, // Only summon once per instance
+ TYPE_GYTH = 4,
+ TYPE_VALTHALAK = 5, // Only summon once per instance
+
+ NPC_SCARSHIELD_INFILTRATOR = 10299,
+ NPC_BLACKHAND_SUMMONER = 9818,
+ NPC_BLACKHAND_VETERAN = 9819,
+ NPC_PYROGUARD_EMBERSEER = 9816,
+ NPC_BLACKHAND_INCANCERATOR = 10316,
+ NPC_LORD_VICTOR_NEFARIUS = 10162,
+ NPC_GYTH = 10339,
+
+ // Doors
+ GO_EMBERSEER_IN = 175244,
+ GO_DOORS = 175705,
+ GO_EMBERSEER_OUT = 175153,
+ GO_GYTH_ENTRY_DOOR = 164726,
+ GO_GYTH_COMBAT_DOOR = 175185, // control in boss_script, because will auto-close after each wave
+ GO_GYTH_EXIT_DOOR = 175186,
+
+
+ GO_ROOM_7_RUNE = 175194,
+ GO_ROOM_3_RUNE = 175195,
+ GO_ROOM_6_RUNE = 175196,
+ GO_ROOM_1_RUNE = 175197,
+ GO_ROOM_5_RUNE = 175198,
+ GO_ROOM_2_RUNE = 175199,
+ GO_ROOM_4_RUNE = 175200,
+
+ GO_ROOKERY_EGG = 175124,
+};
+
+class MANGOS_DLL_DECL instance_blackrock_spire : public ScriptedInstance
+{
+ public:
+ instance_blackrock_spire(Map* pMap);
+ ~instance_blackrock_spire() {}
+
+ void Initialize();
+
+ void OnObjectCreate(GameObject* pGo);
+ void OnCreatureCreate(Creature* pCreature);
+
+ void SetData(uint32 uiType, uint32 uiData);
+ void SetData64(uint32 uiType, uint64 uiData);
+ uint32 GetData(uint32 uiType);
+ uint64 GetData64(uint32 uiType);
+
+ const char* Save() { return strInstData.c_str(); }
+ void Load(const char* chrIn);
+
+ void DoSortRoomEventMobs();
+ void GetIncanceratorGUIDList(std::list &lList) { lList = m_lIncanceratorGUIDList; }
+ void GetRookeryEggGUIDList(std::list &lList) { lList = m_lRookeryEggGUIDList; }
+
+ protected:
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint64 m_uiEmberseerGUID;
+ uint64 m_uiNefariusGUID;
+ uint64 m_uiGythGUID;
+ uint64 m_uiInfiltratorGUID;
+
+ uint64 m_uiEmberseerInDoorGUID;
+ uint64 m_uiEmberseerCombatDoorGUID;
+ uint64 m_uiEmberseerOutDoorGUID;
+ uint64 m_uiGythEntryDoorGUID;
+ uint64 m_uiGythCombatDoorGUID;
+ uint64 m_uiGythExitDoorGUID;
+
+ uint64 m_auiRoomRuneGUID[MAX_ROOMS];
+ std::list m_alRoomEventMobGUIDSorted[MAX_ROOMS];
+ std::list m_lRoomEventMobGUIDList;
+ std::list m_lIncanceratorGUIDList;
+ std::list m_lRookeryEggGUIDList;
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp
new file mode 100644
index 0000000..88a2a78
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp
@@ -0,0 +1,109 @@
+/* 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_Drakkisath
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_FIRENOVA = 23462,
+ SPELL_CLEAVE = 20691,
+ SPELL_CONFLIGURATION = 16805,
+ SPELL_THUNDERCLAP = 15548 //Not sure if right ID. 23931 would be a harder possibility.
+};
+
+struct MANGOS_DLL_DECL boss_drakkisathAI : public ScriptedAI
+{
+ boss_drakkisathAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiFireNovaTimer;
+ uint32 m_uiCleaveTimer;
+ uint32 m_uiConfligurationTimer;
+ uint32 m_uiThunderclapTimer;
+
+ void Reset()
+ {
+ m_uiFireNovaTimer = 6000;
+ m_uiCleaveTimer = 8000;
+ m_uiConfligurationTimer = 15000;
+ m_uiThunderclapTimer = 17000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // FireNova
+ if (m_uiFireNovaTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FIRENOVA);
+ m_uiFireNovaTimer = 10000;
+ }
+ else
+ m_uiFireNovaTimer -= uiDiff;
+
+ // Cleave
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleaveTimer = 8000;
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ // Confliguration
+ if (m_uiConfligurationTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CONFLIGURATION, 0, m_creature->getVictim()->GetGUID());
+ m_uiConfligurationTimer = 18000;
+ }
+ else
+ m_uiConfligurationTimer -= uiDiff;
+
+ // Thunderclap
+ if (m_uiThunderclapTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_THUNDERCLAP);
+ m_uiThunderclapTimer = 20000;
+ }
+ else
+ m_uiThunderclapTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_drakkisath(Creature* pCreature)
+{
+ return new boss_drakkisathAI(pCreature);
+}
+
+void AddSC_boss_drakkisath()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_drakkisath";
+ newscript->GetAI = &GetAI_boss_drakkisath;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp
new file mode 100644
index 0000000..ab6e364
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp
@@ -0,0 +1,248 @@
+/* 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_Gyth
+SD%Complete: 100
+SDComment: Whole Event needs some rewrite
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+#include "blackrock_spire.h"
+
+enum
+{
+ SPELL_CORROSIVEACID = 20667,
+ SPELL_FREEZE = 16350, // ID was wrong!
+ SPELL_FLAMEBREATH = 20712,
+ SPELL_ROOT_SELF = 33356,
+
+ MODEL_ID_INVISIBLE = 11686,
+ MODEL_ID_GYTH_MOUNTED = 9723,
+ MODEL_ID_GYTH = 9806,
+
+ NPC_FIRE_TONGUE = 10372,
+ NPC_CHROMATIC_WHELP = 10442,
+ NPC_CHROMATIC_DRAGON = 10447,
+ NPC_BLACKHAND_ELITE = 10317,
+ NPC_REND_BLACKHAND = 10429
+};
+
+struct MANGOS_DLL_DECL boss_gythAI : public ScriptedAI
+{
+ boss_gythAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (instance_blackrock_spire*) pCreature->GetInstanceData();
+ Reset();
+ }
+
+ instance_blackrock_spire* m_pInstance;
+ uint64 m_uiCombatDoorGUID;
+ uint32 uiAggroTimer;
+ uint32 uiDragonsTimer;
+ uint32 uiOrcTimer;
+ uint32 uiCorrosiveAcidTimer;
+ uint32 uiFreezeTimer;
+ uint32 uiFlamebreathTimer;
+ uint32 uiLine1Count;
+ uint32 uiLine2Count;
+
+ bool m_bSummonedRend;
+ bool m_bAggro;
+ bool m_bRootSelf;
+
+ void Reset()
+ {
+ uiDragonsTimer = 3000;
+ uiOrcTimer = 60000;
+ uiAggroTimer = 60000;
+ uiCorrosiveAcidTimer = 8000;
+ uiFreezeTimer = 11000;
+ uiFlamebreathTimer = 4000;
+ m_bSummonedRend = false;
+ m_bAggro = false;
+ m_bRootSelf = false;
+
+ // how many times should the two lines of summoned creatures be spawned
+ // min 2 x 2, max 7 lines of attack in total
+ uiLine1Count = urand(2, 5);
+ uiLine2Count = urand(2, 7 - uiLine1Count);
+
+ // Invisible for event start
+ m_creature->SetDisplayId(MODEL_ID_INVISIBLE);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (m_pInstance)
+ {
+ m_pInstance->SetData(TYPE_GYTH, IN_PROGRESS);
+ m_uiCombatDoorGUID = m_pInstance->GetData64(GO_GYTH_COMBAT_DOOR);
+ }
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_GYTH, DONE);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_GYTH, FAIL);
+ }
+
+ void SummonCreatureWithRandomTarget(uint32 uiCreatureId)
+ {
+ float fX, fY, fZ;
+ m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 2*INTERACTION_DISTANCE, fX, fY, fZ);
+ fX = std::min(m_creature->GetPositionX(), fX); // Halfcircle - suits better the rectangular form
+ if (Creature* pSummoned = m_creature->SummonCreature(uiCreatureId, fX, fY, fZ, 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 240000))
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ pSummoned->AI()->AttackStart(pTarget);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!m_bRootSelf)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ROOT_SELF);
+ m_bRootSelf = true;
+ }
+
+ if (!m_bAggro && uiLine1Count == 0 && uiLine2Count == 0)
+ {
+ if (uiAggroTimer < uiDiff)
+ {
+ m_bAggro = true;
+ // Visible now!
+ m_creature->SetDisplayId(MODEL_ID_GYTH_MOUNTED);
+ m_creature->setFaction(14);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->RemoveAurasDueToSpell(SPELL_ROOT_SELF);
+ if (m_pInstance)
+ m_pInstance->DoUseDoorOrButton(m_uiCombatDoorGUID);
+
+ }
+ else
+ uiAggroTimer -= uiDiff;
+ }
+
+ // Summon Dragon pack. 2 Dragons and 3 Whelps
+ if (!m_bAggro && !m_bSummonedRend && uiLine1Count > 0)
+ {
+ if (uiDragonsTimer < uiDiff)
+ {
+ SummonCreatureWithRandomTarget(NPC_FIRE_TONGUE);
+ SummonCreatureWithRandomTarget(NPC_FIRE_TONGUE);
+ SummonCreatureWithRandomTarget(NPC_CHROMATIC_WHELP);
+ SummonCreatureWithRandomTarget(NPC_CHROMATIC_WHELP);
+ SummonCreatureWithRandomTarget(NPC_CHROMATIC_WHELP);
+ --uiLine1Count;
+ if (m_pInstance)
+ m_pInstance->DoUseDoorOrButton(m_uiCombatDoorGUID);
+ uiDragonsTimer = 60000;
+ }
+ else
+ uiDragonsTimer -= uiDiff;
+ }
+
+ //Summon Orc pack. 1 Orc Handler 1 Elite Dragonkin and 3 Whelps
+ if (!m_bAggro && !m_bSummonedRend && uiLine1Count == 0 && uiLine2Count > 0)
+ {
+ if (uiOrcTimer < uiDiff)
+ {
+ SummonCreatureWithRandomTarget(NPC_CHROMATIC_DRAGON);
+ SummonCreatureWithRandomTarget(NPC_BLACKHAND_ELITE);
+ SummonCreatureWithRandomTarget(NPC_CHROMATIC_WHELP);
+ SummonCreatureWithRandomTarget(NPC_CHROMATIC_WHELP);
+ SummonCreatureWithRandomTarget(NPC_CHROMATIC_WHELP);
+ if (m_pInstance)
+ m_pInstance->DoUseDoorOrButton(m_uiCombatDoorGUID);
+ --uiLine2Count;
+ uiOrcTimer = 60000;
+ }
+ else
+ uiOrcTimer -= uiDiff;
+ }
+
+ // we take part in the fight
+ if (m_bAggro)
+ {
+ // CorrosiveAcid_Timer
+ if (uiCorrosiveAcidTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_CORROSIVEACID);
+ uiCorrosiveAcidTimer = 7000;
+ }
+ else
+ uiCorrosiveAcidTimer -= uiDiff;
+
+ // Freeze_Timer
+ if (uiFreezeTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_FREEZE) == CAST_OK)
+ uiFreezeTimer = 16000;
+ }
+ else
+ uiFreezeTimer -= uiDiff;
+
+ // Flamebreath_Timer
+ if (uiFlamebreathTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FLAMEBREATH);
+ uiFlamebreathTimer = 10500;
+ }
+ else
+ uiFlamebreathTimer -= uiDiff;
+
+ //Summon Rend
+ if (!m_bSummonedRend && m_creature->GetHealthPercent() < 11.0f)
+ {
+ // summon Rend and Change model to normal Gyth
+ // Inturrupt any spell casting
+ m_creature->InterruptNonMeleeSpells(false);
+ // Gyth model
+ m_creature->SetDisplayId(MODEL_ID_GYTH);
+ m_creature->SummonCreature(NPC_REND_BLACKHAND, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 900000);
+ m_bSummonedRend = true;
+ }
+
+ DoMeleeAttackIfReady();
+ } // end if Aggro
+ }
+};
+
+CreatureAI* GetAI_boss_gyth(Creature* pCreature)
+{
+ return new boss_gythAI(pCreature);
+}
+
+void AddSC_boss_gyth()
+{
+ Script* pNewScript;
+ pNewScript = new Script;
+ pNewScript->Name = "boss_gyth";
+ pNewScript->GetAI = &GetAI_boss_gyth;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp
new file mode 100644
index 0000000..e5c6b29
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp
@@ -0,0 +1,91 @@
+/* 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_Halycon
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_CROWDPUMMEL 10887
+#define SPELL_MIGHTYBLOW 14099
+
+#define ADD_1X -169.839203f
+#define ADD_1Y -324.961395f
+#define ADD_1Z 64.401443f
+#define ADD_1O 3.124724f
+
+struct MANGOS_DLL_DECL boss_halyconAI : public ScriptedAI
+{
+ boss_halyconAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 CrowdPummel_Timer;
+ uint32 MightyBlow_Timer;
+ bool Summoned;
+
+ void Reset()
+ {
+ CrowdPummel_Timer = 8000;
+ MightyBlow_Timer = 14000;
+ Summoned = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //CrowdPummel_Timer
+ if (CrowdPummel_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CROWDPUMMEL);
+ CrowdPummel_Timer = 14000;
+ }else CrowdPummel_Timer -= diff;
+
+ //MightyBlow_Timer
+ if (MightyBlow_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MIGHTYBLOW);
+ MightyBlow_Timer = 10000;
+ }else MightyBlow_Timer -= diff;
+
+ //Summon Gizrul
+ if (!Summoned && m_creature->GetHealthPercent() < 25.0f)
+ {
+ m_creature->SummonCreature(10268,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,300000);
+ Summoned = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_halycon(Creature* pCreature)
+{
+ return new boss_halyconAI(pCreature);
+}
+
+void AddSC_boss_halycon()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_halycon";
+ newscript->GetAI = &GetAI_boss_halycon;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp
new file mode 100644
index 0000000..7e3c7da
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp
@@ -0,0 +1,133 @@
+/* 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_Highlord_Omokk
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_WARSTOMP = 24375,
+ SPELL_STRIKE = 18368,
+ SPELL_REND = 18106,
+ SPELL_SUNDERARMOR = 24317,
+ SPELL_KNOCKAWAY = 20686,
+ SPELL_SLOW = 22356
+};
+
+struct MANGOS_DLL_DECL boss_highlordomokkAI : public ScriptedAI
+{
+ boss_highlordomokkAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiWarStompTimer;
+ uint32 m_uiStrikeTimer;
+ uint32 m_uiRendTimer;
+ uint32 m_uiSunderArmorTimer;
+ uint32 m_uiKnockAwayTimer;
+ uint32 m_uiSlowTimer;
+
+ void Reset()
+ {
+ m_uiWarStompTimer = 15000;
+ m_uiStrikeTimer = 10000;
+ m_uiRendTimer = 14000;
+ m_uiSunderArmorTimer = 2000;
+ m_uiKnockAwayTimer = 18000;
+ m_uiSlowTimer = 24000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // WarStomp
+ if (m_uiWarStompTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_WARSTOMP);
+ m_uiWarStompTimer = 14000;
+ }
+ else
+ m_uiWarStompTimer -= uiDiff;
+
+ // Strike
+ if (m_uiStrikeTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_STRIKE);
+ m_uiStrikeTimer = 10000;
+ }
+ else
+ m_uiStrikeTimer -= uiDiff;
+
+ // Rend
+ if (m_uiRendTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_REND);
+ m_uiRendTimer = 18000;
+ }
+ else
+ m_uiRendTimer -= uiDiff;
+
+ // Sunder Armor
+ if (m_uiSunderArmorTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUNDERARMOR);
+ m_uiSunderArmorTimer = 25000;
+ }
+ else
+ m_uiSunderArmorTimer -= uiDiff;
+
+ // KnockAway
+ if (m_uiKnockAwayTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_KNOCKAWAY);
+ m_uiKnockAwayTimer = 12000;
+ }
+ else
+ m_uiKnockAwayTimer -= uiDiff;
+
+ // Slow
+ if (m_uiSlowTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_SLOW);
+ m_uiSlowTimer = 18000;
+ }
+ else
+ m_uiSlowTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_highlordomokk(Creature* pCreature)
+{
+ return new boss_highlordomokkAI(pCreature);
+}
+
+void AddSC_boss_highlordomokk()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_highlord_omokk";
+ newscript->GetAI = &GetAI_boss_highlordomokk;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp
new file mode 100644
index 0000000..5e5ac5e
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp
@@ -0,0 +1,92 @@
+/* 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_Mother_Smolderweb
+SD%Complete: 100
+SDComment: Uncertain how often mother's milk is casted
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_CRYSTALIZE = 16104,
+ SPELL_MOTHERSMILK = 16468,
+ SPELL_SUMMON_SPIRE_SPIDERLING = 16103
+};
+
+struct MANGOS_DLL_DECL boss_mothersmolderwebAI : public ScriptedAI
+{
+ boss_mothersmolderwebAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiCrystalizeTimer;
+ uint32 m_uiMothersMilkTimer;
+
+ void Reset()
+ {
+ m_uiCrystalizeTimer = 20000;
+ m_uiMothersMilkTimer = 10000;
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (m_creature->GetHealth() <= uiDamage)
+ DoCastSpellIfCan(m_creature, SPELL_SUMMON_SPIRE_SPIDERLING, CAST_TRIGGERED);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Crystalize
+ if (m_uiCrystalizeTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_CRYSTALIZE);
+ m_uiCrystalizeTimer = 15000;
+ }
+ else
+ m_uiCrystalizeTimer -= uiDiff;
+
+ // Mothers Milk
+ if (m_uiMothersMilkTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_MOTHERSMILK);
+ m_uiMothersMilkTimer = urand(5000, 12500);
+ }
+ else
+ m_uiMothersMilkTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_mothersmolderweb(Creature* pCreature)
+{
+ return new boss_mothersmolderwebAI(pCreature);
+}
+
+void AddSC_boss_mothersmolderweb()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_mother_smolderweb";
+ newscript->GetAI = &GetAI_boss_mothersmolderweb;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp
new file mode 100644
index 0000000..2eb540a
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp
@@ -0,0 +1,142 @@
+/* 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_Overlord_Wyrmthalak
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_BLASTWAVE = 11130,
+ SPELL_SHOUT = 23511,
+ SPELL_CLEAVE = 20691,
+ SPELL_KNOCKAWAY = 20686,
+
+ NPC_SPIRESTONE_WARLORD = 9216,
+ NPC_SMOLDERTHORN_BERSERKER = 9268
+
+};
+
+const float afLocations[2][4]=
+{
+ {-39.355381f, -513.456482f, 88.472046f, 4.679872f},
+ {-49.875881f, -511.896942f, 88.195160f, 4.613114f}
+};
+
+struct MANGOS_DLL_DECL boss_overlordwyrmthalakAI : public ScriptedAI
+{
+ boss_overlordwyrmthalakAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiBlastWaveTimer;
+ uint32 m_uiShoutTimer;
+ uint32 m_uiCleaveTimer;
+ uint32 m_uiKnockawayTimer;
+ bool m_bSummoned;
+
+ void Reset()
+ {
+ m_uiBlastWaveTimer = 20000;
+ m_uiShoutTimer = 2000;
+ m_uiCleaveTimer = 6000;
+ m_uiKnockawayTimer = 12000;
+ m_bSummoned = false;
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() != NPC_SPIRESTONE_WARLORD && pSummoned->GetEntry() != NPC_SMOLDERTHORN_BERSERKER)
+ return;
+
+ if (m_creature->getVictim())
+ {
+ Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+ pSummoned->AI()->AttackStart(pTarget ? pTarget : m_creature->getVictim());
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // BlastWave
+ if (m_uiBlastWaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BLASTWAVE);
+ m_uiBlastWaveTimer = 20000;
+ }
+ else
+ m_uiBlastWaveTimer -= uiDiff;
+
+ // Shout
+ if (m_uiShoutTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_SHOUT);
+ m_uiShoutTimer = 10000;
+ }
+ else
+ m_uiShoutTimer -= uiDiff;
+
+ // Cleave
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleaveTimer = 7000;
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ // Knockaway
+ if (m_uiKnockawayTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_KNOCKAWAY);
+ m_uiKnockawayTimer = 14000;
+ }
+ else
+ m_uiKnockawayTimer -= uiDiff;
+
+ // Summon two Beserks
+ if (!m_bSummoned && m_creature->GetHealthPercent() < 51.0f)
+ {
+ m_creature->SummonCreature(NPC_SPIRESTONE_WARLORD, afLocations[0][0], afLocations[0][1], afLocations[0][2], afLocations[0][3], TEMPSUMMON_TIMED_DESPAWN, 300000);
+ m_creature->SummonCreature(NPC_SMOLDERTHORN_BERSERKER, afLocations[1][0], afLocations[1][1], afLocations[1][2], afLocations[1][3], TEMPSUMMON_TIMED_DESPAWN, 300000);
+
+ m_bSummoned = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_overlordwyrmthalak(Creature* pCreature)
+{
+ return new boss_overlordwyrmthalakAI(pCreature);
+}
+
+void AddSC_boss_overlordwyrmthalak()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_overlord_wyrmthalak";
+ newscript->GetAI = &GetAI_boss_overlordwyrmthalak;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp
new file mode 100644
index 0000000..d9ecd66
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp
@@ -0,0 +1,122 @@
+/* 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_Pyroguard_Emberseer
+SD%Complete: 100
+SDComment: Event to activate Emberseer NYI - 'aggro'-text missing
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+#include "blackrock_spire.h"
+
+enum
+{
+ SPELL_FIRENOVA = 23462,
+ SPELL_FLAMEBUFFET = 23341,
+ SPELL_PYROBLAST = 20228 // guesswork, but best fitting in spells-area, was 17274 (has mana cost)
+};
+
+struct MANGOS_DLL_DECL boss_pyroguard_emberseerAI : public ScriptedAI
+{
+ boss_pyroguard_emberseerAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (instance_blackrock_spire*) pCreature->GetInstanceData();
+ Reset();
+ }
+
+ instance_blackrock_spire* m_pInstance;
+ uint32 m_uiFireNovaTimer;
+ uint32 m_uiFlameBuffetTimer;
+ uint32 m_uiPyroBlastTimer;
+
+ void Reset()
+ {
+ m_uiFireNovaTimer = 6000;
+ m_uiFlameBuffetTimer = 3000;
+ m_uiPyroBlastTimer = 14000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_EMBERSEER, IN_PROGRESS);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_EMBERSEER, DONE);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_EMBERSEER, FAIL);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // FireNova Timer
+ if (m_uiFireNovaTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FIRENOVA);
+ m_uiFireNovaTimer = 6000;
+ }
+ else
+ m_uiFireNovaTimer -= uiDiff;
+
+ // FlameBuffet Timer
+ if (m_uiFlameBuffetTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FLAMEBUFFET);
+ m_uiFlameBuffetTimer = 14000;
+ }
+ else
+ m_uiFlameBuffetTimer -= uiDiff;
+
+ // PyroBlast Timer
+ if (m_uiPyroBlastTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_PYROBLAST);
+ m_uiPyroBlastTimer = 15000;
+ }
+ else
+ m_uiPyroBlastTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_pyroguard_emberseer(Creature* pCreature)
+{
+ return new boss_pyroguard_emberseerAI(pCreature);
+}
+
+void AddSC_boss_pyroguard_emberseer()
+{
+ Script* pNewScript;
+ pNewScript = new Script;
+ pNewScript->Name = "boss_pyroguard_emberseer";
+ pNewScript->GetAI = &GetAI_boss_pyroguard_emberseer;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp
new file mode 100644
index 0000000..c99ce92
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp
@@ -0,0 +1,89 @@
+/* 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_Quartmaster_Zigris
+SD%Complete: 100
+SDComment: Needs revision
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_SHOOT = 16496,
+ SPELL_STUNBOMB = 16497,
+ SPELL_HEALING_POTION = 15504,
+ SPELL_HOOKEDNET = 15609
+};
+
+struct MANGOS_DLL_DECL boss_quatermasterzigrisAI : public ScriptedAI
+{
+ boss_quatermasterzigrisAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiShootTimer;
+ uint32 m_uiStunBombTimer;
+ //uint32 HelingPotion_Timer;
+
+ void Reset()
+ {
+ m_uiShootTimer = 1000;
+ m_uiStunBombTimer = 16000;
+ //HelingPotion_Timer = 25000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Shoot
+ if (m_uiShootTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOOT);
+ m_uiShootTimer = 500;
+ }
+ else
+ m_uiShootTimer -= uiDiff;
+
+ // StunBomb
+ if (m_uiStunBombTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_STUNBOMB);
+ m_uiStunBombTimer = 14000;
+ }
+ else
+ m_uiStunBombTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_quatermasterzigris(Creature* pCreature)
+{
+ return new boss_quatermasterzigrisAI(pCreature);
+}
+
+void AddSC_boss_quatermasterzigris()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "quartermaster_zigris";
+ newscript->GetAI = &GetAI_boss_quatermasterzigris;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp
new file mode 100644
index 0000000..919669d
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp
@@ -0,0 +1,97 @@
+/* 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_Rend_Blackhand
+SD%Complete: 100
+SDComment: Intro event NYI
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_WHIRLWIND = 26038,
+ SPELL_CLEAVE = 20691,
+ SPELL_THUNDERCLAP = 23931 //Not sure if he cast this spell
+};
+
+struct MANGOS_DLL_DECL boss_rend_blackhandAI : public ScriptedAI
+{
+ boss_rend_blackhandAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiWhirlWindTimer;
+ uint32 m_uiCleaveTimer;
+ uint32 m_uiThunderclapTimer;
+
+ void Reset()
+ {
+ m_uiWhirlWindTimer = 20000;
+ m_uiCleaveTimer = 5000;
+ m_uiThunderclapTimer = 9000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // WhirlWind
+ if (m_uiWhirlWindTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_WHIRLWIND);
+ m_uiWhirlWindTimer = 18000;
+ }
+ else
+ m_uiWhirlWindTimer -= uiDiff;
+
+ // Cleave
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleaveTimer = 10000;
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ // Thunderclap
+ if (m_uiThunderclapTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_THUNDERCLAP);
+ m_uiThunderclapTimer = 16000;
+ }
+ else
+ m_uiThunderclapTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_rend_blackhand(Creature* pCreature)
+{
+ return new boss_rend_blackhandAI(pCreature);
+}
+
+void AddSC_boss_rend_blackhand()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_rend_blackhand";
+ newscript->GetAI = &GetAI_boss_rend_blackhand;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp
new file mode 100644
index 0000000..189d803
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.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: Boss_Shadow_Hunter_Voshgajin
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_CURSEOFBLOOD = 24673,
+ SPELL_HEX = 16708,
+ SPELL_CLEAVE = 20691
+};
+
+struct MANGOS_DLL_DECL boss_shadowvoshAI : public ScriptedAI
+{
+ boss_shadowvoshAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiCurseOfBloodTimer;
+ uint32 m_uiHexTimer;
+ uint32 m_uiCleaveTimer;
+
+ void Reset()
+ {
+ m_uiCurseOfBloodTimer = 2000;
+ m_uiHexTimer = 8000;
+ m_uiCleaveTimer = 14000;
+
+ //m_creature->CastSpell(m_creature,SPELL_ICEARMOR,true);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Curse Of Blood
+ if (m_uiCurseOfBloodTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_CURSEOFBLOOD);
+ m_uiCurseOfBloodTimer = 45000;
+ }
+ else
+ m_uiCurseOfBloodTimer -= uiDiff;
+
+ // Hex
+ if (m_uiHexTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_HEX);
+ m_uiHexTimer = 15000;
+ }
+ else
+ m_uiHexTimer -= uiDiff;
+
+ // Cleave
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleaveTimer = 7000;
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_shadowvosh(Creature* pCreature)
+{
+ return new boss_shadowvoshAI(pCreature);
+}
+
+void AddSC_boss_shadowvosh()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_shadow_hunter_voshgajin";
+ newscript->GetAI = &GetAI_boss_shadowvosh;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp
new file mode 100644
index 0000000..74424fa
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp
@@ -0,0 +1,99 @@
+/* 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_The_Best
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_FLAMEBREAK = 16785,
+ SPELL_IMMOLATE = 20294,
+ SPELL_TERRIFYINGROAR = 14100
+};
+
+struct MANGOS_DLL_DECL boss_thebeastAI : public ScriptedAI
+{
+ boss_thebeastAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiFlamebreakTimer;
+ uint32 m_uiImmolateTimer;
+ uint32 m_uiTerrifyingRoarTimer;
+
+ void Reset()
+ {
+ m_uiFlamebreakTimer = 12000;
+ m_uiImmolateTimer = 3000;
+ m_uiTerrifyingRoarTimer = 23000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Flamebreak
+ if (m_uiFlamebreakTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FLAMEBREAK);
+ m_uiFlamebreakTimer = 10000;
+ }
+ else
+ m_uiFlamebreakTimer -= uiDiff;
+
+ // Immolate
+ if (m_uiImmolateTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_IMMOLATE);
+
+ m_uiImmolateTimer = 8000;
+ }
+ else
+ m_uiImmolateTimer -= uiDiff;
+
+ // Terrifying Roar
+ if (m_uiTerrifyingRoarTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_TERRIFYINGROAR);
+ m_uiTerrifyingRoarTimer = 20000;
+ }
+ else
+ m_uiTerrifyingRoarTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_thebeast(Creature* pCreature)
+{
+ return new boss_thebeastAI(pCreature);
+}
+
+void AddSC_boss_thebeast()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_the_beast";
+ newscript->GetAI = &GetAI_boss_thebeast;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp b/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp
new file mode 100644
index 0000000..6cc7dca
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp
@@ -0,0 +1,118 @@
+/* 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_Warmaster_Voone
+SD%Complete: 100
+SDComment:
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_SNAPKICK 15618
+#define SPELL_CLEAVE 15284
+#define SPELL_UPPERCUT 10966
+#define SPELL_MORTALSTRIKE 15708
+#define SPELL_PUMMEL 15615
+#define SPELL_THROWAXE 16075
+
+struct MANGOS_DLL_DECL boss_warmastervooneAI : public ScriptedAI
+{
+ boss_warmastervooneAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Snapkick_Timer;
+ uint32 Cleave_Timer;
+ uint32 Uppercut_Timer;
+ uint32 MortalStrike_Timer;
+ uint32 Pummel_Timer;
+ uint32 ThrowAxe_Timer;
+
+ void Reset()
+ {
+ Snapkick_Timer = 8000;
+ Cleave_Timer = 14000;
+ Uppercut_Timer = 20000;
+ MortalStrike_Timer = 12000;
+ Pummel_Timer = 32000;
+ ThrowAxe_Timer = 1000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Snapkick_Timer
+ if (Snapkick_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SNAPKICK);
+ Snapkick_Timer = 6000;
+ }else Snapkick_Timer -= diff;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = 12000;
+ }else Cleave_Timer -= diff;
+
+ //Uppercut_Timer
+ if (Uppercut_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_UPPERCUT);
+ Uppercut_Timer = 14000;
+ }else Uppercut_Timer -= diff;
+
+ //MortalStrike_Timer
+ if (MortalStrike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MORTALSTRIKE);
+ MortalStrike_Timer = 10000;
+ }else MortalStrike_Timer -= diff;
+
+ //Pummel_Timer
+ if (Pummel_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_PUMMEL);
+ Pummel_Timer = 16000;
+ }else Pummel_Timer -= diff;
+
+ //ThrowAxe_Timer
+ if (ThrowAxe_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_THROWAXE);
+ ThrowAxe_Timer = 8000;
+ }else ThrowAxe_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_warmastervoone(Creature* pCreature)
+{
+ return new boss_warmastervooneAI(pCreature);
+}
+
+void AddSC_boss_warmastervoone()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_warmaster_voone";
+ newscript->GetAI = &GetAI_boss_warmastervoone;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp b/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp
new file mode 100644
index 0000000..afc1399
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp
@@ -0,0 +1,301 @@
+/* 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_blackrock_spire
+SD%Complete: 50
+SDComment: To really get this instance working, many encounters will need more love - and also the DB content is surely not yet perfect.
+SDCategory: Blackrock Spire
+EndScriptData */
+
+#include "precompiled.h"
+#include "blackrock_spire.h"
+
+enum
+{
+ AREATRIGGER_ENTER_UBRS = 2046,
+ AREATRIGGER_STADIUM = 2026
+};
+
+/* Areatrigger
+1470 Instance Entry
+1628 LBRS, between Spiders and Ogres
+1946 LBRS, ubrs pre-quest giver (1)
+1986 LBRS, ubrs pre-quest giver (2)
+1987 LBRS, ubrs pre-quest giver (3)
+2026 UBRS, stadium event trigger
+2046 UBRS, way to upper
+2066 UBRS, The Beast - Exit (to the dark chamber)
+2067 UBRS, The Beast - Entry
+2068 LBRS, fall out of map
+3726 UBRS, entrance to BWL
+*/
+
+instance_blackrock_spire::instance_blackrock_spire(Map* pMap) : ScriptedInstance(pMap),
+ m_uiEmberseerGUID(0),
+ m_uiNefariusGUID(0),
+ m_uiGythGUID(0),
+ m_uiInfiltratorGUID(0),
+
+ m_uiEmberseerInDoorGUID(0),
+ m_uiEmberseerCombatDoorGUID(0),
+ m_uiEmberseerOutDoorGUID(0),
+
+ m_uiGythEntryDoorGUID(0),
+ m_uiGythCombatDoorGUID(0),
+ m_uiGythExitDoorGUID(0)
+{
+ Initialize();
+}
+
+void instance_blackrock_spire::Initialize()
+{
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+ memset(&m_auiRoomRuneGUID, 0, sizeof(m_auiRoomRuneGUID));
+}
+
+void instance_blackrock_spire::OnObjectCreate(GameObject* pGo)
+{
+ switch(pGo->GetEntry())
+ {
+ case GO_EMBERSEER_IN:
+ m_uiEmberseerInDoorGUID = pGo->GetGUID();
+ if (GetData(TYPE_ROOM_EVENT) == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_DOORS:
+ m_uiEmberseerCombatDoorGUID = pGo->GetGUID();
+ break;
+ case GO_EMBERSEER_OUT:
+ m_uiEmberseerOutDoorGUID = pGo->GetGUID();
+ if (GetData(TYPE_EMBERSEER) == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_GYTH_ENTRY_DOOR:
+ m_uiGythEntryDoorGUID = pGo->GetGUID();
+ break;
+ case GO_GYTH_COMBAT_DOOR:
+ m_uiGythCombatDoorGUID = pGo->GetGUID();
+ break;
+ case GO_GYTH_EXIT_DOOR:
+ m_uiGythExitDoorGUID = pGo->GetGUID();
+ if (GetData(TYPE_GYTH) == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+
+ case GO_ROOM_1_RUNE: m_auiRoomRuneGUID[0] = pGo->GetGUID(); break;
+ case GO_ROOM_2_RUNE: m_auiRoomRuneGUID[1] = pGo->GetGUID(); break;
+ case GO_ROOM_3_RUNE: m_auiRoomRuneGUID[2] = pGo->GetGUID(); break;
+ case GO_ROOM_4_RUNE: m_auiRoomRuneGUID[3] = pGo->GetGUID(); break;
+ case GO_ROOM_5_RUNE: m_auiRoomRuneGUID[4] = pGo->GetGUID(); break;
+ case GO_ROOM_6_RUNE: m_auiRoomRuneGUID[5] = pGo->GetGUID(); break;
+ case GO_ROOM_7_RUNE: m_auiRoomRuneGUID[6] = pGo->GetGUID(); break;
+
+ case GO_ROOKERY_EGG: m_lRookeryEggGUIDList.push_back(pGo->GetGUID()); break;
+ }
+}
+
+void instance_blackrock_spire::OnCreatureCreate(Creature* pCreature)
+{
+ switch(pCreature->GetEntry())
+ {
+ case NPC_PYROGUARD_EMBERSEER: m_uiEmberseerGUID = pCreature->GetEntry(); break;
+ case NPC_LORD_VICTOR_NEFARIUS: m_uiNefariusGUID = pCreature->GetGUID(); break;
+ case NPC_GYTH: m_uiGythGUID = pCreature->GetGUID(); break;
+ case NPC_SCARSHIELD_INFILTRATOR: m_uiInfiltratorGUID = pCreature->GetGUID(); break;
+
+ case NPC_BLACKHAND_SUMMONER:
+ case NPC_BLACKHAND_VETERAN: m_lRoomEventMobGUIDList.push_back(pCreature->GetGUID()); break;
+ case NPC_BLACKHAND_INCANCERATOR: m_lIncanceratorGUIDList.push_back(pCreature->GetGUID()); break;
+ }
+}
+
+void instance_blackrock_spire::SetData(uint32 uiType, uint32 uiData)
+{
+ switch(uiType)
+ {
+ case TYPE_ROOM_EVENT:
+ if (uiData == DONE)
+ DoUseDoorOrButton(m_uiEmberseerInDoorGUID);
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_EMBERSEER:
+ if (uiData == IN_PROGRESS || uiData == FAIL)
+ DoUseDoorOrButton(m_uiEmberseerCombatDoorGUID);
+ else if (uiData == DONE)
+ {
+ DoUseDoorOrButton(m_uiEmberseerCombatDoorGUID);
+ DoUseDoorOrButton(m_uiEmberseerOutDoorGUID);
+ }
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_FLAMEWREATH:
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_GYTH:
+ if (uiData == IN_PROGRESS || uiData == FAIL)
+ DoUseDoorOrButton(m_uiGythEntryDoorGUID);
+ else if (uiData == DONE)
+ {
+ DoUseDoorOrButton(m_uiGythEntryDoorGUID);
+ DoUseDoorOrButton(m_uiGythExitDoorGUID);
+ }
+ m_auiEncounter[3] = uiData;
+ break;
+ case TYPE_VALTHALAK:
+ m_auiEncounter[4] = 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] << " " << m_auiEncounter[4];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+}
+
+void instance_blackrock_spire::SetData64(uint32 uiType, uint64 uiData)
+{
+ if (uiType == TYPE_ROOM_EVENT && GetData(TYPE_ROOM_EVENT) == IN_PROGRESS)
+ {
+ uint8 uiNotEmptyRoomsCount = 0;
+ for (uint8 i = 0; i< MAX_ROOMS; i++)
+ {
+ if (m_auiRoomRuneGUID[i]) // This check is used, to ensure which runes still need processing
+ {
+ m_alRoomEventMobGUIDSorted[i].remove(uiData);
+ if (m_alRoomEventMobGUIDSorted[i].empty())
+ {
+ DoUseDoorOrButton(m_auiRoomRuneGUID[i]);
+ m_auiRoomRuneGUID[i] = 0;
+ }
+ else
+ uiNotEmptyRoomsCount++; // found an not empty room
+ }
+ }
+ if (!uiNotEmptyRoomsCount)
+ SetData(TYPE_ROOM_EVENT, DONE);
+ }
+}
+
+void instance_blackrock_spire::Load(const char* chrIn)
+{
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3] >> m_auiEncounter[4];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+}
+
+uint32 instance_blackrock_spire::GetData(uint32 uiType)
+{
+ switch(uiType)
+ {
+ case TYPE_ROOM_EVENT: return m_auiEncounter[0];
+ case TYPE_EMBERSEER: return m_auiEncounter[1];
+ case TYPE_FLAMEWREATH: return m_auiEncounter[2];
+ case TYPE_GYTH: return m_auiEncounter[3];
+ case TYPE_VALTHALAK: return m_auiEncounter[4];
+ }
+ return 0;
+}
+
+uint64 instance_blackrock_spire::GetData64(uint32 uiType)
+{
+ switch (uiType)
+ {
+ case NPC_PYROGUARD_EMBERSEER: return m_uiEmberseerGUID;
+ case NPC_LORD_VICTOR_NEFARIUS: return m_uiNefariusGUID;
+ case NPC_GYTH: return m_uiGythGUID;
+ case NPC_SCARSHIELD_INFILTRATOR: return m_uiInfiltratorGUID;
+ case GO_GYTH_COMBAT_DOOR: return m_uiGythCombatDoorGUID;
+ }
+ return 0;
+}
+
+void instance_blackrock_spire::DoSortRoomEventMobs()
+{
+ if (GetData(TYPE_ROOM_EVENT) != NOT_STARTED)
+ return;
+ for (uint8 i = 0; i < MAX_ROOMS; i++)
+ if (GameObject* pRune = instance->GetGameObject(m_auiRoomRuneGUID[i]))
+ for (std::list::const_iterator itr = m_lRoomEventMobGUIDList.begin(); itr != m_lRoomEventMobGUIDList.end(); itr++)
+ if (Creature* pCreature = instance->GetCreature(*itr))
+ if (pCreature->isAlive() && pCreature->GetDistance(pRune) < 10.0f)
+ m_alRoomEventMobGUIDSorted[i].push_back(*itr);
+
+ SetData(TYPE_ROOM_EVENT, IN_PROGRESS);
+}
+
+InstanceData* GetInstanceData_instance_blackrock_spire(Map* pMap)
+{
+ return new instance_blackrock_spire(pMap);
+}
+
+bool AreaTrigger_at_blackrock_spire(Player* pPlayer, AreaTriggerEntry const* pAt)
+{
+ if (pPlayer->isDead())
+ return false;
+
+ switch (pAt->id)
+ {
+ case AREATRIGGER_ENTER_UBRS:
+ if (instance_blackrock_spire* pInstance = (instance_blackrock_spire*) pPlayer->GetInstanceData())
+ pInstance->DoSortRoomEventMobs();
+ break;
+ case AREATRIGGER_STADIUM:
+ if (instance_blackrock_spire* pInstance = (instance_blackrock_spire*) pPlayer->GetInstanceData())
+ if (Creature* pGyth = pInstance->instance->GetCreature(pInstance->GetData64(NPC_GYTH)))
+ if (pGyth->isAlive() && !pGyth->isInCombat())
+ pGyth->AI()->AttackStart(pPlayer);
+ break;
+ }
+ return false;
+}
+
+void AddSC_instance_blackrock_spire()
+{
+ Script* pNewScript;
+ pNewScript = new Script;
+ pNewScript->Name = "instance_blackrock_spire";
+ pNewScript->GetInstanceData = &GetInstanceData_instance_blackrock_spire;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "at_blackrock_spire";
+ pNewScript->pAreaTrigger = &AreaTrigger_at_blackrock_spire;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp
new file mode 100644
index 0000000..8126703
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp
@@ -0,0 +1,111 @@
+/* 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_Broodlord_Lashlayer
+SD%Complete: 100
+SDComment:
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_AGGRO -1469000
+#define SAY_LEASH -1469001
+
+#define SPELL_CLEAVE 26350
+#define SPELL_BLASTWAVE 23331
+#define SPELL_MORTALSTRIKE 24573
+#define SPELL_KNOCKBACK 25778
+
+struct MANGOS_DLL_DECL boss_broodlordAI : public ScriptedAI
+{
+ boss_broodlordAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Cleave_Timer;
+ uint32 BlastWave_Timer;
+ uint32 MortalStrike_Timer;
+ uint32 KnockBack_Timer;
+
+ void Reset()
+ {
+ Cleave_Timer = 8000; //These times are probably wrong
+ BlastWave_Timer = 12000;
+ MortalStrike_Timer = 20000;
+ KnockBack_Timer = 30000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = 7000;
+ }else Cleave_Timer -= diff;
+
+ // BlastWave
+ if (BlastWave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BLASTWAVE);
+ BlastWave_Timer = urand(8000, 16000);
+ }else BlastWave_Timer -= diff;
+
+ //MortalStrike_Timer
+ if (MortalStrike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MORTALSTRIKE);
+ MortalStrike_Timer = urand(25000, 35000);
+ }else MortalStrike_Timer -= diff;
+
+ if (KnockBack_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KNOCKBACK);
+ //Drop 50% aggro
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50);
+
+ KnockBack_Timer = urand(15000, 30000);
+ }else KnockBack_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+
+ if (EnterEvadeIfOutOfCombatArea(diff))
+ DoScriptText(SAY_LEASH, m_creature);
+ }
+};
+CreatureAI* GetAI_boss_broodlord(Creature* pCreature)
+{
+ return new boss_broodlordAI(pCreature);
+}
+
+void AddSC_boss_broodlord()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_broodlord";
+ newscript->GetAI = &GetAI_boss_broodlord;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp
new file mode 100644
index 0000000..ab58af5
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp
@@ -0,0 +1,315 @@
+/* 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_Chromaggus
+SD%Complete: 95
+SDComment: Chromatic Mutation disabled due to lack of core support
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ EMOTE_GENERIC_FRENZY_KILL = -1000001,
+ EMOTE_SHIMMER = -1469003,
+
+ //These spells are actually called elemental shield
+ //What they do is decrease all damage by 75% then they increase
+ //One school of damage by 1100%
+ SPELL_FIRE_VURNALBILTY = 22277,
+ SPELL_FROST_VURNALBILTY = 22278,
+ SPELL_SHADOW_VURNALBILTY = 22279,
+ SPELL_NATURE_VURNALBILTY = 22280,
+ SPELL_ARCANE_VURNALBILTY = 22281,
+
+ SPELL_INCINERATE = 23308, //Incinerate 23308,23309
+ SPELL_TIMELAPSE = 23310, //Time lapse 23310, 23311(old threat mod that was removed in 2.01)
+ SPELL_CORROSIVEACID = 23313, //Corrosive Acid 23313, 23314
+ SPELL_IGNITEFLESH = 23315, //Ignite Flesh 23315,23316
+ SPELL_FROSTBURN = 23187, //Frost burn 23187, 23189
+
+ //Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them
+ //Since Scripted spells arn't coded I'll just write a function that does the same thing
+ SPELL_BROODAF_BLUE = 23153, //Blue affliction 23153
+ SPELL_BROODAF_BLACK = 23154, //Black affliction 23154
+ SPELL_BROODAF_RED = 23155, //Red affliction 23155 (23168 on death)
+ SPELL_BROODAF_BRONZE = 23170, //Bronze Affliction 23170
+ SPELL_BROODAF_GREEN = 23169, //Brood Affliction Green 23169
+
+ SPELL_CHROMATIC_MUT_1 = 23174, //Spell cast on player if they get all 5 debuffs
+
+ SPELL_FRENZY = 28371, //The frenzy spell may be wrong
+ SPELL_ENRAGE = 28747
+};
+
+struct MANGOS_DLL_DECL boss_chromaggusAI : public ScriptedAI
+{
+ boss_chromaggusAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ //Select the 2 breaths that we are going to use until despawned
+ //5 possiblities for the first breath, 4 for the second, 20 total possiblites
+ //This way we don't end up casting 2 of the same breath
+ //TL TL would be stupid
+ srand(time(NULL));
+ switch(urand(0, 19))
+ {
+ //B1 - Incin
+ case 0:
+ Breath1_Spell = SPELL_INCINERATE;
+ Breath2_Spell = SPELL_TIMELAPSE;
+ break;
+ case 1:
+ Breath1_Spell = SPELL_INCINERATE;
+ Breath2_Spell = SPELL_CORROSIVEACID;
+ break;
+ case 2:
+ Breath1_Spell = SPELL_INCINERATE;
+ Breath2_Spell = SPELL_IGNITEFLESH;
+ break;
+ case 3:
+ Breath1_Spell = SPELL_INCINERATE;
+ Breath2_Spell = SPELL_FROSTBURN;
+ break;
+
+ //B1 - TL
+ case 4:
+ Breath1_Spell = SPELL_TIMELAPSE;
+ Breath2_Spell = SPELL_INCINERATE;
+ break;
+ case 5:
+ Breath1_Spell = SPELL_TIMELAPSE;
+ Breath2_Spell = SPELL_CORROSIVEACID;
+ break;
+ case 6:
+ Breath1_Spell = SPELL_TIMELAPSE;
+ Breath2_Spell = SPELL_IGNITEFLESH;
+ break;
+ case 7:
+ Breath1_Spell = SPELL_TIMELAPSE;
+ Breath2_Spell = SPELL_FROSTBURN;
+ break;
+
+ //B1 - Acid
+ case 8:
+ Breath1_Spell = SPELL_CORROSIVEACID;
+ Breath2_Spell = SPELL_INCINERATE;
+ break;
+ case 9:
+ Breath1_Spell = SPELL_CORROSIVEACID;
+ Breath2_Spell = SPELL_TIMELAPSE;
+ break;
+ case 10:
+ Breath1_Spell = SPELL_CORROSIVEACID;
+ Breath2_Spell = SPELL_IGNITEFLESH;
+ break;
+ case 11:
+ Breath1_Spell = SPELL_CORROSIVEACID;
+ Breath2_Spell = SPELL_FROSTBURN;
+ break;
+
+ //B1 - Ignite
+ case 12:
+ Breath1_Spell = SPELL_IGNITEFLESH;
+ Breath2_Spell = SPELL_INCINERATE;
+ break;
+ case 13:
+ Breath1_Spell = SPELL_IGNITEFLESH;
+ Breath2_Spell = SPELL_CORROSIVEACID;
+ break;
+ case 14:
+ Breath1_Spell = SPELL_IGNITEFLESH;
+ Breath2_Spell = SPELL_TIMELAPSE;
+ break;
+ case 15:
+ Breath1_Spell = SPELL_IGNITEFLESH;
+ Breath2_Spell = SPELL_FROSTBURN;
+ break;
+
+ //B1 - Frost
+ case 16:
+ Breath1_Spell = SPELL_FROSTBURN;
+ Breath2_Spell = SPELL_INCINERATE;
+ break;
+ case 17:
+ Breath1_Spell = SPELL_FROSTBURN;
+ Breath2_Spell = SPELL_TIMELAPSE;
+ break;
+ case 18:
+ Breath1_Spell = SPELL_FROSTBURN;
+ Breath2_Spell = SPELL_CORROSIVEACID;
+ break;
+ case 19:
+ Breath1_Spell = SPELL_FROSTBURN;
+ Breath2_Spell = SPELL_IGNITEFLESH;
+ break;
+ };
+
+ EnterEvadeMode();
+ }
+
+ uint32 Breath1_Spell;
+ uint32 Breath2_Spell;
+ uint32 CurrentVurln_Spell;
+
+ uint32 Shimmer_Timer;
+ uint32 Breath1_Timer;
+ uint32 Breath2_Timer;
+ uint32 Affliction_Timer;
+ uint32 Frenzy_Timer;
+ bool Enraged;
+
+ void Reset()
+ {
+ CurrentVurln_Spell = 0; //We use this to store our last vurlnability spell so we can remove it later
+
+ Shimmer_Timer = 0; //Time till we change vurlnerabilites
+ Breath1_Timer = 30000; //First breath is 30 seconds
+ Breath2_Timer = 60000; //Second is 1 minute so that we can alternate
+ Affliction_Timer = 10000; //This is special - 5 seconds means that we cast this on 1 pPlayer every 5 sconds
+ Frenzy_Timer = 15000;
+
+ Enraged = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Shimmer_Timer Timer
+ if (Shimmer_Timer < diff)
+ {
+ //Remove old vurlnability spell
+ if (CurrentVurln_Spell)
+ m_creature->RemoveAurasDueToSpell(CurrentVurln_Spell);
+
+ //Cast new random vurlnabilty on self
+ uint32 spell;
+ switch(urand(0, 4))
+ {
+ case 0: spell = SPELL_FIRE_VURNALBILTY; break;
+ case 1: spell = SPELL_FROST_VURNALBILTY; break;
+ case 2: spell = SPELL_SHADOW_VURNALBILTY; break;
+ case 3: spell = SPELL_NATURE_VURNALBILTY; break;
+ case 4: spell = SPELL_ARCANE_VURNALBILTY; break;
+ }
+
+ if (DoCastSpellIfCan(m_creature, spell) == CAST_OK)
+ {
+ CurrentVurln_Spell = spell;
+
+ DoScriptText(EMOTE_SHIMMER, m_creature);
+ Shimmer_Timer = 45000;
+ }
+ }else Shimmer_Timer -= diff;
+
+ //Breath1_Timer
+ if (Breath1_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),Breath1_Spell);
+ Breath1_Timer = 60000;
+ }else Breath1_Timer -= diff;
+
+ //Breath2_Timer
+ if (Breath2_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),Breath2_Spell);
+ Breath2_Timer = 60000;
+ }else Breath2_Timer -= diff;
+
+ //Affliction_Timer
+ if (Affliction_Timer < diff)
+ {
+ uint32 SpellAfflict = 0;
+
+ switch(urand(0, 4))
+ {
+ case 0: SpellAfflict = SPELL_BROODAF_BLUE; break;
+ case 1: SpellAfflict = SPELL_BROODAF_BLACK; break;
+ case 2: SpellAfflict = SPELL_BROODAF_RED; break;
+ case 3: SpellAfflict = SPELL_BROODAF_BRONZE; break;
+ case 4: SpellAfflict = SPELL_BROODAF_GREEN; break;
+ }
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ if (pUnit)
+ {
+ //Cast affliction
+ DoCastSpellIfCan(pUnit, SpellAfflict, CAST_TRIGGERED);
+
+ //Chromatic mutation if target is effected by all afflictions
+ if (pUnit->HasAura(SPELL_BROODAF_BLUE, EFFECT_INDEX_0)
+ && pUnit->HasAura(SPELL_BROODAF_BLACK, EFFECT_INDEX_0)
+ && pUnit->HasAura(SPELL_BROODAF_RED, EFFECT_INDEX_0)
+ && pUnit->HasAura(SPELL_BROODAF_BRONZE, EFFECT_INDEX_0)
+ && pUnit->HasAura(SPELL_BROODAF_GREEN, EFFECT_INDEX_0))
+ {
+ //target->RemoveAllAuras();
+ //DoCastSpellIfCan(target,SPELL_CHROMATIC_MUT_1);
+
+ //Chromatic mutation is causing issues
+ //Assuming it is caused by a lack of core support for Charm
+ //So instead we instant kill our target
+
+ //WORKAROUND
+ if (pUnit->GetTypeId() == TYPEID_PLAYER)
+ pUnit->CastSpell(pUnit, 5, false);
+ }
+ }
+ }
+
+ Affliction_Timer = 10000;
+ }else Affliction_Timer -= diff;
+
+ //Frenzy_Timer
+ if (Frenzy_Timer < diff)
+ {
+ if (DoCastSpellIfCan(m_creature,SPELL_FRENZY) == CAST_OK)
+ {
+ DoScriptText(EMOTE_GENERIC_FRENZY_KILL, m_creature);
+ Frenzy_Timer = urand(10000, 15000);
+ }
+ }else Frenzy_Timer -= diff;
+
+ //Enrage if not already enraged and below 20%
+ if (!Enraged && m_creature->GetHealthPercent() < 20.0f)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_ENRAGE);
+ Enraged = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_chromaggus(Creature* pCreature)
+{
+ return new boss_chromaggusAI(pCreature);
+}
+
+void AddSC_boss_chromaggus()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_chromaggus";
+ newscript->GetAI = &GetAI_boss_chromaggus;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp
new file mode 100644
index 0000000..cae016c
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp
@@ -0,0 +1,103 @@
+/* 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_Ebonroc
+SD%Complete: 50
+SDComment: Shadow of Ebonroc needs core support
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_SHADOWFLAME 22539
+#define SPELL_WINGBUFFET 18500
+#define SPELL_SHADOWOFEBONROC 23340
+#define SPELL_HEAL 41386 //Thea Heal spell of his Shadow
+
+struct MANGOS_DLL_DECL boss_ebonrocAI : public ScriptedAI
+{
+ boss_ebonrocAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ShadowFlame_Timer;
+ uint32 WingBuffet_Timer;
+ uint32 ShadowOfEbonroc_Timer;
+ uint32 Heal_Timer;
+
+ void Reset()
+ {
+ ShadowFlame_Timer = 15000; //These times are probably wrong
+ WingBuffet_Timer = 30000;
+ ShadowOfEbonroc_Timer = 45000;
+ Heal_Timer = 1000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Shadowflame Timer
+ if (ShadowFlame_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWFLAME);
+ ShadowFlame_Timer = urand(12000, 15000);
+ }else ShadowFlame_Timer -= diff;
+
+ //Wing Buffet Timer
+ if (WingBuffet_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_WINGBUFFET);
+ WingBuffet_Timer = 25000;
+ }else WingBuffet_Timer -= diff;
+
+ //Shadow of Ebonroc Timer
+ if (ShadowOfEbonroc_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWOFEBONROC);
+ ShadowOfEbonroc_Timer = urand(25000, 35000);
+ }else ShadowOfEbonroc_Timer -= diff;
+
+ if (m_creature->getVictim()->HasAura(SPELL_SHADOWOFEBONROC, EFFECT_INDEX_0))
+ {
+ if (Heal_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HEAL);
+ Heal_Timer = urand(1000, 3000);
+ }else Heal_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_ebonroc(Creature* pCreature)
+{
+ return new boss_ebonrocAI(pCreature);
+}
+
+void AddSC_boss_ebonroc()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_ebonroc";
+ newscript->GetAI = &GetAI_boss_ebonroc;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp
new file mode 100644
index 0000000..e246b3c
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp
@@ -0,0 +1,94 @@
+/* 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_Firemaw
+SD%Complete: 100
+SDComment:
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_SHADOWFLAME 22539
+#define SPELL_WINGBUFFET 23339
+#define SPELL_FLAMEBUFFET 23341
+
+struct MANGOS_DLL_DECL boss_firemawAI : public ScriptedAI
+{
+ boss_firemawAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ShadowFlame_Timer;
+ uint32 WingBuffet_Timer;
+ uint32 FlameBuffet_Timer;
+
+ void Reset()
+ {
+ ShadowFlame_Timer = 30000; //These times are probably wrong
+ WingBuffet_Timer = 24000;
+ FlameBuffet_Timer = 5000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowFlame_Timer
+ if (ShadowFlame_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWFLAME);
+ ShadowFlame_Timer = urand(15000, 18000);
+ }else ShadowFlame_Timer -= diff;
+
+ //WingBuffet_Timer
+ if (WingBuffet_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_WINGBUFFET);
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-75);
+
+ WingBuffet_Timer = 25000;
+ }else WingBuffet_Timer -= diff;
+
+ //FlameBuffet_Timer
+ if (FlameBuffet_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FLAMEBUFFET);
+ FlameBuffet_Timer = 5000;
+ }else FlameBuffet_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_firemaw(Creature* pCreature)
+{
+ return new boss_firemawAI(pCreature);
+}
+
+void AddSC_boss_firemaw()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_firemaw";
+ newscript->GetAI = &GetAI_boss_firemaw;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp
new file mode 100644
index 0000000..0c11c6d
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp
@@ -0,0 +1,102 @@
+/* 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_Flamegor
+SD%Complete: 100
+SDComment:
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ EMOTE_GENERIC_FRENZY = -1000002,
+
+ SPELL_SHADOWFLAME = 22539,
+ SPELL_WINGBUFFET = 23339,
+ SPELL_FRENZY = 23342 //This spell periodically triggers fire nova
+};
+
+struct MANGOS_DLL_DECL boss_flamegorAI : public ScriptedAI
+{
+ boss_flamegorAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ShadowFlame_Timer;
+ uint32 WingBuffet_Timer;
+ uint32 Frenzy_Timer;
+
+ void Reset()
+ {
+ ShadowFlame_Timer = 21000; //These times are probably wrong
+ WingBuffet_Timer = 35000;
+ Frenzy_Timer = 10000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowFlame_Timer
+ if (ShadowFlame_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWFLAME);
+ ShadowFlame_Timer = urand(15000, 22000);
+ }else ShadowFlame_Timer -= diff;
+
+ //WingBuffet_Timer
+ if (WingBuffet_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_WINGBUFFET);
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-75);
+
+ WingBuffet_Timer = 25000;
+ }else WingBuffet_Timer -= diff;
+
+ //Frenzy_Timer
+ if (Frenzy_Timer < diff)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK)
+ {
+ DoScriptText(EMOTE_GENERIC_FRENZY, m_creature);
+ Frenzy_Timer = urand(8000, 10000);
+ }
+ }else Frenzy_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_flamegor(Creature* pCreature)
+{
+ return new boss_flamegorAI(pCreature);
+}
+
+void AddSC_boss_flamegor()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_flamegor";
+ newscript->GetAI = &GetAI_boss_flamegor;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp
new file mode 100644
index 0000000..355f66c
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp
@@ -0,0 +1,225 @@
+/* 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_Nefarian
+SD%Complete: 80
+SDComment: Some issues with class calls effecting more than one class
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_AGGRO -1469007
+#define SAY_XHEALTH -1469008
+#define SAY_SHADOWFLAME -1469009
+#define SAY_RAISE_SKELETONS -1469010
+#define SAY_SLAY -1469011
+#define SAY_DEATH -1469012
+
+#define SAY_MAGE -1469013
+#define SAY_WARRIOR -1469014
+#define SAY_DRUID -1469015
+#define SAY_PRIEST -1469016
+#define SAY_PALADIN -1469017
+#define SAY_SHAMAN -1469018
+#define SAY_WARLOCK -1469019
+#define SAY_HUNTER -1469020
+#define SAY_ROGUE -1469021
+
+#define SPELL_SHADOWFLAME_INITIAL 22972
+#define SPELL_SHADOWFLAME 22539
+#define SPELL_BELLOWINGROAR 22686
+#define SPELL_VEILOFSHADOW 7068
+#define SPELL_CLEAVE 20691
+#define SPELL_TAILLASH 23364
+#define SPELL_BONECONTRUST 23363 //23362, 23361
+
+#define SPELL_MAGE 23410 //wild magic
+#define SPELL_WARRIOR 23397 //beserk
+#define SPELL_DRUID 23398 // cat form
+#define SPELL_PRIEST 23401 // corrupted healing
+#define SPELL_PALADIN 23418 //syphon blessing
+#define SPELL_SHAMAN 23425 //totems
+#define SPELL_WARLOCK 23427 //infernals
+#define SPELL_HUNTER 23436 //bow broke
+#define SPELL_ROGUE 23414 //Paralise
+
+struct MANGOS_DLL_DECL boss_nefarianAI : public ScriptedAI
+{
+ boss_nefarianAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ShadowFlame_Timer;
+ uint32 BellowingRoar_Timer;
+ uint32 VeilOfShadow_Timer;
+ uint32 Cleave_Timer;
+ uint32 TailLash_Timer;
+ uint32 ClassCall_Timer;
+ bool Phase3;
+
+ void Reset()
+ {
+ ShadowFlame_Timer = 12000; //These times are probably wrong
+ BellowingRoar_Timer = 30000;
+ VeilOfShadow_Timer = 15000;
+ Cleave_Timer = 7000;
+ TailLash_Timer = 10000;
+ ClassCall_Timer = 35000; //35-40 seconds
+ Phase3 = false;
+ }
+
+ void KilledUnit(Unit* Victim)
+ {
+ if (urand(0, 4))
+ return;
+
+ DoScriptText(SAY_SLAY, m_creature, Victim);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ switch(urand(0, 3))
+ {
+ case 0: DoScriptText(SAY_XHEALTH, m_creature); break;
+ case 1: DoScriptText(SAY_AGGRO, m_creature); break;
+ case 2: DoScriptText(SAY_SHADOWFLAME, m_creature); break;
+ }
+
+ DoCastSpellIfCan(pWho,SPELL_SHADOWFLAME_INITIAL);
+
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowFlame_Timer
+ if (ShadowFlame_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWFLAME);
+ ShadowFlame_Timer = 12000;
+ }else ShadowFlame_Timer -= diff;
+
+ //BellowingRoar_Timer
+ if (BellowingRoar_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BELLOWINGROAR);
+ BellowingRoar_Timer = 30000;
+ }else BellowingRoar_Timer -= diff;
+
+ //VeilOfShadow_Timer
+ if (VeilOfShadow_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_VEILOFSHADOW);
+ VeilOfShadow_Timer = 15000;
+ }else VeilOfShadow_Timer -= diff;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = 7000;
+ }else Cleave_Timer -= diff;
+
+ //TailLash_Timer
+ if (TailLash_Timer < diff)
+ {
+ //Cast NYI since we need a better check for behind target
+ //DoCastSpellIfCan(m_creature->getVictim(),SPELL_TAILLASH);
+
+ TailLash_Timer = 10000;
+ }else TailLash_Timer -= diff;
+
+ //ClassCall_Timer
+ if (ClassCall_Timer < diff)
+ {
+ //Cast a random class call
+ //On official it is based on what classes are currently on the hostil list
+ //but we can't do that yet so just randomly call one
+
+ switch(urand(0, 8))
+ {
+ case 0:
+ DoScriptText(SAY_MAGE, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_MAGE);
+ break;
+ case 1:
+ DoScriptText(SAY_WARRIOR, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_WARRIOR);
+ break;
+ case 2:
+ DoScriptText(SAY_DRUID, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_DRUID);
+ break;
+ case 3:
+ DoScriptText(SAY_PRIEST, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_PRIEST);
+ break;
+ case 4:
+ DoScriptText(SAY_PALADIN, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_PALADIN);
+ break;
+ case 5:
+ DoScriptText(SAY_SHAMAN, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_SHAMAN);
+ break;
+ case 6:
+ DoScriptText(SAY_WARLOCK, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_WARLOCK);
+ break;
+ case 7:
+ DoScriptText(SAY_HUNTER, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_HUNTER);
+ break;
+ case 8:
+ DoScriptText(SAY_ROGUE, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_ROGUE);
+ break;
+ }
+
+ ClassCall_Timer = urand(35000, 40000);
+ }else ClassCall_Timer -= diff;
+
+ //Phase3 begins when we are below X health
+ if (!Phase3 && m_creature->GetHealthPercent() < 20.0f)
+ {
+ Phase3 = true;
+ DoScriptText(SAY_RAISE_SKELETONS, m_creature);
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_nefarian(Creature* pCreature)
+{
+ return new boss_nefarianAI(pCreature);
+}
+
+void AddSC_boss_nefarian()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_nefarian";
+ newscript->GetAI = &GetAI_boss_nefarian;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp
new file mode 100644
index 0000000..e6ac0fb
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp
@@ -0,0 +1,138 @@
+/* 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_Razorgore
+SD%Complete: 50
+SDComment: Needs additional review. Phase 1 NYI (Grethok the Controller)
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+//Razorgore Phase 2 Script
+enum
+{
+ SAY_EGGS_BROKEN1 = -1469022,
+ SAY_EGGS_BROKEN2 = -1469023,
+ SAY_EGGS_BROKEN3 = -1469024,
+ SAY_DEATH = -1469025,
+
+ SPELL_CLEAVE = 19632,
+ SPELL_WARSTOMP = 24375,
+ SPELL_FIREBALLVOLLEY = 22425,
+ SPELL_CONFLAGRATION = 23023
+};
+
+struct MANGOS_DLL_DECL boss_razorgoreAI : public ScriptedAI
+{
+ boss_razorgoreAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiCleaveTimer;
+ uint32 m_uiWarStompTimer;
+ uint32 m_uiFireballVolleyTimer;
+ uint32 m_uiConflagrationTimer;
+
+ void Reset()
+ {
+ m_uiCleaveTimer = 15000; //These times are probably wrong
+ m_uiWarStompTimer = 35000;
+ m_uiConflagrationTimer = 12000;
+ m_uiFireballVolleyTimer = 7000;
+
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Cleave
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleaveTimer = urand(7000, 10000);
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ // WarStomp
+ if (m_uiWarStompTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_WARSTOMP);
+ m_uiWarStompTimer = urand(15000, 25000);
+ }
+ else
+ m_uiWarStompTimer -= uiDiff;
+
+ // Fireball Volley
+ if (m_uiFireballVolleyTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FIREBALLVOLLEY);
+ m_uiFireballVolleyTimer = urand(12000, 15000);
+ }
+ else
+ m_uiFireballVolleyTimer -= uiDiff;
+
+ // Conflagration
+ if (m_uiConflagrationTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CONFLAGRATION);
+ //We will remove this threat reduction and add an aura check.
+
+ //if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ //m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50);
+
+ m_uiConflagrationTimer = 12000;
+ }
+ else
+ m_uiConflagrationTimer -= uiDiff;
+
+ // Aura Check. If the gamer is affected by confliguration we attack a random gamer.
+ if (m_creature->getVictim()->HasAura(SPELL_CONFLAGRATION, EFFECT_INDEX_0))
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
+ m_creature->TauntApply(pTarget);
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_razorgore(Creature* pCreature)
+{
+ return new boss_razorgoreAI(pCreature);
+}
+
+void AddSC_boss_razorgore()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_razorgore";
+ newscript->GetAI = &GetAI_boss_razorgore;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp
new file mode 100644
index 0000000..3fb679f
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp
@@ -0,0 +1,259 @@
+/* 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_Vaelastrasz
+SD%Complete: 75
+SDComment: Burning Adrenaline not correctly implemented in core
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_LINE1 -1469026
+#define SAY_LINE2 -1469027
+#define SAY_LINE3 -1469028
+#define SAY_HALFLIFE -1469029
+#define SAY_KILLTARGET -1469030
+
+#define GOSSIP_ITEM "Start Event "
+
+#define SPELL_ESSENCEOFTHERED 23513
+#define SPELL_FLAMEBREATH 23461
+#define SPELL_FIRENOVA 23462
+#define SPELL_TAILSWIPE 15847
+#define SPELL_BURNINGADRENALINE 23620
+#define SPELL_CLEAVE 20684 //Chain cleave is most likely named something different and contains a dummy effect
+
+struct MANGOS_DLL_DECL boss_vaelAI : public ScriptedAI
+{
+ boss_vaelAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ pCreature->setFaction(35);
+ pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ Reset();
+ }
+
+ uint64 PlayerGUID;
+ uint32 SpeachTimer;
+ uint32 SpeachNum;
+ uint32 Cleave_Timer;
+ uint32 FlameBreath_Timer;
+ uint32 FireNova_Timer;
+ uint32 BurningAdrenalineCaster_Timer;
+ uint32 BurningAdrenalineTank_Timer;
+ uint32 TailSwipe_Timer;
+ bool HasYelled;
+ bool DoingSpeach;
+
+ void Reset()
+ {
+ PlayerGUID = 0;
+ SpeachTimer = 0;
+ SpeachNum = 0;
+ Cleave_Timer = 8000; //These times are probably wrong
+ FlameBreath_Timer = 11000;
+ BurningAdrenalineCaster_Timer = 15000;
+ BurningAdrenalineTank_Timer = 45000;
+ FireNova_Timer = 5000;
+ TailSwipe_Timer = 20000;
+ HasYelled = false;
+ DoingSpeach = false;
+ }
+
+ void BeginSpeach(Unit* target)
+ {
+ //Stand up and begin speach
+ PlayerGUID = target->GetGUID();
+
+ //10 seconds
+ DoScriptText(SAY_LINE1, m_creature);
+
+ SpeachTimer = 10000;
+ SpeachNum = 0;
+ DoingSpeach = true;
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ if (urand(0, 4))
+ return;
+
+ DoScriptText(SAY_KILLTARGET, m_creature, victim);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_ESSENCEOFTHERED);
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Speach
+ if (DoingSpeach)
+ {
+ if (SpeachTimer < diff)
+ {
+ switch (SpeachNum)
+ {
+ case 0:
+ //16 seconds till next line
+ DoScriptText(SAY_LINE2, m_creature);
+ SpeachTimer = 16000;
+ ++SpeachNum;
+ break;
+ case 1:
+ //This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!"
+ DoScriptText(SAY_LINE3, m_creature);
+ SpeachTimer = 10000;
+ ++SpeachNum;
+ break;
+ case 2:
+ m_creature->setFaction(103);
+ m_creature->SetHealth(int(m_creature->GetMaxHealth()*.3));
+
+ if (PlayerGUID)
+ {
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(PlayerGUID))
+ AttackStart(pPlayer);
+
+ DoCastSpellIfCan(m_creature, SPELL_ESSENCEOFTHERED);
+ }
+ SpeachTimer = 0;
+ DoingSpeach = false;
+ break;
+ }
+ }else SpeachTimer -= diff;
+ }
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Yell if hp lower than 15%
+ if (m_creature->GetHealthPercent() < 15.0f && !HasYelled)
+ {
+ DoScriptText(SAY_HALFLIFE, m_creature);
+ HasYelled = true;
+ }
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = 15000;
+ }else Cleave_Timer -= diff;
+
+ //FlameBreath_Timer
+ if (FlameBreath_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FLAMEBREATH);
+ FlameBreath_Timer = urand(4000, 8000);
+ }else FlameBreath_Timer -= diff;
+
+ //BurningAdrenalineCaster_Timer
+ if (BurningAdrenalineCaster_Timer < diff)
+ {
+ Unit* target = NULL;
+
+ int i = 0 ;
+ while (i < 3) // max 3 tries to get a random target with power_mana
+ {
+ ++i;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1);//not aggro leader
+ if (target)
+ if (target->getPowerType() == POWER_MANA)
+ i=3;
+ }
+ if (target) // cast on self (see below)
+ target->CastSpell(target,SPELL_BURNINGADRENALINE,1);
+
+ BurningAdrenalineCaster_Timer = 15000;
+ }else BurningAdrenalineCaster_Timer -= diff;
+
+ //BurningAdrenalineTank_Timer
+ if (BurningAdrenalineTank_Timer < diff)
+ {
+ // have the victim cast the spell on himself otherwise the third effect aura will be applied
+ // to Vael instead of the player
+ m_creature->getVictim()->CastSpell(m_creature->getVictim(),SPELL_BURNINGADRENALINE,1);
+
+ BurningAdrenalineTank_Timer = 45000;
+ }else BurningAdrenalineTank_Timer -= diff;
+
+ //FireNova_Timer
+ if (FireNova_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FIRENOVA);
+ FireNova_Timer = 5000;
+ }else FireNova_Timer -= diff;
+
+ //TailSwipe_Timer
+ if (TailSwipe_Timer < diff)
+ {
+ //Only cast if we are behind
+ /*if (!m_creature->HasInArc(M_PI, m_creature->getVictim()))
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_TAILSWIPE);
+ }*/
+
+ TailSwipe_Timer = 20000;
+ }else TailSwipe_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool GossipSelect_boss_vael(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF + 1) //Fight time
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (boss_vaelAI* pVaelAI = dynamic_cast(pCreature->AI()))
+ pVaelAI->BeginSpeach((Unit*)pPlayer);
+ }
+
+ return true;
+}
+
+bool GossipHello_boss_vael(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID());
+
+ return true;
+}
+
+CreatureAI* GetAI_boss_vael(Creature* pCreature)
+{
+ return new boss_vaelAI(pCreature);
+}
+
+void AddSC_boss_vael()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_vaelastrasz";
+ newscript->GetAI = &GetAI_boss_vael;
+ newscript->pGossipHello = &GossipHello_boss_vael;
+ newscript->pGossipSelect = &GossipSelect_boss_vael;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp b/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp
new file mode 100644
index 0000000..e47cd58
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp
@@ -0,0 +1,387 @@
+/* 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_Victor_Nefarius
+SD%Complete: 75
+SDComment: Missing some text, Vael beginning event, and spawns Nef in wrong place
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_GAMESBEGIN_1 -1469004
+#define SAY_GAMESBEGIN_2 -1469005
+#define SAY_VAEL_INTRO -1469006 //when he corrupts Vaelastrasz
+
+#define GOSSIP_ITEM_1 "I've made no mistakes."
+#define GOSSIP_ITEM_2 "You have lost your mind, Nefarius. You speak in riddles."
+#define GOSSIP_ITEM_3 "Please do."
+
+#define CREATURE_BRONZE_DRAKANOID 14263
+#define CREATURE_BLUE_DRAKANOID 14261
+#define CREATURE_RED_DRAKANOID 14264
+#define CREATURE_GREEN_DRAKANOID 14262
+#define CREATURE_BLACK_DRAKANOID 14265
+
+#define CREATURE_CHROMATIC_DRAKANOID 14302
+#define CREATURE_NEFARIAN 11583
+
+#define ADD_X1 -7591.151855f
+#define ADD_X2 -7514.598633f
+#define ADD_Y1 -1204.051880f
+#define ADD_Y2 -1150.448853f
+#define ADD_Z1 476.800476f
+#define ADD_Z2 476.796570f
+
+#define NEF_X -7445.0f
+#define NEF_Y -1332.0f
+#define NEF_Z 536.0f
+
+#define HIDE_X -7592.0f
+#define HIDE_Y -1264.0f
+#define HIDE_Z 481.0f
+
+#define SPELL_SHADOWBOLT 21077
+#define SPELL_FEAR 26070
+
+//This script is complicated
+//Instead of morphing Victor Nefarius we will have him control phase 1
+//And then have him spawn "Nefarian" for phase 2
+//When phase 2 starts Victor Nefarius will go into hiding and stop attacking
+//If Nefarian despawns because he killed the players then this guy will EnterEvadeMode
+//and allow players to start the event over
+//If nefarian dies then he will kill himself then he will kill himself in his hiding place
+//To prevent players from doing the event twice
+
+struct MANGOS_DLL_DECL boss_victor_nefariusAI : public ScriptedAI
+{
+ boss_victor_nefariusAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ NefarianGUID = 0;
+ Reset();
+ srand(time(NULL));
+ switch(urand(0, 19))
+ {
+ case 0:
+ DrakType1 = CREATURE_BRONZE_DRAKANOID;
+ DrakType2 = CREATURE_BLUE_DRAKANOID;
+ break;
+ case 1:
+ DrakType1 = CREATURE_BRONZE_DRAKANOID;
+ DrakType2 = CREATURE_RED_DRAKANOID;
+ break;
+ case 2:
+ DrakType1 = CREATURE_BRONZE_DRAKANOID;
+ DrakType2 = CREATURE_GREEN_DRAKANOID;
+ break;
+ case 3:
+ DrakType1 = CREATURE_BRONZE_DRAKANOID;
+ DrakType2 = CREATURE_BLACK_DRAKANOID;
+ break;
+ case 4:
+ DrakType1 = CREATURE_BLUE_DRAKANOID;
+ DrakType2 = CREATURE_BRONZE_DRAKANOID;
+ break;
+ case 5:
+ DrakType1 = CREATURE_BLUE_DRAKANOID;
+ DrakType2 = CREATURE_RED_DRAKANOID;
+ break;
+ case 6:
+ DrakType1 = CREATURE_BLUE_DRAKANOID;
+ DrakType2 = CREATURE_GREEN_DRAKANOID;
+ break;
+ case 7:
+ DrakType1 = CREATURE_BLUE_DRAKANOID;
+ DrakType2 = CREATURE_BLACK_DRAKANOID;
+ break;
+ case 8:
+ DrakType1 = CREATURE_RED_DRAKANOID;
+ DrakType2 = CREATURE_BRONZE_DRAKANOID;
+ break;
+ case 9:
+ DrakType1 = CREATURE_RED_DRAKANOID;
+ DrakType2 = CREATURE_BLUE_DRAKANOID;
+ break;
+ case 10:
+ DrakType1 = CREATURE_RED_DRAKANOID;
+ DrakType2 = CREATURE_GREEN_DRAKANOID;
+ break;
+ case 11:
+ DrakType1 = CREATURE_RED_DRAKANOID;
+ DrakType2 = CREATURE_BLACK_DRAKANOID;
+ break;
+ case 12:
+ DrakType1 = CREATURE_GREEN_DRAKANOID;
+ DrakType2 = CREATURE_BRONZE_DRAKANOID;
+ break;
+ case 13:
+ DrakType1 = CREATURE_GREEN_DRAKANOID;
+ DrakType2 = CREATURE_BLUE_DRAKANOID;
+ break;
+ case 14:
+ DrakType1 = CREATURE_GREEN_DRAKANOID;
+ DrakType2 = CREATURE_RED_DRAKANOID;
+ break;
+ case 15:
+ DrakType1 = CREATURE_GREEN_DRAKANOID;
+ DrakType2 = CREATURE_BLACK_DRAKANOID;
+ break;
+ case 16:
+ DrakType1 = CREATURE_BLACK_DRAKANOID;
+ DrakType2 = CREATURE_BRONZE_DRAKANOID;
+ break;
+ case 17:
+ DrakType1 = CREATURE_BLACK_DRAKANOID;
+ DrakType2 = CREATURE_BLUE_DRAKANOID;
+ break;
+ case 18:
+ DrakType1 = CREATURE_BLACK_DRAKANOID;
+ DrakType2 = CREATURE_GREEN_DRAKANOID;
+ break;
+ case 19:
+ DrakType1 = CREATURE_BLACK_DRAKANOID;
+ DrakType2 = CREATURE_RED_DRAKANOID;
+ break;
+ }
+ }
+
+ uint32 SpawnedAdds;
+ uint32 AddSpawnTimer;
+ uint32 ShadowBoltTimer;
+ uint32 FearTimer;
+ uint32 MindControlTimer;
+ uint32 ResetTimer;
+ uint32 DrakType1;
+ uint32 DrakType2;
+ uint64 NefarianGUID;
+ uint32 NefCheckTime;
+
+ void Reset()
+ {
+ SpawnedAdds = 0;
+ AddSpawnTimer = 10000;
+ ShadowBoltTimer = 5000;
+ FearTimer = 8000;
+ ResetTimer = 900000; //On official it takes him 15 minutes(900 seconds) to reset. We are only doing 1 minute to make testing easier
+ NefarianGUID = 0;
+ NefCheckTime = 2000;
+
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS,1);
+ m_creature->setFaction(35);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void BeginEvent(Player* target)
+ {
+ DoScriptText(SAY_GAMESBEGIN_2, m_creature);
+
+ //MaNGOS::Singleton::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin();
+ /*
+ list ::iterator i = MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin();
+
+ for (i = MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().begin(); i != MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->GetPlayers().end(); ++i)
+ {
+ AttackStart((*i));
+ }
+ */
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS,0);
+ m_creature->setFaction(103);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ AttackStart(target);
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ //We simply use this function to find players until we can use Map->GetPlayers()
+
+ if (who && who->GetTypeId() == TYPEID_PLAYER && m_creature->IsHostileTo(who))
+ {
+ //Add them to our threat list
+ m_creature->AddThreat(who);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Only do this if we haven't spawned nef yet
+ if (SpawnedAdds < 42)
+ {
+ //ShadowBoltTimer
+ if (ShadowBoltTimer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target)
+ DoCastSpellIfCan(target,SPELL_SHADOWBOLT);
+
+ ShadowBoltTimer = urand(3000, 10000);
+ }else ShadowBoltTimer -= diff;
+
+ //FearTimer
+ if (FearTimer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target)
+ DoCastSpellIfCan(target,SPELL_FEAR);
+
+ FearTimer = urand(10000, 20000);
+ }else FearTimer -= diff;
+
+ //Add spawning mechanism
+ if (AddSpawnTimer < diff)
+ {
+ //Spawn 2 random types of creatures at the 2 locations
+ uint32 CreatureID;
+ Creature* Spawned = NULL;
+ Unit* target = NULL;
+
+ //1 in 3 chance it will be a chromatic
+ if (!urand(0, 2))
+ CreatureID = CREATURE_CHROMATIC_DRAKANOID;
+ else CreatureID = DrakType1;
+
+ ++SpawnedAdds;
+
+ //Spawn creature and force it to start attacking a random target
+ Spawned = m_creature->SummonCreature(CreatureID,ADD_X1,ADD_Y1,ADD_Z1,5.000f,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000);
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target && Spawned)
+ {
+ Spawned->AI()->AttackStart(target);
+ Spawned->setFaction(103);
+ }
+
+ //1 in 3 chance it will be a chromatic
+ if (!urand(0, 2))
+ CreatureID = CREATURE_CHROMATIC_DRAKANOID;
+ else CreatureID = DrakType2;
+
+ ++SpawnedAdds;
+
+ target = NULL;
+ Spawned = NULL;
+ Spawned = m_creature->SummonCreature(CreatureID,ADD_X2,ADD_Y2,ADD_Z2,5.000,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000);
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target && Spawned)
+ {
+ Spawned->AI()->AttackStart(target);
+ Spawned->setFaction(103);
+ }
+
+ //Begin phase 2 by spawning Nefarian and what not
+ if (SpawnedAdds >= 42)
+ {
+ //Teleport Victor Nefarius way out of the map
+ //MapManager::Instance().GetMap(m_creature->GetMapId(), m_creature)->CreatureRelocation(m_creature,0,0,-5000,0);
+
+ //Inturrupt any spell casting
+ m_creature->InterruptNonMeleeSpells(false);
+
+ //Root self
+ DoCastSpellIfCan(m_creature,33356);
+
+ //Make super invis
+ DoCastSpellIfCan(m_creature,8149);
+
+ //Teleport self to a hiding spot
+ m_creature->NearTeleportTo(HIDE_X, HIDE_Y, HIDE_Z, 0.0f);
+
+ //Spawn nef and have him attack a random target
+ Creature* Nefarian = m_creature->SummonCreature(CREATURE_NEFARIAN,NEF_X,NEF_Y,NEF_Z,0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,120000);
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+
+ if (target && Nefarian)
+ {
+ Nefarian->AI()->AttackStart(target);
+ Nefarian->setFaction(103);
+ NefarianGUID = Nefarian->GetGUID();
+ }
+ else error_log("SD2: Blackwing Lair: Unable to spawn nefarian properly.");
+ }
+
+ AddSpawnTimer = 4000;
+ }else AddSpawnTimer -= diff;
+ }
+ else if (NefarianGUID)
+ {
+ if (NefCheckTime < diff)
+ {
+ Creature* pNefarian = m_creature->GetMap()->GetCreature(NefarianGUID);
+
+ //If nef is dead then we die to so the players get out of combat
+ //and cannot repeat the event
+ if (!pNefarian || !pNefarian->isAlive())
+ {
+ NefarianGUID = 0;
+ m_creature->ForcedDespawn();
+ }
+
+ NefCheckTime = 2000;
+ }else NefCheckTime -= diff;
+ }
+ }
+};
+
+CreatureAI* GetAI_boss_victor_nefarius(Creature* pCreature)
+{
+ return new boss_victor_nefariusAI(pCreature);
+}
+
+bool GossipHello_boss_victor_nefarius(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1 , GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(7134, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_boss_victor_nefarius(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(7198, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->SEND_GOSSIP_MENU(7199, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ DoScriptText(SAY_GAMESBEGIN_1, pCreature);
+ if (boss_victor_nefariusAI* pNefAI = dynamic_cast(pCreature->AI()))
+ pNefAI->BeginEvent(pPlayer);
+ break;
+ }
+ return true;
+}
+
+void AddSC_boss_victor_nefarius()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_victor_nefarius";
+ newscript->GetAI = &GetAI_boss_victor_nefarius;
+ newscript->pGossipHello = &GossipHello_boss_victor_nefarius;
+ newscript->pGossipSelect = &GossipSelect_boss_victor_nefarius;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp b/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp
new file mode 100644
index 0000000..6a0a8bb
--- /dev/null
+++ b/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp
@@ -0,0 +1,24 @@
+/* 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_Blackwing_Lair
+SD%Complete: 0
+SDComment:
+SDCategory: Blackwing Lair
+EndScriptData */
+
+#include "precompiled.h"
diff --git a/scripts/eastern_kingdoms/blasted_lands.cpp b/scripts/eastern_kingdoms/blasted_lands.cpp
new file mode 100644
index 0000000..65a9555
--- /dev/null
+++ b/scripts/eastern_kingdoms/blasted_lands.cpp
@@ -0,0 +1,159 @@
+/* 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: Blasted_Lands
+SD%Complete: 90
+SDComment: Quest support: 2784, 2801, 3628. Missing some texts for Fallen Hero. Teleporter to Rise of the Defiler missing group support.
+SDCategory: Blasted Lands
+EndScriptData */
+
+/* ContentData
+npc_deathly_usher
+npc_fallen_hero_of_horde
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_deathly_usher
+######*/
+
+#define GOSSIP_ITEM_USHER "I wish to to visit the Rise of the Defiler."
+
+#define SPELL_TELEPORT_SINGLE 12885
+#define SPELL_TELEPORT_SINGLE_IN_GROUP 13142
+#define SPELL_TELEPORT_GROUP 27686
+
+bool GossipHello_npc_deathly_usher(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(3628) == QUEST_STATUS_INCOMPLETE && pPlayer->HasItemCount(10757, 1))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_USHER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_deathly_usher(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer, SPELL_TELEPORT_SINGLE, true);
+ }
+
+ return true;
+}
+
+/*######
+## npc_fallen_hero_of_horde
+######*/
+
+#define GOSSIP_ITEM_FALLEN "Continue..."
+
+#define GOSSIP_ITEM_FALLEN1 "What could be worse than death?"
+#define GOSSIP_ITEM_FALLEN2 "Subordinates?"
+#define GOSSIP_ITEM_FALLEN3 "What are the stones of binding?"
+#define GOSSIP_ITEM_FALLEN4 "You can count on me, Hero"
+#define GOSSIP_ITEM_FALLEN5 "I shall"
+
+bool GossipHello_npc_fallen_hero_of_horde(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(2784) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Why are you here?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ if (pPlayer->GetQuestStatus(2801) == QUEST_STATUS_INCOMPLETE && pPlayer->GetTeam() == HORDE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Continue story...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+
+ if (pPlayer->GetQuestStatus(2801) == QUEST_STATUS_INCOMPLETE && pPlayer->GetTeam() == ALLIANCE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Why are you here?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_fallen_hero_of_horde(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
+ pPlayer->SEND_GOSSIP_MENU(1392, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+11:
+ pPlayer->SEND_GOSSIP_MENU(1411, pCreature->GetGUID());
+ if (pPlayer->GetQuestStatus(2784) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->AreaExploredOrEventHappens(2784);
+ if (pPlayer->GetTeam() == ALLIANCE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(1411, pCreature->GetGUID());
+ }
+ break;
+
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21);
+ pPlayer->SEND_GOSSIP_MENU(1451, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+21:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
+ pPlayer->SEND_GOSSIP_MENU(1452, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+22:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23);
+ pPlayer->SEND_GOSSIP_MENU(1453, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+23:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24);
+ pPlayer->SEND_GOSSIP_MENU(1454, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+24:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25);
+ pPlayer->SEND_GOSSIP_MENU(1455, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+25:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FALLEN5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 26);
+ pPlayer->SEND_GOSSIP_MENU(1456, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+26:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(2801);
+ break;
+ }
+ return true;
+}
+
+void AddSC_blasted_lands()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_deathly_usher";
+ newscript->pGossipHello = &GossipHello_npc_deathly_usher;
+ newscript->pGossipSelect = &GossipSelect_npc_deathly_usher;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_fallen_hero_of_horde";
+ newscript->pGossipHello = &GossipHello_npc_fallen_hero_of_horde;
+ newscript->pGossipSelect = &GossipSelect_npc_fallen_hero_of_horde;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/boss_kruul.cpp b/scripts/eastern_kingdoms/boss_kruul.cpp
new file mode 100644
index 0000000..fb52ed3
--- /dev/null
+++ b/scripts/eastern_kingdoms/boss_kruul.cpp
@@ -0,0 +1,178 @@
+/* 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_Kruul
+SD%Complete: 100
+SDComment: Highlord Kruul are presumably no longer in-game on regular bases, however future events could bring him back.
+SDCategory: Bosses
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_SHADOWVOLLEY 21341
+#define SPELL_CLEAVE 20677
+#define SPELL_THUNDERCLAP 23931
+#define SPELL_TWISTEDREFLECTION 21063
+#define SPELL_VOIDBOLT 21066
+#define SPELL_RAGE 21340
+#define SPELL_CAPTURESOUL 21054
+
+struct MANGOS_DLL_DECL boss_kruulAI : public ScriptedAI
+{
+ boss_kruulAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ShadowVolley_Timer;
+ uint32 Cleave_Timer;
+ uint32 ThunderClap_Timer;
+ uint32 TwistedReflection_Timer;
+ uint32 VoidBolt_Timer;
+ uint32 Rage_Timer;
+ uint32 Hound_Timer;
+ int Rand;
+ int RandX;
+ int RandY;
+ Creature* Summoned;
+
+ void Reset()
+ {
+ ShadowVolley_Timer = 10000;
+ Cleave_Timer = 14000;
+ ThunderClap_Timer = 20000;
+ TwistedReflection_Timer = 25000;
+ VoidBolt_Timer = 30000;
+ Rage_Timer = 60000; //Cast rage after 1 minute
+ Hound_Timer = 8000;
+ }
+
+ void KilledUnit()
+ {
+ // When a player, pet or totem gets killed, Lord Kazzak casts this spell to instantly regenerate 70,000 health.
+ DoCastSpellIfCan(m_creature,SPELL_CAPTURESOUL);
+
+ }
+
+ void SummonHounds(Unit* victim)
+ {
+ Rand = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: RandX = 0 - Rand; break;
+ case 1: RandX = 0 + Rand; break;
+ }
+ Rand = 0;
+ Rand = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: RandY = 0 - Rand; break;
+ case 1: RandY = 0 + Rand; break;
+ }
+ Rand = 0;
+ Summoned = DoSpawnCreature(19207, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(victim);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowVolley_Timer
+ if (ShadowVolley_Timer < diff)
+ {
+ if (rand()%100 < 46)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWVOLLEY);
+ }
+
+ ShadowVolley_Timer = 5000;
+ }else ShadowVolley_Timer -= diff;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ if (rand()%100 < 50)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ }
+
+ Cleave_Timer = 10000;
+ }else Cleave_Timer -= diff;
+
+ //ThunderClap_Timer
+ if (ThunderClap_Timer < diff)
+ {
+ if (rand()%100 < 20)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_THUNDERCLAP);
+ }
+
+ ThunderClap_Timer = 12000;
+ }else ThunderClap_Timer -= diff;
+
+ //TwistedReflection_Timer
+ if (TwistedReflection_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_TWISTEDREFLECTION);
+ TwistedReflection_Timer = 30000;
+ }else TwistedReflection_Timer -= diff;
+
+ //VoidBolt_Timer
+ if (VoidBolt_Timer < diff)
+ {
+ if (rand()%100 < 40)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_VOIDBOLT);
+ }
+
+ VoidBolt_Timer = 18000;
+ }else VoidBolt_Timer -= diff;
+
+ //Rage_Timer
+ if (Rage_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_RAGE);
+ Rage_Timer = 70000;
+ }else Rage_Timer -= diff;
+
+ //Hound_Timer
+ if (Hound_Timer < diff)
+ {
+ SummonHounds(m_creature->getVictim());
+ SummonHounds(m_creature->getVictim());
+ SummonHounds(m_creature->getVictim());
+
+ Hound_Timer = 45000;
+ }else Hound_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_kruul(Creature* pCreature)
+{
+ return new boss_kruulAI(pCreature);
+}
+
+void AddSC_boss_kruul()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_kruul";
+ newscript->GetAI = &GetAI_boss_kruul;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/burning_steppes.cpp b/scripts/eastern_kingdoms/burning_steppes.cpp
new file mode 100644
index 0000000..0c125ad
--- /dev/null
+++ b/scripts/eastern_kingdoms/burning_steppes.cpp
@@ -0,0 +1,149 @@
+/* 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: Burning_Steppes
+SD%Complete: 100
+SDComment: Quest support: 4224, 4866
+SDCategory: Burning Steppes
+EndScriptData */
+
+/* ContentData
+npc_ragged_john
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_ragged_john
+######*/
+
+struct MANGOS_DLL_DECL npc_ragged_johnAI : public ScriptedAI
+{
+ npc_ragged_johnAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ void Reset() {}
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ if (who->HasAura(16468, EFFECT_INDEX_0))
+ {
+ if (who->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(who, 15) && who->isInAccessablePlaceFor(m_creature))
+ {
+ DoCastSpellIfCan(who,16472);
+ ((Player*)who)->AreaExploredOrEventHappens(4866);
+ }
+ }
+
+ if (!m_creature->getVictim() && who->isTargetableForAttack() && (m_creature->IsHostileTo(who)) && who->isInAccessablePlaceFor(m_creature))
+ {
+ if (!m_creature->CanFly() && m_creature->GetDistanceZ(who) > CREATURE_Z_ATTACK_RANGE)
+ return;
+
+ float attackRadius = m_creature->GetAttackDistance(who);
+ if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->IsWithinLOSInMap(who))
+ {
+ who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+ AttackStart(who);
+ }
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_ragged_john(Creature* pCreature)
+{
+ return new npc_ragged_johnAI(pCreature);
+}
+
+bool GossipHello_npc_ragged_john(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(4224) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Official buisness, John. I need some information about Marsha Windsor. Tell me about the last time you saw him.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(2713, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_ragged_john(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "So what did you do?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(2714, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Start making sense, dwarf. I don't want to have anything to do with your cracker, your pappy, or any sort of 'discreditin'.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(2715, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Ironfoe?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->SEND_GOSSIP_MENU(2716, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Interesting... continue John.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
+ pPlayer->SEND_GOSSIP_MENU(2717, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "So that's how Windsor died...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
+ pPlayer->SEND_GOSSIP_MENU(2718, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "So how did he die?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
+ pPlayer->SEND_GOSSIP_MENU(2719, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+6:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Ok so where the hell is he? Wait a minute! Are you drunk?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
+ pPlayer->SEND_GOSSIP_MENU(2720, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+7:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "WHY is he in Blackrock Depths?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 8);
+ pPlayer->SEND_GOSSIP_MENU(2721, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+8:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "300? So the Dark Irons killed him and dragged him into the Depths?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 9);
+ pPlayer->SEND_GOSSIP_MENU(2722, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+9:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Ahh... Ironfoe", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 10);
+ pPlayer->SEND_GOSSIP_MENU(2723, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+10:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Thanks, Ragged John. Your story was very uplifting and informative", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
+ pPlayer->SEND_GOSSIP_MENU(2725, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+11:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(4224);
+ break;
+ }
+ return true;
+}
+
+void AddSC_burning_steppes()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_ragged_john";
+ newscript->GetAI = &GetAI_npc_ragged_john;
+ newscript->pGossipHello = &GossipHello_npc_ragged_john;
+ newscript->pGossipSelect = &GossipSelect_npc_ragged_john;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/deadmines/deadmines.cpp b/scripts/eastern_kingdoms/deadmines/deadmines.cpp
new file mode 100644
index 0000000..0a8a27c
--- /dev/null
+++ b/scripts/eastern_kingdoms/deadmines/deadmines.cpp
@@ -0,0 +1,69 @@
+/* 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: Deadmines
+SD%Complete: 90
+SDComment: Contains GO for event at end door
+SDCategory: Deadmines
+EndScriptData */
+
+#include "precompiled.h"
+#include "deadmines.h"
+
+bool GOHello_go_door_lever_dm(Player* pPlayer, GameObject* pGo)
+{
+ ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData();
+
+ if (!pInstance)
+ return false;
+
+ GameObject* pGoDoor = pInstance->instance->GetGameObject(pInstance->GetData64(DATA_DEFIAS_DOOR));
+
+ if (pGoDoor && pGoDoor->GetGoState() == 1)
+ return false;
+
+ return true;
+}
+
+bool GOHello_go_defias_cannon(Player* pPlayer, GameObject* pGo)
+{
+ ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData();
+
+ if (!pInstance)
+ return false;
+
+ if (pInstance->GetData(TYPE_DEFIAS_ENDDOOR) == DONE || pInstance->GetData(TYPE_DEFIAS_ENDDOOR) == IN_PROGRESS)
+ return false;
+
+ pInstance->SetData(TYPE_DEFIAS_ENDDOOR, IN_PROGRESS);
+ return false;
+}
+
+void AddSC_deadmines()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "go_door_lever_dm";
+ newscript->pGOHello = &GOHello_go_door_lever_dm;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "go_defias_cannon";
+ newscript->pGOHello = &GOHello_go_defias_cannon;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/deadmines/deadmines.h b/scripts/eastern_kingdoms/deadmines/deadmines.h
new file mode 100644
index 0000000..3537da6
--- /dev/null
+++ b/scripts/eastern_kingdoms/deadmines/deadmines.h
@@ -0,0 +1,25 @@
+/* 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 */
+
+#ifndef DEF_DEADMINES_H
+#define DEF_DEADMINES_H
+
+enum
+{
+ MAX_ENCOUNTER = 1,
+
+ TYPE_DEFIAS_ENDDOOR = 1,
+ DATA_DEFIAS_DOOR = 2,
+
+ INST_SAY_ALARM1 = -1036000,
+ INST_SAY_ALARM2 = -1036001,
+
+ GO_DOOR_LEVER = 101833,
+ GO_IRON_CLAD = 16397,
+ GO_DEFIAS_CANNON = 16398,
+ NPC_MR_SMITE = 646,
+ NPC_PIRATE = 657
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp b/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp
new file mode 100644
index 0000000..6974c2f
--- /dev/null
+++ b/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp
@@ -0,0 +1,151 @@
+/* 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_Deadmines
+SD%Complete: 0
+SDComment: Placeholder
+SDCategory: Deadmines
+EndScriptData */
+
+#include "precompiled.h"
+#include "deadmines.h"
+
+struct MANGOS_DLL_DECL instance_deadmines : public ScriptedInstance
+{
+ instance_deadmines(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ uint64 m_uiIronCladGUID;
+ uint64 m_uiCannonGUID;
+ uint64 m_uiSmiteGUID;
+
+ uint32 m_uiIronDoor_Timer;
+ uint32 m_uiDoor_Step;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiIronCladGUID = 0;
+ m_uiCannonGUID = 0;
+ m_uiSmiteGUID = 0;
+
+ m_uiIronDoor_Timer = 0;
+ m_uiDoor_Step = 0;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ if (pCreature->GetEntry() == NPC_MR_SMITE)
+ m_uiSmiteGUID = pCreature->GetGUID();
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ if (pGo->GetEntry() == GO_IRON_CLAD)
+ m_uiIronCladGUID = pGo->GetGUID();
+
+ if (pGo->GetEntry() == GO_DEFIAS_CANNON)
+ m_uiCannonGUID = pGo->GetGUID();
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ if (uiType == TYPE_DEFIAS_ENDDOOR)
+ {
+ if (uiData == IN_PROGRESS)
+ {
+ if (GameObject* pGo = instance->GetGameObject(m_uiIronCladGUID))
+ {
+ pGo->SetGoState(GO_STATE_ACTIVE_ALTERNATIVE);
+ m_uiIronDoor_Timer = 3000;
+ }
+ }
+ m_auiEncounter[0] = uiData;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ if (uiType == TYPE_DEFIAS_ENDDOOR)
+ return m_auiEncounter[0];
+
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ if (uiData == DATA_DEFIAS_DOOR)
+ return m_uiIronCladGUID;
+
+ return 0;
+ }
+
+ void Update(uint32 uiDiff)
+ {
+ if (m_uiIronDoor_Timer)
+ {
+ if (m_uiIronDoor_Timer <= uiDiff)
+ {
+ if (Creature* pMrSmite = instance->GetCreature(m_uiSmiteGUID))
+ {
+ switch(m_uiDoor_Step)
+ {
+ case 0:
+ DoScriptText(INST_SAY_ALARM1,pMrSmite);
+ m_uiIronDoor_Timer = 2000;
+ ++m_uiDoor_Step;
+ break;
+ case 1:
+ if (Creature* pi1 = pMrSmite->SummonCreature(NPC_PIRATE, 93.68f, -678.63f, 7.71f, 2.09f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000))
+ pi1->GetMotionMaster()->MovePoint(0, 100.11f, -670.65f, 7.42f);
+ if (Creature* pi2 = pMrSmite->SummonCreature(NPC_PIRATE, 102.63f, -685.07f, 7.42f, 1.28f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000))
+ pi2->GetMotionMaster()->MovePoint(0, 100.11f, -670.65f, 7.42f);
+ ++m_uiDoor_Step;
+ m_uiIronDoor_Timer = 10000;
+ break;
+ case 2:
+ DoScriptText(INST_SAY_ALARM2,pMrSmite);
+ m_uiDoor_Step = 0;
+ m_uiIronDoor_Timer = 0;
+ debug_log("SD2: Instance Deadmines: Iron door event reached end.");
+ break;
+ }
+ }
+ else
+ m_uiIronDoor_Timer = 0;
+ }
+ else
+ m_uiIronDoor_Timer -= uiDiff;
+ }
+ }
+};
+
+InstanceData* GetInstanceData_instance_deadmines(Map* pMap)
+{
+ return new instance_deadmines(pMap);
+}
+
+void AddSC_instance_deadmines()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_deadmines";
+ newscript->GetInstanceData = &GetInstanceData_instance_deadmines;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/dun_morogh.cpp b/scripts/eastern_kingdoms/dun_morogh.cpp
new file mode 100644
index 0000000..eb75ed4
--- /dev/null
+++ b/scripts/eastern_kingdoms/dun_morogh.cpp
@@ -0,0 +1,91 @@
+/* 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: Dun_Morogh
+SD%Complete: 50
+SDComment: Quest support: 1783
+SDCategory: Dun Morogh
+EndScriptData */
+
+/* ContentData
+npc_narm_faulk
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_narm_faulk
+######*/
+
+#define SAY_HEAL -1000187
+
+struct MANGOS_DLL_DECL npc_narm_faulkAI : public ScriptedAI
+{
+ uint32 lifeTimer;
+ bool spellHit;
+
+ npc_narm_faulkAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ lifeTimer = 120000;
+ m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+ m_creature->SetStandState(UNIT_STAND_STATE_DEAD);
+ spellHit = false;
+ }
+
+ void MoveInLineOfSight(Unit *who) { }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (m_creature->IsStandState())
+ {
+ if (lifeTimer < diff)
+ m_creature->AI()->EnterEvadeMode();
+ else
+ lifeTimer -= diff;
+ }
+ }
+
+ void SpellHit(Unit *Hitter, const SpellEntry *Spellkind)
+ {
+ if (Spellkind->Id == 8593 && !spellHit)
+ {
+ DoCastSpellIfCan(m_creature,32343);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
+ //m_creature->RemoveAllAuras();
+ DoScriptText(SAY_HEAL, m_creature, Hitter);
+ spellHit = true;
+ }
+ }
+
+};
+CreatureAI* GetAI_npc_narm_faulk(Creature* pCreature)
+{
+ return new npc_narm_faulkAI(pCreature);
+}
+
+void AddSC_dun_morogh()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_narm_faulk";
+ newscript->GetAI = &GetAI_npc_narm_faulk;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/eastern_plaguelands.cpp b/scripts/eastern_kingdoms/eastern_plaguelands.cpp
new file mode 100644
index 0000000..9ec8c94
--- /dev/null
+++ b/scripts/eastern_kingdoms/eastern_plaguelands.cpp
@@ -0,0 +1,176 @@
+/* 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: Eastern_Plaguelands
+SD%Complete: 100
+SDComment: Quest support: 5211, 5742. Special vendor Augustus the Touched
+SDCategory: Eastern Plaguelands
+EndScriptData */
+
+/* ContentData
+mobs_ghoul_flayer
+npc_augustus_the_touched
+npc_darrowshire_spirit
+npc_tirion_fordring
+EndContentData */
+
+#include "precompiled.h"
+
+//id8530 - cannibal ghoul
+//id8531 - gibbering ghoul
+//id8532 - diseased flayer
+
+struct MANGOS_DLL_DECL mobs_ghoul_flayerAI : public ScriptedAI
+{
+ mobs_ghoul_flayerAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset() { }
+
+ void JustDied(Unit* Killer)
+ {
+ if (Killer->GetTypeId() == TYPEID_PLAYER)
+ m_creature->SummonCreature(11064, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 60000);
+ }
+
+};
+
+CreatureAI* GetAI_mobs_ghoul_flayer(Creature* pCreature)
+{
+ return new mobs_ghoul_flayerAI(pCreature);
+}
+
+/*######
+## npc_augustus_the_touched
+######*/
+
+bool GossipHello_npc_augustus_the_touched(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(6164))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_augustus_the_touched(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_TRADE)
+ pPlayer->SEND_VENDORLIST(pCreature->GetGUID());
+ return true;
+}
+
+/*######
+## npc_darrowshire_spirit
+######*/
+
+#define SPELL_SPIRIT_SPAWNIN 17321
+
+struct MANGOS_DLL_DECL npc_darrowshire_spiritAI : public ScriptedAI
+{
+ npc_darrowshire_spiritAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ DoCastSpellIfCan(m_creature,SPELL_SPIRIT_SPAWNIN);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+};
+
+CreatureAI* GetAI_npc_darrowshire_spirit(Creature* pCreature)
+{
+ return new npc_darrowshire_spiritAI(pCreature);
+}
+
+bool GossipHello_npc_darrowshire_spirit(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->SEND_GOSSIP_MENU(3873, pCreature->GetGUID());
+ pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID());
+ pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ return true;
+}
+
+/*######
+## npc_tirion_fordring
+######*/
+
+bool GossipHello_npc_tirion_fordring(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(5742) == QUEST_STATUS_INCOMPLETE && pPlayer->getStandState() == UNIT_STAND_STATE_SIT)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I am ready to hear your tale, Tirion.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_tirion_fordring(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Thank you, Tirion. What of your identity?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(4493, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "That is terrible.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->SEND_GOSSIP_MENU(4494, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I will, Tirion.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
+ pPlayer->SEND_GOSSIP_MENU(4495, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(5742);
+ break;
+ }
+ return true;
+}
+
+void AddSC_eastern_plaguelands()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "mobs_ghoul_flayer";
+ newscript->GetAI = &GetAI_mobs_ghoul_flayer;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_augustus_the_touched";
+ newscript->pGossipHello = &GossipHello_npc_augustus_the_touched;
+ newscript->pGossipSelect = &GossipSelect_npc_augustus_the_touched;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_darrowshire_spirit";
+ newscript->GetAI = &GetAI_npc_darrowshire_spirit;
+ newscript->pGossipHello = &GossipHello_npc_darrowshire_spirit;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_tirion_fordring";
+ newscript->pGossipHello = &GossipHello_npc_tirion_fordring;
+ newscript->pGossipSelect = &GossipSelect_npc_tirion_fordring;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/elwynn_forest.cpp b/scripts/eastern_kingdoms/elwynn_forest.cpp
new file mode 100644
index 0000000..1610552
--- /dev/null
+++ b/scripts/eastern_kingdoms/elwynn_forest.cpp
@@ -0,0 +1,91 @@
+/* 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: Elwynn_Forest
+SD%Complete: 50
+SDComment: Quest support: 1786
+SDCategory: Elwynn Forest
+EndScriptData */
+
+/* ContentData
+npc_henze_faulk
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_henze_faulk
+######*/
+
+#define SAY_HEAL -1000187
+
+struct MANGOS_DLL_DECL npc_henze_faulkAI : public ScriptedAI
+{
+ uint32 lifeTimer;
+ bool spellHit;
+
+ npc_henze_faulkAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ lifeTimer = 120000;
+ m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+ m_creature->SetStandState(UNIT_STAND_STATE_DEAD); // lay down
+ spellHit = false;
+ }
+
+ void MoveInLineOfSight(Unit *who) { }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (m_creature->IsStandState())
+ {
+ if (lifeTimer < diff)
+ m_creature->AI()->EnterEvadeMode();
+ else
+ lifeTimer -= diff;
+ }
+ }
+
+ void SpellHit(Unit *Hitter, const SpellEntry *Spellkind)
+ {
+ if (Spellkind->Id == 8593 && !spellHit)
+ {
+ DoCastSpellIfCan(m_creature,32343);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
+ //m_creature->RemoveAllAuras();
+ DoScriptText(SAY_HEAL, m_creature, Hitter);
+ spellHit = true;
+ }
+ }
+
+};
+CreatureAI* GetAI_npc_henze_faulk(Creature* pCreature)
+{
+ return new npc_henze_faulkAI(pCreature);
+}
+
+void AddSC_elwynn_forest()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_henze_faulk";
+ newscript->GetAI = &GetAI_npc_henze_faulk;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/eversong_woods.cpp b/scripts/eastern_kingdoms/eversong_woods.cpp
new file mode 100644
index 0000000..f552cc0
--- /dev/null
+++ b/scripts/eastern_kingdoms/eversong_woods.cpp
@@ -0,0 +1,464 @@
+/* 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: Eversong_Woods
+SD%Complete: 100
+SDComment: Quest support: 8483, 8488, 9686
+SDCategory: Eversong Woods
+EndScriptData */
+
+/* ContentData
+npc_kelerun_bloodmourn
+go_harbinger_second_trial
+npc_prospector_anvilward
+npc_apprentice_mirveda
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_kelerun_bloodmourn
+######*/
+
+enum
+{
+ NPC_KELERUN = 17807,
+ NPC_BLOODWRATH = 17809,
+ NPC_LIGHTREND = 17810,
+ NPC_SWIFTBLADE = 17811,
+ NPC_SUNSTRIKER = 17812,
+
+ GO_SECOND_TRIAL = 182052,
+ QUEST_SECOND_TRIAL = 9686,
+ MAX_CHALLENGER = 4
+};
+
+const uint32 uiChallengerId[4] = {NPC_BLOODWRATH, NPC_LIGHTREND, NPC_SWIFTBLADE, NPC_SUNSTRIKER};
+
+const int32 uiSayId[4] =
+{
+ -1000319,
+ -1000320,
+ -1000321,
+ -1000322
+};
+
+float fChallengerLoc[4][4]=
+{
+ {10110.667f, -6628.059f, 4.100f, 2.708f},
+ {10093.919f, -6634.340f, 4.098f, 1.106f},
+ {10087.565f, -6617.282f, 4.098f, 5.887f},
+ {10104.807f, -6611.145f, 4.101f, 4.265f}
+};
+
+struct MANGOS_DLL_DECL npc_kelerun_bloodmournAI : public ScriptedAI
+{
+ npc_kelerun_bloodmournAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiNpcFlags = pCreature->GetUInt32Value(UNIT_NPC_FLAGS);
+ Reset();
+ }
+
+ uint32 m_uiNpcFlags;
+ uint64 m_uiPlayerGUID;
+ uint64 uiChallengerGUID[MAX_CHALLENGER];
+
+ uint8 m_uiChallengerCount;
+
+ uint32 m_uiTimeOutTimer;
+ uint32 m_uiCheckAliveStateTimer;
+ uint32 m_uiEngageTimer;
+
+ bool m_bIsEventInProgress;
+
+ void Reset()
+ {
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS, m_uiNpcFlags);
+
+ m_uiPlayerGUID = 0;
+
+ memset(&uiChallengerGUID, 0, sizeof(uiChallengerGUID));
+
+ m_uiChallengerCount = 0;
+
+ m_uiTimeOutTimer = 60000;
+ m_uiCheckAliveStateTimer = 2500;
+ m_uiEngageTimer = 0;
+
+ m_bIsEventInProgress = false;
+ }
+
+ void StartEvent()
+ {
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
+ m_bIsEventInProgress = true;
+ }
+
+ bool CanProgressEvent(uint64 uiPlayer)
+ {
+ if (m_bIsEventInProgress)
+ {
+ m_uiPlayerGUID = uiPlayer;
+ DoSpawnChallengers();
+ m_uiEngageTimer = 15000;
+
+ return true;
+ }
+
+ return false;
+ }
+
+ void DoSpawnChallengers()
+ {
+ for(uint8 i = 0; i < MAX_CHALLENGER; ++i)
+ {
+ if (Creature* pCreature = m_creature->SummonCreature(uiChallengerId[i],
+ fChallengerLoc[i][0], fChallengerLoc[i][1],
+ fChallengerLoc[i][2], fChallengerLoc[i][3],
+ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000))
+ {
+ uiChallengerGUID[i] = pCreature->GetGUID();
+ pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_bIsEventInProgress)
+ {
+ if (m_uiTimeOutTimer && m_uiTimeOutTimer < uiDiff)
+ {
+ if (!m_uiPlayerGUID)
+ {
+ //player are expected to use GO within a minute, if not, event will fail.
+ Reset();
+ return;
+ }
+
+ m_uiTimeOutTimer = 0;
+ }
+ else
+ m_uiTimeOutTimer -= uiDiff;
+
+ if (m_uiCheckAliveStateTimer < uiDiff)
+ {
+ if (Creature* pChallenger = m_creature->GetMap()->GetCreature(uiChallengerGUID[m_uiChallengerCount]))
+ {
+ if (!pChallenger->isAlive())
+ {
+ Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID);
+
+ if (pPlayer && !pPlayer->isAlive())
+ {
+ Reset();
+ return;
+ }
+
+ ++m_uiChallengerCount;
+
+ //count starts at 0
+ if (m_uiChallengerCount == MAX_CHALLENGER)
+ {
+ if (pPlayer && pPlayer->isAlive())
+ pPlayer->GroupEventHappens(QUEST_SECOND_TRIAL, m_creature);
+
+ Reset();
+ return;
+ }
+ else
+ m_uiEngageTimer = 15000;
+ }
+ }
+ m_uiCheckAliveStateTimer = 2500;
+ }
+ else
+ m_uiCheckAliveStateTimer -= uiDiff;
+
+ if (m_uiEngageTimer && m_uiEngageTimer < uiDiff)
+ {
+ Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID);
+
+ if (pPlayer && pPlayer->isAlive())
+ {
+ if (Creature* pCreature = m_creature->GetMap()->GetCreature(uiChallengerGUID[m_uiChallengerCount]))
+ {
+ DoScriptText(uiSayId[m_uiChallengerCount], m_creature, pPlayer);
+ pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ pCreature->AI()->AttackStart(pPlayer);
+ }
+ }
+
+ m_uiEngageTimer = 0;
+ }
+ else
+ m_uiEngageTimer -= uiDiff;
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_kelerun_bloodmourn(Creature* pCreature)
+{
+ return new npc_kelerun_bloodmournAI(pCreature);
+}
+
+//easiest way is to expect database to respawn GO at quest accept (quest_start_script)
+bool QuestAccept_npc_kelerun_bloodmourn(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_SECOND_TRIAL)
+ {
+ if (npc_kelerun_bloodmournAI* pKelrunAI = dynamic_cast(pCreature->AI()))
+ pKelrunAI->StartEvent();
+ }
+
+ return true;
+}
+
+bool GOHello_go_harbinger_second_trial(Player* pPlayer, GameObject* pGO)
+{
+ if (pGO->GetGoType() == GAMEOBJECT_TYPE_GOOBER)
+ {
+ if (Creature* pCreature = GetClosestCreatureWithEntry(pGO, NPC_KELERUN, 30.0f))
+ {
+ npc_kelerun_bloodmournAI* pKelrunAI = dynamic_cast(pCreature->AI());
+ if (pKelrunAI && pKelrunAI->CanProgressEvent(pPlayer->GetGUID()))
+ return false;
+ }
+ }
+
+ return false;
+}
+
+/*######
+## npc_prospector_anvilward
+######*/
+enum
+{
+ SAY_ANVIL1 = -1000209,
+ SAY_ANVIL2 = -1000210,
+
+ FACTION_DEFAULT = 35,
+ FACTION_HOSTILE = 24,
+
+ QUEST_THE_DWARVEN_SPY = 8483
+};
+
+struct MANGOS_DLL_DECL npc_prospector_anvilwardAI : public npc_escortAI
+{
+ // CreatureAI functions
+ npc_prospector_anvilwardAI(Creature* pCreature) : npc_escortAI(pCreature) {Reset();}
+
+ // Pure Virtual Functions
+ void WaypointReached(uint32 uiPointId)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch (uiPointId)
+ {
+ case 0:
+ DoScriptText(SAY_ANVIL1, m_creature, pPlayer);
+ break;
+ case 5:
+ DoScriptText(SAY_ANVIL2, m_creature, pPlayer);
+ break;
+ case 6:
+ m_creature->setFaction(FACTION_HOSTILE);
+ break;
+ }
+ }
+
+ void Reset()
+ {
+ //Default npc faction
+ m_creature->setFaction(FACTION_DEFAULT);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ //Default npc faction
+ m_creature->setFaction(FACTION_DEFAULT);
+ }
+};
+
+CreatureAI* GetAI_npc_prospector_anvilward(Creature* pCreature)
+{
+ return new npc_prospector_anvilwardAI(pCreature);
+}
+
+#define GOSSIP_ITEM_MOMENT "I need a moment of your time, sir."
+#define GOSSIP_ITEM_SHOW "Why... yes, of course. I've something to show you right inside this building, Mr. Anvilward."
+
+bool GossipHello_npc_prospector_anvilward(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(QUEST_THE_DWARVEN_SPY) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MOMENT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(8239, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_prospector_anvilward(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SHOW, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(8240, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (npc_prospector_anvilwardAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID());
+
+ break;
+ }
+ return true;
+}
+
+/*######
+## npc_apprentice_mirveda
+######*/
+
+enum
+{
+ QUEST_UNEXPECTED_RESULT = 8488,
+
+ SPELL_FIREBALL = 20811,
+
+ NPC_GHARSUL = 15958,
+ NPC_ANGERSHADE = 15656
+};
+
+struct MANGOS_DLL_DECL npc_apprentice_mirvedaAI : public ScriptedAI
+{
+ npc_apprentice_mirvedaAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint8 m_uiMobCount;
+ uint32 m_uiFireballTimer;
+ uint64 m_uiPlayerGUID;
+
+ void Reset()
+ {
+ m_uiMobCount = 0;
+ m_uiPlayerGUID = 0;
+ m_uiFireballTimer = 0;
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID);
+
+ if (pPlayer && pPlayer->GetQuestStatus(QUEST_UNEXPECTED_RESULT) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->SendQuestFailed(QUEST_UNEXPECTED_RESULT);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->AI()->AttackStart(m_creature);
+ ++m_uiMobCount;
+ }
+
+ void SummonedCreatureJustDied(Creature* pKilled)
+ {
+ --m_uiMobCount;
+
+ if (m_uiMobCount)
+ return;
+
+ Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID);
+
+ if (pPlayer && pPlayer->GetQuestStatus(QUEST_UNEXPECTED_RESULT) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->GroupEventHappens(QUEST_UNEXPECTED_RESULT, m_creature);
+
+ m_uiPlayerGUID = 0;
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ }
+
+ void StartEvent(uint64 uiPlayerGUID)
+ {
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ m_uiPlayerGUID = uiPlayerGUID;
+
+ m_creature->SummonCreature(NPC_GHARSUL, 8745.0f, -7134.32f, 35.22f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 4000);
+ m_creature->SummonCreature(NPC_ANGERSHADE, 8745.0f, -7134.32f, 35.22f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 4000);
+ m_creature->SummonCreature(NPC_ANGERSHADE, 8745.0f, -7134.32f, 35.22f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 4000);
+ }
+
+ void UpdateAI (const uint32 uiDiff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiFireballTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FIREBALL) == CAST_OK)
+ m_uiFireballTimer = urand(4000, 6000);
+ }
+ else
+ m_uiFireballTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool QuestAccept_unexpected_results(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_UNEXPECTED_RESULT)
+ if (npc_apprentice_mirvedaAI* pMirvedaAI = dynamic_cast(pCreature->AI()))
+ pMirvedaAI->StartEvent(pPlayer->GetGUID());
+ return true;
+}
+
+CreatureAI* GetAI_npc_apprentice_mirvedaAI(Creature* pCreature)
+{
+ return new npc_apprentice_mirvedaAI (pCreature);
+}
+
+void AddSC_eversong_woods()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_kelerun_bloodmourn";
+ pNewScript->GetAI = &GetAI_npc_kelerun_bloodmourn;
+ pNewScript->pQuestAccept = &QuestAccept_npc_kelerun_bloodmourn;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "go_harbinger_second_trial";
+ pNewScript->pGOHello = &GOHello_go_harbinger_second_trial;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_prospector_anvilward";
+ pNewScript->GetAI = &GetAI_npc_prospector_anvilward;
+ pNewScript->pGossipHello = &GossipHello_npc_prospector_anvilward;
+ pNewScript->pGossipSelect = &GossipSelect_npc_prospector_anvilward;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_apprentice_mirveda";
+ pNewScript->GetAI = GetAI_npc_apprentice_mirvedaAI;
+ pNewScript->pQuestAccept = &QuestAccept_unexpected_results;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/ghostlands.cpp b/scripts/eastern_kingdoms/ghostlands.cpp
new file mode 100644
index 0000000..cfbc26d
--- /dev/null
+++ b/scripts/eastern_kingdoms/ghostlands.cpp
@@ -0,0 +1,274 @@
+/* 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: Ghostlands
+SD%Complete: 100
+SDComment: Quest support: 9212, 9692. Obtain Budd's Guise of Zul'aman. Vendor Rathis Tomber
+SDCategory: Ghostlands
+EndScriptData */
+
+/* ContentData
+npc_blood_knight_dawnstar
+npc_budd_nedreck
+npc_ranger_lilatha
+npc_rathis_tomber
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_blood_knight_dawnstar
+######*/
+
+#define GOSSIP_ITEM_INSIGNIA "Take Blood Knight Insignia"
+
+bool GossipHello_npc_blood_knight_dawnstar(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(9692) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(24226,1,true))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_INSIGNIA,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_blood_knight_dawnstar(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ if (Item* pItem = pPlayer->StoreNewItemInInventorySlot(24226, 1))
+ pPlayer->SendNewItem(pItem, 1, true, false);
+
+ pPlayer->CLOSE_GOSSIP_MENU();
+ }
+ return true;
+}
+
+/*######
+## npc_budd_nedreck
+######*/
+
+#define GOSSIP_ITEM_DISGUISE "You gave the crew disguises?"
+
+bool GossipHello_npc_budd_nedreck(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(11166) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT,GOSSIP_ITEM_DISGUISE,GOSSIP_SENDER_MAIN,GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_budd_nedreck(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction==GOSSIP_ACTION_INFO_DEF)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer, 42540, false);
+ }
+ return true;
+}
+
+/*######
+## npc_ranger_lilatha
+######*/
+
+enum
+{
+ SAY_START = -1000140,
+ SAY_PROGRESS1 = -1000141,
+ SAY_PROGRESS2 = -1000142,
+ SAY_PROGRESS3 = -1000143,
+ SAY_END1 = -1000144,
+ SAY_END2 = -1000145,
+ CAPTAIN_ANSWER = -1000146,
+
+ QUEST_CATACOMBS = 9212,
+ GO_CAGE = 181152,
+ NPC_CAPTAIN_HELIOS = 16220,
+ FACTION_SMOON_E = 1603,
+};
+
+struct MANGOS_DLL_DECL npc_ranger_lilathaAI : public npc_escortAI
+{
+ npc_ranger_lilathaAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_uiGoCageGUID = 0;
+ m_uiHeliosGUID = 0;
+ Reset();
+ }
+
+ uint64 m_uiGoCageGUID;
+ uint64 m_uiHeliosGUID;
+
+ void MoveInLineOfSight(Unit* pUnit)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ if (!m_uiHeliosGUID && pUnit->GetEntry() == NPC_CAPTAIN_HELIOS)
+ {
+ if (m_creature->IsWithinDistInMap(pUnit, 30.0f))
+ m_uiHeliosGUID = pUnit->GetGUID();
+ }
+ }
+
+ npc_escortAI::MoveInLineOfSight(pUnit);
+ }
+
+ void WaypointReached(uint32 i)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch(i)
+ {
+ case 0:
+ if (GameObject* pGoTemp = GetClosestGameObjectWithEntry(m_creature, GO_CAGE, 10.0f))
+ {
+ m_uiGoCageGUID = pGoTemp->GetGUID();
+ pGoTemp->SetGoState(GO_STATE_ACTIVE);
+ }
+
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ DoScriptText(SAY_START, m_creature, pPlayer);
+ break;
+ case 1:
+ if (GameObject* pGo = m_creature->GetMap()->GetGameObject(m_uiGoCageGUID))
+ pGo->SetGoState(GO_STATE_READY);
+ break;
+ case 5:
+ DoScriptText(SAY_PROGRESS1, m_creature, pPlayer);
+ break;
+ case 11:
+ DoScriptText(SAY_PROGRESS2, m_creature, pPlayer);
+ break;
+ case 18:
+ DoScriptText(SAY_PROGRESS3, m_creature, pPlayer);
+ if (Creature* pSum1 = m_creature->SummonCreature(16342, 7627.083984f, -7532.538086f, 152.128616f, 1.082733f, TEMPSUMMON_DEAD_DESPAWN, 0))
+ pSum1->AI()->AttackStart(m_creature);
+ if (Creature* pSum2 = m_creature->SummonCreature(16343, 7620.432129f, -7532.550293f, 152.454865f, 0.827478f, TEMPSUMMON_DEAD_DESPAWN, 0))
+ pSum2->AI()->AttackStart(pPlayer);
+ break;
+ case 19:
+ SetRun();
+ break;
+ case 25:
+ SetRun(false);
+ break;
+ case 30:
+ pPlayer->GroupEventHappens(QUEST_CATACOMBS, m_creature);
+ break;
+ case 32:
+ DoScriptText(SAY_END1, m_creature, pPlayer);
+ break;
+ case 33:
+ DoScriptText(SAY_END2, m_creature, pPlayer);
+ if (Creature* pHelios = m_creature->GetMap()->GetCreature(m_uiHeliosGUID))
+ DoScriptText(CAPTAIN_ANSWER, pHelios, m_creature);
+ break;
+ }
+ }
+
+ void Reset()
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ m_uiGoCageGUID = 0;
+ m_uiHeliosGUID = 0;
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_ranger_lilathaAI(Creature* pCreature)
+{
+ return new npc_ranger_lilathaAI(pCreature);
+}
+
+bool QuestAccept_npc_ranger_lilatha(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_CATACOMBS)
+ {
+ pCreature->setFaction(FACTION_SMOON_E);
+
+ if (npc_ranger_lilathaAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+/*######
+## npc_rathis_tomber
+######*/
+
+bool GossipHello_npc_rathis_tomber(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(9152))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+ pPlayer->SEND_GOSSIP_MENU(8432, pCreature->GetGUID());
+ }else
+ pPlayer->SEND_GOSSIP_MENU(8431, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_rathis_tomber(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_TRADE)
+ pPlayer->SEND_VENDORLIST(pCreature->GetGUID());
+
+ return true;
+}
+
+void AddSC_ghostlands()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_blood_knight_dawnstar";
+ newscript->pGossipHello = &GossipHello_npc_blood_knight_dawnstar;
+ newscript->pGossipSelect = &GossipSelect_npc_blood_knight_dawnstar;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_budd_nedreck";
+ newscript->pGossipHello = &GossipHello_npc_budd_nedreck;
+ newscript->pGossipSelect = &GossipSelect_npc_budd_nedreck;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_ranger_lilatha";
+ newscript->GetAI = &GetAI_npc_ranger_lilathaAI;
+ newscript->pQuestAccept = &QuestAccept_npc_ranger_lilatha;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_rathis_tomber";
+ newscript->pGossipHello = &GossipHello_npc_rathis_tomber;
+ newscript->pGossipSelect = &GossipSelect_npc_rathis_tomber;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/gnomeregan/boss_thermaplugg.cpp b/scripts/eastern_kingdoms/gnomeregan/boss_thermaplugg.cpp
new file mode 100644
index 0000000..9920cb1
--- /dev/null
+++ b/scripts/eastern_kingdoms/gnomeregan/boss_thermaplugg.cpp
@@ -0,0 +1,272 @@
+/* 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_Mekgineer_Thermaplugg
+SD%Complete: 90 - Timer
+SDComment: Timer need improvement, especially for bomb-spawning
+SDCategory: Gnomeregan
+EndScriptData */
+
+#include "precompiled.h"
+#include "gnomeregan.h"
+
+enum
+{
+ SAY_AGGRO = -1090024,
+ SAY_PHASE = -1090025,
+ SAY_BOMB = -1090026,
+ SAY_SLAY = -1090027,
+
+ SPELL_ACTIVATE_BOMB_A = 11511, // Target Dest = -530.754 670.571 -313.784
+ SPELL_ACTIVATE_BOMB_B = 11795, // Target Dest = -530.754 670.571 -313.784
+ SPELL_KNOCK_AWAY = 10101,
+ SPELL_KNOCK_AWAY_AOE = 11130,
+ SPELL_WALKING_BOMB_EFFECT = 11504,
+
+ NPC_WALKING_BOMB = 7915,
+};
+
+static const float fBombSpawnZ = -316.2625f;
+
+struct MANGOS_DLL_DECL boss_thermapluggAI : public ScriptedAI
+{
+ boss_thermapluggAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (instance_gnomeregan*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ instance_gnomeregan* m_pInstance;
+ bool m_bIsPhaseTwo;
+
+ uint32 m_uiKnockAwayTimer;
+ uint32 m_uiActivateBombTimer;
+
+ sBombFace* m_asBombFaces;
+ float m_afSpawnPos[3];
+
+ std::list m_lSummonedBombGUIDs;
+ std::list m_lLandedBombGUIDs;
+
+ void Reset()
+ {
+ m_uiKnockAwayTimer = urand(17000, 20000);
+ m_uiActivateBombTimer = urand(10000, 15000);
+ m_bIsPhaseTwo = false;
+ m_asBombFaces = NULL;
+
+ memset(&m_afSpawnPos, 0.0f, sizeof(m_afSpawnPos));
+ m_lLandedBombGUIDs.clear();
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(SAY_SLAY, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_THERMAPLUGG, DONE);
+
+ m_lSummonedBombGUIDs.clear();
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (m_pInstance)
+ {
+ m_pInstance->SetData(TYPE_THERMAPLUGG, IN_PROGRESS);
+ m_asBombFaces = m_pInstance->GetBombFaces();
+ }
+
+ m_afSpawnPos[0] = m_creature->GetPositionX();
+ m_afSpawnPos[1] = m_creature->GetPositionY();
+ m_afSpawnPos[2] = m_creature->GetPositionZ();
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_THERMAPLUGG, FAIL);
+
+ // Remove remaining bombs
+ for (std::list::const_iterator itr = m_lSummonedBombGUIDs.begin(); itr != m_lSummonedBombGUIDs.end(); itr++)
+ {
+ if (Creature* pBomb = m_creature->GetMap()->GetCreature(*itr))
+ pBomb->ForcedDespawn();
+ }
+ m_lSummonedBombGUIDs.clear();
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_WALKING_BOMB)
+ {
+ m_lSummonedBombGUIDs.push_back(pSummoned->GetGUID());
+ // calculate point for falling down
+ float fX, fY;
+ fX = 0.2*m_afSpawnPos[0] + 0.8*pSummoned->GetPositionX();
+ fY = 0.2*m_afSpawnPos[1] + 0.8*pSummoned->GetPositionY();
+ pSummoned->GetMotionMaster()->MovePoint(1, fX, fY, m_afSpawnPos[2] - 2.0f);
+ }
+ }
+
+ void SummonedMovementInform(Creature* pSummoned, uint32 uiMotionType, uint32 uiPointId)
+ {
+ if (pSummoned->GetEntry() == NPC_WALKING_BOMB && uiMotionType == POINT_MOTION_TYPE && uiPointId == 1)
+ m_lLandedBombGUIDs.push_back(pSummoned->GetGUID());
+ }
+
+ void SummonedCreatureDespawn(Creature* pSummoned)
+ {
+ m_lSummonedBombGUIDs.remove(pSummoned->GetGUID());
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Movement of Summoned mobs
+ if (!m_lLandedBombGUIDs.empty())
+ {
+ for (std::list::const_iterator itr = m_lLandedBombGUIDs.begin(); itr != m_lLandedBombGUIDs.end(); itr++)
+ {
+ if (Creature* pBomb = m_creature->GetMap()->GetCreature(*itr))
+ pBomb->GetMotionMaster()->MoveFollow(m_creature, 0.0f, 0.0f);
+ }
+ m_lLandedBombGUIDs.clear();
+ }
+
+ if (!m_bIsPhaseTwo && m_creature->GetHealthPercent() < 50.0f)
+ {
+ DoScriptText(SAY_PHASE, m_creature);
+ m_bIsPhaseTwo = true;
+ }
+
+ if (m_uiKnockAwayTimer < uiDiff)
+ {
+ if (m_bIsPhaseTwo)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_KNOCK_AWAY_AOE) == CAST_OK)
+ m_uiKnockAwayTimer = 12000;
+ }
+ else
+ {
+ if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_KNOCK_AWAY) == CAST_OK)
+ m_uiKnockAwayTimer = urand(17000, 20000);
+ }
+ }
+ else
+ m_uiKnockAwayTimer -= uiDiff;
+
+ if (m_uiActivateBombTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature, m_bIsPhaseTwo ? SPELL_ACTIVATE_BOMB_B : SPELL_ACTIVATE_BOMB_A) == CAST_OK)
+ {
+ m_uiActivateBombTimer = (m_bIsPhaseTwo ? urand(6, 12) : urand(12, 17))*IN_MILLISECONDS;
+ if (!urand(0, 5)) // TODO, chance/ place for this correct?
+ DoScriptText(SAY_BOMB, m_creature);
+ }
+ }
+ else
+ m_uiActivateBombTimer -= uiDiff;
+
+ // Spawn bombs
+ if (m_asBombFaces)
+ {
+ for (uint8 i = 0; i < MAX_GNOME_FACES; i++)
+ {
+ if (m_asBombFaces[i].m_bActivated)
+ {
+ if (m_asBombFaces[i].m_uiBombTimer < uiDiff)
+ {
+ // Calculate the spawning position as 90% between face and thermaplugg spawn-pos, and hight hardcoded
+ float fX = 0.0f, fY = 0.0f;
+ if (GameObject* pFace = m_creature->GetMap()->GetGameObject(m_asBombFaces[i].m_uiGnomeFaceGUID))
+ {
+ fX = 0.35*m_afSpawnPos[0] + 0.65*pFace->GetPositionX();
+ fY = 0.35*m_afSpawnPos[1] + 0.65*pFace->GetPositionY();
+ }
+ m_creature->SummonCreature(NPC_WALKING_BOMB, fX, fY, fBombSpawnZ, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ m_asBombFaces[i].m_uiBombTimer = urand(10000, 25000); // TODO
+ }
+ else
+ m_asBombFaces[i].m_uiBombTimer -= uiDiff;
+ }
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_thermaplugg(Creature* pCreature)
+{
+ return new boss_thermapluggAI(pCreature);
+}
+
+bool EffectDummyCreature_spell_boss_thermaplugg(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Creature* pCreatureTarget)
+{
+ if ((uiSpellId != SPELL_ACTIVATE_BOMB_A && uiSpellId != SPELL_ACTIVATE_BOMB_B) || uiEffIndex != EFFECT_INDEX_0)
+ return false;
+
+ // This spell should select a random Bomb-Face and activate it if needed
+ if (instance_gnomeregan* pInstance = (instance_gnomeregan*)pCreatureTarget->GetInstanceData())
+ pInstance->DoActivateBombFace(urand(0, MAX_GNOME_FACES - 1));
+
+ return true;
+}
+
+bool GOHello_go_gnomeface_button(Player* pPlayer, GameObject* pGo)
+{
+ instance_gnomeregan* pInstance = (instance_gnomeregan*)pPlayer->GetInstanceData();
+ if (!pInstance)
+ return false;
+
+ // If a button is used, the related face should be deactivated (if already activated)
+ switch (pGo->GetEntry())
+ {
+ case GO_BUTTON_1: pInstance->DoDeactivateBombFace(0); break;
+ case GO_BUTTON_2: pInstance->DoDeactivateBombFace(1); break;
+ case GO_BUTTON_3: pInstance->DoDeactivateBombFace(2); break;
+ case GO_BUTTON_4: pInstance->DoDeactivateBombFace(3); break;
+ case GO_BUTTON_5: pInstance->DoDeactivateBombFace(4); break;
+ case GO_BUTTON_6: pInstance->DoDeactivateBombFace(5); break;
+ }
+
+ return false;
+}
+
+void AddSC_boss_thermaplugg()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "boss_thermaplugg";
+ pNewScript->GetAI = &GetAI_boss_thermaplugg;
+ pNewScript->pEffectDummyCreature = &EffectDummyCreature_spell_boss_thermaplugg;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "go_gnomeface_button";
+ pNewScript->pGOHello = &GOHello_go_gnomeface_button;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp b/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp
new file mode 100644
index 0000000..7b3286d
--- /dev/null
+++ b/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp
@@ -0,0 +1,80 @@
+/* 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: gnomeregan
+SD%Complete: 80
+SDComment: Grubbis Encounter
+SDCategory: Gnomeregan
+EndScriptData */
+
+/* ContentData
+npc_blastmaster_emi_shortfuse
+EndContentData */
+
+#include "precompiled.h"
+#include "gnomeregan.h"
+#include "escort_ai.h"
+
+/*######
+## npc_blastmaster_emi_shortfuse
+######*/
+
+enum
+{
+ SAY_START = -1090000,
+ SAY_INTRO_1 = -1090001,
+ SAY_INTRO_2 = -1090002,
+ SAY_INTRO_3 = -1090003,
+ SAY_INTRO_4 = -1090004,
+ SAY_LOOK_1 = -1090005,
+ SAY_HEAR_1 = -1090006,
+ SAY_AGGRO = -1090007,
+ SAY_CHARGE_1 = -1090008,
+ SAY_CHARGE_2 = -1090009,
+ SAY_BLOW_1_10 = -1090010,
+ SAY_BLOW_1_5 = -1090011,
+ SAY_BLOW_1 = -1090012,
+ SAY_FINISH_1 = -1090013,
+ SAY_LOOK_2 = -1090014,
+ SAY_HEAR_2 = -1090015,
+ SAY_CHARGE_3 = -1090016,
+ SAY_CHARGE_4 = -1090017,
+ SAY_BLOW_2_10 = -1090018,
+ SAY_BLOW_2_5 = -1090019,
+ SAY_BLOW_SOON = -1090020,
+ SAY_BLOW_2 = -1090021,
+ SAY_FINISH_2 = -1090022,
+
+ SAY_GRUBBIS_SPAWN = -1090023,
+
+ GOSSIP_ITEM_START = -3090000,
+
+ SPELL_EXPLOSION_NORTH = 12158,
+ SPELL_EXPLOSION_SOUTH = 12159,
+ SPELL_FIREWORKS_RED = 11542,
+
+ MAX_SUMMON_POSITIONS = 33,
+
+ NPC_GRUBBIS = 7361,
+ NPC_CHOMPER = 6215,
+ NPC_CAVERNDEEP_BURROWER = 6206,
+ NPC_CAVERNDEEP_AMBUSHER = 6207
+};
+
+void AddSC_gnomeregan()
+{
+}
diff --git a/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h b/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h
new file mode 100644
index 0000000..bea823f
--- /dev/null
+++ b/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h
@@ -0,0 +1,93 @@
+/* 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 */
+
+#ifndef DEF_GNOMEREGAN_H
+#define DEF_GNOMEREGAN_H
+
+enum
+{
+ MAX_ENCOUNTER = 2, // Only Grubbis and Thermaplugg need treatment
+ MAX_GNOME_FACES = 6,
+ MAX_EXPLOSIVES_PER_SIDE = 2,
+
+ TYPE_GRUBBIS = 1,
+ TYPE_THERMAPLUGG = 2,
+ TYPE_EXPLOSIVE_CHARGE = 3,
+
+ DATA_EXPLOSIVE_CHARGE_1 = 1,
+ DATA_EXPLOSIVE_CHARGE_2 = 2,
+ DATA_EXPLOSIVE_CHARGE_3 = 3,
+ DATA_EXPLOSIVE_CHARGE_4 = 4,
+ DATA_EXPLOSIVE_CHARGE_USE = 5,
+
+ NPC_BLASTMASTER_SHORTFUSE = 7998,
+
+ GO_RED_ROCKET = 103820,
+ GO_CAVE_IN_NORTH = 146085,
+ GO_CAVE_IN_SOUTH = 146086,
+ GO_EXPLOSIVE_CHARGE = 144065,
+ GO_THE_FINAL_CHAMBER = 142207,
+
+ GO_GNOME_FACE_1 = 142211,
+ GO_GNOME_FACE_2 = 142210,
+ GO_GNOME_FACE_3 = 142209,
+ GO_GNOME_FACE_4 = 142208,
+ GO_GNOME_FACE_5 = 142213,
+ GO_GNOME_FACE_6 = 142212,
+
+ GO_BUTTON_1 = 142214,
+ GO_BUTTON_2 = 142215,
+ GO_BUTTON_3 = 142216,
+ GO_BUTTON_4 = 142217,
+ GO_BUTTON_5 = 142218,
+ GO_BUTTON_6 = 142219
+};
+
+struct sBombFace
+{
+ uint64 m_uiGnomeFaceGUID;
+ bool m_bActivated;
+ uint32 m_uiBombTimer;
+};
+
+class MANGOS_DLL_DECL instance_gnomeregan : public ScriptedInstance
+{
+ public:
+ instance_gnomeregan(Map* pMap);
+ ~instance_gnomeregan() {}
+
+ void Initialize();
+
+ void OnCreatureCreate(Creature* pCreature);
+ void OnObjectCreate(GameObject* pGo);
+
+ void SetData(uint32 uiType, uint32 uiData);
+ uint32 GetData(uint32 uiType);
+ uint64 GetData64(uint32 uiData);
+
+ sBombFace* GetBombFaces();
+ void DoActivateBombFace(uint8 uiIndex);
+ void DoDeactivateBombFace(uint8 uiIndex);
+
+ const char* Save() { return strInstData.c_str(); }
+ void Load(const char* chrIn);
+
+ protected:
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ sBombFace m_asBombFaces[MAX_GNOME_FACES];
+ uint64 m_auiExplosiveSortedGUIDs[2][MAX_EXPLOSIVES_PER_SIDE];
+
+ uint64 m_uiBlastmasterShortfuseGUID;
+ uint64 m_uiCaveInNorthGUID;
+ uint64 m_uiCaveInSouthGUID;
+ uint64 m_uiDoorFinalChamberGUID;
+
+ std::list m_lExplosiveCharges;
+ std::list m_luiSpawnedExplosiveChargeGUIDs;
+ std::list m_lRedRocketGUIDs;
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp b/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp
new file mode 100644
index 0000000..882469e
--- /dev/null
+++ b/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp
@@ -0,0 +1,292 @@
+/* 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_Gnomeregan
+SD%Complete: 90%
+SDComment: Support for Grubbis and Thermaplugg Encounters
+SDCategory: Gnomeregan
+EndScriptData */
+
+#include "precompiled.h"
+#include "gnomeregan.h"
+
+instance_gnomeregan::instance_gnomeregan(Map* pMap) : ScriptedInstance(pMap),
+ m_uiBlastmasterShortfuseGUID(0),
+ m_uiCaveInNorthGUID(0),
+ m_uiCaveInSouthGUID(0),
+ m_uiDoorFinalChamberGUID(0)
+{
+ Initialize();
+}
+
+void instance_gnomeregan::Initialize()
+{
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+ memset(&m_asBombFaces, 0, sizeof(m_asBombFaces));
+ memset(&m_auiExplosiveSortedGUIDs, 0, sizeof(m_auiExplosiveSortedGUIDs));
+}
+
+void instance_gnomeregan::OnCreatureCreate(Creature* pCreature)
+{
+ switch (pCreature->GetEntry())
+ {
+ case NPC_BLASTMASTER_SHORTFUSE: m_uiBlastmasterShortfuseGUID = pCreature->GetGUID(); break;
+ }
+}
+
+void instance_gnomeregan::OnObjectCreate(GameObject* pGo)
+{
+ switch(pGo->GetEntry())
+ {
+ case GO_RED_ROCKET: m_lRedRocketGUIDs.push_back(pGo->GetGUID()); break;
+ case GO_CAVE_IN_NORTH: m_uiCaveInNorthGUID = pGo->GetGUID(); break;
+ case GO_CAVE_IN_SOUTH: m_uiCaveInSouthGUID = pGo->GetGUID(); break;
+ case GO_EXPLOSIVE_CHARGE: m_lExplosiveCharges.push_back(pGo); break;
+ case GO_THE_FINAL_CHAMBER: m_uiDoorFinalChamberGUID = pGo->GetGUID(); break;
+
+ case GO_GNOME_FACE_1: m_asBombFaces[0].m_uiGnomeFaceGUID = pGo->GetGUID(); break;
+ case GO_GNOME_FACE_2: m_asBombFaces[1].m_uiGnomeFaceGUID = pGo->GetGUID(); break;
+ case GO_GNOME_FACE_3: m_asBombFaces[2].m_uiGnomeFaceGUID = pGo->GetGUID(); break;
+ case GO_GNOME_FACE_4: m_asBombFaces[3].m_uiGnomeFaceGUID = pGo->GetGUID(); break;
+ case GO_GNOME_FACE_5: m_asBombFaces[4].m_uiGnomeFaceGUID = pGo->GetGUID(); break;
+ case GO_GNOME_FACE_6: m_asBombFaces[5].m_uiGnomeFaceGUID = pGo->GetGUID(); break;
+ }
+}
+
+static bool sortFromEastToWest(GameObject* pFirst, GameObject* pSecond)
+{
+ return pFirst && pSecond && pFirst->GetPositionY() < pSecond->GetPositionY();
+}
+
+void instance_gnomeregan::SetData(uint32 uiType, uint32 uiData)
+{
+ switch(uiType)
+ {
+ case TYPE_GRUBBIS:
+ m_auiEncounter[0] = uiData;
+ if (uiData == IN_PROGRESS)
+ {
+ // Sort the explosive charges if needed
+ if (!m_lExplosiveCharges.empty())
+ {
+ // Sort from east to west
+ m_lExplosiveCharges.sort(sortFromEastToWest);
+
+ // Sort to south and north
+ uint8 uiCounterSouth = 0;
+ uint8 uiCounterNorth = 0;
+ GameObject* pCaveInSouth = instance->GetGameObject(m_uiCaveInSouthGUID);
+ GameObject* pCaveInNorth = instance->GetGameObject(m_uiCaveInNorthGUID);
+ if (pCaveInSouth && pCaveInNorth)
+ {
+ for (std::list::iterator itr = m_lExplosiveCharges.begin(); itr != m_lExplosiveCharges.end(); itr++)
+ {
+ if ((*itr)->GetDistanceOrder(pCaveInSouth, pCaveInNorth) && uiCounterSouth < MAX_EXPLOSIVES_PER_SIDE)
+ {
+ m_auiExplosiveSortedGUIDs[0][uiCounterSouth] = (*itr)->GetGUID();
+ uiCounterSouth++;
+ }
+ else if (uiCounterNorth < MAX_EXPLOSIVES_PER_SIDE)
+ {
+ m_auiExplosiveSortedGUIDs[1][uiCounterNorth] = (*itr)->GetGUID();
+ uiCounterNorth++;
+ }
+ }
+ m_lExplosiveCharges.clear();
+ }
+ }
+ }
+ if (uiData == FAIL)
+ {
+ // Despawn possible spawned explosive charges
+ SetData(TYPE_EXPLOSIVE_CHARGE, DATA_EXPLOSIVE_CHARGE_USE);
+ }
+ if (uiData == DONE)
+ {
+ for (std::list::const_iterator itr = m_lRedRocketGUIDs.begin(); itr != m_lRedRocketGUIDs.end(); itr++)
+ DoRespawnGameObject(*itr, HOUR);
+ }
+ break;
+ case TYPE_EXPLOSIVE_CHARGE:
+ switch (uiData)
+ {
+ case DATA_EXPLOSIVE_CHARGE_1:
+ DoRespawnGameObject(m_auiExplosiveSortedGUIDs[0][0], HOUR);
+ m_luiSpawnedExplosiveChargeGUIDs.push_back(m_auiExplosiveSortedGUIDs[0][0]);
+ break;
+ case DATA_EXPLOSIVE_CHARGE_2:
+ DoRespawnGameObject(m_auiExplosiveSortedGUIDs[0][1], HOUR);
+ m_luiSpawnedExplosiveChargeGUIDs.push_back(m_auiExplosiveSortedGUIDs[0][1]);
+ break;
+ case DATA_EXPLOSIVE_CHARGE_3:
+ DoRespawnGameObject(m_auiExplosiveSortedGUIDs[1][0], HOUR);
+ m_luiSpawnedExplosiveChargeGUIDs.push_back(m_auiExplosiveSortedGUIDs[1][0]);
+ break;
+ case DATA_EXPLOSIVE_CHARGE_4:
+ DoRespawnGameObject(m_auiExplosiveSortedGUIDs[1][1], HOUR);
+ m_luiSpawnedExplosiveChargeGUIDs.push_back(m_auiExplosiveSortedGUIDs[1][1]);
+ break;
+ case DATA_EXPLOSIVE_CHARGE_USE:
+ Creature* pBlastmaster = instance->GetCreature(m_uiBlastmasterShortfuseGUID);
+ if (!pBlastmaster)
+ break;
+ for (std::list::const_iterator itr = m_luiSpawnedExplosiveChargeGUIDs.begin(); itr != m_luiSpawnedExplosiveChargeGUIDs.end(); itr++)
+ {
+ if (GameObject* pExplosive = instance->GetGameObject(*itr))
+ pExplosive->Use(pBlastmaster);
+ }
+ m_luiSpawnedExplosiveChargeGUIDs.clear();
+ break;
+ }
+ return;
+ case TYPE_THERMAPLUGG:
+ m_auiEncounter[1] = uiData;
+ if (uiData == IN_PROGRESS)
+ {
+ // Make Door locked
+ if (GameObject* pDoor = instance->GetGameObject(m_uiDoorFinalChamberGUID))
+ {
+ if (pDoor->getLootState() == GO_ACTIVATED)
+ pDoor->ResetDoorOrButton();
+
+ // Doesn't work here, because the flags are to be reseted on next tick in GO::Update
+ pDoor->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
+ }
+
+ // Always directly activates this bomb-face
+ DoActivateBombFace(2);
+ }
+ else if (uiData == DONE || uiData == FAIL)
+ {
+ // Make Door unlocked again
+ if (GameObject* pDoor = instance->GetGameObject(m_uiDoorFinalChamberGUID))
+ {
+ if (pDoor->getLootState() == GO_READY)
+ pDoor->UseDoorOrButton();
+ pDoor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
+ }
+
+ // Deactivate all remaining BombFaces
+ for (uint8 i = 0; i < MAX_GNOME_FACES; i++)
+ DoDeactivateBombFace(i);
+ }
+ break;
+ }
+
+ if (uiData == DONE)
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+}
+
+void instance_gnomeregan::Load(const char* chrIn)
+{
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+}
+
+uint32 instance_gnomeregan::GetData(uint32 uiType)
+{
+ switch(uiType)
+ {
+ case TYPE_GRUBBIS: return m_auiEncounter[0];
+ case TYPE_THERMAPLUGG: return m_auiEncounter[1];
+ default:
+ return 0;
+ }
+}
+
+uint64 instance_gnomeregan::GetData64(uint32 uiData)
+{
+ switch(uiData)
+ {
+ case GO_CAVE_IN_NORTH: return m_uiCaveInNorthGUID;
+ case GO_CAVE_IN_SOUTH: return m_uiCaveInSouthGUID;
+ default:
+ return 0;
+ }
+}
+
+sBombFace* instance_gnomeregan::GetBombFaces()
+{
+ return m_asBombFaces;
+}
+
+void instance_gnomeregan::DoActivateBombFace(uint8 uiIndex)
+{
+ if (uiIndex >= MAX_GNOME_FACES)
+ return;
+
+ if (!m_asBombFaces[uiIndex].m_bActivated)
+ {
+ DoUseDoorOrButton(m_asBombFaces[uiIndex].m_uiGnomeFaceGUID);
+ m_asBombFaces[uiIndex].m_bActivated = true;
+ m_asBombFaces[uiIndex].m_uiBombTimer = 3000;
+ }
+}
+
+void instance_gnomeregan::DoDeactivateBombFace(uint8 uiIndex)
+{
+ if (uiIndex >= MAX_GNOME_FACES)
+ return;
+
+ if (m_asBombFaces[uiIndex].m_bActivated)
+ {
+ DoUseDoorOrButton(m_asBombFaces[uiIndex].m_uiGnomeFaceGUID);
+ m_asBombFaces[uiIndex].m_bActivated = false;
+ m_asBombFaces[uiIndex].m_uiBombTimer = 0;
+ }
+}
+
+InstanceData* GetInstanceData_instance_gnomeregan(Map* pMap)
+{
+ return new instance_gnomeregan(pMap);
+}
+
+void AddSC_instance_gnomeregan()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "instance_gnomeregan";
+ pNewScript->GetInstanceData = &GetInstanceData_instance_gnomeregan;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/hinterlands.cpp b/scripts/eastern_kingdoms/hinterlands.cpp
new file mode 100644
index 0000000..e9656bf
--- /dev/null
+++ b/scripts/eastern_kingdoms/hinterlands.cpp
@@ -0,0 +1,341 @@
+/* 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: Hinterlands
+SD%Complete: 100
+SDComment: Quest support: 836, 2742
+SDCategory: The Hinterlands
+EndScriptData */
+
+/* ContentData
+npc_00x09hl
+npc_rinji
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+ /*######
+## npc_00x09hl
+######*/
+
+enum
+{
+ SAY_OOX_START = -1000287,
+ SAY_OOX_AGGRO1 = -1000288,
+ SAY_OOX_AGGRO2 = -1000289,
+ SAY_OOX_AMBUSH = -1000290,
+ SAY_OOX_END = -1000292,
+
+ QUEST_RESQUE_OOX_09 = 836,
+
+ NPC_MARAUDING_OWL = 7808,
+ NPC_VILE_AMBUSHER = 7809
+};
+
+struct MANGOS_DLL_DECL npc_00x09hlAI : public npc_escortAI
+{
+ npc_00x09hlAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void Reset() { }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 26:
+ DoScriptText(SAY_OOX_AMBUSH, m_creature);
+ break;
+ case 43:
+ DoScriptText(SAY_OOX_AMBUSH, m_creature);
+ break;
+ case 64:
+ DoScriptText(SAY_OOX_END, m_creature);
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_RESQUE_OOX_09, m_creature);
+ break;
+ }
+ }
+
+ void WaypointStart(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 27:
+ for(uint8 i = 0; i < 3; ++i)
+ {
+ float fX, fY, fZ;
+ m_creature->GetRandomPoint(147.927444f, -3851.513428f, 130.893f, 7.0f, fX, fY, fZ);
+
+ m_creature->SummonCreature(NPC_MARAUDING_OWL, fX, fY, fZ, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 25000);
+ }
+ break;
+ case 44:
+ for(uint8 i = 0; i < 3; ++i)
+ {
+ float fX, fY, fZ;
+ m_creature->GetRandomPoint(-141.151581f, -4291.213867f, 120.130f, 7.0f, fX, fY, fZ);
+
+ m_creature->SummonCreature(NPC_VILE_AMBUSHER, fX, fY, fZ, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 25000);
+ }
+ break;
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (pWho->GetEntry() == NPC_MARAUDING_OWL || pWho->GetEntry() == NPC_VILE_AMBUSHER)
+ return;
+
+ DoScriptText(urand(0, 1) ? SAY_OOX_AGGRO1 : SAY_OOX_AGGRO2, m_creature);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->GetMotionMaster()->MovePoint(0, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
+ }
+};
+
+bool QuestAccept_npc_00x09hl(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_RESQUE_OOX_09)
+ {
+ pCreature->SetStandState(UNIT_STAND_STATE_STAND);
+ pCreature->setFaction((pPlayer->GetTeam() == ALLIANCE) ? FACTION_ESCORT_A_PASSIVE : FACTION_ESCORT_H_PASSIVE);
+
+ DoScriptText(SAY_OOX_START, pCreature, pPlayer);
+
+ if (npc_00x09hlAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_00x09hl(Creature* pCreature)
+{
+ return new npc_00x09hlAI(pCreature);
+}
+
+/*######
+## npc_rinji
+######*/
+
+enum
+{
+ SAY_RIN_FREE = -1000403,
+ SAY_RIN_BY_OUTRUNNER = -1000404,
+ SAY_RIN_HELP_1 = -1000405,
+ SAY_RIN_HELP_2 = -1000406,
+ SAY_RIN_COMPLETE = -1000407,
+ SAY_RIN_PROGRESS_1 = -1000408,
+ SAY_RIN_PROGRESS_2 = -1000409,
+
+ QUEST_RINJI_TRAPPED = 2742,
+ NPC_RANGER = 2694,
+ NPC_OUTRUNNER = 2691,
+ GO_RINJI_CAGE = 142036
+};
+
+struct Location
+{
+ float m_fX, m_fY, m_fZ;
+};
+
+Location m_afAmbushSpawn[] =
+{
+ {191.29620f, -2839.329346f, 107.388f},
+ {70.972466f, -2848.674805f, 109.459f}
+};
+
+Location m_afAmbushMoveTo[] =
+{
+ {166.63038f, -2824.780273f, 108.153f},
+ {70.886589f, -2874.335449f, 116.675f}
+};
+
+struct MANGOS_DLL_DECL npc_rinjiAI : public npc_escortAI
+{
+ npc_rinjiAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_bIsByOutrunner = false;
+ m_iSpawnId = 0;
+ Reset();
+ }
+
+ bool m_bIsByOutrunner;
+ uint32 m_uiPostEventCount;
+ uint32 m_uiPostEventTimer;
+ int m_iSpawnId;
+
+ void Reset()
+ {
+ m_uiPostEventCount = 0;
+ m_uiPostEventTimer = 3000;
+ }
+
+ void JustRespawned()
+ {
+ m_bIsByOutrunner = false;
+ m_iSpawnId = 0;
+
+ npc_escortAI::JustRespawned();
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ if (pWho->GetEntry() == NPC_OUTRUNNER && !m_bIsByOutrunner)
+ {
+ DoScriptText(SAY_RIN_BY_OUTRUNNER, pWho);
+ m_bIsByOutrunner = true;
+ }
+
+ if (urand(0, 3))
+ return;
+
+ //only if attacked and escorter is not in combat?
+ DoScriptText(urand(0, 1) ? SAY_RIN_HELP_1 : SAY_RIN_HELP_2, m_creature);
+ }
+ }
+
+ void DoSpawnAmbush(bool bFirst)
+ {
+ if (!bFirst)
+ m_iSpawnId = 1;
+
+ m_creature->SummonCreature(NPC_RANGER,
+ m_afAmbushSpawn[m_iSpawnId].m_fX, m_afAmbushSpawn[m_iSpawnId].m_fY, m_afAmbushSpawn[m_iSpawnId].m_fZ, 0.0f,
+ TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
+
+ for(int i = 0; i < 2; ++i)
+ {
+ m_creature->SummonCreature(NPC_OUTRUNNER,
+ m_afAmbushSpawn[m_iSpawnId].m_fX, m_afAmbushSpawn[m_iSpawnId].m_fY, m_afAmbushSpawn[m_iSpawnId].m_fZ, 0.0f,
+ TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pSummoned->GetMotionMaster()->MovePoint(0, m_afAmbushMoveTo[m_iSpawnId].m_fX, m_afAmbushMoveTo[m_iSpawnId].m_fY, m_afAmbushMoveTo[m_iSpawnId].m_fZ);
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch(uiPointId)
+ {
+ case 1:
+ DoScriptText(SAY_RIN_FREE, m_creature, pPlayer);
+ break;
+ case 7:
+ DoSpawnAmbush(true);
+ break;
+ case 13:
+ DoSpawnAmbush(false);
+ break;
+ case 17:
+ DoScriptText(SAY_RIN_COMPLETE, m_creature, pPlayer);
+ pPlayer->GroupEventHappens(QUEST_RINJI_TRAPPED, m_creature);
+ SetRun();
+ m_uiPostEventCount = 1;
+ break;
+ }
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ //Check if we have a current target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && m_uiPostEventCount)
+ {
+ if (m_uiPostEventTimer < uiDiff)
+ {
+ m_uiPostEventTimer = 3000;
+
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ switch(m_uiPostEventCount)
+ {
+ case 1:
+ DoScriptText(SAY_RIN_PROGRESS_1, m_creature, pPlayer);
+ ++m_uiPostEventCount;
+ break;
+ case 2:
+ DoScriptText(SAY_RIN_PROGRESS_2, m_creature, pPlayer);
+ m_uiPostEventCount = 0;
+ break;
+ }
+ }
+ else
+ {
+ m_creature->ForcedDespawn();
+ return;
+ }
+ }
+ else
+ m_uiPostEventTimer -= uiDiff;
+ }
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool QuestAccept_npc_rinji(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_RINJI_TRAPPED)
+ {
+ if (GameObject* pGo = GetClosestGameObjectWithEntry(pCreature, GO_RINJI_CAGE, INTERACTION_DISTANCE))
+ pGo->UseDoorOrButton();
+
+ if (npc_rinjiAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_rinji(Creature* pCreature)
+{
+ return new npc_rinjiAI(pCreature);
+}
+
+void AddSC_hinterlands()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_00x09hl";
+ pNewScript->GetAI = &GetAI_npc_00x09hl;
+ pNewScript->pQuestAccept = &QuestAccept_npc_00x09hl;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_rinji";
+ pNewScript->GetAI = &GetAI_npc_rinji;
+ pNewScript->pQuestAccept = &QuestAccept_npc_rinji;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/ironforge.cpp b/scripts/eastern_kingdoms/ironforge.cpp
new file mode 100644
index 0000000..91f7fa4
--- /dev/null
+++ b/scripts/eastern_kingdoms/ironforge.cpp
@@ -0,0 +1,93 @@
+/* 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: Ironforge
+SD%Complete: 100
+SDComment: Quest support: 3702
+SDCategory: Ironforge
+EndScriptData */
+
+/* ContentData
+npc_royal_historian_archesonus
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_royal_historian_archesonus
+######*/
+
+#define GOSSIP_ITEM_ROYAL "I am ready to listen"
+#define GOSSIP_ITEM_ROYAL_1 "That is tragic. How did this happen?"
+#define GOSSIP_ITEM_ROYAL_2 "Interesting, continue please."
+#define GOSSIP_ITEM_ROYAL_3 "Unbelievable! How dare they??"
+#define GOSSIP_ITEM_ROYAL_4 "Of course I will help!"
+
+bool GossipHello_npc_royal_historian_archesonus(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(3702) == QUEST_STATUS_INCOMPLETE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ pPlayer->SEND_GOSSIP_MENU(2235, pCreature->GetGUID());
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_royal_historian_archesonus(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(2236, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(2237, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->SEND_GOSSIP_MENU(2238, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ROYAL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
+ pPlayer->SEND_GOSSIP_MENU(2239, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(3702);
+ break;
+ }
+ return true;
+}
+
+void AddSC_ironforge()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_royal_historian_archesonus";
+ newscript->pGossipHello = &GossipHello_npc_royal_historian_archesonus;
+ newscript->pGossipSelect = &GossipSelect_npc_royal_historian_archesonus;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/isle_of_queldanas.cpp b/scripts/eastern_kingdoms/isle_of_queldanas.cpp
new file mode 100644
index 0000000..bb24930
--- /dev/null
+++ b/scripts/eastern_kingdoms/isle_of_queldanas.cpp
@@ -0,0 +1,91 @@
+/* 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: Isle_of_Queldanas
+SD%Complete: 100
+SDComment: Quest support: 11524, 11525, 11533, 11543
+SDCategory: Isle Of Quel'Danas
+EndScriptData */
+
+/* ContentData
+npc_ayren_cloudbreaker
+npc_converted_sentry
+npc_unrestrained_dragonhawk
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_converted_sentry
+######*/
+
+#define SAY_CONVERTED_1 -1000188
+#define SAY_CONVERTED_2 -1000189
+
+#define SPELL_CONVERT_CREDIT 45009
+
+struct MANGOS_DLL_DECL npc_converted_sentryAI : public ScriptedAI
+{
+ npc_converted_sentryAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ bool Credit;
+ uint32 Timer;
+
+ void Reset()
+ {
+ Credit = false;
+ Timer = 2500;
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ return;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!Credit)
+ {
+ if (Timer <= diff)
+ {
+ uint32 i = urand(1,2);
+ if (i==1)
+ DoScriptText(SAY_CONVERTED_1, m_creature);
+ else
+ DoScriptText(SAY_CONVERTED_2, m_creature);
+
+ DoCastSpellIfCan(m_creature,SPELL_CONVERT_CREDIT);
+ ((Pet*)m_creature)->SetDuration(7500);
+ Credit = true;
+ }else Timer -= diff;
+ }
+ }
+};
+CreatureAI* GetAI_npc_converted_sentry(Creature* pCreature)
+{
+ return new npc_converted_sentryAI(pCreature);
+}
+
+void AddSC_isle_of_queldanas()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_converted_sentry";
+ newscript->GetAI = &GetAI_npc_converted_sentry;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/boss_curator.cpp b/scripts/eastern_kingdoms/karazhan/boss_curator.cpp
new file mode 100644
index 0000000..2ff7e5a
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_curator.cpp
@@ -0,0 +1,211 @@
+/* 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_Curator
+SD%Complete: 80%
+SDComment:
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_AGGRO = -1532057,
+ SAY_SUMMON1 = -1532058,
+ SAY_SUMMON2 = -1532059,
+ SAY_EVOCATE = -1532060,
+ SAY_ENRAGE = -1532061,
+ SAY_KILL1 = -1532062,
+ SAY_KILL2 = -1532063,
+ SAY_DEATH = -1532064,
+
+ // Flare
+ NPC_ASTRAL_FLARE = 17096,
+ SPELL_ASTRAL_FLARE_PASSIVE = 30234,
+
+ // The Curator
+ SPELL_HATEFUL_BOLT = 30383,
+ SPELL_EVOCATION = 30254,
+ SPELL_ENRAGE = 30403,
+ SPELL_BERSERK = 26662
+};
+
+struct MANGOS_DLL_DECL boss_curatorAI : public ScriptedAI
+{
+ boss_curatorAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiFlareTimer;
+ uint32 m_uiHatefulBoltTimer;
+ uint32 m_uiBerserkTimer;
+
+ bool m_bIsBerserk;
+ bool m_bIsEnraged;
+
+ void Reset()
+ {
+ m_uiFlareTimer = 10000;
+ m_uiHatefulBoltTimer = 15000; // This time may be wrong
+ m_uiBerserkTimer = 12*MINUTE*IN_MILLISECONDS;
+ m_bIsBerserk = false;
+ m_bIsEnraged = false;
+
+ m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_KILL1 : SAY_KILL2, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_ASTRAL_FLARE)
+ {
+ // Flare start with agro on it's target, should be immune to arcane
+ pSummoned->CastSpell(pSummoned, SPELL_ASTRAL_FLARE_PASSIVE, false);
+ pSummoned->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_ARCANE, true);
+
+ if (m_creature->getVictim())
+ {
+ Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1);
+
+ pSummoned->AddThreat(pTarget ? pTarget : m_creature->getVictim(), 1000.0f);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // always decrease BerserkTimer
+ if (!m_bIsBerserk)
+ {
+ if (m_uiBerserkTimer < uiDiff)
+ {
+ // break evocation if we are under it's effect
+ if (m_creature->HasAura(SPELL_EVOCATION))
+ m_creature->RemoveAurasDueToSpell(SPELL_EVOCATION);
+
+ if (DoCastSpellIfCan(m_creature, SPELL_BERSERK, CAST_INTERRUPT_PREVIOUS) == CAST_OK)
+ {
+ // ScriptText needs confirmation
+ DoScriptText(SAY_ENRAGE, m_creature);
+
+ // don't know if he's supposed to do summon/evocate after hard enrage (probably not)
+ m_bIsBerserk = true;
+ }
+ }
+ else
+ m_uiBerserkTimer -= uiDiff;
+ }
+
+ // not supposed to do anything while evocate
+ if (m_creature->HasAura(SPELL_EVOCATION))
+ return;
+
+ if (!m_bIsEnraged && !m_bIsBerserk)
+ {
+ if (m_uiFlareTimer < uiDiff)
+ {
+ m_uiFlareTimer = 10000;
+
+ // summon Astral Flare
+ DoSpawnCreature(NPC_ASTRAL_FLARE, rand()%37, rand()%37, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+
+ // reduce mana by 10% of maximum
+ if (int32 iMana = m_creature->GetMaxPower(POWER_MANA))
+ {
+ m_creature->ModifyPower(POWER_MANA, -(iMana/10));
+
+ //if this get's us below 10%, then we evocate (the 10th should be summoned now
+ if (m_creature->GetPower(POWER_MANA)*10 < m_creature->GetMaxPower(POWER_MANA))
+ {
+ DoScriptText(SAY_EVOCATE, m_creature);
+
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ m_creature->CastSpell(m_creature, SPELL_EVOCATION, false);
+
+ //this small delay should make first flare appear fast after evocate, and also prevent possible spawn flood
+ m_uiFlareTimer = 1000;
+ return;
+ }
+ else
+ {
+ switch(urand(0, 3))
+ {
+ case 0: DoScriptText(SAY_SUMMON1, m_creature); break;
+ case 1: DoScriptText(SAY_SUMMON2, m_creature); break;
+ }
+ }
+ }
+ }
+ else
+ m_uiFlareTimer -= uiDiff;
+
+ if (m_creature->GetHealthPercent() < 15.0f)
+ {
+ if (!m_creature->IsNonMeleeSpellCasted(false))
+ {
+ m_bIsEnraged = true;
+ DoScriptText(SAY_ENRAGE, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ }
+ }
+ }
+
+ if (m_uiHatefulBoltTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 1))
+ m_creature->CastSpell(pTarget, SPELL_HATEFUL_BOLT, false);
+
+ m_uiHatefulBoltTimer = m_bIsEnraged ? 7000 : 15000;
+ }
+ else
+ m_uiHatefulBoltTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_curator(Creature* pCreature)
+{
+ return new boss_curatorAI(pCreature);
+}
+
+void AddSC_boss_curator()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_curator";
+ newscript->GetAI = &GetAI_boss_curator;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp b/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp
new file mode 100644
index 0000000..3ab3921
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp
@@ -0,0 +1,159 @@
+/* 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_Maiden_of_Virtue
+SD%Complete: 100
+SDComment:
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_AGGRO = -1532018,
+ SAY_SLAY1 = -1532019,
+ SAY_SLAY2 = -1532020,
+ SAY_SLAY3 = -1532021,
+ SAY_REPENTANCE1 = -1532022,
+ SAY_REPENTANCE2 = -1532023,
+ SAY_DEATH = -1532024,
+
+ SPELL_REPENTANCE = 29511,
+ SPELL_HOLYFIRE = 29522,
+ SPELL_HOLYWRATH = 32445,
+ SPELL_HOLYGROUND = 29512
+};
+
+struct MANGOS_DLL_DECL boss_maiden_of_virtueAI : public ScriptedAI
+{
+ boss_maiden_of_virtueAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiRepentance_Timer;
+ uint32 m_uiHolyfire_Timer;
+ uint32 m_uiHolywrath_Timer;
+ uint32 m_uiHolyground_Timer;
+
+ void Reset()
+ {
+ m_uiRepentance_Timer = urand(25000, 40000);
+ m_uiHolyfire_Timer = urand(8000, 25000);
+ m_uiHolywrath_Timer = urand(15000, 25000);
+ m_uiHolyground_Timer = 3000;
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ switch(urand(0, 5)) // 50% chance to say something out of 3 texts
+ {
+ case 0: DoScriptText(SAY_SLAY1, m_creature); break;
+ case 1: DoScriptText(SAY_SLAY2, m_creature); break;
+ case 2: DoScriptText(SAY_SLAY3, m_creature); break;
+ }
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+ void Aggro(Unit *pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiHolyground_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HOLYGROUND, CAST_TRIGGERED); //Triggered so it doesn't interrupt her at all
+ m_uiHolyground_Timer = 3000;
+ }
+ else
+ m_uiHolyground_Timer -= uiDiff;
+
+ if (m_uiRepentance_Timer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_REPENTANCE) == CAST_OK)
+ {
+ DoScriptText(urand(0, 1) ? SAY_REPENTANCE1 : SAY_REPENTANCE2, m_creature);
+
+ //A little randomness on that spell
+ m_uiRepentance_Timer = urand(25000, 35000);
+ }
+ }
+ else
+ m_uiRepentance_Timer -= uiDiff;
+
+ if (m_uiHolyfire_Timer < uiDiff)
+ {
+ //Time for an omgwtfpwn code to make maiden cast holy fire only on units outside the holy ground's 18 yard range
+ Unit* pTarget = NULL;
+ std::vector target_list;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
+ {
+ pTarget = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
+
+ if (pTarget && !pTarget->IsWithinDist(m_creature, 12.0f, false))
+ target_list.push_back(pTarget);
+
+ pTarget = NULL;
+ }
+
+ if (target_list.size())
+ {
+ if (pTarget = *(target_list.begin()+rand()%target_list.size()))
+ DoCastSpellIfCan(pTarget,SPELL_HOLYFIRE);
+ }
+
+ m_uiHolyfire_Timer = urand(8000, 23000); //Anywhere from 8 to 23 seconds, good luck having several of those in a row!
+ }
+ else
+ m_uiHolyfire_Timer -= uiDiff;
+
+ if (m_uiHolywrath_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget, SPELL_HOLYWRATH);
+
+ m_uiHolywrath_Timer = urand(20000, 25000); //20-25 secs sounds nice
+ }
+ else
+ m_uiHolywrath_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_maiden_of_virtue(Creature* pCreature)
+{
+ return new boss_maiden_of_virtueAI(pCreature);
+}
+
+void AddSC_boss_maiden_of_virtue()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_maiden_of_virtue";
+ newscript->GetAI = &GetAI_boss_maiden_of_virtue;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp b/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp
new file mode 100644
index 0000000..def618a
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp
@@ -0,0 +1,351 @@
+/* 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_Midnight
+SD%Complete: 90
+SDComment: Use SPELL_SUMMON_ATTUMEN and SPELL_SUMMON_ATTUMEN_MOUNTED instead of SummonCreature.
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_MIDNIGHT_KILL = -1532000,
+ SAY_APPEAR1 = -1532001,
+ SAY_APPEAR2 = -1532002,
+ SAY_APPEAR3 = -1532003,
+ SAY_MOUNT = -1532004,
+ SAY_KILL1 = -1532005,
+ SAY_KILL2 = -1532006,
+ SAY_DISARMED = -1532007,
+ SAY_DEATH = -1532008,
+ SAY_RANDOM1 = -1532009,
+ SAY_RANDOM2 = -1532010,
+
+ SPELL_SHADOWCLEAVE = 29832,
+ SPELL_INTANGIBLE_PRESENCE = 29833,
+ SPELL_BERSERKER_CHARGE = 26561, //Only when mounted
+ SPELL_SUMMON_ATTUMEN = 29714,
+ SPELL_SUMMON_ATTUMEN_MOUNTED= 29799,
+
+ MOUNTED_DISPLAYID = 16040, // should use creature 16152 instead of changing displayid
+
+ //Attumen (TODO: Use the summoning spell instead of creature id. It works , but is not convenient for us)
+ SUMMON_ATTUMEN = 15550
+};
+
+struct MANGOS_DLL_DECL boss_midnightAI : public ScriptedAI
+{
+ boss_midnightAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint64 m_uiAttumenGUID;
+ uint8 m_uiPhase;
+ uint32 m_uiMount_Timer;
+
+ void Reset()
+ {
+ m_uiPhase = 1;
+ m_uiAttumenGUID = 0;
+ m_uiMount_Timer = 0;
+
+ m_creature->SetVisibility(VISIBILITY_ON);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (m_uiPhase == 2)
+ {
+ if (Creature* pAttumen = m_creature->GetMap()->GetCreature(m_uiAttumenGUID))
+ DoScriptText(SAY_MIDNIGHT_KILL, pAttumen);
+ }
+ }
+
+ void Mount(Creature* pAttumen)
+ {
+ DoScriptText(SAY_MOUNT, pAttumen);
+ m_uiPhase = 3;
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ pAttumen->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ float fAngle = m_creature->GetAngle(pAttumen);
+ float fDistance = m_creature->GetDistance2d(pAttumen);
+
+ float fNewX = m_creature->GetPositionX() + cos(fAngle)*(fDistance/2) ;
+ float fNewY = m_creature->GetPositionY() + sin(fAngle)*(fDistance/2) ;
+ float fNewZ = 50.0f;
+
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MovePoint(0, fNewX, fNewY, fNewZ);
+
+ fDistance += 10.0f;
+ fNewX = m_creature->GetPositionX() + cos(fAngle)*(fDistance/2);
+ fNewY = m_creature->GetPositionY() + sin(fAngle)*(fDistance/2);
+
+ pAttumen->GetMotionMaster()->Clear();
+ pAttumen->GetMotionMaster()->MovePoint(0, fNewX, fNewY, fNewZ);
+
+ m_uiMount_Timer = 1000;
+ }
+
+ void SetMidnight(Creature *, uint64); //Below ..
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ switch(m_uiPhase)
+ {
+ case 1:
+ if (m_creature->GetHealthPercent() < 95.0f)
+ {
+ m_uiPhase = 2;
+
+ if (Creature* pAttumen = m_creature->SummonCreature(SUMMON_ATTUMEN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 30000))
+ {
+ m_uiAttumenGUID = pAttumen->GetGUID();
+ pAttumen->AI()->AttackStart(m_creature->getVictim());
+ SetMidnight(pAttumen, m_creature->GetGUID());
+
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_APPEAR1, pAttumen); break;
+ case 1: DoScriptText(SAY_APPEAR2, pAttumen); break;
+ case 2: DoScriptText(SAY_APPEAR3, pAttumen); break;
+ }
+ }
+ }
+ break;
+ case 2:
+ if (m_creature->GetHealthPercent() < 25.0f)
+ {
+ if (Creature* pAttumen = m_creature->GetMap()->GetCreature(m_uiAttumenGUID))
+ Mount(pAttumen);
+ }
+ break;
+ case 3:
+ if (m_uiMount_Timer)
+ {
+ if (m_uiMount_Timer <= uiDiff)
+ {
+ m_uiMount_Timer = 0;
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ m_creature->GetMotionMaster()->MoveIdle();
+
+ if (Creature *pAttumen = m_creature->GetMap()->GetCreature(m_uiAttumenGUID))
+ {
+ pAttumen->SetDisplayId(MOUNTED_DISPLAYID);
+ pAttumen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ if (pAttumen->getVictim())
+ {
+ pAttumen->GetMotionMaster()->MoveChase(pAttumen->getVictim());
+ pAttumen->SetUInt64Value(UNIT_FIELD_TARGET, pAttumen->getVictim()->GetGUID());
+ }
+ pAttumen->SetFloatValue(OBJECT_FIELD_SCALE_X,1);
+ }
+ }
+ else
+ m_uiMount_Timer -= uiDiff;
+ }
+ break;
+ }
+
+ if (m_uiPhase != 3)
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_midnight(Creature* pCreature)
+{
+ return new boss_midnightAI(pCreature);
+}
+
+struct MANGOS_DLL_DECL boss_attumenAI : public ScriptedAI
+{
+ boss_attumenAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ Reset();
+ m_uiPhase = 1;
+
+ m_uiCleaveTimer = urand(10000, 16000);
+ m_uiCurseTimer = 30000;
+ m_uiRandomYellTimer = urand(30000, 60000); //Occasionally yell
+ m_uiChargeTimer = 20000;
+ m_uiResetTimer = 0;
+ }
+
+ uint64 m_uiMidnightGUID;
+ uint8 m_uiPhase;
+ uint32 m_uiCleaveTimer;
+ uint32 m_uiCurseTimer;
+ uint32 m_uiRandomYellTimer;
+ uint32 m_uiChargeTimer; //only when mounted
+ uint32 m_uiResetTimer;
+
+ void Reset()
+ {
+ m_uiResetTimer = 2000;
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_KILL1 : SAY_KILL2, m_creature);
+ }
+
+ void SpellHit(Unit* pSource, const SpellEntry* pSpell)
+ {
+ if (pSpell->Mechanic == MECHANIC_DISARM)
+ DoScriptText(SAY_DISARMED, m_creature);
+ }
+
+ void JustDied(Unit* pVictim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (Creature* pMidnight = m_creature->GetMap()->GetCreature(m_uiMidnightGUID))
+ pMidnight->DealDamage(pMidnight, pMidnight->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_uiResetTimer)
+ {
+ if (m_uiResetTimer <= uiDiff)
+ {
+ m_uiResetTimer = 0;
+
+ if (Creature *pMidnight = m_creature->GetMap()->GetCreature(m_uiMidnightGUID))
+ {
+ pMidnight->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ pMidnight->SetVisibility(VISIBILITY_ON);
+ }
+ m_uiMidnightGUID = 0;
+
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ else
+ m_uiResetTimer -= uiDiff;
+ }
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE))
+ return;
+
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOWCLEAVE);
+ m_uiCleaveTimer = urand(10000, 16000);
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ if (m_uiCurseTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_INTANGIBLE_PRESENCE);
+ m_uiCurseTimer = 30000;
+ }
+ else
+ m_uiCurseTimer -= uiDiff;
+
+ if (m_uiRandomYellTimer < uiDiff)
+ {
+ DoScriptText(urand(0, 1) ? SAY_RANDOM1 : SAY_RANDOM2, m_creature);
+ m_uiRandomYellTimer = urand(30000, 60000);
+ }
+ else
+ m_uiRandomYellTimer -= uiDiff;
+
+ if (m_creature->GetDisplayId() == MOUNTED_DISPLAYID)
+ {
+ if (m_uiChargeTimer < uiDiff)
+ {
+ Unit *target = NULL;
+ std::vector target_list;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
+ {
+ target = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
+
+ if (target && !target->IsWithinDist(m_creature, ATTACK_DISTANCE, false))
+ target_list.push_back(target);
+
+ target = NULL;
+ }
+
+ if (target_list.size())
+ {
+ if (target = *(target_list.begin()+rand()%target_list.size()))
+ DoCastSpellIfCan(target, SPELL_BERSERKER_CHARGE);
+ }
+
+ m_uiChargeTimer = 20000;
+ }
+ else
+ m_uiChargeTimer -= uiDiff;
+ }
+ else
+ {
+ if (m_creature->GetHealthPercent() < 25.0f)
+ {
+ if (Creature *pMidnight = m_creature->GetMap()->GetCreature(m_uiMidnightGUID))
+ {
+ if (boss_midnightAI* pMidnightAI = dynamic_cast(pMidnight->AI()))
+ pMidnightAI->Mount(m_creature);
+
+ m_creature->SetHealth(pMidnight->GetHealth());
+ DoResetThreat();
+ }
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+void boss_midnightAI::SetMidnight(Creature* pAttumen, uint64 uiValue)
+{
+ if (boss_attumenAI* pAttumenAI = dynamic_cast(pAttumen->AI()))
+ pAttumenAI->m_uiMidnightGUID = uiValue;
+}
+
+CreatureAI* GetAI_boss_attumen(Creature* pCreature)
+{
+ return new boss_attumenAI(pCreature);
+}
+
+void AddSC_boss_attumen()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_attumen";
+ newscript->GetAI = &GetAI_boss_attumen;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_midnight";
+ newscript->GetAI = &GetAI_boss_midnight;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp b/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp
new file mode 100644
index 0000000..83653f0
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp
@@ -0,0 +1,843 @@
+/* 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_Moroes
+SD%Complete: 95
+SDComment:
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+#include "karazhan.h"
+
+enum
+{
+ SAY_AGGRO = -1532011,
+ SAY_SPECIAL_1 = -1532012,
+ SAY_SPECIAL_2 = -1532013,
+ SAY_KILL_1 = -1532014,
+ SAY_KILL_2 = -1532015,
+ SAY_KILL_3 = -1532016,
+ SAY_DEATH = -1532017,
+
+ SPELL_VANISH = 29448,
+ SPELL_GARROTE = 37066,
+ SPELL_BLIND = 34694,
+ SPELL_GOUGE = 29425,
+ SPELL_FRENZY = 37023
+};
+
+const float afLocations[4][4]=
+{
+ {-10991.0f, -1884.33f, 81.73f, 0.614315f},
+ {-10989.4f, -1885.88f, 81.73f, 0.904913f},
+ {-10978.1f, -1887.07f, 81.73f, 2.035550f},
+ {-10975.9f, -1885.81f, 81.73f, 2.253890f}
+};
+
+const uint32 auiAdds[6]=
+{
+ 17007,
+ 19872,
+ 19873,
+ 19874,
+ 19875,
+ 19876
+};
+
+struct MANGOS_DLL_DECL boss_moroesAI : public ScriptedAI
+{
+ boss_moroesAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_bFirstTime = true;
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint64 m_auiAddGUID[4];
+ uint32 m_auiAddId[4];
+
+ uint32 m_uiVanish_Timer;
+ uint32 m_uiBlind_Timer;
+ uint32 m_uiGouge_Timer;
+ uint32 m_uiWait_Timer;
+ uint32 m_uiCheckAdds_Timer;
+
+ bool m_bFirstTime;
+ bool m_bInVanish;
+ bool m_bEnrage;
+
+ void Reset()
+ {
+ m_uiVanish_Timer = 30000;
+ m_uiBlind_Timer = 35000;
+ m_uiGouge_Timer = 23000;
+ m_uiWait_Timer = 0;
+ m_uiCheckAdds_Timer = 5000;
+
+ m_bEnrage = false;
+ m_bInVanish = false;
+
+ SpawnAdds();
+
+ m_creature->setFaction(16);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_MOROES, NOT_STARTED);
+ }
+
+ void StartEvent()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_MOROES, IN_PROGRESS);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ StartEvent();
+ DoScriptText(SAY_AGGRO, m_creature);
+ AddsAttack();
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ 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 JustDied(Unit* pVictim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_MOROES, DONE);
+
+ //remove aura from spell Garrote when Moroes dies
+ Map* pMap = m_creature->GetMap();
+ if (pMap->IsDungeon())
+ {
+ Map::PlayerList const &PlayerList = pMap->GetPlayers();
+
+ if (PlayerList.isEmpty())
+ return;
+
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ {
+ if (i->getSource()->isAlive() && i->getSource()->HasAura(SPELL_GARROTE, EFFECT_INDEX_0))
+ i->getSource()->RemoveAurasDueToSpell(SPELL_GARROTE);
+ }
+ }
+ }
+
+ void SpawnAdds()
+ {
+ if (m_bFirstTime)
+ {
+ std::vector vAddList;
+
+ for(uint8 i = 0; i < 6; ++i)
+ vAddList.push_back(auiAdds[i]);
+
+ while(vAddList.size() > 4)
+ vAddList.erase((vAddList.begin())+(rand()%vAddList.size()));
+
+ uint8 i = 0;
+ for(std::vector::iterator itr = vAddList.begin(); itr != vAddList.end(); ++itr, ++i)
+ {
+ if (Creature* pCreature = m_creature->SummonCreature(*itr, afLocations[i][0], afLocations[i][1], afLocations[i][2], afLocations[i][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000))
+ {
+ m_auiAddGUID[i] = pCreature->GetGUID();
+ m_auiAddId[i] = *itr;
+ }
+ }
+
+ m_bFirstTime = false;
+ }
+ else
+ {
+ for(uint8 i = 0; i < 4; ++i)
+ {
+ if (Creature* pCreature = m_creature->GetMap()->GetCreature(m_auiAddGUID[i]))
+ {
+ if (!pCreature->isAlive()) // Exists but is dead
+ {
+ pCreature->Respawn();
+ pCreature->AI()->EnterEvadeMode();
+ }
+ else if (!pCreature->IsInEvadeMode()) // Exists and is alive
+ {
+ pCreature->AI()->EnterEvadeMode();
+ }
+ }
+ else
+ { // Does not exist
+ if (Creature* pCreature = m_creature->SummonCreature(m_auiAddId[i], afLocations[i][0], afLocations[i][1], afLocations[i][2], afLocations[i][3], TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000))
+ m_auiAddGUID[i] = pCreature->GetGUID();
+ }
+ }
+ }
+ }
+
+ void AddsAttack()
+ {
+ for(uint8 i = 0; i < 4; ++i)
+ {
+ if (m_auiAddGUID[i])
+ {
+ Creature* pTemp = m_creature->GetMap()->GetCreature(m_auiAddGUID[i]);
+ if (pTemp && pTemp->isAlive())
+ pTemp->AI()->AttackStart(m_creature->getVictim());
+ else
+ EnterEvadeMode();
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_pInstance && !m_pInstance->GetData(TYPE_MOROES))
+ EnterEvadeMode();
+
+ if (!m_bEnrage && m_creature->GetHealthPercent() < 30.0f)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FRENZY);
+ m_bEnrage = true;
+ }
+
+ if (m_uiCheckAdds_Timer < uiDiff)
+ {
+ for (uint8 i = 0; i < 4; ++i)
+ {
+ if (m_auiAddGUID[i])
+ {
+ Creature* pTemp = m_creature->GetMap()->GetCreature(m_auiAddGUID[i]);
+ if (pTemp && pTemp->isAlive() && (!pTemp->SelectHostileTarget() || !pTemp->getVictim()))
+ pTemp->AI()->AttackStart(m_creature->getVictim());
+ }
+ }
+ m_uiCheckAdds_Timer = 5000;
+ }
+ else
+ m_uiCheckAdds_Timer -= uiDiff;
+
+ if (!m_bEnrage)
+ {
+ // Cast Vanish, then Garrote random victim
+ if (m_uiVanish_Timer < uiDiff)
+ {
+ m_creature->setFaction(35);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ DoCastSpellIfCan(m_creature, SPELL_VANISH);
+ m_bInVanish = true;
+ m_uiVanish_Timer = 30000;
+ m_uiWait_Timer = 5000;
+ }
+ else
+ m_uiVanish_Timer -= uiDiff;
+
+ if (m_bInVanish)
+ {
+ if (m_uiWait_Timer < uiDiff)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SPECIAL_1 : SAY_SPECIAL_2, m_creature);
+
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ pTarget->CastSpell(pTarget, SPELL_GARROTE, true);
+
+ m_creature->setFaction(16);
+ 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_bInVanish = false;
+ }
+ else
+ m_uiWait_Timer -= uiDiff;
+ }
+
+ //Gouge highest aggro, and attack second highest
+ if (m_uiGouge_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_GOUGE);
+ m_uiGouge_Timer = 40000;
+ }
+ else
+ m_uiGouge_Timer -= uiDiff;
+
+ if (m_uiBlind_Timer < uiDiff)
+ {
+ Unit* pTarget = NULL;
+
+ ThreatList const& vThreatList = m_creature->getThreatManager().getThreatList();
+ if (vThreatList.empty())
+ return;
+
+ std::vector vTargetList;
+
+ for (ThreatList::const_iterator itr = vThreatList.begin();itr != vThreatList.end(); ++itr)
+ {
+ pTarget = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
+
+ if (pTarget && pTarget->IsWithinDist(m_creature, ATTACK_DISTANCE, false))
+ vTargetList.push_back(pTarget);
+ }
+
+ if (!vTargetList.empty())
+ pTarget = *(vTargetList.begin()+rand()%vTargetList.size());
+
+ if (pTarget)
+ DoCastSpellIfCan(pTarget, SPELL_BLIND);
+
+ m_uiBlind_Timer = 40000;
+ }
+ else
+ m_uiBlind_Timer -= uiDiff;
+ }
+
+ if (!m_bInVanish)
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_moroes_guestAI : public ScriptedAI
+{
+ ScriptedInstance* m_pInstance;
+
+ uint64 m_auiGuestGUID[4];
+
+ boss_moroes_guestAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ memset(&m_auiGuestGUID, 0, sizeof(m_auiGuestGUID));
+
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ AcquireGUID();
+ Reset();
+ }
+
+ void Reset()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_MOROES, NOT_STARTED);
+ }
+
+ void AcquireGUID()
+ {
+ if (!m_pInstance)
+ return;
+
+ m_auiGuestGUID[0] = m_pInstance->GetData64(DATA_MOROES);
+
+ if (Creature* pMoroes = m_creature->GetMap()->GetCreature(m_auiGuestGUID[0]))
+ {
+ for(uint8 i = 0; i < 3; ++i)
+ {
+ uint64 uiGUID = 0;
+
+ if (boss_moroesAI* pMoroesAI = dynamic_cast(pMoroes->AI()))
+ uiGUID = pMoroesAI->m_auiAddGUID[i];
+
+ if (uiGUID && uiGUID != m_creature->GetGUID())
+ m_auiGuestGUID[i+1] = uiGUID;
+ }
+ }
+ }
+
+ Unit* SelectTarget()
+ {
+ if (uint64 uiTempGUID = m_auiGuestGUID[rand()%4])
+ {
+ Creature* pTemp = m_creature->GetMap()->GetCreature(uiTempGUID);
+ if (pTemp && pTemp->isAlive())
+ return pTemp;
+ }
+
+ return m_creature;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_pInstance && !m_pInstance->GetData(TYPE_MOROES))
+ EnterEvadeMode();
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+enum
+{
+ SPELL_MANABURN = 29405,
+ SPELL_MINDFLY = 29570,
+ SPELL_SWPAIN = 34441,
+ SPELL_SHADOWFORM = 29406
+};
+
+struct MANGOS_DLL_DECL boss_baroness_dorothea_millstipeAI : public boss_moroes_guestAI
+{
+ //Shadow Priest
+ boss_baroness_dorothea_millstipeAI(Creature* pCreature) : boss_moroes_guestAI(pCreature) { Reset(); }
+
+ uint32 m_uiManaBurn_Timer;
+ uint32 m_uiMindFlay_Timer;
+ uint32 m_uiShadowWordPain_Timer;
+
+ void Reset()
+ {
+ m_uiManaBurn_Timer = 7000;
+ m_uiMindFlay_Timer = 1000;
+ m_uiShadowWordPain_Timer = 6000;
+
+ DoCastSpellIfCan(m_creature, SPELL_SHADOWFORM, CAST_TRIGGERED);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_moroes_guestAI::UpdateAI(uiDiff);
+
+ if (m_uiMindFlay_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MINDFLY);
+ m_uiMindFlay_Timer = 12000; //3sec channeled
+ }
+ else
+ m_uiMindFlay_Timer -= uiDiff;
+
+ if (m_uiManaBurn_Timer < uiDiff)
+ {
+ Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+ if (pTarget && pTarget->getPowerType() == POWER_MANA)
+ DoCastSpellIfCan(pTarget, SPELL_MANABURN);
+
+ m_uiManaBurn_Timer = 5000; //3 sec cast
+ }
+ else
+ m_uiManaBurn_Timer -= uiDiff;
+
+ if (m_uiShadowWordPain_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ DoCastSpellIfCan(pTarget, SPELL_SWPAIN);
+ m_uiShadowWordPain_Timer = 7000;
+ }
+ }
+ else
+ m_uiShadowWordPain_Timer -= uiDiff;
+ }
+};
+
+enum
+{
+ SPELL_HAMMEROFJUSTICE = 13005,
+ SPELL_JUDGEMENTOFCOMMAND = 29386,
+ SPELL_SEALOFCOMMAND = 29385
+};
+
+struct MANGOS_DLL_DECL boss_baron_rafe_dreugerAI : public boss_moroes_guestAI
+{
+ //Retr Pally
+ boss_baron_rafe_dreugerAI(Creature* pCreature) : boss_moroes_guestAI(pCreature) { Reset(); }
+
+ uint32 m_uiHammerOfJustice_Timer;
+ uint32 m_uiSealOfCommand_Timer;
+ uint32 m_uiJudgementOfCommand_Timer;
+
+ void Reset()
+ {
+ m_uiHammerOfJustice_Timer = 1000;
+ m_uiSealOfCommand_Timer = 7000;
+ m_uiJudgementOfCommand_Timer = m_uiSealOfCommand_Timer + 29000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_moroes_guestAI::UpdateAI(uiDiff);
+
+ if (m_uiSealOfCommand_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_SEALOFCOMMAND);
+ m_uiSealOfCommand_Timer = 32000;
+ m_uiJudgementOfCommand_Timer = 29000;
+ }
+ else
+ m_uiSealOfCommand_Timer -= uiDiff;
+
+ if (m_uiJudgementOfCommand_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_JUDGEMENTOFCOMMAND);
+ m_uiJudgementOfCommand_Timer = m_uiSealOfCommand_Timer + 29000;
+ }
+ else
+ m_uiJudgementOfCommand_Timer -= uiDiff;
+
+ if (m_uiHammerOfJustice_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAMMEROFJUSTICE);
+ m_uiHammerOfJustice_Timer = 12000;
+ }
+ else
+ m_uiHammerOfJustice_Timer -= uiDiff;
+ }
+};
+
+enum
+{
+ SPELL_DISPELMAGIC = 15090, // Self or other guest+Moroes
+ SPELL_GREATERHEAL = 29564, // Self or other guest+Moroes
+ SPELL_HOLYFIRE = 29563,
+ SPELL_PWSHIELD = 29408
+};
+
+struct MANGOS_DLL_DECL boss_lady_catriona_von_indiAI : public boss_moroes_guestAI
+{
+ //Holy Priest
+ boss_lady_catriona_von_indiAI(Creature* pCreature) : boss_moroes_guestAI(pCreature) { Reset(); }
+
+ uint32 m_uiDispelMagic_Timer;
+ uint32 m_uiGreaterHeal_Timer;
+ uint32 m_uiHolyFire_Timer;
+ uint32 m_uiPowerWordShield_Timer;
+
+ void Reset()
+ {
+ m_uiDispelMagic_Timer = 11000;
+ m_uiGreaterHeal_Timer = 1500;
+ m_uiHolyFire_Timer = 5000;
+ m_uiPowerWordShield_Timer = 1000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_moroes_guestAI::UpdateAI(uiDiff);
+
+ if (m_uiPowerWordShield_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_PWSHIELD);
+ m_uiPowerWordShield_Timer = 15000;
+ }
+ else
+ m_uiPowerWordShield_Timer -= uiDiff;
+
+ if (m_uiGreaterHeal_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(SelectTarget(), SPELL_GREATERHEAL);
+ m_uiGreaterHeal_Timer = 17000;
+ }
+ else
+ m_uiGreaterHeal_Timer -= uiDiff;
+
+ if (m_uiHolyFire_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HOLYFIRE);
+ m_uiHolyFire_Timer = 22000;
+ }
+ else
+ m_uiHolyFire_Timer -= uiDiff;
+
+ if (m_uiDispelMagic_Timer < uiDiff)
+ {
+ if (Unit* pTarget = urand(0, 1) ? SelectTarget() : m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_DISPELMAGIC);
+
+ m_uiDispelMagic_Timer = 25000;
+ }
+ else
+ m_uiDispelMagic_Timer -= uiDiff;
+ }
+};
+
+enum
+{
+ SPELL_CLEANSE = 29380, //Self or other guest+Moroes
+ SPELL_GREATERBLESSOFMIGHT = 29381, //Self or other guest+Moroes
+ SPELL_HOLYLIGHT = 29562, //Self or other guest+Moroes
+ SPELL_DIVINESHIELD = 41367
+};
+
+struct MANGOS_DLL_DECL boss_lady_keira_berrybuckAI : public boss_moroes_guestAI
+{
+ //Holy Pally
+ boss_lady_keira_berrybuckAI(Creature* pCreature) : boss_moroes_guestAI(pCreature) { Reset(); }
+
+ uint32 m_uiCleanse_Timer;
+ uint32 m_uiGreaterBless_Timer;
+ uint32 m_uiHolyLight_Timer;
+ uint32 m_uiDivineShield_Timer;
+
+ void Reset()
+ {
+ m_uiCleanse_Timer = 13000;
+ m_uiGreaterBless_Timer = 1000;
+ m_uiHolyLight_Timer = 7000;
+ m_uiDivineShield_Timer = 31000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_moroes_guestAI::UpdateAI(uiDiff);
+
+ if (m_uiDivineShield_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_DIVINESHIELD);
+ m_uiDivineShield_Timer = 31000;
+ }
+ else
+ m_uiDivineShield_Timer -= uiDiff;
+
+ if (m_uiHolyLight_Timer < uiDiff)
+ {
+ DoCast(SelectTarget(), SPELL_HOLYLIGHT);
+ m_uiHolyLight_Timer = 10000;
+ }
+ else
+ m_uiHolyLight_Timer -= uiDiff;
+
+ if (m_uiGreaterBless_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(SelectTarget(), SPELL_GREATERBLESSOFMIGHT);
+ m_uiGreaterBless_Timer = 50000;
+ }
+ else
+ m_uiGreaterBless_Timer -= uiDiff;
+
+ if (m_uiCleanse_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(SelectTarget(), SPELL_CLEANSE);
+ m_uiCleanse_Timer = 10000;
+ }
+ else
+ m_uiCleanse_Timer -= uiDiff;
+ }
+};
+
+enum
+{
+ SPELL_HAMSTRING = 9080,
+ SPELL_MORTALSTRIKE = 29572,
+ SPELL_WHIRLWIND = 29573
+};
+
+struct MANGOS_DLL_DECL boss_lord_robin_darisAI : public boss_moroes_guestAI
+{
+ //Arms Warr
+ boss_lord_robin_darisAI(Creature* pCreature) : boss_moroes_guestAI(pCreature) { Reset(); }
+
+ uint32 m_uiHamstring_Timer;
+ uint32 m_uiMortalStrike_Timer;
+ uint32 m_uiWhirlWind_Timer;
+
+ void Reset()
+ {
+ m_uiHamstring_Timer = 7000;
+ m_uiMortalStrike_Timer = 10000;
+ m_uiWhirlWind_Timer = 21000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_moroes_guestAI::UpdateAI(uiDiff);
+
+ if (m_uiHamstring_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAMSTRING);
+ m_uiHamstring_Timer = 12000;
+ }
+ else
+ m_uiHamstring_Timer -= uiDiff;
+
+ if (m_uiMortalStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTALSTRIKE);
+ m_uiMortalStrike_Timer = 18000;
+ }
+ else
+ m_uiMortalStrike_Timer -= uiDiff;
+
+ if (m_uiWhirlWind_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_WHIRLWIND);
+ m_uiWhirlWind_Timer = 21000;
+ }
+ else
+ m_uiWhirlWind_Timer -= uiDiff;
+ }
+};
+
+enum
+{
+ SPELL_DISARM = 8379,
+ SPELL_HEROICSTRIKE = 29567,
+ SPELL_SHIELDBASH = 11972,
+ SPELL_SHIELDWALL = 29390
+};
+
+struct MANGOS_DLL_DECL boss_lord_crispin_ferenceAI : public boss_moroes_guestAI
+{
+ //Arms Warr
+ boss_lord_crispin_ferenceAI(Creature* pCreature) : boss_moroes_guestAI(pCreature) { Reset(); }
+
+ uint32 m_uiDisarm_Timer;
+ uint32 m_uiHeroicStrike_Timer;
+ uint32 m_uiShieldBash_Timer;
+ uint32 m_uiShieldWall_Timer;
+
+ void Reset()
+ {
+ m_uiDisarm_Timer = 6000;
+ m_uiHeroicStrike_Timer = 10000;
+ m_uiShieldBash_Timer = 8000;
+ m_uiShieldWall_Timer = 4000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_moroes_guestAI::UpdateAI(uiDiff);
+
+ if (m_uiDisarm_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_DISARM);
+ m_uiDisarm_Timer = 12000;
+ }
+ else
+ m_uiDisarm_Timer -= uiDiff;
+
+ if (m_uiHeroicStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HEROICSTRIKE);
+ m_uiHeroicStrike_Timer = 10000;
+ }else m_uiHeroicStrike_Timer -= uiDiff;
+
+ if (m_uiShieldBash_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHIELDBASH);
+ m_uiShieldBash_Timer = 13000;
+ }
+ else
+ m_uiShieldBash_Timer -= uiDiff;
+
+ if (m_uiShieldWall_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_SHIELDWALL);
+ m_uiShieldWall_Timer = 21000;
+ }
+ else
+ m_uiShieldWall_Timer -= uiDiff;
+ }
+};
+
+CreatureAI* GetAI_boss_moroes(Creature* pCreature)
+{
+ return new boss_moroesAI(pCreature);
+}
+
+CreatureAI* GetAI_baroness_dorothea_millstipe(Creature* pCreature)
+{
+ return new boss_baroness_dorothea_millstipeAI(pCreature);
+}
+
+CreatureAI* GetAI_baron_rafe_dreuger(Creature* pCreature)
+{
+ return new boss_baron_rafe_dreugerAI(pCreature);
+}
+
+CreatureAI* GetAI_lady_catriona_von_indi(Creature* pCreature)
+{
+ return new boss_lady_catriona_von_indiAI(pCreature);
+}
+
+CreatureAI* GetAI_lady_keira_berrybuck(Creature* pCreature)
+{
+ return new boss_lady_keira_berrybuckAI(pCreature);
+}
+
+CreatureAI* GetAI_lord_robin_daris(Creature* pCreature)
+{
+ return new boss_lord_robin_darisAI(pCreature);
+}
+
+CreatureAI* GetAI_lord_crispin_ference(Creature* pCreature)
+{
+ return new boss_lord_crispin_ferenceAI(pCreature);
+}
+
+void AddSC_boss_moroes()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_moroes";
+ newscript->GetAI = &GetAI_boss_moroes;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_baroness_dorothea_millstipe";
+ newscript->GetAI = &GetAI_baroness_dorothea_millstipe;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_baron_rafe_dreuger";
+ newscript->GetAI = &GetAI_baron_rafe_dreuger;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_lady_catriona_von_indi";
+ newscript->GetAI = &GetAI_lady_catriona_von_indi;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_lady_keira_berrybuck";
+ newscript->GetAI = &GetAI_lady_keira_berrybuck;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_lord_robin_daris";
+ newscript->GetAI = &GetAI_lord_robin_daris;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_lord_crispin_ference";
+ newscript->GetAI = &GetAI_lord_crispin_ference;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp b/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp
new file mode 100644
index 0000000..8b8f392
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp
@@ -0,0 +1,228 @@
+/* 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_Netherspite
+SD%Complete: 30%
+SDComment: find spell ID for tail swipe added in patch 3.0.2
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+#include "karazhan.h"
+
+enum
+{
+ //netherspite spells
+ SPELL_NETHERBURN = 30522,
+ SPELL_VOID_ZONE = 37063,
+ SPELL_NETHERBREATH = 38523,
+ SPELL_EMPOWERMENT = 38549,
+ SPELL_NETHER_INFUSION = 38688,
+ SPELL_NETHERSPITE_ROAR = 38684,
+ SPELL_BANISH_VISUAL = 39833,
+ SPELL_ROOT = 42716,
+
+ //void zone spells
+ SPELL_CONSUMPTION = 30497,
+
+ //beam buffs
+ SPELL_PERSEVERENCE_NS = 30466,
+ SPELL_PERSEVERENCE_PLR = 30421,
+ SPELL_SERENITY_NS = 30467,
+ SPELL_SERENITY_PLR = 30422,
+ SPELL_DOMINANCE_NS = 30468,
+ SPELL_DOMINANCE_PLR = 30423,
+
+ //beam debuffs
+ SPELL_EXHAUSTION_DOM = 38639,
+ SPELL_EXHAUSTION_SER = 38638,
+ SPELL_EXHAUSTION_PER = 38637,
+
+ //beam spells
+ SPELL_BEAM_DOM = 30402,
+ SPELL_BEAM_SER = 30401,
+ SPELL_BEAM_PER = 30400,
+ SPELL_BLUE_PORTAL = 30491,
+ SPELL_GREEN_PORTAL = 30490,
+ SPELL_RED_PORTAL = 30487,
+
+ //emotes
+ EMOTE_PHASE_BEAM = -1532089,
+ EMOTE_PHASE_BANISH = -1532090,
+
+ //npcs
+ NPC_PORTAL_CREATURE = 17369,
+ NPC_VOID_ZONE = 16697
+};
+
+struct SpawnLocation
+{
+ float x, y, z;
+};
+
+// at first spawn portals got fixed coords, should be shuffled in subsequent beam phases
+static SpawnLocation PortalCoordinates[] =
+{
+ {-11105.508789f, -1600.851685f, 279.950256f},
+ {-11195.353516f, -1613.237183f, 278.237258f},
+ {-11137.846680f, -1685.607422f, 278.239258f}
+};
+
+enum Phases
+{
+ BEAM_PHASE = 0,
+ BANISH_PHASE = 1,
+};
+
+struct MANGOS_DLL_DECL boss_netherspiteAI : public ScriptedAI
+{
+ boss_netherspiteAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ bool m_bIsEnraged;
+ uint8 m_uiActivePhase;
+
+ uint32 m_uiEnrageTimer;
+ uint32 m_uiVoidZoneTimer;
+ uint32 m_uiPhaseSwitchTimer;
+ uint32 m_uiNetherbreathTimer;
+
+
+ void Reset()
+ {
+ m_bIsEnraged = false;
+ m_uiActivePhase = BEAM_PHASE;
+
+ m_uiEnrageTimer = MINUTE*9*IN_MILLISECONDS;
+ m_uiVoidZoneTimer = 15000;
+ m_uiPhaseSwitchTimer = MINUTE*IN_MILLISECONDS;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_NETHERSPITE, IN_PROGRESS);
+
+ DoCastSpellIfCan(m_creature, SPELL_NETHERBURN);
+ m_creature->SetInCombatWithZone();
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_NETHERSPITE, DONE);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_NETHERSPITE, NOT_STARTED);
+ }
+
+ void SwitchPhases()
+ {
+ if (m_uiActivePhase == BEAM_PHASE)
+ {
+ m_uiActivePhase = BANISH_PHASE;
+ DoScriptText(EMOTE_PHASE_BANISH, m_creature);
+
+ m_uiNetherbreathTimer = 500;
+ m_uiPhaseSwitchTimer = (MINUTE/2)*IN_MILLISECONDS;
+ }
+ else
+ {
+ m_uiActivePhase = BEAM_PHASE;
+ DoScriptText(EMOTE_PHASE_BEAM, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_NETHERSPITE_ROAR);
+
+ m_uiPhaseSwitchTimer = MINUTE*IN_MILLISECONDS;
+ }
+
+ //reset threat every phase switch
+ DoResetThreat();
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiPhaseSwitchTimer <= uiDiff)
+ SwitchPhases();
+ else
+ m_uiPhaseSwitchTimer -= uiDiff;
+
+ if (!m_bIsEnraged)
+ {
+ if (m_uiEnrageTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_NETHER_INFUSION, CAST_FORCE_CAST);
+ m_bIsEnraged = true;
+ }
+ else
+ m_uiEnrageTimer -= uiDiff;
+ }
+
+ if (m_uiActivePhase == BEAM_PHASE)
+ {
+ if (m_uiVoidZoneTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_VOID_ZONE, true);
+
+ m_uiVoidZoneTimer = 15000;
+ }
+ else
+ m_uiVoidZoneTimer -= uiDiff;
+
+ }
+ else
+ {
+ if (m_uiNetherbreathTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_NETHERBREATH);
+
+ m_uiNetherbreathTimer = urand(4000, 5000);
+ }
+ else
+ m_uiNetherbreathTimer -= uiDiff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_netherspite(Creature* pCreature)
+{
+ return new boss_netherspiteAI(pCreature);
+}
+
+void AddSC_boss_netherspite()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_netherspite";
+ newscript->GetAI = &GetAI_boss_netherspite;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp b/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp
new file mode 100644
index 0000000..9087abb
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp
@@ -0,0 +1,36 @@
+/* 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_Nightbane
+SD%Complete: 0
+SDComment: Place holder
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_BELLOWING_ROAR = 39427,
+ SPELL_CHARRED_EARTH = 30129, //Also 30209 (Target Charred Earth) triggers this
+ SPELL_DISTRACTING_ASH = 30130,
+ SPELL_SMOLDERING_BREATH = 30210,
+ SPELL_TAIL_SWEEP = 25653,
+ SPELL_RAIN_OF_BONES = 37098,
+ SPELL_SMOKING_BLAST = 37057,
+ SPELL_FIREBALL_BARRAGE = 30282
+};
diff --git a/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp b/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp
new file mode 100644
index 0000000..b6d8ade
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp
@@ -0,0 +1,644 @@
+/* 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_Prince_Malchezzar
+SD%Complete: 100
+SDComment:
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_AGGRO -1532091
+#define SAY_AXE_TOSS1 -1532092
+#define SAY_AXE_TOSS2 -1532093
+#define SAY_SPECIAL1 -1532094
+#define SAY_SPECIAL2 -1532095
+#define SAY_SPECIAL3 -1532096
+#define SAY_SLAY1 -1532097
+#define SAY_SLAY2 -1532098
+#define SAY_SLAY3 -1532099
+#define SAY_SUMMON1 -1532100
+#define SAY_SUMMON2 -1532101
+#define SAY_DEATH -1532102
+
+// 18 Coordinates for Infernal spawns
+struct InfernalPoint
+{
+ float x,y;
+};
+
+#define INFERNAL_Z 275.5
+
+static InfernalPoint InfernalPoints[] =
+{
+ {-10922.8f, -1985.2f},
+ {-10916.2f, -1996.2f},
+ {-10932.2f, -2008.1f},
+ {-10948.8f, -2022.1f},
+ {-10958.7f, -1997.7f},
+ {-10971.5f, -1997.5f},
+ {-10990.8f, -1995.1f},
+ {-10989.8f, -1976.5f},
+ {-10971.6f, -1973.0f},
+ {-10955.5f, -1974.0f},
+ {-10939.6f, -1969.8f},
+ {-10958.0f, -1952.2f},
+ {-10941.7f, -1954.8f},
+ {-10943.1f, -1988.5f},
+ {-10948.8f, -2005.1f},
+ {-10984.0f, -2019.3f},
+ {-10932.8f, -1979.6f},
+ {-10935.7f, -1996.0f}
+};
+
+#define TOTAL_INFERNAL_POINTS 18
+
+//Enfeeble is supposed to reduce hp to 1 and then heal player back to full when it ends
+//Along with reducing healing and regen while enfeebled to 0%
+//This spell effect will only reduce healing
+
+#define SPELL_ENFEEBLE 30843 //Enfeeble during phase 1 and 2
+#define SPELL_ENFEEBLE_EFFECT 41624
+
+#define SPELL_SHADOWNOVA 30852 //Shadownova used during all phases
+#define SPELL_SW_PAIN 30854 //Shadow word pain during phase 1 and 3 (different targeting rules though)
+#define SPELL_THRASH_PASSIVE 12787 //Extra attack chance during phase 2
+#define SPELL_SUNDER_ARMOR 30901 //Sunder armor during phase 2
+#define SPELL_THRASH_AURA 12787 //Passive proc chance for thrash
+#define SPELL_EQUIP_AXES 30857 //Visual for axe equiping
+#define SPELL_AMPLIFY_DAMAGE 39095 //Amplifiy during phase 3
+#define SPELL_CLEAVE 30131 //Same as Nightbane.
+#define SPELL_HELLFIRE 30859 //Infenals' hellfire aura
+#define NETHERSPITE_INFERNAL 17646 //The netherspite infernal creature
+#define MALCHEZARS_AXE 17650 //Malchezar's axes (creatures), summoned during phase 3
+
+#define INFERNAL_MODEL_INVISIBLE 11686 //Infernal Effects
+#define SPELL_INFERNAL_RELAY 30834
+
+#define EQUIP_ID_AXE 33542 //Axes info
+
+//---------Infernal code first
+struct MANGOS_DLL_DECL netherspite_infernalAI : public ScriptedAI
+{
+ netherspite_infernalAI(Creature* pCreature) : ScriptedAI(pCreature) ,
+ malchezaar(0), HellfireTimer(0), CleanupTimer(0), point(NULL) {Reset();}
+
+ uint32 HellfireTimer;
+ uint32 CleanupTimer;
+ uint64 malchezaar;
+ InfernalPoint *point;
+
+ void Reset() {}
+ void MoveInLineOfSight(Unit *who) {}
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (HellfireTimer)
+ {
+ if (HellfireTimer <= diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HELLFIRE);
+ HellfireTimer = 0;
+ } else HellfireTimer -= diff;
+ }
+
+ if (CleanupTimer)
+ {
+ if (CleanupTimer <= diff)
+ {
+ Cleanup();
+ CleanupTimer = 0;
+ } else CleanupTimer -= diff;
+ }
+ }
+
+ void KilledUnit(Unit *who)
+ {
+ if (Creature *pMalchezaar = m_creature->GetMap()->GetCreature(malchezaar))
+ pMalchezaar->AI()->KilledUnit(who);
+ }
+
+ void SpellHit(Unit *who, const SpellEntry *spell)
+ {
+ if (spell->Id == SPELL_INFERNAL_RELAY)
+ {
+ m_creature->SetDisplayId(m_creature->GetUInt32Value(UNIT_FIELD_NATIVEDISPLAYID));
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ HellfireTimer = 4000;
+ CleanupTimer = 170000;
+ }
+ }
+
+ void DamageTaken(Unit *done_by, uint32 &damage)
+ {
+ if (done_by->GetGUID() != malchezaar)
+ damage = 0;
+ }
+
+ void Cleanup(); //below ...
+};
+
+struct MANGOS_DLL_DECL boss_malchezaarAI : public ScriptedAI
+{
+ boss_malchezaarAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ for(uint8 i =0; i < 2; ++i)
+ axes[i] = 0;
+
+ Reset();
+ }
+
+ uint32 EnfeebleTimer;
+ uint32 EnfeebleResetTimer;
+ uint32 ShadowNovaTimer;
+ uint32 SWPainTimer;
+ uint32 SunderArmorTimer;
+ uint32 AmplifyDamageTimer;
+ uint32 Cleave_Timer;
+ uint32 InfernalTimer;
+ uint32 AxesTargetSwitchTimer;
+ uint32 InfernalCleanupTimer;
+
+ std::vector infernals;
+ std::vector positions;
+
+ uint64 axes[2];
+ uint64 enfeeble_targets[5];
+ uint64 enfeeble_health[5];
+
+ uint32 phase;
+
+ void Reset()
+ {
+ AxesCleanup();
+ ClearWeapons();
+ InfernalCleanup();
+ positions.clear();
+
+ for(int i =0; i < 5; ++i)
+ {
+ enfeeble_targets[i] = 0;
+ enfeeble_health[i] = 0;
+ }
+
+ for(int i = 0; i < TOTAL_INFERNAL_POINTS; ++i)
+ positions.push_back(&InfernalPoints[i]);
+
+ EnfeebleTimer = 30000;
+ EnfeebleResetTimer = 38000;
+ ShadowNovaTimer = 35500;
+ SWPainTimer = 20000;
+ AmplifyDamageTimer = 5000;
+ Cleave_Timer = 8000;
+ InfernalTimer = 45000;
+ InfernalCleanupTimer = 47000;
+ AxesTargetSwitchTimer = urand(7500, 20000);
+ SunderArmorTimer = urand(5000, 10000);
+ phase = 1;
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_SLAY1, m_creature); break;
+ case 1: DoScriptText(SAY_SLAY2, m_creature); break;
+ case 2: DoScriptText(SAY_SLAY3, m_creature); break;
+ }
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ AxesCleanup();
+ ClearWeapons();
+ InfernalCleanup();
+ positions.clear();
+
+ for(int i = 0; i < TOTAL_INFERNAL_POINTS; ++i)
+ positions.push_back(&InfernalPoints[i]);
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void InfernalCleanup()
+ {
+ //Infernal Cleanup
+ for(std::vector::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr)
+ {
+ Creature *pInfernal = m_creature->GetMap()->GetCreature(*itr);
+ if (pInfernal && pInfernal->isAlive())
+ {
+ pInfernal->SetVisibility(VISIBILITY_OFF);
+ pInfernal->SetDeathState(JUST_DIED);
+ }
+ }
+ infernals.clear();
+ }
+
+ void AxesCleanup()
+ {
+ for(int i=0; i<2;++i)
+ {
+ Creature *axe = m_creature->GetMap()->GetCreature(axes[i]);
+ if (axe && axe->isAlive())
+ axe->DealDamage(axe, axe->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ axes[i] = 0;
+ }
+ }
+
+ void ClearWeapons()
+ {
+ SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_UNEQUIP, EQUIP_NO_CHANGE);
+
+ //damage
+ const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, cinfo->mindmg);
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, cinfo->maxdmg);
+ m_creature->UpdateDamagePhysical(BASE_ATTACK);
+ }
+
+ void EnfeebleHealthEffect()
+ {
+ const SpellEntry *info = GetSpellStore()->LookupEntry(SPELL_ENFEEBLE_EFFECT);
+ if (!info)
+ return;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ std::vector targets;
+
+ if (tList.empty())
+ return;
+
+ //begin + 1 , so we don't target the one with the highest threat
+ ThreatList::const_iterator itr = tList.begin();
+ std::advance(itr, 1);
+ for(; itr!= tList.end(); ++itr) //store the threat list in a different container
+ {
+ Unit *target = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
+ //only on alive players
+ if (target && target->isAlive() && target->GetTypeId() == TYPEID_PLAYER)
+ targets.push_back(target);
+ }
+
+ //cut down to size if we have more than 5 targets
+ while(targets.size() > 5)
+ targets.erase(targets.begin()+rand()%targets.size());
+
+ int i = 0;
+ for(std::vector::iterator iter = targets.begin(); iter!= targets.end(); ++iter, ++i)
+ {
+ Unit *target = *iter;
+ if (target)
+ {
+ enfeeble_targets[i] = target->GetGUID();
+ enfeeble_health[i] = target->GetHealth();
+
+ target->CastSpell(target, SPELL_ENFEEBLE, true, 0, 0, m_creature->GetGUID());
+ target->SetHealth(1);
+ }
+ }
+
+ }
+
+ void EnfeebleResetHealth()
+ {
+ for(int i = 0; i < 5; ++i)
+ {
+ Player* pTarget = m_creature->GetMap()->GetPlayer(enfeeble_targets[i]);
+
+ if (pTarget && pTarget->isAlive())
+ pTarget->SetHealth(enfeeble_health[i]);
+
+ enfeeble_targets[i] = 0;
+ enfeeble_health[i] = 0;
+ }
+ }
+
+ void SummonInfernal(const uint32 diff)
+ {
+ InfernalPoint *point = NULL;
+ float posX,posY,posZ;
+ if ((m_creature->GetMapId() != 532) || positions.empty())
+ {
+ m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 60, posX, posY, posZ);
+ }
+ else
+ {
+ std::vector::iterator itr = positions.begin()+rand()%positions.size();
+ point = *itr;
+ positions.erase(itr);
+
+ posX = point->x;
+ posY = point->y;
+ posZ = INFERNAL_Z;
+ }
+
+ Creature *Infernal = m_creature->SummonCreature(NETHERSPITE_INFERNAL, posX, posY, posZ, 0, TEMPSUMMON_TIMED_DESPAWN, 180000);
+
+ if (Infernal)
+ {
+ Infernal->SetDisplayId(INFERNAL_MODEL_INVISIBLE);
+ Infernal->setFaction(m_creature->getFaction());
+
+ netherspite_infernalAI* pInfernalAI = dynamic_cast(Infernal->AI());
+
+ if (pInfernalAI)
+ {
+ if (point)
+ pInfernalAI->point = point;
+
+ pInfernalAI->malchezaar = m_creature->GetGUID();
+ }
+
+ infernals.push_back(Infernal->GetGUID());
+ DoCastSpellIfCan(Infernal, SPELL_INFERNAL_RELAY);
+ }
+
+ DoScriptText(urand(0, 1) ? SAY_SUMMON1 : SAY_SUMMON2, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (EnfeebleResetTimer)
+ {
+ if (EnfeebleResetTimer <= diff) //Let's not forget to reset that
+ {
+ EnfeebleResetHealth();
+ EnfeebleResetTimer=0;
+ } else EnfeebleResetTimer -= diff;
+ }
+
+ if (m_creature->hasUnitState(UNIT_STAT_STUNNED)) //While shifting to phase 2 malchezaar stuns himself
+ return;
+
+ if (m_creature->GetUInt64Value(UNIT_FIELD_TARGET)!=m_creature->getVictim()->GetGUID())
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, m_creature->getVictim()->GetGUID());
+
+ if (phase == 1)
+ {
+ if (m_creature->GetHealthPercent() < 60.0f)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+
+ phase = 2;
+
+ //animation
+ DoCastSpellIfCan(m_creature, SPELL_EQUIP_AXES);
+
+ //text
+ DoScriptText(SAY_AXE_TOSS1, m_creature);
+
+ //passive thrash aura
+ m_creature->CastSpell(m_creature, SPELL_THRASH_AURA, true);
+
+ //models
+ SetEquipmentSlots(false, EQUIP_ID_AXE, EQUIP_ID_AXE, EQUIP_NO_CHANGE);
+
+ //damage
+ const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 2*cinfo->mindmg);
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 2*cinfo->maxdmg);
+ m_creature->UpdateDamagePhysical(BASE_ATTACK);
+
+ m_creature->SetBaseWeaponDamage(OFF_ATTACK, MINDAMAGE, cinfo->mindmg);
+ m_creature->SetBaseWeaponDamage(OFF_ATTACK, MAXDAMAGE, cinfo->maxdmg);
+ //Sigh, updating only works on main attack , do it manually ....
+ m_creature->SetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE, cinfo->mindmg);
+ m_creature->SetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE, cinfo->maxdmg);
+
+ m_creature->SetAttackTime(OFF_ATTACK, (m_creature->GetAttackTime(BASE_ATTACK)*150)/100);
+ }
+ }
+ else if (phase == 2)
+ {
+ if (m_creature->GetHealthPercent() < 30.0f)
+ {
+ InfernalTimer = 15000;
+
+ phase = 3;
+
+ ClearWeapons();
+
+ //remove thrash
+ m_creature->RemoveAurasDueToSpell(SPELL_THRASH_AURA);
+
+ DoScriptText(SAY_AXE_TOSS2, m_creature);
+
+ Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+ for(uint32 i=0; i<2; ++i)
+ {
+ Creature *axe = m_creature->SummonCreature(MALCHEZARS_AXE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000);
+ if (axe)
+ {
+ axe->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ axe->setFaction(m_creature->getFaction());
+
+ axes[i] = axe->GetGUID();
+ if (target)
+ {
+ axe->AI()->AttackStart(target);
+ // axe->getThreatManager().tauntApply(target); //Taunt Apply and fade out does not work properly
+ // So we'll use a hack to add a lot of threat to our target
+ axe->AddThreat(target, 10000000.0f);
+ }
+ }
+ }
+
+ if (ShadowNovaTimer > 35000)
+ ShadowNovaTimer = EnfeebleTimer + 5000;
+
+ return;
+ }
+
+ if (SunderArmorTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUNDER_ARMOR);
+ SunderArmorTimer = urand(10000, 18000);
+
+ }else SunderArmorTimer -= diff;
+
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ Cleave_Timer = urand(6000, 12000);
+
+ }else Cleave_Timer -= diff;
+ }
+ else
+ {
+ if (AxesTargetSwitchTimer < diff)
+ {
+ AxesTargetSwitchTimer = urand(7500, 20000);
+
+ Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+ if (target)
+ {
+ for(int i = 0; i < 2; ++i)
+ {
+ Creature *axe = m_creature->GetMap()->GetCreature(axes[i]);
+ if (axe)
+ {
+ float threat = 1000000.0f;
+ if (axe->getVictim() && m_creature->getThreatManager().getThreat(axe->getVictim()))
+ {
+ threat = axe->getThreatManager().getThreat(axe->getVictim());
+ axe->getThreatManager().modifyThreatPercent(axe->getVictim(), -100);
+ }
+ if (target)
+ axe->AddThreat(target, threat);
+ //axe->getThreatManager().tauntFadeOut(axe->getVictim());
+ //axe->getThreatManager().tauntApply(target);
+ }
+ }
+ }
+ } else AxesTargetSwitchTimer -= diff;
+
+ if (AmplifyDamageTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_AMPLIFY_DAMAGE);
+
+ AmplifyDamageTimer = urand(20000, 30000);
+ }else AmplifyDamageTimer -= diff;
+ }
+
+ //Time for global and double timers
+ if (InfernalTimer < diff)
+ {
+ SummonInfernal(diff);
+ InfernalTimer = phase == 3 ? 14500 : 44500; //15 secs in phase 3, 45 otherwise
+ }else InfernalTimer -= diff;
+
+ if (ShadowNovaTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOWNOVA);
+ ShadowNovaTimer = phase == 3 ? 31000 : -1;
+ } else ShadowNovaTimer -= diff;
+
+ if (phase != 2)
+ {
+ if (SWPainTimer < diff)
+ {
+ Unit* target = NULL;
+ if (phase == 1)
+ target = m_creature->getVictim(); // the tank
+ else //anyone but the tank
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1);
+
+ if (target)
+ DoCastSpellIfCan(target, SPELL_SW_PAIN);
+
+ SWPainTimer = 20000;
+ }else SWPainTimer -= diff;
+ }
+
+ if (phase != 3)
+ {
+ if (EnfeebleTimer < diff)
+ {
+ EnfeebleHealthEffect();
+ EnfeebleTimer = 30000;
+ ShadowNovaTimer = 5000;
+ EnfeebleResetTimer = 9000;
+ }else EnfeebleTimer -= diff;
+ }
+
+ if (phase==2)
+ DoMeleeAttacksIfReady();
+ else
+ DoMeleeAttackIfReady();
+ }
+
+ void DoMeleeAttacksIfReady()
+ {
+ if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE) && !m_creature->IsNonMeleeSpellCasted(false))
+ {
+ //Check for base attack
+ if (m_creature->isAttackReady() && m_creature->getVictim())
+ {
+ m_creature->AttackerStateUpdate(m_creature->getVictim());
+ m_creature->resetAttackTimer();
+ }
+ //Check for offhand attack
+ if (m_creature->isAttackReady(OFF_ATTACK) && m_creature->getVictim())
+ {
+ m_creature->AttackerStateUpdate(m_creature->getVictim(), OFF_ATTACK);
+ m_creature->resetAttackTimer(OFF_ATTACK);
+ }
+ }
+ }
+
+ void Cleanup(Creature *infernal, InfernalPoint *point)
+ {
+ for(std::vector::iterator itr = infernals.begin(); itr!= infernals.end(); ++itr)
+ if (*itr == infernal->GetGUID())
+ {
+ infernals.erase(itr);
+ break;
+ }
+
+ positions.push_back(point);
+ }
+};
+
+void netherspite_infernalAI::Cleanup()
+{
+ Creature* pMalchezaar = m_creature->GetMap()->GetCreature(malchezaar);
+
+ if (pMalchezaar && pMalchezaar->isAlive())
+ {
+ if (boss_malchezaarAI* pMalAI = dynamic_cast(pMalchezaar->AI()))
+ pMalAI->Cleanup(m_creature, point);
+ }
+}
+
+CreatureAI* GetAI_netherspite_infernal(Creature* pCreature)
+{
+ return new netherspite_infernalAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_malchezaar(Creature* pCreature)
+{
+ return new boss_malchezaarAI(pCreature);
+}
+
+void AddSC_netherspite_infernal()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "netherspite_infernal";
+ newscript->GetAI = &GetAI_netherspite_infernal;
+ newscript->RegisterSelf();
+}
+
+void AddSC_boss_malchezaar()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_malchezaar";
+ newscript->GetAI = &GetAI_boss_malchezaar;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp b/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp
new file mode 100644
index 0000000..dbebf3b
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp
@@ -0,0 +1,559 @@
+/* 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_Shade_of_Aran
+SD%Complete: 95
+SDComment: Flame wreath missing cast animation, mods won't trigger.
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+#include "karazhan.h"
+#include "GameObject.h"
+
+enum
+{
+ SAY_AGGRO1 = -1532073,
+ SAY_AGGRO2 = -1532074,
+ SAY_AGGRO3 = -1532075,
+ SAY_FLAMEWREATH1 = -1532076,
+ SAY_FLAMEWREATH2 = -1532077,
+ SAY_BLIZZARD1 = -1532078,
+ SAY_BLIZZARD2 = -1532079,
+ SAY_EXPLOSION1 = -1532080,
+ SAY_EXPLOSION2 = -1532081,
+ SAY_DRINK = -1532082, //Low Mana / AoE Pyroblast
+ SAY_ELEMENTALS = -1532083,
+ SAY_KILL1 = -1532084,
+ SAY_KILL2 = -1532085,
+ SAY_TIMEOVER = -1532086,
+ SAY_DEATH = -1532087,
+ SAY_ATIESH = -1532088, //Atiesh is equipped by a raid member
+
+ //Spells
+ SPELL_FROSTBOLT = 29954,
+ SPELL_FIREBALL = 29953,
+ SPELL_ARCMISSLE = 29955,
+ SPELL_CHAINSOFICE = 29991,
+ SPELL_DRAGONSBREATH = 29964,
+ SPELL_MASSSLOW = 30035,
+ SPELL_FLAME_WREATH = 29946,
+ SPELL_AOE_CS = 29961,
+ SPELL_PLAYERPULL = 32265,
+ SPELL_AEXPLOSION = 29973,
+ SPELL_MASS_POLY = 29963,
+ SPELL_BLINK_CENTER = 29967,
+ SPELL_ELEMENTALS = 29962,
+ SPELL_CONJURE = 29975,
+ SPELL_DRINK = 30024,
+ SPELL_POTION = 32453,
+ SPELL_AOE_PYROBLAST = 29978,
+
+ SPELL_EXPLOSION = 20476,
+ SPELL_KNOCKBACK_500 = 11027,
+
+ //Creature Spells
+ SPELL_CIRCULAR_BLIZZARD = 29951, //29952 is the REAL circular blizzard that leaves persistant blizzards that last for 10 seconds
+ SPELL_WATERBOLT = 31012,
+ SPELL_SHADOW_PYRO = 29978,
+
+ //Creatures
+ NPC_WATER_ELEMENTAL = 17167,
+ NPC_SHADOW_OF_ARAN = 18254,
+ NPC_ARAN_BLIZZARD = 17161
+};
+
+enum SuperSpell
+{
+ SUPER_FLAME = 0,
+ SUPER_BLIZZARD,
+ SUPER_AE,
+};
+
+struct MANGOS_DLL_DECL boss_aranAI : public ScriptedAI
+{
+ boss_aranAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiSecondarySpell_Timer;
+ uint32 m_uiNormalCast_Timer;
+ uint32 m_uiSuperCast_Timer;
+ uint32 m_uiBerserk_Timer;
+ uint32 m_uiCloseDoor_Timer; // Don't close the door right on aggro in case some people are still entering.
+
+ uint8 m_uiLastSuperSpell;
+
+ uint32 m_uiFlameWreath_Timer;
+ uint32 m_uiFlameWreathCheck_Timer;
+ uint64 m_uiFlameWreathTarget[3];
+ float m_fFWTargPosX[3];
+ float m_fFWTargPosY[3];
+
+ uint32 m_uiCurrentNormalSpell;
+ uint32 m_uiArcaneCooldown;
+ uint32 m_uiFireCooldown;
+ uint32 m_uiFrostCooldown;
+
+ uint32 m_uiDrinkInturrupt_Timer;
+
+ bool m_bElementalsSpawned;
+ bool m_bDrinking;
+ bool m_bDrinkInturrupted;
+
+ void Reset()
+ {
+ m_uiSecondarySpell_Timer = 5000;
+ m_uiNormalCast_Timer = 0;
+ m_uiSuperCast_Timer = 35000;
+ m_uiBerserk_Timer = 720000;
+ m_uiCloseDoor_Timer = 15000;
+
+ m_uiLastSuperSpell = urand(0, 2);
+
+ m_uiFlameWreath_Timer = 0;
+ m_uiFlameWreathCheck_Timer = 0;
+
+ m_uiCurrentNormalSpell = 0;
+ m_uiArcaneCooldown = 0;
+ m_uiFireCooldown = 0;
+ m_uiFrostCooldown = 0;
+
+ m_uiDrinkInturrupt_Timer = 10000;
+
+ m_bElementalsSpawned = false;
+ m_bDrinking = false;
+ m_bDrinkInturrupted = false;
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARAN, NOT_STARTED);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_KILL1 : SAY_KILL2, m_creature);
+ }
+
+ void JustDied(Unit* pVictim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARAN, DONE);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_AGGRO1, m_creature); break;
+ case 1: DoScriptText(SAY_AGGRO2, m_creature); break;
+ case 2: DoScriptText(SAY_AGGRO3, m_creature); break;
+ }
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARAN, IN_PROGRESS);
+ }
+
+ void FlameWreathEffect()
+ {
+ std::vector targets;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ if (tList.empty())
+ return;
+
+ //store the threat list in a different container
+ for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
+ {
+ Unit* pTarget = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
+
+ //only on alive players
+ if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER)
+ targets.push_back(pTarget);
+ }
+
+ //cut down to size if we have more than 3 targets
+ while(targets.size() > 3)
+ targets.erase(targets.begin()+rand()%targets.size());
+
+ uint32 i = 0;
+ for(std::vector::iterator itr = targets.begin(); itr!= targets.end(); ++itr)
+ {
+ if (*itr)
+ {
+ m_uiFlameWreathTarget[i] = (*itr)->GetGUID();
+ m_fFWTargPosX[i] = (*itr)->GetPositionX();
+ m_fFWTargPosY[i] = (*itr)->GetPositionY();
+ m_creature->CastSpell((*itr), SPELL_FLAME_WREATH, true);
+ ++i;
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiCloseDoor_Timer)
+ {
+ if (m_uiCloseDoor_Timer <= uiDiff)
+ {
+ if (m_pInstance)
+ {
+ if (GameObject* pDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_GO_LIBRARY_DOOR)))
+ pDoor->SetGoState(GO_STATE_READY);
+
+ m_uiCloseDoor_Timer = 0;
+ }
+ }
+ else
+ m_uiCloseDoor_Timer -= uiDiff;
+ }
+
+ //Cooldowns for casts
+ if (m_uiArcaneCooldown)
+ {
+ if (m_uiArcaneCooldown >= uiDiff)
+ m_uiArcaneCooldown -= uiDiff;
+ else
+ m_uiArcaneCooldown = 0;
+ }
+
+ if (m_uiFireCooldown)
+ {
+ if (m_uiFireCooldown >= uiDiff)
+ m_uiFireCooldown -= uiDiff;
+ else
+ m_uiFireCooldown = 0;
+ }
+
+ if (m_uiFrostCooldown)
+ {
+ if (m_uiFrostCooldown >= uiDiff)
+ m_uiFrostCooldown -= uiDiff;
+ else
+ m_uiFrostCooldown = 0;
+ }
+
+ if (!m_bDrinking && m_creature->GetMaxPower(POWER_MANA) && (m_creature->GetPower(POWER_MANA)*100 / m_creature->GetMaxPower(POWER_MANA)) < 20)
+ {
+ m_bDrinking = true;
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoScriptText(SAY_DRINK, m_creature);
+
+ if (!m_bDrinkInturrupted)
+ {
+ m_creature->CastSpell(m_creature, SPELL_MASS_POLY, true);
+ m_creature->CastSpell(m_creature, SPELL_CONJURE, false);
+ m_creature->CastSpell(m_creature, SPELL_DRINK, false);
+ m_creature->SetStandState(UNIT_STAND_STATE_SIT);
+ m_uiDrinkInturrupt_Timer = 10000;
+ }
+ }
+
+ //Drink Inturrupt
+ if (m_bDrinking && m_bDrinkInturrupted)
+ {
+ m_bDrinking = false;
+ m_creature->RemoveAurasDueToSpell(SPELL_DRINK);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->SetPower(POWER_MANA, m_creature->GetMaxPower(POWER_MANA)-32000);
+ m_creature->CastSpell(m_creature, SPELL_POTION, false);
+ }
+
+ //Drink Inturrupt Timer
+ if (m_bDrinking && !m_bDrinkInturrupted)
+ {
+ if (m_uiDrinkInturrupt_Timer >= uiDiff)
+ m_uiDrinkInturrupt_Timer -= uiDiff;
+ else
+ {
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->CastSpell(m_creature, SPELL_POTION, true);
+ m_creature->CastSpell(m_creature, SPELL_AOE_PYROBLAST, false);
+ m_bDrinkInturrupted = true;
+ m_bDrinking = false;
+ }
+ }
+
+ //Don't execute any more code if we are drinking
+ if (m_bDrinking)
+ return;
+
+ //Normal casts
+ if (m_uiNormalCast_Timer < uiDiff)
+ {
+ if (!m_creature->IsNonMeleeSpellCasted(false))
+ {
+ Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+ if (!pTarget)
+ return;
+
+ uint32 auiSpells[3];
+ uint8 uiAvailableSpells = 0;
+
+ //Check for what spells are not on cooldown
+ if (!m_uiArcaneCooldown)
+ auiSpells[uiAvailableSpells++] = SPELL_ARCMISSLE;
+ if (!m_uiFireCooldown)
+ auiSpells[uiAvailableSpells++] = SPELL_FIREBALL;
+ if (!m_uiFrostCooldown)
+ auiSpells[uiAvailableSpells++] = SPELL_FROSTBOLT;
+
+ //If no available spells wait 1 second and try again
+ if (uiAvailableSpells)
+ {
+ m_uiCurrentNormalSpell = auiSpells[rand() % uiAvailableSpells];
+ DoCastSpellIfCan(pTarget, m_uiCurrentNormalSpell);
+ }
+ }
+ m_uiNormalCast_Timer = 1000;
+ }
+ else
+ m_uiNormalCast_Timer -= uiDiff;
+
+ if (m_uiSecondarySpell_Timer < uiDiff)
+ {
+ switch(urand(0, 1))
+ {
+ case 0:
+ DoCastSpellIfCan(m_creature, SPELL_AOE_CS);
+ break;
+ case 1:
+ if (Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pUnit, SPELL_CHAINSOFICE);
+ break;
+ }
+ m_uiSecondarySpell_Timer = urand(5000, 20000);
+ }
+ else
+ m_uiSecondarySpell_Timer -= uiDiff;
+
+ if (m_uiSuperCast_Timer < uiDiff)
+ {
+ uint8 auiAvailable[2];
+
+ switch (m_uiLastSuperSpell)
+ {
+ case SUPER_AE:
+ auiAvailable[0] = SUPER_FLAME;
+ auiAvailable[1] = SUPER_BLIZZARD;
+ break;
+ case SUPER_FLAME:
+ auiAvailable[0] = SUPER_AE;
+ auiAvailable[1] = SUPER_BLIZZARD;
+ break;
+ case SUPER_BLIZZARD:
+ auiAvailable[0] = SUPER_FLAME;
+ auiAvailable[1] = SUPER_AE;
+ break;
+ }
+
+ m_uiLastSuperSpell = auiAvailable[urand(0, 2)];
+
+ switch (m_uiLastSuperSpell)
+ {
+ case SUPER_AE:
+ DoScriptText(urand(0, 1) ? SAY_EXPLOSION1 : SAY_EXPLOSION2, m_creature);
+
+ m_creature->CastSpell(m_creature, SPELL_BLINK_CENTER, true);
+ m_creature->CastSpell(m_creature, SPELL_PLAYERPULL, true);
+ m_creature->CastSpell(m_creature, SPELL_MASSSLOW, true);
+ m_creature->CastSpell(m_creature, SPELL_AEXPLOSION, false);
+ break;
+
+ case SUPER_FLAME:
+ DoScriptText(urand(0, 1) ? SAY_FLAMEWREATH1 : SAY_FLAMEWREATH2, m_creature);
+
+ m_uiFlameWreath_Timer = 20000;
+ m_uiFlameWreathCheck_Timer = 500;
+
+ memset(&m_uiFlameWreathTarget, 0, sizeof(m_uiFlameWreathTarget));
+
+ FlameWreathEffect();
+ break;
+
+ case SUPER_BLIZZARD:
+ DoScriptText(urand(0, 1) ? SAY_BLIZZARD1 : SAY_BLIZZARD2, m_creature);
+
+ if (Creature* pSpawn = m_creature->SummonCreature(NPC_ARAN_BLIZZARD, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 25000))
+ {
+ pSpawn->setFaction(m_creature->getFaction());
+ pSpawn->CastSpell(pSpawn, SPELL_CIRCULAR_BLIZZARD, false);
+ }
+ break;
+ }
+
+ m_uiSuperCast_Timer = urand(35000, 40000);
+ }
+ else
+ m_uiSuperCast_Timer -= uiDiff;
+
+ if (!m_bElementalsSpawned && m_creature->GetHealthPercent() < 40.0f)
+ {
+ m_bElementalsSpawned = true;
+
+ for (uint32 i = 0; i < 4; ++i)
+ {
+ if (Creature* pElemental = m_creature->SummonCreature(NPC_WATER_ELEMENTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 90000))
+ {
+ pElemental->Attack(m_creature->getVictim(), true);
+ pElemental->setFaction(m_creature->getFaction());
+ }
+ }
+
+ DoScriptText(SAY_ELEMENTALS, m_creature);
+ }
+
+ if (m_uiBerserk_Timer < uiDiff)
+ {
+ for (uint32 i = 0; i < 5; ++i)
+ {
+ if (Creature* pShadow = m_creature->SummonCreature(NPC_SHADOW_OF_ARAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000))
+ {
+ pShadow->Attack(m_creature->getVictim(), true);
+ pShadow->setFaction(m_creature->getFaction());
+ }
+ }
+
+ DoScriptText(SAY_TIMEOVER, m_creature);
+
+ m_uiBerserk_Timer = 60000;
+ }
+ else
+ m_uiBerserk_Timer -= uiDiff;
+
+ //Flame Wreath check
+ if (m_uiFlameWreath_Timer)
+ {
+ if (m_uiFlameWreath_Timer >= uiDiff)
+ m_uiFlameWreath_Timer -= uiDiff;
+ else
+ m_uiFlameWreath_Timer = 0;
+
+ if (m_uiFlameWreathCheck_Timer < uiDiff)
+ {
+ for (uint32 i = 0; i < 3; ++i)
+ {
+ if (!m_uiFlameWreathTarget[i])
+ continue;
+
+ Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiFlameWreathTarget[i]);
+
+ if (pPlayer && !pPlayer->IsWithinDist2d(m_fFWTargPosX[i], m_fFWTargPosY[i], 3.0f))
+ {
+ pPlayer->CastSpell(pPlayer, SPELL_EXPLOSION, true, 0, 0, m_creature->GetGUID());
+ pPlayer->CastSpell(pPlayer, SPELL_KNOCKBACK_500, true);
+ m_uiFlameWreathTarget[i] = 0;
+ }
+ }
+ m_uiFlameWreathCheck_Timer = 500;
+ }
+ else
+ m_uiFlameWreathCheck_Timer -= uiDiff;
+ }
+
+ if (m_uiArcaneCooldown && m_uiFireCooldown && m_uiFrostCooldown)
+ DoMeleeAttackIfReady();
+ }
+
+ void DamageTaken(Unit* pAttacker, uint32 &damage)
+ {
+ if (!m_bDrinkInturrupted && m_bDrinking && damage)
+ m_bDrinkInturrupted = true;
+ }
+
+ void SpellHit(Unit* pAttacker, const SpellEntry* Spell)
+ {
+ //We only care about inturrupt effects and only if they are durring a spell currently being casted
+ if ((Spell->Effect[0]!=SPELL_EFFECT_INTERRUPT_CAST &&
+ Spell->Effect[1]!=SPELL_EFFECT_INTERRUPT_CAST &&
+ Spell->Effect[2]!=SPELL_EFFECT_INTERRUPT_CAST) || !m_creature->IsNonMeleeSpellCasted(false))
+ return;
+
+ //Inturrupt effect
+ m_creature->InterruptNonMeleeSpells(false);
+
+ //Normally we would set the cooldown equal to the spell duration
+ //but we do not have access to the DurationStore
+
+ switch (m_uiCurrentNormalSpell)
+ {
+ case SPELL_ARCMISSLE: m_uiArcaneCooldown = 5000; break;
+ case SPELL_FIREBALL: m_uiFireCooldown = 5000; break;
+ case SPELL_FROSTBOLT: m_uiFrostCooldown = 5000; break;
+ }
+ }
+};
+
+struct MANGOS_DLL_DECL water_elementalAI : public ScriptedAI
+{
+ water_elementalAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiCast_Timer;
+
+ void Reset()
+ {
+ m_uiCast_Timer = urand(2000, 5000);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiCast_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_WATERBOLT);
+ m_uiCast_Timer = urand(2000, 5000);
+ }
+ else
+ m_uiCast_Timer -= uiDiff;
+ }
+};
+
+CreatureAI* GetAI_boss_aran(Creature* pCreature)
+{
+ return new boss_aranAI(pCreature);
+}
+
+CreatureAI* GetAI_water_elemental(Creature* pCreature)
+{
+ return new water_elementalAI(pCreature);
+}
+
+void AddSC_boss_shade_of_aran()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_shade_of_aran";
+ newscript->GetAI = &GetAI_boss_aran;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_aran_elemental";
+ newscript->GetAI = &GetAI_water_elemental;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp b/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp
new file mode 100644
index 0000000..e913671
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp
@@ -0,0 +1,363 @@
+/* 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_Terestian_Illhoof
+SD%Complete: 95
+SDComment: Complete! Needs adjustments to use spell though.
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+#include "karazhan.h"
+
+enum
+{
+ SAY_SLAY1 = -1532065,
+ SAY_SLAY2 = -1532066,
+ SAY_DEATH = -1532067,
+ SAY_AGGRO = -1532068,
+ SAY_SACRIFICE1 = -1532069,
+ SAY_SACRIFICE2 = -1532070,
+ SAY_SUMMON1 = -1532071,
+ SAY_SUMMON2 = -1532072,
+
+ SPELL_SUMMON_DEMONCHAINS = 30120, // Summons demonic chains that maintain the ritual of sacrifice.
+ SPELL_DEMON_CHAINS = 30206, // Instant - Visual Effect
+ SPELL_ENRAGE = 23537, // Increases the caster's attack speed by 50% and the Physical damage it deals by 219 to 281 for 10 min.
+ SPELL_SHADOW_BOLT = 30055, // Hurls a bolt of dark magic at an enemy, inflicting Shadow damage.
+ SPELL_SACRIFICE = 30115, // Teleports and adds the debuff
+ SPELL_BERSERK = 32965, // Increases attack speed by 75%. Periodically casts Shadow Bolt Volley.
+
+ SPELL_SUMMON_IMP = 30066, // Summons Kil'rek
+
+ SPELL_SUMMON_FIENDISH_IMP = 30184,
+ SPELL_FIENDISH_PORTAL = 30171, // Opens portal and summons Fiendish Portal, 2 sec cast
+ SPELL_FIENDISH_PORTAL_1 = 30179, // Opens portal and summons Fiendish Portal, instant cast
+
+ SPELL_FIREBOLT = 30050, // Blasts a target for 150 Fire damage.
+
+ SPELL_BROKEN_PACT = 30065, // All damage taken increased by 25%.
+ SPELL_AMPLIFY_FLAMES = 30053, // Increases the Fire damage taken by an enemy by 500 for 25 sec.
+
+ NPC_DEMONCHAINS = 17248,
+ NPC_FIENDISHIMP = 17267,
+ NPC_PORTAL = 17265,
+ NPC_KILREK = 17229
+};
+
+struct MANGOS_DLL_DECL mob_demon_chainAI : public ScriptedAI
+{
+ mob_demon_chainAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ Reset();
+ }
+
+ uint64 m_uiSacrificeGUID;
+
+ void Reset()
+ {
+ m_uiSacrificeGUID = 0;
+ }
+
+ void AttackStart(Unit* pWho) {}
+ void MoveInLineOfSight(Unit* pWho) {}
+
+ void JustDied(Unit* pKiller)
+ {
+ if (m_uiSacrificeGUID)
+ {
+ if (Player* pSacrifice = m_creature->GetMap()->GetPlayer(m_uiSacrificeGUID))
+ pSacrifice->RemoveAurasDueToSpell(SPELL_SACRIFICE);
+ }
+ }
+};
+
+struct MANGOS_DLL_DECL boss_terestianAI : public ScriptedAI
+{
+ boss_terestianAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ memset(&m_uiPortalGUID, 0, sizeof(m_uiPortalGUID));
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bSummonKilrek = true;
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint64 m_uiPortalGUID[2];
+
+ uint32 m_uiSummonKilrekTimer;
+ uint32 m_uiSacrifice_Timer;
+ uint32 m_uiShadowbolt_Timer;
+ uint32 m_uiSummon_Timer;
+ uint32 m_uiBerserk_Timer;
+
+ bool m_bSummonKilrek;
+ bool m_bSummonedPortals;
+ bool m_bBerserk;
+
+ void Reset()
+ {
+ m_uiSummonKilrekTimer = 5000;
+ m_uiSacrifice_Timer = 30000;
+ m_uiShadowbolt_Timer = 5000;
+ m_uiSummon_Timer = 10000;
+ m_uiBerserk_Timer = 600000;
+
+ m_bSummonedPortals = false;
+ m_bBerserk = false;
+
+ if (!m_pInstance)
+ return;
+
+ for(uint8 i = 0; i < 2; ++i)
+ {
+ if (m_uiPortalGUID[i])
+ {
+ if (Creature* pPortal = m_pInstance->instance->GetCreature(m_uiPortalGUID[i]))
+ pPortal->ForcedDespawn();
+
+ m_uiPortalGUID[i] = 0;
+ }
+ }
+
+ if (!m_creature->isAlive())
+ return;
+
+ m_pInstance->SetData(TYPE_TERESTIAN, NOT_STARTED);
+
+ if (!m_creature->GetPet())
+ m_bSummonKilrek = true;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+
+ if (Pet* pKilrek = m_creature->GetPet())
+ pKilrek->SetInCombatWithZone();
+
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_TERESTIAN, IN_PROGRESS);
+ else
+ ERROR_INST_DATA(m_creature);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ switch(pSummoned->GetEntry())
+ {
+ case NPC_PORTAL:
+ {
+ if (m_uiPortalGUID[0])
+ {
+ m_uiPortalGUID[1] = pSummoned->GetGUID();
+
+ if (npc_fiendish_portalAI* pPortalAI = dynamic_cast(pSummoned->AI()))
+ pPortalAI->m_uiSummonTimer = 10000;
+ }
+ else
+ {
+ m_uiPortalGUID[0] = pSummoned->GetGUID();
+ DoCastSpellIfCan(m_creature, SPELL_FIENDISH_PORTAL_1, CAST_TRIGGERED);
+ }
+
+ break;
+ }
+ case NPC_KILREK:
+ m_creature->RemoveAurasDueToSpell(SPELL_BROKEN_PACT);
+ break;
+ }
+ }
+
+ void SummonedCreatureJustDied(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_KILREK)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BROKEN_PACT, CAST_TRIGGERED);
+ m_bSummonKilrek = true;
+ }
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (!m_pInstance)
+ return;
+
+ for(uint8 i = 0; i < 2; ++i)
+ {
+ if (m_uiPortalGUID[i])
+ {
+ if (Creature* pPortal = m_pInstance->instance->GetCreature(m_uiPortalGUID[i]))
+ pPortal->ForcedDespawn();
+
+ m_uiPortalGUID[i] = 0;
+ }
+ }
+
+ m_pInstance->SetData(TYPE_TERESTIAN, DONE);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_bSummonKilrek)
+ {
+ if (m_uiSummonKilrekTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_IMP) == CAST_OK)
+ {
+ m_uiSummonKilrekTimer = 45000;
+ m_bSummonKilrek = false;
+ }
+ }
+ else
+ m_uiSummonKilrekTimer -= uiDiff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiSacrifice_Timer < uiDiff)
+ {
+ Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1);
+ if (pTarget && pTarget->isAlive() && pTarget->GetTypeId() == TYPEID_PLAYER)
+ {
+ DoCastSpellIfCan(pTarget, SPELL_SACRIFICE, CAST_TRIGGERED);
+
+ if (Creature* pChains = m_creature->SummonCreature(NPC_DEMONCHAINS, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 21000))
+ {
+ if (mob_demon_chainAI* pDemonAI = dynamic_cast(pChains->AI()))
+ pDemonAI->m_uiSacrificeGUID = pTarget->GetGUID();
+
+ pChains->CastSpell(pChains, SPELL_DEMON_CHAINS, true);
+
+ DoScriptText(urand(0, 1) ? SAY_SACRIFICE1 : SAY_SACRIFICE2, m_creature);
+
+ m_uiSacrifice_Timer = 30000;
+ }
+ }
+ }
+ else
+ m_uiSacrifice_Timer -= uiDiff;
+
+ if (m_uiShadowbolt_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOW_BOLT);
+ m_uiShadowbolt_Timer = 10000;
+ }
+ else
+ m_uiShadowbolt_Timer -= uiDiff;
+
+ if (!m_bSummonedPortals)
+ {
+ if (m_uiSummon_Timer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_FIENDISH_PORTAL, CAST_INTERRUPT_PREVIOUS) == CAST_OK)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SUMMON1 : SAY_SUMMON2, m_creature);
+ m_bSummonedPortals = true;
+ }
+ }
+ else
+ m_uiSummon_Timer -= uiDiff;
+ }
+
+ if (!m_bBerserk)
+ {
+ if (m_uiBerserk_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BERSERK, CAST_INTERRUPT_PREVIOUS);
+ m_bBerserk = true;
+ }
+ else
+ m_uiBerserk_Timer -= uiDiff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+npc_fiendish_portalAI::npc_fiendish_portalAI(Creature* pCreature) : ScriptedAI(pCreature),
+ m_uiSummonTimer(5000)
+{
+ Reset();
+}
+
+void npc_fiendish_portalAI::Reset()
+{
+}
+
+void npc_fiendish_portalAI::JustSummoned(Creature* pSummoned)
+{
+ pSummoned->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
+ pSummoned->SetInCombatWithZone();
+}
+
+void npc_fiendish_portalAI::UpdateAI(const uint32 uiDiff)
+{
+ if (m_uiSummonTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_SUMMON_FIENDISH_IMP);
+ m_uiSummonTimer = 10000;
+ }
+ else
+ m_uiSummonTimer -= uiDiff;
+}
+
+CreatureAI* GetAI_npc_fiendish_portal(Creature* pCreature)
+{
+ return new npc_fiendish_portalAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_demon_chain(Creature* pCreature)
+{
+ return new mob_demon_chainAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_terestian_illhoof(Creature* pCreature)
+{
+ return new boss_terestianAI(pCreature);
+}
+
+void AddSC_boss_terestian_illhoof()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_terestian_illhoof";
+ newscript->GetAI = &GetAI_boss_terestian_illhoof;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_fiendish_portal";
+ newscript->GetAI = &GetAI_npc_fiendish_portal;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_demon_chain";
+ newscript->GetAI = &GetAI_mob_demon_chain;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp b/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp
new file mode 100644
index 0000000..ae53231
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp
@@ -0,0 +1,1520 @@
+/* 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: Bosses_Opera
+SD%Complete: 90
+SDComment: Oz, Hood, and RAJ event implemented. RAJ event requires more testing.
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+#include "karazhan.h"
+
+/***********************************/
+/*** OPERA WIZARD OF OZ EVENT *****/
+/*********************************/
+
+#define SAY_DOROTHEE_DEATH -1532025
+#define SAY_DOROTHEE_SUMMON -1532026
+#define SAY_DOROTHEE_TITO_DEATH -1532027
+#define SAY_DOROTHEE_AGGRO -1532028
+
+#define SAY_ROAR_AGGRO -1532029
+#define SAY_ROAR_DEATH -1532030
+#define SAY_ROAR_SLAY -1532031
+
+#define SAY_STRAWMAN_AGGRO -1532032
+#define SAY_STRAWMAN_DEATH -1532033
+#define SAY_STRAWMAN_SLAY -1532034
+
+#define SAY_TINHEAD_AGGRO -1532035
+#define SAY_TINHEAD_DEATH -1532036
+#define SAY_TINHEAD_SLAY -1532037
+#define EMOTE_RUST -1532038
+
+#define SAY_CRONE_AGGRO -1532039
+#define SAY_CRONE_AGGRO2 -1532040
+#define SAY_CRONE_DEATH -1532041
+#define SAY_CRONE_SLAY -1532042
+
+/**** Spells ****/
+// Dorothee
+#define SPELL_WATERBOLT 31012
+#define SPELL_SCREAM 31013
+#define SPELL_SUMMONTITO 31014
+
+// Tito
+#define SPELL_YIPPING 31015
+
+// Strawman
+#define SPELL_BRAIN_BASH 31046
+#define SPELL_BRAIN_WIPE 31069
+#define SPELL_BURNING_STRAW 31075
+
+// Tinhead
+#define SPELL_CLEAVE 31043
+#define SPELL_RUST 31086
+
+// Roar
+#define SPELL_MANGLE 31041
+#define SPELL_SHRED 31042
+#define SPELL_FRIGHTENED_SCREAM 31013
+
+// Crone
+#define SPELL_CHAIN_LIGHTNING 32337
+
+// Cyclone
+#define SPELL_KNOCKBACK 32334
+#define SPELL_CYCLONE_VISUAL 32332
+
+/** Creature Entries **/
+#define CREATURE_TITO 17548
+#define CREATURE_CYCLONE 18412
+#define CREATURE_CRONE 18168
+
+void SummonCroneIfReady(ScriptedInstance* pInstance, Creature* pCreature)
+{
+ pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, SPECIAL); // Increment DeathCount
+
+ if (pInstance->GetData(DATA_OPERA_OZ_DEATHCOUNT) == 4)
+ {
+ if (Creature* pCrone = pCreature->SummonCreature(CREATURE_CRONE, -10891.96f, -1755.95f, pCreature->GetPositionZ(), 4.64f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS))
+ {
+ if (pCreature->getVictim())
+ pCrone->AI()->AttackStart(pCreature->getVictim());
+ }
+ }
+};
+
+struct MANGOS_DLL_DECL boss_dorotheeAI : public ScriptedAI
+{
+ boss_dorotheeAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 AggroTimer;
+
+ uint32 WaterBoltTimer;
+ uint32 FearTimer;
+ uint32 SummonTitoTimer;
+
+ bool SummonedTito;
+ bool TitoDied;
+
+ void Reset()
+ {
+ AggroTimer = 500;
+
+ WaterBoltTimer = 5000;
+ FearTimer = 15000;
+ SummonTitoTimer = 47500;
+
+ SummonedTito = false;
+ TitoDied = false;
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_DOROTHEE_AGGRO, m_creature);
+ }
+
+ void JustReachedHome()
+ {
+ m_creature->ForcedDespawn();
+ }
+
+ void SummonTito(); // See below
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_DOROTHEE_DEATH, m_creature);
+
+ if (m_pInstance)
+ SummonCroneIfReady(m_pInstance, m_creature);
+ }
+
+ void AttackStart(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::AttackStart(who);
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (AggroTimer)
+ {
+ if (AggroTimer <= diff)
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ AggroTimer = 0;
+ }else AggroTimer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (WaterBoltTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_WATERBOLT);
+
+ WaterBoltTimer = TitoDied ? 1500 : 5000;
+ }else WaterBoltTimer -= diff;
+
+ if (FearTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SCREAM);
+ FearTimer = 30000;
+ }else FearTimer -= diff;
+
+ if (!SummonedTito)
+ {
+ if (SummonTitoTimer < diff)
+ SummonTito();
+ else SummonTitoTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL mob_titoAI : public ScriptedAI
+{
+ mob_titoAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ Reset();
+ }
+
+ uint64 DorotheeGUID;
+ uint32 YipTimer;
+
+ void Reset()
+ {
+ DorotheeGUID = 0;
+ YipTimer = 10000;
+ }
+
+ void JustDied(Unit* killer)
+ {
+ if (DorotheeGUID)
+ {
+ Creature* Dorothee = m_creature->GetMap()->GetCreature(DorotheeGUID);
+ if (Dorothee && Dorothee->isAlive())
+ {
+ if (boss_dorotheeAI* pDoroAI = dynamic_cast(Dorothee->AI()))
+ pDoroAI->TitoDied = true;
+
+ DoScriptText(SAY_DOROTHEE_TITO_DEATH, Dorothee);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (YipTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_YIPPING);
+ YipTimer = 10000;
+ }else YipTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+void boss_dorotheeAI::SummonTito()
+{
+ if (Creature* pTito = m_creature->SummonCreature(CREATURE_TITO, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000))
+ {
+ DoScriptText(SAY_DOROTHEE_SUMMON, m_creature);
+
+ if (mob_titoAI* pTitoAI = dynamic_cast(pTito->AI()))
+ pTitoAI->DorotheeGUID = m_creature->GetGUID();
+
+ pTito->AI()->AttackStart(m_creature->getVictim());
+
+ SummonedTito = true;
+ TitoDied = false;
+ }
+}
+
+struct MANGOS_DLL_DECL boss_strawmanAI : public ScriptedAI
+{
+ boss_strawmanAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 AggroTimer;
+ uint32 BrainBashTimer;
+ uint32 BrainWipeTimer;
+
+ void Reset()
+ {
+ AggroTimer = 13000;
+ BrainBashTimer = 5000;
+ BrainWipeTimer = 7000;
+ }
+
+ void AttackStart(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::AttackStart(who);
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_STRAWMAN_AGGRO, m_creature);
+ }
+
+ void JustReachedHome()
+ {
+ m_creature->ForcedDespawn();
+ }
+
+ void SpellHit(Unit* caster, const SpellEntry *Spell)
+ {
+ if ((Spell->SchoolMask == SPELL_SCHOOL_MASK_FIRE) && !urand(0, 1))
+ {
+ /*
+ if (not direct damage(aoe,dot))
+ return;
+ */
+
+ DoCastSpellIfCan(m_creature, SPELL_BURNING_STRAW, true);
+ }
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_STRAWMAN_DEATH, m_creature);
+
+ if (m_pInstance)
+ SummonCroneIfReady(m_pInstance, m_creature);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_STRAWMAN_SLAY, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (AggroTimer)
+ {
+ if (AggroTimer <= diff)
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ AggroTimer = 0;
+ }else AggroTimer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (BrainBashTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_BRAIN_BASH);
+ BrainBashTimer = 15000;
+ }else BrainBashTimer -= diff;
+
+ if (BrainWipeTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_BRAIN_WIPE);
+
+ BrainWipeTimer = 20000;
+ }else BrainWipeTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_tinheadAI : public ScriptedAI
+{
+ boss_tinheadAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 AggroTimer;
+ uint32 CleaveTimer;
+ uint32 RustTimer;
+
+ uint8 RustCount;
+
+ void Reset()
+ {
+ AggroTimer = 15000;
+ CleaveTimer = 5000;
+ RustTimer = 30000;
+
+ RustCount = 0;
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_TINHEAD_AGGRO, m_creature);
+ }
+
+ void JustReachedHome()
+ {
+ m_creature->ForcedDespawn();
+ }
+
+ void AttackStart(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::AttackStart(who);
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_TINHEAD_DEATH, m_creature);
+
+ if (m_pInstance)
+ SummonCroneIfReady(m_pInstance, m_creature);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_TINHEAD_SLAY, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (AggroTimer)
+ {
+ if (AggroTimer <= diff)
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ AggroTimer = 0;
+ }else AggroTimer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (CleaveTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ CleaveTimer = 5000;
+ }else CleaveTimer -= diff;
+
+ if (RustCount < 8)
+ {
+ if (RustTimer < diff)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_RUST) == CAST_OK)
+ {
+ ++RustCount;
+
+ DoScriptText(EMOTE_RUST, m_creature);
+ RustTimer = 6000;
+ }
+ }else RustTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_roarAI : public ScriptedAI
+{
+ boss_roarAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 AggroTimer;
+ uint32 MangleTimer;
+ uint32 ShredTimer;
+ uint32 ScreamTimer;
+
+ void Reset()
+ {
+ AggroTimer = 20000;
+ MangleTimer = 5000;
+ ShredTimer = 10000;
+ ScreamTimer = 15000;
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void AttackStart(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::AttackStart(who);
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_ROAR_AGGRO, m_creature);
+ }
+
+ void JustReachedHome()
+ {
+ m_creature->ForcedDespawn();
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_ROAR_DEATH, m_creature);
+
+ if (m_pInstance)
+ SummonCroneIfReady(m_pInstance, m_creature);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_ROAR_SLAY, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (AggroTimer)
+ {
+ if (AggroTimer <= diff)
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ AggroTimer = 0;
+ }else AggroTimer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (MangleTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MANGLE);
+ MangleTimer = urand(5000, 8000);
+ }else MangleTimer -= diff;
+
+ if (ShredTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHRED);
+ ShredTimer = urand(10000, 15000);
+ }else ShredTimer -= diff;
+
+ if (ScreamTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FRIGHTENED_SCREAM);
+ ScreamTimer = urand(20000, 30000);
+ }else ScreamTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_croneAI : public ScriptedAI
+{
+ boss_croneAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 CycloneTimer;
+ uint32 ChainLightningTimer;
+
+ void Reset()
+ {
+ CycloneTimer = 30000;
+ ChainLightningTimer = 10000;
+ }
+
+ void JustReachedHome()
+ {
+ m_creature->ForcedDespawn();
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(urand(0, 1) ? SAY_CRONE_AGGRO : SAY_CRONE_AGGRO2, m_creature);
+
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_CRONE_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_OPERA, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ if (CycloneTimer < diff)
+ {
+ Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, rand()%10, rand()%10, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000);
+ if (Cyclone)
+ Cyclone->CastSpell(Cyclone, SPELL_CYCLONE_VISUAL, true);
+ CycloneTimer = 30000;
+ }else CycloneTimer -= diff;
+
+ if (ChainLightningTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CHAIN_LIGHTNING);
+ ChainLightningTimer = 15000;
+ }else ChainLightningTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL mob_cycloneAI : public ScriptedAI
+{
+ mob_cycloneAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ Reset();
+ }
+
+ uint32 MoveTimer;
+
+ void Reset()
+ {
+ MoveTimer = 1000;
+ }
+
+ void MoveInLineOfSight(Unit* who) { }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->HasAura(SPELL_KNOCKBACK, EFFECT_INDEX_0))
+ DoCastSpellIfCan(m_creature, SPELL_KNOCKBACK, CAST_TRIGGERED);
+
+ if (MoveTimer < diff)
+ {
+ float x,y,z;
+ m_creature->GetPosition(x,y,z);
+ float PosX, PosY, PosZ;
+ m_creature->GetRandomPoint(x,y,z,10, PosX, PosY, PosZ);
+ m_creature->GetMotionMaster()->MovePoint(0, PosX, PosY, PosZ);
+ MoveTimer = urand(5000, 8000);
+ }else MoveTimer -= diff;
+ }
+};
+
+CreatureAI* GetAI_boss_dorothee(Creature* pCreature)
+{
+ return new boss_dorotheeAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_strawman(Creature* pCreature)
+{
+ return new boss_strawmanAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_tinhead(Creature* pCreature)
+{
+ return new boss_tinheadAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_roar(Creature* pCreature)
+{
+ return new boss_roarAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_crone(Creature* pCreature)
+{
+ return new boss_croneAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_tito(Creature* pCreature)
+{
+ return new mob_titoAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_cyclone(Creature* pCreature)
+{
+ return new mob_cycloneAI(pCreature);
+}
+
+/**************************************/
+/**** Opera Red Riding Hood Event ****/
+/************************************/
+
+/**** Yells for the Wolf ****/
+#define SAY_WOLF_AGGRO -1532043
+#define SAY_WOLF_SLAY -1532044
+#define SAY_WOLF_HOOD -1532045
+#define SOUND_WOLF_DEATH 9275 //Only sound on death, no text.
+
+/**** Spells For The Wolf ****/
+#define SPELL_LITTLE_RED_RIDING_HOOD 30768
+#define SPELL_TERRIFYING_HOWL 30752
+#define SPELL_WIDE_SWIPE 30761
+
+#define GOSSIP_GRANDMA "What phat lewtz you have grandmother?"
+
+/**** The Wolf's Entry ****/
+#define CREATURE_BIG_BAD_WOLF 17521
+
+bool GossipHello_npc_grandmother(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_GRANDMA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ pPlayer->SEND_GOSSIP_MENU(8990, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_grandmother(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF)
+ {
+ if (Creature* pBigBadWolf = pCreature->SummonCreature(CREATURE_BIG_BAD_WOLF, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS))
+ pBigBadWolf->AI()->AttackStart(pPlayer);
+
+ pCreature->ForcedDespawn();
+ }
+
+ return true;
+}
+
+struct MANGOS_DLL_DECL boss_bigbadwolfAI : public ScriptedAI
+{
+ boss_bigbadwolfAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 ChaseTimer;
+ uint32 FearTimer;
+ uint32 SwipeTimer;
+
+ uint64 HoodGUID;
+ float TempThreat;
+
+ bool IsChasing;
+
+ void Reset()
+ {
+ ChaseTimer = 30000;
+ FearTimer = urand(25000, 35000);
+ SwipeTimer = 5000;
+
+ HoodGUID = 0;
+ TempThreat = 0;
+
+ IsChasing = false;
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_WOLF_AGGRO, m_creature);
+ }
+
+ void JustReachedHome()
+ {
+ m_creature->ForcedDespawn();
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoPlaySoundToSet(m_creature, SOUND_WOLF_DEATH);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_OPERA, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+
+ if (ChaseTimer < diff)
+ {
+ if (!IsChasing)
+ {
+ Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+ if (target && target->GetTypeId() == TYPEID_PLAYER)
+ {
+ DoScriptText(SAY_WOLF_HOOD, m_creature);
+ DoCastSpellIfCan(target, SPELL_LITTLE_RED_RIDING_HOOD, CAST_TRIGGERED);
+
+ TempThreat = m_creature->getThreatManager().getThreat(target);
+ if (TempThreat)
+ m_creature->getThreatManager().modifyThreatPercent(target, -100);
+
+ HoodGUID = target->GetGUID();
+ m_creature->AddThreat(target, 1000000.0f);
+ ChaseTimer = 20000;
+ IsChasing = true;
+ }
+ }
+ else
+ {
+ IsChasing = false;
+
+ if (Player* target = m_creature->GetMap()->GetPlayer(HoodGUID))
+ {
+ HoodGUID = 0;
+
+ if (m_creature->getThreatManager().getThreat(target))
+ m_creature->getThreatManager().modifyThreatPercent(target, -100);
+
+ m_creature->AddThreat(target, TempThreat);
+ TempThreat = 0;
+ }
+
+ ChaseTimer = 40000;
+ }
+ }else ChaseTimer -= diff;
+
+ if (IsChasing)
+ return;
+
+ if (FearTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_TERRIFYING_HOWL);
+ FearTimer = urand(25000, 35000);
+ }else FearTimer -= diff;
+
+ if (SwipeTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_WIDE_SWIPE);
+ SwipeTimer = urand(25000, 30000);
+ }else SwipeTimer -= diff;
+ }
+};
+
+CreatureAI* GetAI_boss_bigbadwolf(Creature* pCreature)
+{
+ return new boss_bigbadwolfAI(pCreature);
+}
+
+/**********************************************/
+/******** Opera Romeo and Juliet Event *******/
+/********************************************/
+
+/**** Speech *****/
+#define SAY_JULIANNE_AGGRO -1532046
+#define SAY_JULIANNE_ENTER -1532047
+#define SAY_JULIANNE_DEATH01 -1532048
+#define SAY_JULIANNE_DEATH02 -1532049
+#define SAY_JULIANNE_RESURRECT -1532050
+#define SAY_JULIANNE_SLAY -1532051
+
+#define SAY_ROMULO_AGGRO -1532052
+#define SAY_ROMULO_DEATH -1532053
+#define SAY_ROMULO_ENTER -1532054
+#define SAY_ROMULO_RESURRECT -1532055
+#define SAY_ROMULO_SLAY -1532056
+
+/***** Spells For Julianne *****/
+#define SPELL_BLINDING_PASSION 30890
+#define SPELL_DEVOTION 30887
+#define SPELL_ETERNAL_AFFECTION 30878
+#define SPELL_POWERFUL_ATTRACTION 30889
+#define SPELL_DRINK_POISON 30907
+
+/***** Spells For Romulo ****/
+#define SPELL_BACKWARD_LUNGE 30815
+#define SPELL_DARING 30841
+#define SPELL_DEADLY_SWATHE 30817
+#define SPELL_POISON_THRUST 30822
+
+/**** Other Misc. Spells ****/
+#define SPELL_UNDYING_LOVE 30951
+#define SPELL_RES_VISUAL 24171
+
+/*** Misc. Information ****/
+#define CREATURE_ROMULO 17533
+#define ROMULO_X -10900
+#define ROMULO_Y -1758
+
+enum RAJPhase
+{
+ PHASE_JULIANNE = 0,
+ PHASE_ROMULO = 1,
+ PHASE_BOTH = 2,
+};
+
+void PretendToDie(Creature* pCreature)
+{
+ pCreature->InterruptNonMeleeSpells(true);
+ pCreature->RemoveAllAuras();
+ pCreature->SetHealth(0);
+ pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pCreature->GetMotionMaster()->MovementExpired(false);
+ pCreature->GetMotionMaster()->MoveIdle();
+ pCreature->SetStandState(UNIT_STAND_STATE_DEAD);
+};
+
+void Resurrect(Creature* target)
+{
+ target->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ target->SetHealth(target->GetMaxHealth());
+ target->SetStandState(UNIT_STAND_STATE_STAND);
+ target->CastSpell(target, SPELL_RES_VISUAL, true);
+ if (target->getVictim())
+ {
+ target->GetMotionMaster()->MoveChase(target->getVictim());
+ target->AI()->AttackStart(target->getVictim());
+ }
+ else
+ target->GetMotionMaster()->Initialize();
+};
+
+struct MANGOS_DLL_DECL boss_julianneAI : public ScriptedAI
+{
+ boss_julianneAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ EntryYellTimer = 1000;
+ AggroYellTimer = 10000;
+ IsFakingDeath = false;
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 EntryYellTimer;
+ uint32 AggroYellTimer;
+
+ uint64 RomuloGUID;
+ uint32 Phase;
+
+ uint32 BlindingPassionTimer;
+ uint32 DevotionTimer;
+ uint32 EternalAffectionTimer;
+ uint32 PowerfulAttractionTimer;
+ uint32 SummonRomuloTimer;
+ uint32 ResurrectTimer;
+ uint32 DrinkPoisonTimer;
+ uint32 ResurrectSelfTimer;
+
+ bool IsFakingDeath;
+ bool SummonedRomulo;
+ bool RomuloDead;
+
+ void Reset()
+ {
+ RomuloGUID = 0;
+ Phase = PHASE_JULIANNE;
+
+ BlindingPassionTimer = 30000;
+ DevotionTimer = 15000;
+ EternalAffectionTimer = 25000;
+ PowerfulAttractionTimer = 5000;
+ SummonRomuloTimer = 10000;
+ ResurrectTimer = 10000;
+ DrinkPoisonTimer = 0;
+ ResurrectSelfTimer = 0;
+
+ if (IsFakingDeath)
+ {
+ Resurrect(m_creature);
+ IsFakingDeath = false;
+ }
+
+ SummonedRomulo = false;
+ RomuloDead = false;
+ }
+
+ void AttackStart(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::AttackStart(who);
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void JustReachedHome()
+ {
+ m_creature->ForcedDespawn();
+ }
+
+ void SpellHit(Unit* caster, const SpellEntry *Spell)
+ {
+ if (Spell->Id == SPELL_DRINK_POISON)
+ {
+ DoScriptText(SAY_JULIANNE_DEATH01, m_creature);
+ DrinkPoisonTimer = 2500;
+ }
+ }
+
+ void DamageTaken(Unit* done_by, uint32 &damage);
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_JULIANNE_DEATH02, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_OPERA, DONE);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_JULIANNE_SLAY, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff);
+};
+
+struct MANGOS_DLL_DECL boss_romuloAI : public ScriptedAI
+{
+ boss_romuloAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ EntryYellTimer = 8000;
+ AggroYellTimer = 15000;
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint64 JulianneGUID;
+ uint32 Phase;
+
+ uint32 EntryYellTimer;
+ uint32 AggroYellTimer;
+ uint32 BackwardLungeTimer;
+ uint32 DaringTimer;
+ uint32 DeadlySwatheTimer;
+ uint32 PoisonThrustTimer;
+ uint32 ResurrectTimer;
+
+ bool IsFakingDeath;
+ bool JulianneDead;
+
+ void Reset()
+ {
+ JulianneGUID = 0;
+ Phase = PHASE_ROMULO;
+
+ BackwardLungeTimer = 15000;
+ DaringTimer = 20000;
+ DeadlySwatheTimer = 25000;
+ PoisonThrustTimer = 10000;
+ ResurrectTimer = 10000;
+
+ IsFakingDeath = false;
+ JulianneDead = false;
+ }
+
+ void JustReachedHome()
+ {
+ m_creature->ForcedDespawn();
+ }
+
+ void DamageTaken(Unit* done_by, uint32 &damage);
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_ROMULO_AGGRO, m_creature);
+
+ if (JulianneGUID)
+ {
+ Creature* Julianne = m_creature->GetMap()->GetCreature(JulianneGUID);
+
+ if (Julianne && Julianne->getVictim())
+ m_creature->AddThreat(Julianne->getVictim());
+ }
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
+ return;
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_ROMULO_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_OPERA, DONE);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_ROMULO_SLAY, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff);
+};
+
+void boss_julianneAI::DamageTaken(Unit* done_by, uint32 &damage)
+{
+ if (damage < m_creature->GetHealth())
+ return;
+
+ //anything below only used if incoming damage will kill
+
+ if (Phase == PHASE_JULIANNE)
+ {
+ damage = 0;
+
+ //this means already drinking, so return
+ if (IsFakingDeath)
+ return;
+
+ m_creature->InterruptNonMeleeSpells(true);
+ DoCastSpellIfCan(m_creature, SPELL_DRINK_POISON);
+
+ IsFakingDeath = true;
+ return;
+ }
+
+ if (Phase == PHASE_ROMULO)
+ {
+ error_log("SD2: boss_julianneAI: cannot take damage in PHASE_ROMULO, why was i here?");
+ damage = 0;
+ return;
+ }
+
+ if (Phase == PHASE_BOTH)
+ {
+ //if this is true then we have to kill romulo too
+ if (RomuloDead)
+ {
+ if (Creature* Romulo = m_creature->GetMap()->GetCreature(RomuloGUID))
+ {
+ Romulo->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ Romulo->GetMotionMaster()->Clear();
+ Romulo->SetDeathState(JUST_DIED);
+ Romulo->CombatStop(true);
+ Romulo->DeleteThreatList();
+ Romulo->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ }
+ return;
+ }
+
+ //if not already returned, then romulo is alive and we can pretend die
+ if (Creature* Romulo = m_creature->GetMap()->GetCreature(RomuloGUID))
+ {
+ PretendToDie(m_creature);
+ IsFakingDeath = true;
+
+ if (boss_romuloAI* pRomAI = dynamic_cast(Romulo->AI()))
+ {
+ pRomAI->ResurrectTimer = 10000;
+ pRomAI->JulianneDead = true;
+ }
+
+ damage = 0;
+ return;
+ }
+ }
+
+ error_log("SD2: boss_julianneAI: DamageTaken reach end of code, that should not happen.");
+}
+
+void boss_romuloAI::DamageTaken(Unit* done_by, uint32 &damage)
+{
+ if (damage < m_creature->GetHealth())
+ return;
+
+ //anything below only used if incoming damage will kill
+
+ if (Phase == PHASE_ROMULO)
+ {
+ DoScriptText(SAY_ROMULO_DEATH, m_creature);
+ PretendToDie(m_creature);
+ IsFakingDeath = true;
+ Phase = PHASE_BOTH;
+
+ if (Creature* Julianne = m_creature->GetMap()->GetCreature(JulianneGUID))
+ {
+ if (boss_julianneAI* pJulAI = dynamic_cast(Julianne->AI()))
+ {
+ pJulAI->ResurrectSelfTimer = 10000;
+ pJulAI->RomuloDead = true;
+ }
+ }
+
+ damage = 0;
+ return;
+ }
+
+ if (Phase == PHASE_BOTH)
+ {
+ if (JulianneDead)
+ {
+ if (Creature* Julianne = m_creature->GetMap()->GetCreature(JulianneGUID))
+ {
+ Julianne->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ Julianne->GetMotionMaster()->Clear();
+ Julianne->SetDeathState(JUST_DIED);
+ Julianne->CombatStop(true);
+ Julianne->DeleteThreatList();
+ Julianne->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ }
+ return;
+ }
+
+ if (Creature* Julianne = m_creature->GetMap()->GetCreature(JulianneGUID))
+ {
+ PretendToDie(m_creature);
+ IsFakingDeath = true;
+
+ if (boss_julianneAI* pJulAI = dynamic_cast(Julianne->AI()))
+ {
+ pJulAI->ResurrectTimer = 10000;
+ pJulAI->RomuloDead = true;
+ }
+
+ damage = 0;
+ return;
+ }
+ }
+
+ error_log("SD2: boss_romuloAI: DamageTaken reach end of code, that should not happen.");
+}
+
+void boss_julianneAI::UpdateAI(const uint32 diff)
+{
+ if (EntryYellTimer)
+ {
+ if (EntryYellTimer <= diff)
+ {
+ DoScriptText(SAY_JULIANNE_ENTER, m_creature);
+ EntryYellTimer = 0;
+ }else EntryYellTimer -= diff;
+ }
+
+ if (AggroYellTimer)
+ {
+ if (AggroYellTimer <= diff)
+ {
+ DoScriptText(SAY_JULIANNE_AGGRO, m_creature);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ m_creature->setFaction(16);
+ AggroYellTimer = 0;
+ }else AggroYellTimer -= diff;
+ }
+
+ if (DrinkPoisonTimer)
+ {
+ //will do this 2secs after spell hit. this is time to display visual as expected
+ if (DrinkPoisonTimer <= diff)
+ {
+ PretendToDie(m_creature);
+ Phase = PHASE_ROMULO;
+ SummonRomuloTimer = 10000;
+ DrinkPoisonTimer = 0;
+ }else DrinkPoisonTimer -= diff;
+ }
+
+ if (Phase == PHASE_ROMULO && !SummonedRomulo)
+ {
+ if (SummonRomuloTimer < diff)
+ {
+ if (Creature* pRomulo = m_creature->SummonCreature(CREATURE_ROMULO, ROMULO_X, ROMULO_Y, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS))
+ {
+ RomuloGUID = pRomulo->GetGUID();
+
+ if (boss_romuloAI* pRomAI = dynamic_cast(pRomulo->AI()))
+ {
+ pRomAI->JulianneGUID = m_creature->GetGUID();
+ pRomAI->Phase = PHASE_ROMULO;
+ }
+
+ pRomulo->SetInCombatWithZone();
+
+ //why?
+ pRomulo->setFaction(16);
+ }
+ SummonedRomulo = true;
+ }else SummonRomuloTimer -= diff;
+ }
+
+ if (ResurrectSelfTimer)
+ {
+ if (ResurrectSelfTimer <= diff)
+ {
+ Resurrect(m_creature);
+ Phase = PHASE_BOTH;
+ IsFakingDeath = false;
+
+ if (m_creature->getVictim())
+ AttackStart(m_creature->getVictim());
+
+ ResurrectSelfTimer = 0;
+ ResurrectTimer = 1000;
+ }else ResurrectSelfTimer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() || IsFakingDeath)
+ return;
+
+ if (RomuloDead)
+ {
+ if (ResurrectTimer < diff)
+ {
+ Creature* pRomulo = m_creature->GetMap()->GetCreature(RomuloGUID);
+ boss_romuloAI* pRomAI = dynamic_cast(pRomulo->AI());
+
+ if (pRomulo && pRomAI && pRomAI->IsFakingDeath)
+ {
+ DoScriptText(SAY_JULIANNE_RESURRECT, m_creature);
+ Resurrect(pRomulo);
+
+ pRomAI->IsFakingDeath = false;
+
+ RomuloDead = false;
+ ResurrectTimer = 10000;
+ }
+ }else ResurrectTimer -= diff;
+ }
+
+ if (BlindingPassionTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_BLINDING_PASSION);
+
+ BlindingPassionTimer = urand(30000, 45000);
+ } else BlindingPassionTimer -= diff;
+
+ if (DevotionTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_DEVOTION);
+ DevotionTimer = urand(15000, 45000);
+ } else DevotionTimer -= diff;
+
+ if (PowerfulAttractionTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_POWERFUL_ATTRACTION);
+
+ PowerfulAttractionTimer = urand(5000, 30000);
+ } else PowerfulAttractionTimer -= diff;
+
+ if (EternalAffectionTimer < diff)
+ {
+ if (urand(0, 1) && SummonedRomulo)
+ {
+ Creature* Romulo = m_creature->GetMap()->GetCreature(RomuloGUID);
+ if (Romulo && Romulo->isAlive() && !RomuloDead)
+ DoCastSpellIfCan(Romulo, SPELL_ETERNAL_AFFECTION);
+ } else DoCastSpellIfCan(m_creature, SPELL_ETERNAL_AFFECTION);
+
+ EternalAffectionTimer = urand(45000, 60000);
+ } else EternalAffectionTimer -= diff;
+
+ DoMeleeAttackIfReady();
+}
+
+void boss_romuloAI::UpdateAI(const uint32 diff)
+{
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() || IsFakingDeath)
+ return;
+
+ if (JulianneDead)
+ {
+ if (ResurrectTimer < diff)
+ {
+ Creature* pJulianne = m_creature->GetMap()->GetCreature(JulianneGUID);
+ boss_julianneAI* pJulAI = dynamic_cast(pJulianne->AI());
+
+ if (pJulianne && pJulAI && pJulAI->IsFakingDeath)
+ {
+ DoScriptText(SAY_ROMULO_RESURRECT, m_creature);
+ Resurrect(pJulianne);
+
+ pJulAI->IsFakingDeath = false;
+
+ JulianneDead = false;
+ ResurrectTimer = 10000;
+ }
+ } else ResurrectTimer -= diff;
+ }
+
+ if (BackwardLungeTimer < diff)
+ {
+ Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1);
+ if (target && !m_creature->HasInArc(M_PI_F, target))
+ {
+ DoCastSpellIfCan(target, SPELL_BACKWARD_LUNGE);
+ BackwardLungeTimer = urand(15000, 30000);
+ }
+ }else BackwardLungeTimer -= diff;
+
+ if (DaringTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_DARING);
+ DaringTimer = urand(20000, 40000);
+ }else DaringTimer -= diff;
+
+ if (DeadlySwatheTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_DEADLY_SWATHE);
+
+ DeadlySwatheTimer = urand(15000, 25000);
+ }else DeadlySwatheTimer -= diff;
+
+ if (PoisonThrustTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_POISON_THRUST);
+ PoisonThrustTimer = urand(10000, 20000);
+ }else PoisonThrustTimer -= diff;
+
+ DoMeleeAttackIfReady();
+}
+
+CreatureAI* GetAI_boss_julianne(Creature* pCreature)
+{
+ return new boss_julianneAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_romulo(Creature* pCreature)
+{
+ return new boss_romuloAI(pCreature);
+}
+
+void AddSC_bosses_opera()
+{
+ Script* newscript;
+
+ // Oz
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_dorothee;
+ newscript->Name = "boss_dorothee";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_strawman;
+ newscript->Name = "boss_strawman";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_tinhead;
+ newscript->Name = "boss_tinhead";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_roar;
+ newscript->Name = "boss_roar";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_crone;
+ newscript->Name = "boss_crone";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_mob_tito;
+ newscript->Name = "mob_tito";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_mob_cyclone;
+ newscript->Name = "mob_cyclone";
+ newscript->RegisterSelf();
+
+ // Hood
+ newscript = new Script;
+ newscript->pGossipHello = &GossipHello_npc_grandmother;
+ newscript->pGossipSelect = &GossipSelect_npc_grandmother;
+ newscript->Name = "npc_grandmother";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_bigbadwolf;
+ newscript->Name = "boss_bigbadwolf";
+ newscript->RegisterSelf();
+
+ // Romeo And Juliet
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_julianne;
+ newscript->Name = "boss_julianne";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_romulo;
+ newscript->Name = "boss_romulo";
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp b/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp
new file mode 100644
index 0000000..5fb9a9e
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp
@@ -0,0 +1,297 @@
+/* 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_Karazhan
+SD%Complete: 70
+SDComment: Instance Script for Karazhan to help in various encounters. TODO: GameObject visibility for Opera event.
+SDCategory: Karazhan
+EndScriptData */
+
+#include "precompiled.h"
+#include "karazhan.h"
+
+/*
+0 - Attumen + Midnight (optional)
+1 - Moroes
+2 - Maiden of Virtue (optional)
+3 - Hyakiss the Lurker / Rokad the Ravager / Shadikith the Glider
+4 - Opera Event
+5 - Curator
+6 - Shade of Aran (optional)
+7 - Terestian Illhoof (optional)
+8 - Netherspite (optional)
+9 - Chess Event
+10 - Prince Malchezzar
+11 - Nightbane
+*/
+
+struct MANGOS_DLL_DECL instance_karazhan : public ScriptedInstance
+{
+ instance_karazhan(Map* pMap) : ScriptedInstance(pMap) {Initialize();}
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint32 m_uiOperaEvent;
+ uint32 m_uiOzDeathCount;
+
+ uint64 m_uiCurtainGUID;
+ uint64 m_uiStageDoorLeftGUID;
+ uint64 m_uiStageDoorRightGUID;
+ uint64 m_uiTerestianGUID;
+ uint64 m_uiMoroesGUID;
+ uint64 m_uiLibraryDoor; // Door at Shade of Aran
+ uint64 m_uiMassiveDoor; // Door at Netherspite
+ uint64 m_uiSideEntranceDoor; // Side Entrance
+ uint64 m_uiGamesmansDoor; // Door before Chess
+ uint64 m_uiGamesmansExitDoor; // Door after Chess
+ uint64 m_uiNetherspaceDoor; // Door at Malchezaar
+ uint64 m_uiDustCoveredChest; // Chest respawn at event complete
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ // 1 - OZ, 2 - HOOD, 3 - RAJ, this never gets altered.
+ m_uiOperaEvent = urand(EVENT_OZ,EVENT_RAJ);
+ m_uiOzDeathCount = 0;
+
+ m_uiCurtainGUID = 0;
+ m_uiStageDoorLeftGUID = 0;
+ m_uiStageDoorRightGUID = 0;
+
+ m_uiTerestianGUID = 0;
+ m_uiMoroesGUID = 0;
+
+ m_uiLibraryDoor = 0;
+ m_uiMassiveDoor = 0;
+ m_uiSideEntranceDoor = 0;
+ m_uiGamesmansDoor = 0;
+ m_uiGamesmansExitDoor = 0;
+ m_uiNetherspaceDoor = 0;
+ m_uiDustCoveredChest = 0;
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ return true;
+
+ return false;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch (pCreature->GetEntry())
+ {
+ case 15688: m_uiTerestianGUID = pCreature->GetGUID(); break;
+ case 15687: m_uiMoroesGUID = pCreature->GetGUID(); break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case 183932: m_uiCurtainGUID = pGo->GetGUID(); break;
+ case 184278:
+ m_uiStageDoorLeftGUID = pGo->GetGUID();
+ if (m_auiEncounter[4] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case 184279:
+ m_uiStageDoorRightGUID = pGo->GetGUID();
+ if (m_auiEncounter[4] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case 184517: m_uiLibraryDoor = pGo->GetGUID(); break;
+ case 185521: m_uiMassiveDoor = pGo->GetGUID(); break;
+ case 184276: m_uiGamesmansDoor = pGo->GetGUID(); break;
+ case 184277: m_uiGamesmansExitDoor = pGo->GetGUID(); break;
+ case 185134: m_uiNetherspaceDoor = pGo->GetGUID(); break;
+ case 184275:
+ m_uiSideEntranceDoor = pGo->GetGUID();
+ if (m_auiEncounter[4] != DONE)
+ pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
+ else
+ pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
+ break;
+ case 185119: m_uiDustCoveredChest = pGo->GetGUID(); break;
+ }
+
+ switch(m_uiOperaEvent)
+ {
+ //TODO: Set DoRespawnGameObject for Opera based on performance
+ case EVENT_OZ:
+ break;
+ case EVENT_HOOD:
+ break;
+ case EVENT_RAJ:
+ break;
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_ATTUMEN: m_auiEncounter[0] = uiData; break;
+ case TYPE_MOROES:
+ if (m_auiEncounter[1] != DONE)
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_MAIDEN: m_auiEncounter[2] = uiData; break;
+ case TYPE_OPTIONAL_BOSS: m_auiEncounter[3] = uiData; break;
+ case TYPE_OPERA:
+ m_auiEncounter[4] = uiData;
+ if (uiData == DONE)
+ {
+ DoUseDoorOrButton(m_uiStageDoorLeftGUID);
+ DoUseDoorOrButton(m_uiStageDoorRightGUID);
+ if (GameObject* pSideEntrance = instance->GetGameObject(m_uiSideEntranceDoor))
+ pSideEntrance->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
+ }
+ break;
+ case TYPE_CURATOR: m_auiEncounter[5] = uiData; break;
+ case TYPE_ARAN:
+ m_auiEncounter[6] = uiData;
+ if (uiData != IN_PROGRESS)
+ DoUseDoorOrButton(m_uiLibraryDoor);
+ break;
+ case TYPE_TERESTIAN: m_auiEncounter[7] = uiData; break;
+ case TYPE_NETHERSPITE:
+ m_auiEncounter[8] = uiData;
+ DoUseDoorOrButton(m_uiMassiveDoor);
+ break;
+ case TYPE_CHESS:
+ if (uiData == DONE)
+ DoRespawnGameObject(m_uiDustCoveredChest,DAY);
+ m_auiEncounter[9] = uiData;
+ break;
+ case TYPE_MALCHEZZAR: m_auiEncounter[10] = uiData; break;
+ case TYPE_NIGHTBANE: m_auiEncounter[11] = uiData; break;
+ case DATA_OPERA_OZ_DEATHCOUNT:
+ if (uiData == SPECIAL)
+ ++m_uiOzDeathCount;
+ else if (uiData == IN_PROGRESS)
+ m_uiOzDeathCount = 0;
+ break;
+ }
+
+ if (uiData == DONE)
+ {
+ 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] << " "
+ << m_auiEncounter[9] << " " << m_auiEncounter[10] << " " << m_auiEncounter[11];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ const char* Save()
+ {
+ return strInstData.c_str();
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch (uiType)
+ {
+ case TYPE_ATTUMEN: return m_auiEncounter[0];
+ case TYPE_MOROES: return m_auiEncounter[1];
+ case TYPE_MAIDEN: return m_auiEncounter[2];
+ case TYPE_OPTIONAL_BOSS: return m_auiEncounter[3];
+ case TYPE_OPERA: return m_auiEncounter[4];
+ case TYPE_CURATOR: return m_auiEncounter[5];
+ case TYPE_ARAN: return m_auiEncounter[6];
+ case TYPE_TERESTIAN: return m_auiEncounter[7];
+ case TYPE_NETHERSPITE: return m_auiEncounter[8];
+ case TYPE_CHESS: return m_auiEncounter[9];
+ case TYPE_MALCHEZZAR: return m_auiEncounter[10];
+ case TYPE_NIGHTBANE: return m_auiEncounter[11];
+ case DATA_OPERA_PERFORMANCE: return m_uiOperaEvent;
+ case DATA_OPERA_OZ_DEATHCOUNT: return m_uiOzDeathCount;
+ }
+
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch (uiData)
+ {
+ case DATA_TERESTIAN: return m_uiTerestianGUID;
+ case DATA_MOROES: return m_uiMoroesGUID;
+ case DATA_GO_STAGEDOORLEFT: return m_uiStageDoorLeftGUID;
+ case DATA_GO_STAGEDOORRIGHT: return m_uiStageDoorRightGUID;
+ case DATA_GO_CURTAINS: return m_uiCurtainGUID;
+ case DATA_GO_LIBRARY_DOOR: return m_uiLibraryDoor;
+ case DATA_GO_MASSIVE_DOOR: return m_uiMassiveDoor;
+ case DATA_GO_SIDE_ENTRANCE_DOOR: return m_uiSideEntranceDoor;
+ case DATA_GO_GAME_DOOR: return m_uiGamesmansDoor;
+ case DATA_GO_GAME_EXIT_DOOR: return m_uiGamesmansExitDoor;
+ case DATA_GO_NETHER_DOOR: return m_uiNetherspaceDoor;
+ }
+
+ return 0;
+ }
+
+ void Load(const char* chrIn)
+ {
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
+ >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7]
+ >> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiEncounter[10] >> m_auiEncounter[11];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead.
+ m_auiEncounter[i] = NOT_STARTED;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstanceData_instance_karazhan(Map* pMap)
+{
+ return new instance_karazhan(pMap);
+}
+
+void AddSC_instance_karazhan()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "instance_karazhan";
+ newscript->GetInstanceData = &GetInstanceData_instance_karazhan;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/karazhan.cpp b/scripts/eastern_kingdoms/karazhan/karazhan.cpp
new file mode 100644
index 0000000..90c709c
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/karazhan.cpp
@@ -0,0 +1,433 @@
+/* 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: Karazhan
+SD%Complete: 100
+SDComment: Support for Barnes (Opera controller) and Berthold (Doorman).
+SDCategory: Karazhan
+EndScriptData */
+
+/* ContentData
+npc_barnes
+npc_berthold
+EndContentData */
+
+#include "precompiled.h"
+#include "karazhan.h"
+#include "escort_ai.h"
+
+/*######
+# npc_barnesAI
+######*/
+
+#define GOSSIP_READY "I'm not an actor."
+
+#define SAY_READY "Splendid, I'm going to get the audience ready. Break a leg!"
+#define SAY_OZ_INTRO1 "Finally, everything is in place. Are you ready for your big stage debut?"
+#define OZ_GOSSIP1 "I'm not an actor."
+#define SAY_OZ_INTRO2 "Don't worry, you'll be fine. You look like a natural!"
+#define OZ_GOSSIP2 "Ok, I'll give it a try, then."
+
+#define SAY_RAJ_INTRO1 "The romantic plays are really tough, but you'll do better this time. You have TALENT. Ready?"
+#define RAJ_GOSSIP1 "I've never been more ready."
+
+#define OZ_GM_GOSSIP1 "[GM] Change event to EVENT_OZ"
+#define OZ_GM_GOSSIP2 "[GM] Change event to EVENT_HOOD"
+#define OZ_GM_GOSSIP3 "[GM] Change event to EVENT_RAJ"
+
+struct Dialogue
+{
+ int32 iTextId;
+ uint32 uiTimer;
+};
+
+static Dialogue aOzDialogue[4]=
+{
+ {-1532103, 6000},
+ {-1532104, 18000},
+ {-1532105, 9000},
+ {-1532106, 15000}
+};
+
+static Dialogue aHoodDialogue[4]=
+{
+ {-1532107, 6000},
+ {-1532108, 10000},
+ {-1532109, 14000},
+ {-1532110, 15000}
+};
+
+static Dialogue aRAJDialogue[4]=
+{
+ {-1532111, 5000},
+ {-1532112, 7000},
+ {-1532113, 14000},
+ {-1532114, 14000}
+};
+
+struct Spawn
+{
+ uint32 uiEntry;
+ float fPosX;
+};
+
+// Entries and spawn locations for creatures in Oz event
+Spawn aSpawns_OZ[4]=
+{
+ {17535, -10896.0f}, // Dorothee
+ {17546, -10891.0f}, // Roar
+ {17547, -10884.0f}, // Tinhead
+ {17543, -10902.0f}, // Strawman
+};
+Spawn Spawn_HOOD = {17603, -10892.0f}; // Grandmother
+Spawn Spawn_RAJ = {17534, -10900.0f}; // Julianne
+
+enum
+{
+ NPC_SPOTLIGHT = 19525,
+
+ SPELL_SPOTLIGHT = 25824,
+ SPELL_TUXEDO = 32616
+};
+
+const float SPAWN_Z = 90.5f;
+const float SPAWN_Y = -1758.0f;
+const float SPAWN_O = 4.738f;
+
+struct MANGOS_DLL_DECL npc_barnesAI : public npc_escortAI
+{
+ npc_barnesAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_bRaidWiped = false;
+ m_uiEventId = 0;
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint64 m_uiSpotlightGUID;
+
+ uint32 m_uiTalkCount;
+ uint32 m_uiTalkTimer;
+ uint32 m_uiWipeTimer;
+ uint32 m_uiEventId;
+
+ bool m_bPerformanceReady;
+ bool m_bRaidWiped;
+
+ void Reset()
+ {
+ m_uiSpotlightGUID = 0;
+
+ m_uiTalkCount = 0;
+ m_uiTalkTimer = 2000;
+ m_uiWipeTimer = 5000;
+
+ m_bPerformanceReady = false;
+
+ if (m_pInstance)
+ m_uiEventId = m_pInstance->GetData(DATA_OPERA_PERFORMANCE);
+ }
+
+ void StartEvent()
+ {
+ if (!m_pInstance)
+ return;
+
+ m_pInstance->SetData(TYPE_OPERA, IN_PROGRESS);
+
+ //resets count for this event, in case earlier failed
+ if (m_uiEventId == EVENT_OZ)
+ m_pInstance->SetData(DATA_OPERA_OZ_DEATHCOUNT, IN_PROGRESS);
+
+ Start(false, 0, NULL, true);
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ if (!m_pInstance)
+ return;
+
+ switch(uiPointId)
+ {
+ case 0:
+ m_creature->CastSpell(m_creature, SPELL_TUXEDO, false);
+ m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_STAGEDOORLEFT));
+ break;
+ case 4:
+ m_uiTalkCount = 0;
+ SetEscortPaused(true);
+
+ if (Creature* pSpotlight = m_creature->SummonCreature(NPC_SPOTLIGHT,
+ m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0.0f,
+ TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 60000))
+ {
+ pSpotlight->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pSpotlight->CastSpell(pSpotlight, SPELL_SPOTLIGHT, false);
+ m_uiSpotlightGUID = pSpotlight->GetGUID();
+ }
+ break;
+ case 8:
+ m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_STAGEDOORLEFT));
+ m_bPerformanceReady = true;
+ break;
+ case 9:
+ PrepareEncounter();
+ m_pInstance->DoUseDoorOrButton(m_pInstance->GetData64(DATA_GO_CURTAINS));
+ break;
+ }
+ }
+
+ void Talk(uint32 uiCount)
+ {
+ int32 iTextId = 0;
+
+ switch(m_uiEventId)
+ {
+ case EVENT_OZ:
+ if (aOzDialogue[uiCount].iTextId)
+ iTextId = aOzDialogue[uiCount].iTextId;
+ if (aOzDialogue[uiCount].uiTimer)
+ m_uiTalkTimer = aOzDialogue[uiCount].uiTimer;
+ break;
+
+ case EVENT_HOOD:
+ if (aHoodDialogue[uiCount].iTextId)
+ iTextId = aHoodDialogue[uiCount].iTextId;
+ if (aHoodDialogue[uiCount].uiTimer)
+ m_uiTalkTimer = aHoodDialogue[uiCount].uiTimer;
+ break;
+
+ case EVENT_RAJ:
+ if (aRAJDialogue[uiCount].iTextId)
+ iTextId = aRAJDialogue[uiCount].iTextId;
+ if (aRAJDialogue[uiCount].uiTimer)
+ m_uiTalkTimer = aRAJDialogue[uiCount].uiTimer;
+ break;
+ }
+
+ if (iTextId)
+ DoScriptText(iTextId, m_creature);
+ }
+
+ void PrepareEncounter()
+ {
+ debug_log("SD2: Barnes Opera Event - Introduction complete - preparing encounter %d", m_uiEventId);
+
+ switch(m_uiEventId)
+ {
+ case EVENT_OZ:
+ for(int i=0; i < 4; ++i)
+ m_creature->SummonCreature(aSpawns_OZ[i].uiEntry, aSpawns_OZ[i].fPosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS);
+ break;
+ case EVENT_HOOD:
+ m_creature->SummonCreature(Spawn_HOOD.uiEntry, Spawn_HOOD.fPosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS);
+ break;
+ case EVENT_RAJ:
+ m_creature->SummonCreature(Spawn_RAJ.uiEntry, Spawn_RAJ.fPosX, SPAWN_Y, SPAWN_Z, SPAWN_O, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, HOUR*2*IN_MILLISECONDS);
+ break;
+ default:
+ error_log("SD2: Barnes Opera Event - Wrong EventId set: %d", m_uiEventId);
+ break;
+ }
+
+ m_bRaidWiped = false;
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (HasEscortState(STATE_ESCORT_PAUSED))
+ {
+ if (m_uiTalkTimer < uiDiff)
+ {
+ if (m_uiTalkCount > 3)
+ {
+ if (Creature* pSpotlight = m_creature->GetMap()->GetCreature(m_uiSpotlightGUID))
+ pSpotlight->ForcedDespawn();
+
+ SetEscortPaused(false);
+ return;
+ }
+
+ Talk(m_uiTalkCount++);
+ }
+ else
+ m_uiTalkTimer -= uiDiff;
+ }
+
+ if (m_bPerformanceReady)
+ {
+ if (!m_bRaidWiped)
+ {
+ if (m_uiWipeTimer < uiDiff)
+ {
+ Map *pMap = m_creature->GetMap();
+ if (!pMap->IsDungeon())
+ return;
+
+ Map::PlayerList const &PlayerList = pMap->GetPlayers();
+ if (PlayerList.isEmpty())
+ return;
+
+ m_bRaidWiped = true;
+ for(Map::PlayerList::const_iterator i = PlayerList.begin();i != PlayerList.end(); ++i)
+ {
+ if (i->getSource()->isAlive() && !i->getSource()->isGameMaster())
+ {
+ m_bRaidWiped = false;
+ break;
+ }
+ }
+
+ if (m_bRaidWiped)
+ EnterEvadeMode();
+
+ m_uiWipeTimer = 15000;
+ }
+ else
+ m_uiWipeTimer -= uiDiff;
+ }
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_barnesAI(Creature* pCreature)
+{
+ return new npc_barnesAI(pCreature);
+}
+
+bool GossipHello_npc_barnes(Player* pPlayer, Creature* pCreature)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ {
+ // Check for death of Moroes and if opera event is not done already
+ if (pInstance->GetData(TYPE_MOROES) == DONE && pInstance->GetData(TYPE_OPERA) != DONE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+
+ if (pPlayer->isGameMaster()) // for GMs we add the possibility to change the event
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, OZ_GM_GOSSIP3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
+ }
+
+ if (npc_barnesAI* pBarnesAI = dynamic_cast(pCreature->AI()))
+ {
+ if (!pBarnesAI->m_bRaidWiped)
+ pPlayer->SEND_GOSSIP_MENU(8970, pCreature->GetGUID());
+ else
+ pPlayer->SEND_GOSSIP_MENU(8975, pCreature->GetGUID());
+
+ return true;
+ }
+ }
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(8978, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_barnes(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ npc_barnesAI* pBarnesAI = dynamic_cast(pCreature->AI());
+
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, OZ_GOSSIP2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(8971, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ if (pBarnesAI)
+ pBarnesAI->StartEvent();
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ if (pBarnesAI && pPlayer->isGameMaster())
+ pBarnesAI->m_uiEventId = EVENT_OZ;
+ outstring_log("SD2: pPlayer (GUID " UI64FMTD ") manually set Opera event to EVENT_OZ", pPlayer->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ if (pBarnesAI && pPlayer->isGameMaster())
+ pBarnesAI->m_uiEventId = EVENT_HOOD;
+ outstring_log("SD2: pPlayer (GUID " UI64FMTD ") manually set Opera event to EVENT_HOOD", pPlayer->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ if (pBarnesAI && pPlayer->isGameMaster())
+ pBarnesAI->m_uiEventId = EVENT_RAJ;
+ outstring_log("SD2: pPlayer (GUID " UI64FMTD ") manually set Opera event to EVENT_RAJ", pPlayer->GetGUID());
+ break;
+ }
+
+ return true;
+}
+
+/*###
+# npc_berthold
+####*/
+
+enum
+{
+ SPELL_TELEPORT = 39567
+};
+
+#define GOSSIP_ITEM_TELEPORT "Teleport me to the Guardian's Library"
+
+bool GossipHello_npc_berthold(Player* pPlayer, Creature* pCreature)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ {
+ // Check if Shade of Aran event is done
+ if (pInstance->GetData(TYPE_ARAN) == DONE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TELEPORT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_berthold(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
+ pPlayer->CastSpell(pPlayer, SPELL_TELEPORT, true);
+
+ pPlayer->CLOSE_GOSSIP_MENU();
+ return true;
+}
+
+void AddSC_karazhan()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_barnes";
+ newscript->GetAI = &GetAI_npc_barnesAI;
+ newscript->pGossipHello = &GossipHello_npc_barnes;
+ newscript->pGossipSelect = &GossipSelect_npc_barnes;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_berthold";
+ newscript->pGossipHello = &GossipHello_npc_berthold;
+ newscript->pGossipSelect = &GossipSelect_npc_berthold;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/karazhan/karazhan.h b/scripts/eastern_kingdoms/karazhan/karazhan.h
new file mode 100644
index 0000000..c9fa18e
--- /dev/null
+++ b/scripts/eastern_kingdoms/karazhan/karazhan.h
@@ -0,0 +1,64 @@
+/* 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 */
+
+#ifndef DEF_KARAZHAN_H
+#define DEF_KARAZHAN_H
+
+enum
+{
+ MAX_ENCOUNTER = 12,
+
+ TYPE_ATTUMEN = 1,
+ TYPE_MOROES = 2,
+ TYPE_MAIDEN = 3,
+ TYPE_OPTIONAL_BOSS = 4,
+ TYPE_OPERA = 5,
+ TYPE_CURATOR = 6,
+ TYPE_ARAN = 7,
+ TYPE_TERESTIAN = 8,
+ TYPE_NETHERSPITE = 9,
+ TYPE_CHESS = 10,
+ TYPE_MALCHEZZAR = 11,
+ TYPE_NIGHTBANE = 12,
+
+ DATA_OPERA_PERFORMANCE = 13,
+ DATA_OPERA_OZ_DEATHCOUNT = 14,
+
+ DATA_TERESTIAN = 16,
+ DATA_MOROES = 17,
+
+ DATA_GO_CURTAINS = 18,
+ DATA_GO_STAGEDOORLEFT = 19,
+ DATA_GO_STAGEDOORRIGHT = 20,
+ DATA_GO_LIBRARY_DOOR = 21,
+ DATA_GO_MASSIVE_DOOR = 22,
+ DATA_GO_NETHER_DOOR = 23,
+ DATA_GO_GAME_DOOR = 24,
+ DATA_GO_GAME_EXIT_DOOR = 25,
+ DATA_GO_SIDE_ENTRANCE_DOOR = 26
+};
+
+enum OperaEvents
+{
+ EVENT_OZ = 1,
+ EVENT_HOOD = 2,
+ EVENT_RAJ = 3
+};
+
+#define ERROR_INST_DATA(a) error_log("SD2: Instance Data for Karazhan not set properly. Encounter for Creature Entry %u may not work properly.", a->GetEntry());
+
+class MANGOS_DLL_DECL npc_fiendish_portalAI : public ScriptedAI
+{
+ public:
+ npc_fiendish_portalAI(Creature* pCreature);
+ ~npc_fiendish_portalAI() {}
+
+ void Reset();
+ void JustSummoned(Creature* pSummoned);
+ void UpdateAI(const uint32 uiDiff);
+
+ uint32 m_uiSummonTimer;
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/loch_modan.cpp b/scripts/eastern_kingdoms/loch_modan.cpp
new file mode 100644
index 0000000..f25ee07
--- /dev/null
+++ b/scripts/eastern_kingdoms/loch_modan.cpp
@@ -0,0 +1,195 @@
+/* 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: Loch_Modan
+SD%Complete: 100
+SDComment: Quest support: 3181 (only to argue with pebblebitty to get to searing gorge, before quest rewarded), 309
+SDCategory: Loch Modan
+EndScriptData */
+
+/* ContentData
+npc_mountaineer_pebblebitty
+npc_miran
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_mountaineer_pebblebitty
+######*/
+
+bool GossipHello_npc_mountaineer_pebblebitty(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (!pPlayer->GetQuestRewardStatus(3181) == 1)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Open the gate please, i need to get to Searing Gorge", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_mountaineer_pebblebitty(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "But i need to get there, now open the gate!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(1833, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Ok, so what is this other way?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->SEND_GOSSIP_MENU(1834, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Doesn't matter, i'm invulnerable.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
+ pPlayer->SEND_GOSSIP_MENU(1835, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Yes...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
+ pPlayer->SEND_GOSSIP_MENU(1836, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Ok, i'll try to remember that.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
+ pPlayer->SEND_GOSSIP_MENU(1837, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+6:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "A key? Ok!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 7);
+ pPlayer->SEND_GOSSIP_MENU(1838, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+7:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ break;
+ }
+ return true;
+}
+
+/*######
+## npc_miran
+######*/
+
+enum
+{
+ QUEST_PROTECTING_THE_SHIPMENT = 309,
+
+ SAY_MIRAN_1 = -1000571,
+ SAY_DARK_IRON_DWARF = -1000572,
+ SAY_MIRAN_2 = -1000573,
+ SAY_MIRAN_3 = -1000574,
+
+ NPC_DARK_IRON_DWARF = 2149
+};
+
+struct Location
+{
+ float m_fX, m_fY, m_fZ, m_fO;
+};
+
+static const Location m_afAmbushSpawn[] =
+{
+ {-5691.93f,-3745.91f,319.159f, 2.21f},
+ {-5706.98f,-3745.39f,318.728f, 1.04f}
+};
+
+struct MANGOS_DLL_DECL npc_miranAI: public npc_escortAI
+{
+ npc_miranAI(Creature* pCreature): npc_escortAI(pCreature)
+ {
+ Reset();
+ }
+
+ uint8 m_uiDwarves;
+
+ void Reset()
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ m_uiDwarves = 0;
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch (uiPointId)
+ {
+ case 19:
+ DoScriptText(SAY_MIRAN_1, m_creature);
+ m_creature->SummonCreature(NPC_DARK_IRON_DWARF, m_afAmbushSpawn[0].m_fX, m_afAmbushSpawn[0].m_fY, m_afAmbushSpawn[0].m_fZ, m_afAmbushSpawn[0].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 25000);
+ m_creature->SummonCreature(NPC_DARK_IRON_DWARF, m_afAmbushSpawn[1].m_fX, m_afAmbushSpawn[1].m_fY, m_afAmbushSpawn[1].m_fZ, m_afAmbushSpawn[1].m_fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 25000);
+ break;
+ case 23:
+ DoScriptText(SAY_MIRAN_3, m_creature);
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_PROTECTING_THE_SHIPMENT, m_creature);
+ break;
+ }
+ }
+
+ void SummonedCreatureJustDied(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_DARK_IRON_DWARF)
+ {
+ --m_uiDwarves;
+ if (!m_uiDwarves)
+ DoScriptText(SAY_MIRAN_2, m_creature);
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_DARK_IRON_DWARF)
+ {
+ if (!m_uiDwarves)
+ DoScriptText(SAY_DARK_IRON_DWARF, pSummoned);
+ ++m_uiDwarves;
+ pSummoned->AI()->AttackStart(m_creature);
+ }
+ }
+};
+
+bool QuestAccept_npc_miran(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_PROTECTING_THE_SHIPMENT)
+ {
+ if (npc_miranAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_miran(Creature* pCreature)
+{
+ return new npc_miranAI(pCreature);
+}
+
+void AddSC_loch_modan()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_mountaineer_pebblebitty";
+ newscript->pGossipHello = &GossipHello_npc_mountaineer_pebblebitty;
+ newscript->pGossipSelect = &GossipSelect_npc_mountaineer_pebblebitty;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_miran";
+ newscript->GetAI = &GetAI_npc_miran;
+ newscript->pQuestAccept = &QuestAccept_npc_miran;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp b/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp
new file mode 100644
index 0000000..79d86d8
--- /dev/null
+++ b/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp
@@ -0,0 +1,631 @@
+/* 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_Felblood_Kaelthas
+SD%Complete: 80
+SDComment: Normal and Heroic Support. Issues: Arcane Spheres do not initially follow targets.
+SDCategory: Magisters' Terrace
+EndScriptData */
+
+#include "precompiled.h"
+#include "magisters_terrace.h"
+#include "WorldPacket.h"
+
+#define SAY_AGGRO -1585023 //This yell should be done when the room is cleared. For now, set it as a movelineofsight yell.
+#define SAY_PHOENIX -1585024
+#define SAY_FLAMESTRIKE -1585025
+#define SAY_GRAVITY_LAPSE -1585026
+#define SAY_TIRED -1585027
+#define SAY_RECAST_GRAVITY -1585028
+#define SAY_DEATH -1585029
+
+/*** Spells ***/
+
+// Phase 1 spells
+#define SPELL_FIREBALL_NORMAL 44189 // Deals 2700-3300 damage at current target
+#define SPELL_FIREBALL_HEROIC 46164 // 4950-6050
+
+#define SPELL_PHOENIX 44194 // Summons a phoenix (Doesn't work?)
+#define SPELL_PHOENIX_BURN 44197 // A spell Phoenix uses to damage everything around
+#define SPELL_REBIRTH_DMG 44196 // DMG if a Phoenix rebirth happen
+
+#define SPELL_FLAME_STRIKE_DUMMY 44191 // Flamestrike indicator before the damage
+#define SPELL_FLAME_STRIKE 44192 // Summons the trigger + animation (projectile)
+
+#define SPELL_SHOCK_BARRIER 46165 // Heroic only; 10k damage shield, followed by Pyroblast
+#define SPELL_PYROBLAST 36819 // Heroic only; 45-55k fire damage
+
+// Phase 2 spells
+#define SPELL_GRAVITY_LAPSE_INITIAL 44224 // Cast at the beginning of every Gravity Lapse
+#define SPELL_GRAVITY_LAPSE_CHANNEL 44251 // Channeled; blue beam animation to every enemy in range
+#define SPELL_TELEPORT_CENTER 44218 // Should teleport people to the center. Requires DB entry in spell_target_position.
+#define SPELL_GRAVITY_LAPSE_FLY 44227 // Hastens flyspeed and allows flying for 1 minute. For some reason removes 44226.
+#define SPELL_GRAVITY_LAPSE_DOT 44226 // Knocks up in the air and applies a 300 DPS DoT.
+#define SPELL_ARCANE_SPHERE_PASSIVE 44263 // Passive auras on Arcane Spheres
+#define SPELL_POWER_FEEDBACK 44233 // Stuns him, making him take 50% more damage for 10 seconds. Cast after Gravity Lapse
+
+/*** Creatures ***/
+#define NPC_FLAME_STRIKE_TRIGGER 24666
+#define CREATURE_PHOENIX 24674
+#define CREATURE_PHOENIX_EGG 24675
+#define CREATURE_ARCANE_SPHERE 24708
+
+/** Locations **/
+float KaelLocations[3][2]=
+{
+ {148.744659f, 181.377426f},
+ {140.823883f, 195.403046f},
+ {156.574188f, 195.650482f},
+};
+
+#define LOCATION_Z -16.727455f
+
+struct MANGOS_DLL_DECL boss_felblood_kaelthasAI : public ScriptedAI
+{
+ boss_felblood_kaelthasAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ bool m_bIsRegularMode;
+
+ uint32 FireballTimer;
+ uint32 PhoenixTimer;
+ uint32 FlameStrikeTimer;
+ uint32 CombatPulseTimer;
+
+ //Heroic only
+ uint32 PyroblastTimer;
+
+ uint32 GravityLapseTimer;
+ uint32 GravityLapsePhase;
+ // 0 = No Gravity Lapse
+ // 1 = Casting Gravity Lapse visual
+ // 2 = Teleported people to self
+ // 3 = Knocked people up in the air
+ // 4 = Applied an aura that allows them to fly, channeling visual, relased Arcane Orbs.
+
+ bool FirstGravityLapse;
+ bool HasTaunted;
+
+ uint8 Phase;
+ // 0 = Not started
+ // 1 = Fireball; Summon Phoenix; Flamestrike
+ // 2 = Gravity Lapses
+
+ void Reset()
+ {
+ // TODO: Timers
+ FireballTimer = 0;
+ PhoenixTimer = 10000;
+ FlameStrikeTimer = 25000;
+ CombatPulseTimer = 0;
+
+ PyroblastTimer = 60000;
+
+ GravityLapseTimer = 0;
+ GravityLapsePhase = 0;
+
+ FirstGravityLapse = true;
+ HasTaunted = false;
+
+ Phase = 0;
+
+ if (m_pInstance)
+ {
+ m_pInstance->SetData(DATA_KAELTHAS_EVENT, NOT_STARTED);
+
+ if (GameObject* pDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_KAEL_DOOR)))
+ pDoor->SetGoState(GO_STATE_ACTIVE); // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here)
+ // Small door opened after event are expected to be closed by default
+ }
+ }
+
+ void JustDied(Unit *killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (!m_pInstance)
+ return;
+
+ if (GameObject* pEncounterDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_KAEL_DOOR)))
+ pEncounterDoor->SetGoState(GO_STATE_ACTIVE); // Open the encounter door
+ }
+
+ void DamageTaken(Unit* done_by, uint32 &damage)
+ {
+ if (damage > m_creature->GetHealth())
+ RemoveGravityLapse(); // Remove Gravity Lapse so that players fall to ground if they kill him when in air.
+ }
+
+ void Aggro(Unit *who)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (GameObject* pEncounterDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_KAEL_DOOR)))
+ pEncounterDoor->SetGoState(GO_STATE_READY); //Close the encounter door, open it in JustDied/Reset
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ if (!HasTaunted && m_creature->IsWithinDistInMap(who, 40.0))
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ HasTaunted = true;
+ }
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_FLAME_STRIKE_TRIGGER)
+ pSummoned->CastSpell(pSummoned, SPELL_FLAME_STRIKE_DUMMY, false, NULL, NULL, m_creature->GetGUID());
+ }
+
+ void SetThreatList(Creature* SummonedUnit)
+ {
+ if (!SummonedUnit)
+ return;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+ if (pUnit && pUnit->isAlive())
+ {
+ float threat = m_creature->getThreatManager().getThreat(pUnit);
+ SummonedUnit->AddThreat(pUnit, threat);
+ }
+ }
+ }
+
+ void TeleportPlayersToSelf()
+ {
+ float x = KaelLocations[0][0];
+ float y = KaelLocations[0][1];
+
+ DoCastSpellIfCan(m_creature, SPELL_TELEPORT_CENTER, CAST_TRIGGERED);
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ if (pUnit && pUnit->GetTypeId() == TYPEID_PLAYER)
+ pUnit->CastSpell(pUnit, SPELL_TELEPORT_CENTER, true);
+ }
+ }
+
+ void CastGravityLapseKnockUp()
+ {
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ // Knockback into the air
+ if (pUnit && pUnit->GetTypeId() == TYPEID_PLAYER)
+ pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_DOT, true, 0, 0, m_creature->GetGUID());
+ }
+ }
+
+ // players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air...
+ void CastGravityLapseFly()
+ {
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ // Also needs an exception in spell system.
+ if (pUnit && pUnit->GetTypeId() == TYPEID_PLAYER)
+ pUnit->CastSpell(pUnit, SPELL_GRAVITY_LAPSE_FLY, true, 0, 0, m_creature->GetGUID());
+ }
+ }
+
+ void RemoveGravityLapse()
+ {
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ if (pUnit && pUnit->GetTypeId() == TYPEID_PLAYER)
+ {
+ pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_FLY);
+ pUnit->RemoveAurasDueToSpell(SPELL_GRAVITY_LAPSE_DOT);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ switch(Phase)
+ {
+ case 0:
+ {
+ // *Heroic mode only:
+ if (!m_bIsRegularMode)
+ {
+ if (PyroblastTimer < diff)
+ {
+ m_creature->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
+ DoCastSpellIfCan(m_creature, SPELL_SHOCK_BARRIER, CAST_TRIGGERED);
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_PYROBLAST);
+ PyroblastTimer = 60000;
+ }else PyroblastTimer -= diff;
+ }
+
+ if (FireballTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FIREBALL_NORMAL : SPELL_FIREBALL_HEROIC);
+ FireballTimer = urand(2000, 6000);
+ }else FireballTimer -= diff;
+
+ if (PhoenixTimer < diff)
+ {
+
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1))
+ {
+ uint32 random = urand(1, 2);
+ float x = KaelLocations[random][0];
+ float y = KaelLocations[random][1];
+
+ if (Creature* Phoenix = m_creature->SummonCreature(CREATURE_PHOENIX, x, y, LOCATION_Z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000))
+ {
+ Phoenix->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE);
+ SetThreatList(Phoenix);
+ Phoenix->AI()->AttackStart(pTarget);
+ DoScriptText(SAY_PHOENIX, m_creature);
+ }
+ }
+
+ PhoenixTimer = 60000;
+ }else PhoenixTimer -= diff;
+
+ if (FlameStrikeTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoCastSpellIfCan(pTarget, SPELL_FLAME_STRIKE);
+ DoScriptText(SAY_FLAMESTRIKE, m_creature);
+ }
+ FlameStrikeTimer = urand(15000, 25000);
+ }else FlameStrikeTimer -= diff;
+
+ // Below 50%
+ if (m_creature->GetHealthPercent() < 50.0f)
+ {
+ m_creature->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_INTERRUPT_CAST, true);
+ m_creature->StopMoving();
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MoveIdle();
+ GravityLapseTimer = 0;
+ GravityLapsePhase = 0;
+ Phase = 1;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ break;
+
+ case 1:
+ {
+ if (GravityLapseTimer < diff)
+ {
+ switch(GravityLapsePhase)
+ {
+ case 0:
+ if (FirstGravityLapse) // Different yells at 50%, and at every following Gravity Lapse
+ {
+ DoScriptText(SAY_GRAVITY_LAPSE, m_creature);
+ FirstGravityLapse = false;
+
+ if (m_pInstance)
+ {
+ if (GameObject* pKaelLeft = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_KAEL_STATUE_LEFT)))
+ pKaelLeft->SetGoState(GO_STATE_ACTIVE);
+
+ if (GameObject* pKaelRight = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_KAEL_STATUE_RIGHT)))
+ pKaelRight->SetGoState(GO_STATE_ACTIVE);
+ }
+ }
+ else
+ {
+ DoScriptText(SAY_RECAST_GRAVITY, m_creature);
+ }
+
+ DoCastSpellIfCan(m_creature, SPELL_GRAVITY_LAPSE_INITIAL);
+ GravityLapseTimer = 2000 + diff;// Don't interrupt the visual spell
+ GravityLapsePhase = 1;
+ break;
+
+ case 1:
+ TeleportPlayersToSelf();
+ GravityLapseTimer = 1000;
+ GravityLapsePhase = 2;
+ break;
+
+ case 2:
+ CastGravityLapseKnockUp();
+ GravityLapseTimer = 1000;
+ GravityLapsePhase = 3;
+ break;
+
+ case 3:
+ CastGravityLapseFly();
+ GravityLapseTimer = 30000;
+ GravityLapsePhase = 4;
+
+
+ for(uint8 i = 0; i < 3; ++i)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ if (Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))
+ Orb->AI()->AttackStart(pTarget);
+ }
+ }
+
+ DoCastSpellIfCan(m_creature, SPELL_GRAVITY_LAPSE_CHANNEL);
+ break;
+
+ case 4:
+ m_creature->InterruptNonMeleeSpells(false);
+ DoScriptText(SAY_TIRED, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_POWER_FEEDBACK);
+ RemoveGravityLapse();
+ GravityLapseTimer = 10000;
+ GravityLapsePhase = 0;
+ break;
+ }
+ }else GravityLapseTimer -= diff;
+ }
+ break;
+ }
+ }
+};
+
+struct MANGOS_DLL_DECL mob_felkael_phoenixAI : public ScriptedAI
+{
+ mob_felkael_phoenixAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ uint32 BurnTimer;
+ uint32 Death_Timer;
+ bool Rebirth;
+ bool FakeDeath;
+
+ void Reset()
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE + UNIT_FLAG_NON_ATTACKABLE);
+ m_creature->CastSpell(m_creature,SPELL_PHOENIX_BURN,true);
+
+ BurnTimer = 2000;
+ Death_Timer = 3000;
+ Rebirth = false;
+ FakeDeath = false;
+ }
+
+ void DamageTaken(Unit* pKiller, uint32 &damage)
+ {
+ if (damage < m_creature->GetHealth())
+ return;
+
+ //Prevent glitch if in fake death
+ if (FakeDeath)
+ {
+ damage = 0;
+ return;
+
+ }
+ //Don't really die in all phases of Kael'Thas
+ if (m_pInstance && m_pInstance->GetData(DATA_KAELTHAS_EVENT) == 0)
+ {
+ //prevent death
+ damage = 0;
+ FakeDeath = true;
+
+ 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);
+
+ }
+
+ }
+
+ void JustDied(Unit* slayer)
+ {
+ m_creature->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+
+ //If we are fake death, we cast revbirth and after that we kill the phoenix to spawn the egg.
+ if (FakeDeath)
+ {
+ if (!Rebirth)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_REBIRTH_DMG);
+ Rebirth = true;
+ }
+
+ if (Rebirth)
+ {
+
+ if (Death_Timer < diff)
+ {
+ m_creature->SummonCreature(CREATURE_PHOENIX_EGG, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 45000);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->RemoveCorpse();
+ Rebirth = false;
+ }else Death_Timer -= diff;
+ }
+
+
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (BurnTimer < diff)
+ {
+ //spell Burn should possible do this, but it doesn't, so do this for now.
+ uint32 dmg = urand(1650,2050);
+ m_creature->DealDamage(m_creature, dmg, 0, DOT, SPELL_SCHOOL_MASK_FIRE, NULL, false);
+ BurnTimer += 2000;
+ } BurnTimer -= diff;
+
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL mob_felkael_phoenix_eggAI : public ScriptedAI
+{
+ mob_felkael_phoenix_eggAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 HatchTimer;
+
+ void Reset()
+ {
+ HatchTimer = 10000;
+
+ }
+
+ void MoveInLineOfSight(Unit* who) {}
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (HatchTimer < diff)
+ {
+ m_creature->SummonCreature(CREATURE_PHOENIX, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
+ m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }else HatchTimer -= diff;
+
+ }
+};
+
+struct MANGOS_DLL_DECL mob_arcane_sphereAI : public ScriptedAI
+{
+ mob_arcane_sphereAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 DespawnTimer;
+ uint32 ChangeTargetTimer;
+
+ void Reset()
+ {
+ DespawnTimer = 30000;
+ ChangeTargetTimer = urand(6000, 12000);
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ DoCastSpellIfCan(m_creature, SPELL_ARCANE_SPHERE_PASSIVE, CAST_TRIGGERED);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (DespawnTimer < diff)
+ m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ else DespawnTimer -= diff;
+
+ if (!m_creature->getVictim() || !m_creature->SelectHostileTarget())
+ return;
+
+ if (ChangeTargetTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ m_creature->TauntApply(pTarget);
+ AttackStart(pTarget);
+ }
+
+ ChangeTargetTimer = urand(5000, 15000);
+ }else ChangeTargetTimer -= diff;
+ }
+};
+
+CreatureAI* GetAI_boss_felblood_kaelthas(Creature* pCreature)
+{
+ return new boss_felblood_kaelthasAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_arcane_sphere(Creature* pCreature)
+{
+ return new mob_arcane_sphereAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_felkael_phoenix(Creature* pCreature)
+{
+ return new mob_felkael_phoenixAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_felkael_phoenix_egg(Creature* pCreature)
+{
+ return new mob_felkael_phoenix_eggAI(pCreature);
+}
+
+void AddSC_boss_felblood_kaelthas()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_felblood_kaelthas";
+ newscript->GetAI = &GetAI_boss_felblood_kaelthas;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_arcane_sphere";
+ newscript->GetAI = &GetAI_mob_arcane_sphere;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_felkael_phoenix";
+ newscript->GetAI = &GetAI_mob_felkael_phoenix;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_felkael_phoenix_egg";
+ newscript->GetAI = &GetAI_mob_felkael_phoenix_egg;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp b/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp
new file mode 100644
index 0000000..f376112
--- /dev/null
+++ b/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp
@@ -0,0 +1,1337 @@
+/* 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_Priestess_Delrissa
+SD%Complete: 65
+SDComment: No Heroic support yet. Needs further testing. Several scripts for pets disabled, not seem to require any special script.
+SDCategory: Magister's Terrace
+EndScriptData */
+
+#include "precompiled.h"
+#include "magisters_terrace.h"
+
+struct Speech
+{
+ int32 id;
+};
+
+static Speech LackeyDeath[]=
+{
+ {-1585013},
+ {-1585014},
+ {-1585015},
+ {-1585016},
+};
+
+static Speech PlayerDeath[]=
+{
+ {-1585017},
+ {-1585018},
+ {-1585019},
+ {-1585020},
+ {-1585021},
+};
+
+enum
+{
+ SAY_AGGRO = -1585012,
+ SAY_DEATH = -1585022,
+
+ SPELL_DISPEL_MAGIC = 27609,
+ SPELL_FLASH_HEAL = 17843,
+ SPELL_SW_PAIN_NORMAL = 14032,
+ SPELL_SW_PAIN_HEROIC = 15654,
+ SPELL_SHIELD = 44291,
+ SPELL_RENEW_NORMAL = 44174,
+ SPELL_RENEW_HEROIC = 46192,
+
+ MAX_ACTIVE_LACKEY = 4
+};
+
+const float fOrientation = 4.98f;
+const float fZLocation = -19.921f;
+
+float LackeyLocations[4][2]=
+{
+ {123.77f, 17.6007f},
+ {131.731f, 15.0827f},
+ {121.563f, 15.6213f},
+ {129.988f, 17.2355f},
+};
+
+const uint32 m_auiAddEntries[] =
+{
+ 24557, //Kagani Nightstrike
+ 24558, //Elris Duskhallow
+ 24554, //Eramas Brightblaze
+ 24561, //Yazzaj
+ 24559, //Warlord Salaris
+ 24555, //Garaxxas
+ 24553, //Apoko
+ 24556, //Zelfan
+};
+
+struct MANGOS_DLL_DECL boss_priestess_delrissaAI : public ScriptedAI
+{
+ boss_priestess_delrissaAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
+ memset(&m_auiLackeyGUID, 0, sizeof(m_auiLackeyGUID));
+ LackeyEntryList.clear();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ bool m_bIsRegularMode;
+
+ std::vector LackeyEntryList;
+ uint64 m_auiLackeyGUID[MAX_ACTIVE_LACKEY];
+
+ uint8 PlayersKilled;
+
+ uint32 HealTimer;
+ uint32 RenewTimer;
+ uint32 ShieldTimer;
+ uint32 SWPainTimer;
+ uint32 DispelTimer;
+
+ void Reset()
+ {
+ PlayersKilled = 0;
+
+ HealTimer = 15000;
+ RenewTimer = 10000;
+ ShieldTimer = 2000;
+ SWPainTimer = 5000;
+ DispelTimer = 7500;
+
+ InitializeLackeys();
+ }
+
+ //this mean she at some point evaded
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(DATA_DELRISSA_EVENT, FAIL);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ for(uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i)
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiLackeyGUID[i]))
+ {
+ if (!pAdd->getVictim())
+ {
+ pWho->SetInCombatWith(pAdd);
+ pAdd->AddThreat(pWho);
+ }
+ }
+ }
+
+ if (m_pInstance)
+ m_pInstance->SetData(DATA_DELRISSA_EVENT, IN_PROGRESS);
+ }
+
+ void InitializeLackeys()
+ {
+ //can be called if creature are dead, so avoid
+ if (!m_creature->isAlive())
+ return;
+
+ uint8 j = 0;
+
+ //it's empty, so first time
+ if (LackeyEntryList.empty())
+ {
+ //pre-allocate size for speed
+ LackeyEntryList.resize((sizeof(m_auiAddEntries) / sizeof(uint32)));
+
+ //fill vector array with entries from creature array
+ for(uint8 i = 0; i < LackeyEntryList.size(); ++i)
+ LackeyEntryList[i] = m_auiAddEntries[i];
+
+ //remove random entries
+ while(LackeyEntryList.size() > MAX_ACTIVE_LACKEY)
+ LackeyEntryList.erase(LackeyEntryList.begin() + rand()%LackeyEntryList.size());
+
+ //summon all the remaining in vector
+ for(std::vector::iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr)
+ {
+ if (Creature* pAdd = m_creature->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ m_auiLackeyGUID[j] = pAdd->GetGUID();
+
+ ++j;
+ }
+ }
+ else
+ {
+ for(std::vector::iterator itr = LackeyEntryList.begin(); itr != LackeyEntryList.end(); ++itr)
+ {
+ Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiLackeyGUID[j]);
+
+ //object already removed, not exist
+ if (!pAdd)
+ {
+ if (Creature* pAdd = m_creature->SummonCreature((*itr), LackeyLocations[j][0], LackeyLocations[j][1], fZLocation, fOrientation, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ m_auiLackeyGUID[j] = pAdd->GetGUID();
+ }
+ ++j;
+ }
+ }
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (victim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ DoScriptText(PlayerDeath[PlayersKilled].id, m_creature);
+
+ if (PlayersKilled < 4)
+ ++PlayersKilled;
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (!m_pInstance)
+ return;
+
+ if (m_pInstance->GetData(DATA_DELRISSA_DEATH_COUNT) == MAX_ACTIVE_LACKEY)
+ m_pInstance->SetData(DATA_DELRISSA_EVENT, DONE);
+ else
+ {
+ if (m_creature->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE))
+ m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (HealTimer < diff)
+ {
+ uint32 health = m_creature->GetHealth();
+ Creature* target = m_creature;
+
+ for(uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i)
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiLackeyGUID[i]))
+ {
+ if (pAdd->isAlive() && pAdd->GetHealth() < health)
+ target = pAdd;
+ }
+ }
+
+ DoCastSpellIfCan(target, SPELL_FLASH_HEAL);
+ HealTimer = 15000;
+ }else HealTimer -= diff;
+
+ if (RenewTimer < diff)
+ {
+ Creature* target = m_creature;
+
+ if (urand(0, 1))
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY]))
+ {
+ if (pAdd->isAlive())
+ target = pAdd;
+ }
+ }
+
+ DoCastSpellIfCan(target, m_bIsRegularMode ? SPELL_RENEW_NORMAL : SPELL_RENEW_HEROIC);
+ RenewTimer = 5000;
+ }else RenewTimer -= diff;
+
+ if (ShieldTimer < diff)
+ {
+ Creature* target = m_creature;
+
+ if (urand(0, 1))
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY]))
+ {
+ if (pAdd->isAlive() && !pAdd->HasAura(SPELL_SHIELD))
+ target = pAdd;
+ }
+ }
+
+ DoCastSpellIfCan(target, SPELL_SHIELD);
+ ShieldTimer = 7500;
+ }else ShieldTimer -= diff;
+
+ if (DispelTimer < diff)
+ {
+ Unit* target = NULL;
+ bool friendly = false;
+
+ if (urand(0, 1))
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+ else
+ {
+ friendly = true;
+
+ if (urand(0, 1))
+ target = m_creature;
+ else
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiLackeyGUID[rand()%MAX_ACTIVE_LACKEY]))
+ {
+ if (pAdd->isAlive())
+ target = pAdd;
+ }
+ }
+ }
+
+ if (target)
+ DoCastSpellIfCan(target, SPELL_DISPEL_MAGIC);
+
+ DispelTimer = 12000;
+ }else DispelTimer -= diff;
+
+ if (SWPainTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_SW_PAIN_NORMAL : SPELL_SW_PAIN_HEROIC);
+
+ SWPainTimer = 10000;
+ }else SWPainTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_priestess_delrissa(Creature* pCreature)
+{
+ return new boss_priestess_delrissaAI(pCreature);
+}
+
+enum
+{
+ SPELL_HEALING_POTION = 15503
+};
+
+//all 8 possible lackey use this common
+struct MANGOS_DLL_DECL boss_priestess_lackey_commonAI : public ScriptedAI
+{
+ boss_priestess_lackey_commonAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ memset(&m_auiLackeyGUIDs, 0, sizeof(m_auiLackeyGUIDs));
+ Reset();
+ AcquireGUIDs();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint64 m_auiLackeyGUIDs[MAX_ACTIVE_LACKEY];
+ uint32 m_uiResetThreatTimer;
+ bool m_bUsedPotion;
+
+ void Reset()
+ {
+ m_bUsedPotion = false;
+
+ // These guys does not follow normal threat system rules
+ // For later development, some alternative threat system should be made
+ // We do not know what this system is based upon, but one theory is class (healers=high threat, dps=medium, etc)
+ // We reset their threat frequently as an alternative until such a system exist
+ m_uiResetThreatTimer = urand(5000, 15000);
+
+ // in case she is not alive and Reset was for some reason called, respawn her (most likely party wipe after killing her)
+ if (Creature* pDelrissa = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_DELRISSA)))
+ {
+ if (!pDelrissa->isAlive())
+ pDelrissa->Respawn();
+ }
+ }
+
+ void EnterCombat(Unit* pWho)
+ {
+ if (!pWho)
+ return;
+
+ if (m_pInstance)
+ {
+ for(uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i)
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiLackeyGUIDs[i]))
+ {
+ if (!pAdd->getVictim() && pAdd != m_creature)
+ {
+ pWho->SetInCombatWith(pAdd);
+ pAdd->AddThreat(pWho);
+ }
+ }
+ }
+
+ if (Creature* pDelrissa = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_DELRISSA)))
+ {
+ if (pDelrissa->isAlive() && !pDelrissa->getVictim())
+ {
+ pWho->SetInCombatWith(pDelrissa);
+ pDelrissa->AddThreat(pWho);
+ }
+ }
+ }
+
+ Aggro(pWho);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (!m_pInstance)
+ return;
+
+ Creature* pDelrissa = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_DELRISSA));
+ uint32 uiLackeyDeathCount = m_pInstance->GetData(DATA_DELRISSA_DEATH_COUNT);
+
+ if (!pDelrissa)
+ return;
+
+ //should delrissa really yell if dead?
+ DoScriptText(LackeyDeath[uiLackeyDeathCount].id, pDelrissa);
+
+ m_pInstance->SetData(DATA_DELRISSA_DEATH_COUNT, SPECIAL);
+
+ //increase local var, since we now may have four dead
+ ++uiLackeyDeathCount;
+
+ if (uiLackeyDeathCount == MAX_ACTIVE_LACKEY)
+ {
+ //time to make her lootable and complete event if she died before lackeys
+ if (!pDelrissa->isAlive())
+ {
+ if (!pDelrissa->HasFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE))
+ pDelrissa->SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+
+ m_pInstance->SetData(DATA_DELRISSA_EVENT, DONE);
+ }
+ }
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pDelrissa = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_DELRISSA)))
+ pDelrissa->AI()->KilledUnit(pVictim);
+ }
+
+ void AcquireGUIDs()
+ {
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pDelrissa = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_DELRISSA)))
+ {
+ boss_priestess_delrissaAI* pDelrissaAI = dynamic_cast(pDelrissa->AI());
+
+ if (!pDelrissaAI)
+ return;
+
+ for(uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i)
+ m_auiLackeyGUIDs[i] = pDelrissaAI->m_auiLackeyGUID[i];
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_bUsedPotion && m_creature->GetHealthPercent() < 25.0f)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HEALING_POTION);
+ m_bUsedPotion = true;
+ }
+
+ if (m_uiResetThreatTimer < uiDiff)
+ {
+ DoResetThreat();
+ m_uiResetThreatTimer = urand(5000, 15000);
+ }else m_uiResetThreatTimer -= uiDiff;
+ }
+};
+
+enum
+{
+ SPELL_KIDNEY_SHOT = 27615,
+ SPELL_GOUGE = 12540,
+ SPELL_KICK = 27613,
+ SPELL_VANISH = 44290,
+ SPELL_BACKSTAB = 15657,
+ SPELL_EVISCERATE = 27611
+};
+
+struct MANGOS_DLL_DECL boss_kagani_nightstrikeAI : public boss_priestess_lackey_commonAI
+{
+ //Rogue
+ boss_kagani_nightstrikeAI(Creature* pCreature) : boss_priestess_lackey_commonAI(pCreature) { Reset(); }
+
+ uint32 Gouge_Timer;
+ uint32 Kick_Timer;
+ uint32 Vanish_Timer;
+ uint32 Eviscerate_Timer;
+ uint32 Wait_Timer;
+ bool InVanish;
+
+ void Reset()
+ {
+ Gouge_Timer = 5500;
+ Kick_Timer = 7000;
+ Vanish_Timer = 2000;
+ Eviscerate_Timer = 6000;
+ Wait_Timer = 5000;
+ InVanish = false;
+ m_creature->SetVisibility(VISIBILITY_ON);
+
+ boss_priestess_lackey_commonAI::Reset();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_priestess_lackey_commonAI::UpdateAI(diff);
+
+ if (Vanish_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_VANISH);
+
+ Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+
+ DoResetThreat();
+
+ if (pUnit)
+ m_creature->AddThreat(pUnit, 1000.0f);
+
+ InVanish = true;
+ Vanish_Timer = 30000;
+ Wait_Timer = 10000;
+ }else Vanish_Timer -= diff;
+
+ if (InVanish)
+ {
+ if (Wait_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_BACKSTAB, CAST_TRIGGERED);
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_KIDNEY_SHOT, CAST_TRIGGERED);
+ m_creature->SetVisibility(VISIBILITY_ON); // ...? Hacklike
+ InVanish = false;
+ }else Wait_Timer -= diff;
+ }
+
+ if (Gouge_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_GOUGE);
+ Gouge_Timer = 5500;
+ }else Gouge_Timer -= diff;
+
+ if (Kick_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_KICK);
+ Kick_Timer = 7000;
+ }else Kick_Timer -= diff;
+
+ if (Eviscerate_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_EVISCERATE);
+ Eviscerate_Timer = 4000;
+ }else Eviscerate_Timer -= diff;
+
+ if (!InVanish)
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_kagani_nightstrike(Creature* pCreature)
+{
+ return new boss_kagani_nightstrikeAI(pCreature);
+}
+
+enum
+{
+ SPELL_IMMOLATE = 44267,
+ SPELL_SHADOW_BOLT = 12471,
+ SPELL_SEED_OF_CORRUPTION = 44141,
+ SPELL_CURSE_OF_AGONY = 14875,
+ SPELL_FEAR = 38595,
+ SPELL_IMP_FIREBALL = 44164,
+ SPELL_SUMMON_IMP = 44163
+};
+
+struct MANGOS_DLL_DECL boss_ellris_duskhallowAI : public boss_priestess_lackey_commonAI
+{
+ //Warlock
+ boss_ellris_duskhallowAI(Creature* pCreature) : boss_priestess_lackey_commonAI(pCreature) { Reset(); }
+
+ uint32 Immolate_Timer;
+ uint32 Shadow_Bolt_Timer;
+ uint32 Seed_of_Corruption_Timer;
+ uint32 Curse_of_Agony_Timer;
+ uint32 Fear_Timer;
+
+ void Reset()
+ {
+ Immolate_Timer = 6000;
+ Shadow_Bolt_Timer = 3000;
+ Seed_of_Corruption_Timer = 2000;
+ Curse_of_Agony_Timer = 1000;
+ Fear_Timer = 10000;
+
+ boss_priestess_lackey_commonAI::Reset();
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_SUMMON_IMP);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_priestess_lackey_commonAI::UpdateAI(diff);
+
+ if (Immolate_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_IMMOLATE);
+ Immolate_Timer = 6000;
+ }else Immolate_Timer -= diff;
+
+ if (Shadow_Bolt_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOW_BOLT);
+ Shadow_Bolt_Timer = 5000;
+ }else Shadow_Bolt_Timer -= diff;
+
+ if (Seed_of_Corruption_Timer < diff)
+ {
+ if (Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pUnit, SPELL_SEED_OF_CORRUPTION);
+
+ Seed_of_Corruption_Timer = 10000;
+ }else Seed_of_Corruption_Timer -= diff;
+
+ if (Curse_of_Agony_Timer < diff)
+ {
+ if (Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pUnit, SPELL_CURSE_OF_AGONY);
+
+ Curse_of_Agony_Timer = 13000;
+ }else Curse_of_Agony_Timer -= diff;
+
+ if (Fear_Timer < diff)
+ {
+ if (Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pUnit, SPELL_FEAR);
+
+ Fear_Timer = 10000;
+ }else Fear_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_ellris_duskhallow(Creature* pCreature)
+{
+ return new boss_ellris_duskhallowAI(pCreature);
+}
+
+enum
+{
+ SPELL_KNOCKDOWN = 11428,
+ SPELL_SNAP_KICK = 46182
+};
+
+struct MANGOS_DLL_DECL boss_eramas_brightblazeAI : public boss_priestess_lackey_commonAI
+{
+ //Monk
+ boss_eramas_brightblazeAI(Creature* pCreature) : boss_priestess_lackey_commonAI(pCreature) { Reset(); }
+
+ uint32 Knockdown_Timer;
+ uint32 Snap_Kick_Timer;
+
+ void Reset()
+ {
+ Knockdown_Timer = 6000;
+ Snap_Kick_Timer = 4500;
+
+ boss_priestess_lackey_commonAI::Reset();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_priestess_lackey_commonAI::UpdateAI(diff);
+
+ if (Knockdown_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KNOCKDOWN);
+ Knockdown_Timer = 6000;
+ }else Knockdown_Timer -= diff;
+
+ if (Snap_Kick_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SNAP_KICK);
+ Snap_Kick_Timer = 4500;
+ }else Snap_Kick_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_eramas_brightblaze(Creature* pCreature)
+{
+ return new boss_eramas_brightblazeAI(pCreature);
+}
+
+enum
+{
+ SPELL_POLYMORPH = 13323,
+ SPELL_ICE_BLOCK = 27619,
+ SPELL_BLIZZARD = 44178,
+ SPELL_ICE_LANCE = 46194,
+ SPELL_CONE_OF_COLD = 38384,
+ SPELL_FROSTBOLT = 15043,
+ SPELL_BLINK = 14514
+};
+
+struct MANGOS_DLL_DECL boss_yazzaiAI : public boss_priestess_lackey_commonAI
+{
+ //Mage
+ boss_yazzaiAI(Creature* pCreature) : boss_priestess_lackey_commonAI(pCreature) { Reset(); }
+
+ bool HasIceBlocked;
+
+ uint32 Polymorph_Timer;
+ uint32 Ice_Block_Timer;
+ uint32 Wait_Timer;
+ uint32 Blizzard_Timer;
+ uint32 Ice_Lance_Timer;
+ uint32 Cone_of_Cold_Timer;
+ uint32 Frostbolt_Timer;
+ uint32 Blink_Timer;
+
+ void Reset()
+ {
+ HasIceBlocked = false;
+
+ Polymorph_Timer = 1000;
+ Ice_Block_Timer = 20000;
+ Wait_Timer = 10000;
+ Blizzard_Timer = 8000;
+ Ice_Lance_Timer = 12000;
+ Cone_of_Cold_Timer = 10000;
+ Frostbolt_Timer = 3000;
+ Blink_Timer = 8000;
+
+ boss_priestess_lackey_commonAI::Reset();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_priestess_lackey_commonAI::UpdateAI(diff);
+
+ if (Polymorph_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ DoCastSpellIfCan(target, SPELL_POLYMORPH);
+ Polymorph_Timer = 20000;
+ }
+ }else Polymorph_Timer -= diff;
+
+ if (m_creature->GetHealthPercent() < 35.0f && !HasIceBlocked)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ICE_BLOCK);
+ HasIceBlocked = true;
+ }
+
+ if (Blizzard_Timer < diff)
+ {
+ if (Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pUnit, SPELL_BLIZZARD);
+
+ Blizzard_Timer = 8000;
+ }else Blizzard_Timer -= diff;
+
+ if (Ice_Lance_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_ICE_LANCE);
+ Ice_Lance_Timer = 12000;
+ }else Ice_Lance_Timer -= diff;
+
+ if (Cone_of_Cold_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CONE_OF_COLD);
+ Cone_of_Cold_Timer = 10000;
+ }else Cone_of_Cold_Timer -= diff;
+
+ if (Frostbolt_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FROSTBOLT);
+ Frostbolt_Timer = 8000;
+ }else Frostbolt_Timer -= diff;
+
+ if (Blink_Timer < diff)
+ {
+ bool InMeleeRange = false;
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
+ {
+ if (Unit* target = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()))
+ {
+ //if in melee range
+ if (target->IsWithinDistInMap(m_creature, 5))
+ {
+ InMeleeRange = true;
+ break;
+ }
+ }
+ }
+
+ //if anybody is in melee range than escape by blink
+ if (InMeleeRange)
+ DoCastSpellIfCan(m_creature, SPELL_BLINK);
+
+ Blink_Timer = 8000;
+ }else Blink_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_yazzai(Creature* pCreature)
+{
+ return new boss_yazzaiAI(pCreature);
+}
+
+enum
+{
+ SPELL_INTERCEPT_STUN = 27577,
+ SPELL_DISARM = 27581,
+ SPELL_PIERCING_HOWL = 23600,
+ SPELL_FRIGHTENING_SHOUT = 19134,
+ SPELL_HAMSTRING = 27584,
+ SPELL_BATTLE_SHOUT = 27578,
+ SPELL_MORTAL_STRIKE = 44268
+};
+
+struct MANGOS_DLL_DECL boss_warlord_salarisAI : public boss_priestess_lackey_commonAI
+{
+ //Warrior
+ boss_warlord_salarisAI(Creature* pCreature) : boss_priestess_lackey_commonAI(pCreature) { Reset(); }
+
+ uint32 Intercept_Stun_Timer;
+ uint32 Disarm_Timer;
+ uint32 Piercing_Howl_Timer;
+ uint32 Frightening_Shout_Timer;
+ uint32 Hamstring_Timer;
+ uint32 Mortal_Strike_Timer;
+
+ void Reset()
+ {
+ Intercept_Stun_Timer = 500;
+ Disarm_Timer = 6000;
+ Piercing_Howl_Timer = 10000;
+ Frightening_Shout_Timer = 18000;
+ Hamstring_Timer = 4500;
+ Mortal_Strike_Timer = 8000;
+
+ boss_priestess_lackey_commonAI::Reset();
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BATTLE_SHOUT);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_priestess_lackey_commonAI::UpdateAI(diff);
+
+ if (Intercept_Stun_Timer < diff)
+ {
+ bool InMeleeRange = false;
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
+ {
+ if (Unit* target = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid()))
+ {
+ //if in melee range
+ if (target->IsWithinDistInMap(m_creature, ATTACK_DISTANCE))
+ {
+ InMeleeRange = true;
+ break;
+ }
+ }
+ }
+
+ //if nobody is in melee range than try to use Intercept
+ if (!InMeleeRange)
+ {
+ if (Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pUnit, SPELL_INTERCEPT_STUN);
+ }
+
+ Intercept_Stun_Timer = 10000;
+ }else Intercept_Stun_Timer -= diff;
+
+ if (Disarm_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_DISARM);
+ Disarm_Timer = 6000;
+ }else Disarm_Timer -= diff;
+
+ if (Hamstring_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAMSTRING);
+ Hamstring_Timer = 4500;
+ }else Hamstring_Timer -= diff;
+
+ if (Mortal_Strike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_STRIKE);
+ Mortal_Strike_Timer = 4500;
+ }else Mortal_Strike_Timer -= diff;
+
+ if (Piercing_Howl_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_PIERCING_HOWL);
+ Piercing_Howl_Timer = 10000;
+ }else Piercing_Howl_Timer -= diff;
+
+ if (Frightening_Shout_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FRIGHTENING_SHOUT);
+ Frightening_Shout_Timer = 18000;
+ }else Frightening_Shout_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_warlord_salaris(Creature* pCreature)
+{
+ return new boss_warlord_salarisAI(pCreature);
+}
+
+enum
+{
+ SPELL_AIMED_SHOT = 44271,
+ SPELL_SHOOT = 15620,
+ SPELL_CONCUSSIVE_SHOT = 27634,
+ SPELL_MULTI_SHOT = 31942,
+ SPELL_WING_CLIP = 44286,
+ SPELL_FREEZING_TRAP = 44136,
+
+ NPC_SLIVER = 24552
+};
+
+struct MANGOS_DLL_DECL boss_garaxxasAI : public boss_priestess_lackey_commonAI
+{
+ //Hunter
+ boss_garaxxasAI(Creature* pCreature) : boss_priestess_lackey_commonAI(pCreature)
+ {
+ SetCombatMovement(false);
+ m_uiPetGUID = 0;
+ Reset();
+ }
+
+ uint64 m_uiPetGUID;
+
+ uint32 Aimed_Shot_Timer;
+ uint32 Shoot_Timer;
+ uint32 Concussive_Shot_Timer;
+ uint32 Multi_Shot_Timer;
+ uint32 Wing_Clip_Timer;
+ uint32 Freezing_Trap_Timer;
+
+ void Reset()
+ {
+ Aimed_Shot_Timer = 6000;
+ Shoot_Timer = 2500;
+ Concussive_Shot_Timer = 8000;
+ Multi_Shot_Timer = 10000;
+ Wing_Clip_Timer = 4000;
+ Freezing_Trap_Timer = 15000;
+
+ Creature* pPet = m_creature->GetMap()->GetCreature(m_uiPetGUID);
+ if (!pPet)
+ m_creature->SummonCreature(NPC_SLIVER, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
+
+ boss_priestess_lackey_commonAI::Reset();
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ m_uiPetGUID = pSummoned->GetGUID();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_priestess_lackey_commonAI::UpdateAI(diff);
+
+ if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
+ {
+ if (Wing_Clip_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_WING_CLIP);
+ Wing_Clip_Timer = 4000;
+ }else Wing_Clip_Timer -= diff;
+
+ if (Freezing_Trap_Timer < diff)
+ {
+ //attempt find go summoned from spell (casted by m_creature)
+ GameObject* pGo = m_creature->GetGameObject(SPELL_FREEZING_TRAP);
+
+ //if we have a pGo, we need to wait (only one trap at a time)
+ if (pGo)
+ Freezing_Trap_Timer = 2500;
+ else
+ {
+ //if pGo does not exist, then we can cast
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FREEZING_TRAP);
+ Freezing_Trap_Timer = 15000;
+ }
+ }else Freezing_Trap_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+ else
+ {
+ if (Concussive_Shot_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CONCUSSIVE_SHOT);
+ Concussive_Shot_Timer = 8000;
+ }else Concussive_Shot_Timer -= diff;
+
+ if (Multi_Shot_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MULTI_SHOT);
+ Multi_Shot_Timer = 10000;
+ }else Multi_Shot_Timer -= diff;
+
+ if (Aimed_Shot_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_AIMED_SHOT);
+ Aimed_Shot_Timer = 6000;
+ }else Aimed_Shot_Timer -= diff;
+
+ if (Shoot_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOOT);
+ Shoot_Timer = 2500;
+ }else Shoot_Timer -= diff;
+ }
+ }
+};
+
+CreatureAI* GetAI_garaxxas(Creature* pCreature)
+{
+ return new boss_garaxxasAI(pCreature);
+}
+
+enum
+{
+ SPELL_WINDFURY_TOTEM = 27621,
+ SPELL_WAR_STOMP = 46026,
+ SPELL_PURGE = 27626,
+ SPELL_LESSER_HEALING_WAVE = 44256,
+ SPELL_FROST_SHOCK = 21401,
+ SPELL_FIRE_NOVA_TOTEM = 44257,
+ SPELL_EARTHBIND_TOTEM = 15786
+};
+
+struct MANGOS_DLL_DECL boss_apokoAI : public boss_priestess_lackey_commonAI
+{
+ //Shaman
+ boss_apokoAI(Creature* pCreature) : boss_priestess_lackey_commonAI(pCreature) { Reset(); }
+
+ uint32 Totem_Timer;
+ uint8 Totem_Amount;
+ uint32 War_Stomp_Timer;
+ uint32 Purge_Timer;
+ uint32 Healing_Wave_Timer;
+ uint32 Frost_Shock_Timer;
+
+ void Reset()
+ {
+ Totem_Timer = 2000;
+ Totem_Amount = 1;
+ War_Stomp_Timer = 10000;
+ Purge_Timer = 8000;
+ Healing_Wave_Timer = 5000;
+ Frost_Shock_Timer = 7000;
+
+ boss_priestess_lackey_commonAI::Reset();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_priestess_lackey_commonAI::UpdateAI(diff);
+
+ if (Totem_Timer < diff)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoCastSpellIfCan(m_creature, SPELL_WINDFURY_TOTEM); break;
+ case 1: DoCastSpellIfCan(m_creature, SPELL_FIRE_NOVA_TOTEM); break;
+ case 2: DoCastSpellIfCan(m_creature, SPELL_EARTHBIND_TOTEM); break;
+ }
+ ++Totem_Amount;
+ Totem_Timer = Totem_Amount*2000;
+ }else Totem_Timer -= diff;
+
+ if (War_Stomp_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_WAR_STOMP);
+ War_Stomp_Timer = 10000;
+ }else War_Stomp_Timer -= diff;
+
+ if (Purge_Timer < diff)
+ {
+ if (Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pUnit, SPELL_PURGE);
+
+ Purge_Timer = 15000;
+ }else Purge_Timer -= diff;
+
+ if (Frost_Shock_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FROST_SHOCK);
+ Frost_Shock_Timer = 7000;
+ }else Frost_Shock_Timer -= diff;
+
+ if (Healing_Wave_Timer < diff)
+ {
+ // std::vector::iterator itr = Group.begin() + rand()%Group.size();
+ // uint64 guid = (*itr)->guid;
+ // if (guid)
+ // {
+ // Unit* pAdd = m_creature->GetMap()->GetUnit((*itr)->guid);
+ // if (pAdd && pAdd->isAlive())
+ // {
+ DoCastSpellIfCan(m_creature, SPELL_LESSER_HEALING_WAVE);
+ Healing_Wave_Timer = 5000;
+ // }
+ // }
+ }else Healing_Wave_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_apoko(Creature* pCreature)
+{
+ return new boss_apokoAI(pCreature);
+}
+
+enum
+{
+ SPELL_GOBLIN_DRAGON_GUN = 44272,
+ SPELL_ROCKET_LAUNCH = 44137,
+ SPELL_RECOMBOBULATE = 44274,
+ SPELL_HIGH_EXPLOSIVE_SHEEP = 44276,
+ SPELL_FEL_IRON_BOMB = 46024,
+ SPELL_SHEEP_EXPLOSION = 44279
+};
+
+struct MANGOS_DLL_DECL boss_zelfanAI : public boss_priestess_lackey_commonAI
+{
+ //Engineer
+ boss_zelfanAI(Creature* pCreature) : boss_priestess_lackey_commonAI(pCreature) { Reset(); }
+
+ uint32 Goblin_Dragon_Gun_Timer;
+ uint32 Rocket_Launch_Timer;
+ uint32 Recombobulate_Timer;
+ uint32 High_Explosive_Sheep_Timer;
+ uint32 Fel_Iron_Bomb_Timer;
+
+ void Reset()
+ {
+ Goblin_Dragon_Gun_Timer = 20000;
+ Rocket_Launch_Timer = 7000;
+ Recombobulate_Timer = 4000;
+ High_Explosive_Sheep_Timer = 10000;
+ Fel_Iron_Bomb_Timer = 15000;
+
+ boss_priestess_lackey_commonAI::Reset();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ boss_priestess_lackey_commonAI::UpdateAI(diff);
+
+ if (Goblin_Dragon_Gun_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_GOBLIN_DRAGON_GUN);
+ Goblin_Dragon_Gun_Timer = 10000;
+ }else Goblin_Dragon_Gun_Timer -= diff;
+
+ if (Rocket_Launch_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_ROCKET_LAUNCH);
+ Rocket_Launch_Timer = 9000;
+ }else Rocket_Launch_Timer -= diff;
+
+ if (Fel_Iron_Bomb_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FEL_IRON_BOMB);
+ Fel_Iron_Bomb_Timer = 15000;
+ }else Fel_Iron_Bomb_Timer -= diff;
+
+ if (Recombobulate_Timer < diff)
+ {
+ for(uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i)
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiLackeyGUIDs[i]))
+ {
+ if (pAdd->IsPolymorphed())
+ {
+ DoCastSpellIfCan(pAdd, SPELL_RECOMBOBULATE);
+ break;
+ }
+ }
+ }
+ Recombobulate_Timer = 2000;
+ }else Recombobulate_Timer -= diff;
+
+ if (High_Explosive_Sheep_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HIGH_EXPLOSIVE_SHEEP);
+ High_Explosive_Sheep_Timer = 65000;
+ }else High_Explosive_Sheep_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_zelfan(Creature* pCreature)
+{
+ return new boss_zelfanAI(pCreature);
+}
+
+//struct MANGOS_DLL_DECL mob_high_explosive_sheepAI : public ScriptedAI
+//{
+// mob_high_explosive_sheepAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+//
+// uint32 Explosion_Timer;
+//
+// void Reset()
+// {
+// Explosion_Timer = 60000;
+// }
+//
+// void JustDied(Unit *Killer){}
+//
+// void UpdateAI(const uint32 diff)
+// {
+// if (Explosion_Timer < diff)
+// {
+// DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHEEP_EXPLOSION);
+// }else
+// Explosion_Timer -= diff;
+// }
+//};
+
+//CreatureAI* GetAI_mob_high_explosive_sheep(Creature* pCreature)
+//{
+// return new mob_high_explosive_sheepAI(pCreature);
+//};
+
+void AddSC_boss_priestess_delrissa()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_priestess_delrissa";
+ newscript->GetAI = &GetAI_boss_priestess_delrissa;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_kagani_nightstrike";
+ newscript->GetAI = &GetAI_boss_kagani_nightstrike;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_ellris_duskhallow";
+ newscript->GetAI = &GetAI_ellris_duskhallow;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_eramas_brightblaze";
+ newscript->GetAI = &GetAI_eramas_brightblaze;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_yazzai";
+ newscript->GetAI = &GetAI_yazzai;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_warlord_salaris";
+ newscript->GetAI = &GetAI_warlord_salaris;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_garaxxas";
+ newscript->GetAI = &GetAI_garaxxas;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_apoko";
+ newscript->GetAI = &GetAI_apoko;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_zelfan";
+ newscript->GetAI = &GetAI_zelfan;
+ newscript->RegisterSelf();
+
+ /*newscript = new Script;
+ newscript->Name = "mob_high_explosive_sheep";
+ newscript->GetAI = &GetAI_mob_high_explosive_sheep;
+ newscript->RegisterSelf();*/
+}
diff --git a/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp b/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp
new file mode 100644
index 0000000..7e72cbe
--- /dev/null
+++ b/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp
@@ -0,0 +1,387 @@
+/* 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_Selin_Fireheart
+SD%Complete: 90
+SDComment: Heroic and Normal Support. Needs further testing.
+SDCategory: Magister's Terrace
+EndScriptData */
+
+#include "precompiled.h"
+#include "magisters_terrace.h"
+
+#define SAY_AGGRO -1585000
+#define SAY_ENERGY -1585001
+#define SAY_EMPOWERED -1585002
+#define SAY_KILL_1 -1585003
+#define SAY_KILL_2 -1585004
+#define SAY_DEATH -1585005
+#define EMOTE_CRYSTAL -1585006
+
+//Crystal effect spells
+#define SPELL_FEL_CRYSTAL_COSMETIC 44374
+#define SPELL_FEL_CRYSTAL_DUMMY 44329
+#define SPELL_FEL_CRYSTAL_VISUAL 44355
+#define SPELL_MANA_RAGE 44320 // This spell triggers 44321, which changes scale and regens mana Requires an entry in spell_script_target
+
+//Selin's spells
+#define SPELL_DRAIN_LIFE 44294
+#define SPELL_FEL_EXPLOSION 44314
+
+#define SPELL_DRAIN_MANA 46153 // Heroic only
+
+#define CRYSTALS_NUMBER 5
+#define DATA_CRYSTALS 6
+
+#define CREATURE_FEL_CRYSTAL 24722
+
+struct MANGOS_DLL_DECL boss_selin_fireheartAI : public ScriptedAI
+{
+ boss_selin_fireheartAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
+
+ Crystals.clear();
+ //GUIDs per instance is static, so we only need to load them once.
+ if (m_pInstance)
+ {
+ uint32 size = m_pInstance->GetData(DATA_FEL_CRYSTAL_SIZE);
+ for(uint8 i = 0; i < size; ++i)
+ {
+ uint64 guid = m_pInstance->GetData64(DATA_FEL_CRYSTAL);
+ debug_log("SD2: Selin: Adding Fel Crystal " UI64FMTD " to list", guid);
+ Crystals.push_back(guid);
+ }
+ }
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ bool m_bIsRegularMode;
+
+ std::list Crystals;
+
+ uint32 DrainLifeTimer;
+ uint32 DrainManaTimer;
+ uint32 FelExplosionTimer;
+ uint32 DrainCrystalTimer;
+ uint32 EmpowerTimer;
+
+ bool IsDraining;
+ bool DrainingCrystal;
+
+ uint64 CrystalGUID; // This will help us create a pointer to the crystal we are draining. We store GUIDs, never units in case unit is deleted/offline (offline if player of course).
+
+ void Reset()
+ {
+ if (m_pInstance)
+ {
+ //for(uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
+ for(std::list::iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
+ {
+ //Creature* pUnit = m_creature->GetMap()->GetCreature(FelCrystals[i]);
+ if (Creature* pCrystal = m_creature->GetMap()->GetCreature(*itr))
+ {
+ if (!pCrystal->isAlive())
+ pCrystal->Respawn(); // Let MaNGOS handle setting death state, etc.
+
+ // Only need to set unselectable flag. You can't attack unselectable units so non_attackable flag is not necessary here.
+ pCrystal->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+ }
+
+ if (GameObject* pDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR)))
+ pDoor->SetGoState(GO_STATE_ACTIVE); // Open the big encounter door. Close it in Aggro and open it only in JustDied(and here)
+ // Small door opened after event are expected to be closed by default
+ // Set Inst data for encounter
+ m_pInstance->SetData(DATA_SELIN_EVENT, NOT_STARTED);
+ }else error_log(ERROR_INST_DATA);
+
+ DrainLifeTimer = urand(3000, 7000);
+ DrainManaTimer = DrainLifeTimer + 5000;
+ FelExplosionTimer = 2100;
+ DrainCrystalTimer = urand(10000, 15000);
+ DrainCrystalTimer = urand(20000, 25000);
+ EmpowerTimer = 10000;
+
+ IsDraining = false;
+ DrainingCrystal = false;
+ CrystalGUID = 0;
+ }
+
+ void SelectNearestCrystal()
+ {
+ if (Crystals.empty())
+ return;
+
+ float ShortestDistance = 0;
+ CrystalGUID = 0;
+ Creature* pCrystal = NULL;
+ Creature* CrystalChosen = NULL;
+ //for(uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
+ for(std::list::iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
+ {
+ pCrystal = m_creature->GetMap()->GetCreature(*itr);
+
+ if (pCrystal && pCrystal->isAlive())
+ {
+ // select nearest
+ if (!CrystalChosen || m_creature->GetDistanceOrder(pCrystal, CrystalChosen, false))
+ {
+ CrystalGUID = pCrystal->GetGUID();
+ CrystalChosen = pCrystal; // Store a copy of pCrystal so we don't need to recreate a pointer to closest crystal for the movement and yell.
+ }
+ }
+ }
+ if (CrystalChosen)
+ {
+ DoScriptText(SAY_ENERGY, m_creature);
+ DoScriptText(EMOTE_CRYSTAL, m_creature);
+
+ CrystalChosen->CastSpell(CrystalChosen, SPELL_FEL_CRYSTAL_COSMETIC, true);
+
+ float x, y, z; // coords that we move to, close to the crystal.
+ CrystalChosen->GetClosePoint(x, y, z, m_creature->GetObjectBoundingRadius(), CONTACT_DISTANCE);
+
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ m_creature->GetMotionMaster()->MovePoint(1, x, y, z);
+ DrainingCrystal = true;
+ }
+ }
+
+ void ShatterRemainingCrystals()
+ {
+ if (Crystals.empty())
+ return;
+
+ //for(uint8 i = 0; i < CRYSTALS_NUMBER; ++i)
+ for(std::list::iterator itr = Crystals.begin(); itr != Crystals.end(); ++itr)
+ {
+ //Creature* pCrystal = m_creature->GetMap()->GetCreature(FelCrystals[i]);
+ Creature* pCrystal = m_creature->GetMap()->GetCreature(*itr);
+
+ if (pCrystal && pCrystal->isAlive())
+ pCrystal->DealDamage(pCrystal, pCrystal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (m_pInstance)
+ {
+ //Close the encounter door, open it in JustDied/Reset
+ if (GameObject* pEncounterDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR)))
+ pEncounterDoor->SetGoState(GO_STATE_READY);
+ }
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_KILL_1 : SAY_KILL_2, m_creature);
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type == POINT_MOTION_TYPE && id == 1)
+ {
+ Creature* CrystalChosen = m_creature->GetMap()->GetCreature(CrystalGUID);
+ if (CrystalChosen && CrystalChosen->isAlive())
+ {
+ // Make the crystal attackable
+ // We also remove NON_ATTACKABLE in case the database has it set.
+ CrystalChosen->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE);
+ CrystalChosen->CastSpell(m_creature, SPELL_MANA_RAGE, true);
+ IsDraining = true;
+ }
+ else
+ {
+ // Make an error message in case something weird happened here
+ error_log("SD2: Selin Fireheart unable to drain crystal as the crystal is either dead or despawned");
+ DrainingCrystal = false;
+ }
+ }
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (!m_pInstance)
+ {
+ error_log(ERROR_INST_DATA);
+ return;
+ }
+
+ m_pInstance->SetData(DATA_SELIN_EVENT, DONE); // Encounter complete!
+
+ if (GameObject* pEncounterDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_SELIN_ENCOUNTER_DOOR)))
+ pEncounterDoor->SetGoState(GO_STATE_ACTIVE); // Open the encounter door
+
+ if (GameObject* pContinueDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_SELIN_DOOR)))
+ pContinueDoor->SetGoState(GO_STATE_ACTIVE); // Open the door leading further in
+
+ ShatterRemainingCrystals();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!DrainingCrystal)
+ {
+ uint32 maxPowerMana = m_creature->GetMaxPower(POWER_MANA);
+ if (maxPowerMana && ((m_creature->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
+ {
+ if (DrainLifeTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_DRAIN_LIFE);
+
+ DrainLifeTimer = 10000;
+ }else DrainLifeTimer -= diff;
+
+ // Heroic only
+ if (!m_bIsRegularMode)
+ {
+ if (DrainManaTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
+ DoCastSpellIfCan(pTarget, SPELL_DRAIN_MANA);
+
+ DrainManaTimer = 10000;
+ }else DrainManaTimer -= diff;
+ }
+ }
+
+ if (FelExplosionTimer < diff)
+ {
+ if (!m_creature->IsNonMeleeSpellCasted(false))
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FEL_EXPLOSION);
+ FelExplosionTimer = 2000;
+ }
+ }else FelExplosionTimer -= diff;
+
+ // If below 10% mana, start recharging
+ maxPowerMana = m_creature->GetMaxPower(POWER_MANA);
+ if (maxPowerMana && ((m_creature->GetPower(POWER_MANA)*100 / maxPowerMana) < 10))
+ {
+ if (DrainCrystalTimer < diff)
+ {
+ SelectNearestCrystal();
+
+ if (m_bIsRegularMode)
+ DrainCrystalTimer = urand(20000, 25000);
+ else
+ DrainCrystalTimer = urand(10000, 15000);
+
+ }else DrainCrystalTimer -= diff;
+ }
+
+ }else
+ {
+ if (IsDraining)
+ {
+ if (EmpowerTimer < diff)
+ {
+ IsDraining = false;
+ DrainingCrystal = false;
+
+ DoScriptText(SAY_EMPOWERED, m_creature);
+
+ Creature* CrystalChosen = m_creature->GetMap()->GetCreature(CrystalGUID);
+ if (CrystalChosen && CrystalChosen->isAlive())
+ // Use Deal Damage to kill it, not SetDeathState.
+ CrystalChosen->DealDamage(CrystalChosen, CrystalChosen->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+
+ CrystalGUID = 0;
+
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ }else EmpowerTimer -= diff;
+ }
+ }
+
+ DoMeleeAttackIfReady(); // No need to check if we are draining crystal here, as the spell has a stun.
+ }
+};
+
+CreatureAI* GetAI_boss_selin_fireheart(Creature* pCreature)
+{
+ return new boss_selin_fireheartAI(pCreature);
+};
+
+struct MANGOS_DLL_DECL mob_fel_crystalAI : public ScriptedAI
+{
+ mob_fel_crystalAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ void Reset() {}
+ void AttackStart(Unit* who) {}
+ void MoveInLineOfSight(Unit* who) {}
+ void UpdateAI(const uint32 diff) {}
+
+ void JustDied(Unit* killer)
+ {
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)m_creature->GetInstanceData())
+ {
+ Creature* pSelin = m_creature->GetMap()->GetCreature(pInstance->GetData64(DATA_SELIN));
+
+ if (pSelin && pSelin->isAlive())
+ {
+ boss_selin_fireheartAI* pSelinAI = dynamic_cast(pSelin->AI());
+
+ if (pSelinAI && pSelinAI->CrystalGUID == m_creature->GetGUID())
+ {
+ // Set this to false if we are the creature that Selin is draining so his AI flows properly
+ pSelinAI->DrainingCrystal = false;
+ pSelinAI->IsDraining = false;
+ pSelinAI->EmpowerTimer = 10000;
+
+ if (pSelin->getVictim())
+ {
+ pSelin->AI()->AttackStart(pSelin->getVictim());
+ pSelin->GetMotionMaster()->MoveChase(pSelin->getVictim());
+ }
+ }
+ }
+ }else error_log(ERROR_INST_DATA);
+ }
+};
+
+CreatureAI* GetAI_mob_fel_crystal(Creature* pCreature)
+{
+ return new mob_fel_crystalAI(pCreature);
+};
+
+void AddSC_boss_selin_fireheart()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_selin_fireheart";
+ newscript->GetAI = &GetAI_boss_selin_fireheart;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_fel_crystal";
+ newscript->GetAI = &GetAI_mob_fel_crystal;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp b/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp
new file mode 100644
index 0000000..08a4e93
--- /dev/null
+++ b/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp
@@ -0,0 +1,228 @@
+/* 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_Vexallus
+SD%Complete: 90
+SDComment: Heroic and Normal support. Needs further testing.
+SDCategory: Magister's Terrace
+EndScriptData */
+
+#include "precompiled.h"
+#include "magisters_terrace.h"
+
+enum
+{
+ SAY_AGGRO = -1585007,
+ SAY_ENERGY = -1585008,
+ SAY_OVERLOAD = -1585009,
+ SAY_KILL = -1585010,
+ EMOTE_DISCHARGE_ENERGY = -1585011,
+
+ //is this text for real?
+ //#define SAY_DEATH "What...happen...ed."
+
+ //Pure energy spell info
+ SPELL_ENERGY_BOLT = 46156,
+ SPELL_ENERGY_FEEDBACK = 44335,
+
+ //Vexallus spell info
+ SPELL_CHAIN_LIGHTNING = 44318,
+ SPELL_H_CHAIN_LIGHTNING = 46380, //heroic spell
+ SPELL_OVERLOAD = 44353,
+ SPELL_ARCANE_SHOCK = 44319,
+ SPELL_H_ARCANE_SHOCK = 46381, //heroic spell
+
+ SPELL_SUMMON_PURE_ENERGY = 44322, //mod scale -10
+ H_SPELL_SUMMON_PURE_ENERGY1 = 46154, //mod scale -5
+ H_SPELL_SUMMON_PURE_ENERGY2 = 46159, //mod scale -5
+
+ //Creatures
+ NPC_PURE_ENERGY = 24745,
+
+ INTERVAL_MODIFIER = 15,
+ INTERVAL_SWITCH = 6
+};
+
+struct MANGOS_DLL_DECL boss_vexallusAI : public ScriptedAI
+{
+ boss_vexallusAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ bool m_bIsRegularMode;
+
+ uint32 ChainLightningTimer;
+ uint32 ArcaneShockTimer;
+ uint32 OverloadTimer;
+ uint32 IntervalHealthAmount;
+ bool Enraged;
+
+ void Reset()
+ {
+ ChainLightningTimer = 8000;
+ ArcaneShockTimer = 5000;
+ OverloadTimer = 1200;
+ IntervalHealthAmount = 1;
+ Enraged = false;
+
+ if (m_pInstance)
+ m_pInstance->SetData(DATA_VEXALLUS_EVENT, NOT_STARTED);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(SAY_KILL, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(DATA_VEXALLUS_EVENT, DONE);
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(DATA_VEXALLUS_EVENT, IN_PROGRESS);
+ }
+
+ void JustSummoned(Creature *summoned)
+ {
+ if (Unit *temp = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ summoned->GetMotionMaster()->MoveFollow(temp,0,0);
+
+ //spells are SUMMON_TYPE_GUARDIAN, so using setOwner should be ok
+ summoned->SetOwnerGUID(m_creature->GetGUID());
+ summoned->CastSpell(summoned,SPELL_ENERGY_BOLT,false,0,0,m_creature->GetGUID());
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!Enraged)
+ {
+ //used for check, when Vexallus cast adds 85%, 70%, 55%, 40%, 25%
+ if (m_creature->GetHealthPercent() <= float(100 - INTERVAL_MODIFIER*IntervalHealthAmount))
+ {
+ //increase amount, unless we're at 10%, then we switch and return
+ if (IntervalHealthAmount == INTERVAL_SWITCH)
+ {
+ Enraged = true;
+ return;
+ }
+ else
+ ++IntervalHealthAmount;
+
+ DoScriptText(SAY_ENERGY, m_creature);
+ DoScriptText(EMOTE_DISCHARGE_ENERGY, m_creature);
+
+ if (m_bIsRegularMode)
+ m_creature->CastSpell(m_creature,SPELL_SUMMON_PURE_ENERGY,false);
+ else
+ {
+ m_creature->CastSpell(m_creature,H_SPELL_SUMMON_PURE_ENERGY1,false);
+ m_creature->CastSpell(m_creature,H_SPELL_SUMMON_PURE_ENERGY2,false);
+ }
+
+ //below are workaround summons, remove when summoning spells w/implicitTarget 73 implemented in Mangos
+ m_creature->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
+
+ if (!m_bIsRegularMode)
+ m_creature->SummonCreature(NPC_PURE_ENERGY, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ }
+
+ if (ChainLightningTimer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(target, m_bIsRegularMode ? SPELL_CHAIN_LIGHTNING : SPELL_H_CHAIN_LIGHTNING);
+
+ ChainLightningTimer = 8000;
+ }else ChainLightningTimer -= diff;
+
+ if (ArcaneShockTimer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(target, m_bIsRegularMode ? SPELL_ARCANE_SHOCK : SPELL_H_ARCANE_SHOCK);
+
+ ArcaneShockTimer = 8000;
+ }else ArcaneShockTimer -= diff;
+ }
+ else
+ {
+ if (OverloadTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_OVERLOAD);
+
+ OverloadTimer = 2000;
+ }else OverloadTimer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_vexallus(Creature* pCreature)
+{
+ return new boss_vexallusAI(pCreature);
+};
+
+struct MANGOS_DLL_DECL mob_pure_energyAI : public ScriptedAI
+{
+ mob_pure_energyAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset() { }
+
+ void JustDied(Unit* slayer)
+ {
+ if (Unit *temp = m_creature->GetOwner())
+ {
+ if (temp && temp->isAlive())
+ slayer->CastSpell(slayer, SPELL_ENERGY_FEEDBACK, true, 0, 0, temp->GetGUID());
+ }
+ }
+
+ void MoveInLineOfSight(Unit *who) { }
+ void AttackStart(Unit *who) { }
+};
+
+CreatureAI* GetAI_mob_pure_energy(Creature* pCreature)
+{
+ return new mob_pure_energyAI(pCreature);
+};
+
+void AddSC_boss_vexallus()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_vexallus";
+ newscript->GetAI = &GetAI_boss_vexallus;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_pure_energy";
+ newscript->GetAI = &GetAI_mob_pure_energy;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp b/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp
new file mode 100644
index 0000000..b88484b
--- /dev/null
+++ b/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp
@@ -0,0 +1,207 @@
+/* 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_Magisters_Terrace
+SD%Complete: 60
+SDComment: Designed only for Selin Fireheart
+SDCategory: Magister's Terrace
+EndScriptData */
+
+#include "precompiled.h"
+#include "magisters_terrace.h"
+
+#define MAX_ENCOUNTER 4
+
+/*
+0 - Selin Fireheart
+1 - Vexallus
+2 - Priestess Delrissa
+3 - Kael'thas Sunstrider
+*/
+
+struct MANGOS_DLL_DECL instance_magisters_terrace : public ScriptedInstance
+{
+ instance_magisters_terrace(Map* pMap) : ScriptedInstance(pMap) {Initialize();}
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ uint32 m_uiDelrissaDeathCount;
+
+ std::list FelCrystals;
+ std::list::iterator CrystalItr;
+
+ uint64 m_uiSelinGUID;
+ uint64 m_uiDelrissaGUID;
+ uint64 m_uiVexallusDoorGUID;
+ uint64 m_uiSelinDoorGUID;
+ uint64 m_uiSelinEncounterDoorGUID;
+ uint64 m_uiDelrissaDoorGUID;
+ uint64 m_uiKaelDoorGUID;
+ uint64 m_auiKaelStatue[2];
+
+ bool m_bInitializedItr;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+ memset(&m_auiKaelStatue, 0, sizeof(m_auiKaelStatue));
+
+ FelCrystals.clear();
+
+ m_uiDelrissaDeathCount = 0;
+
+ m_uiSelinGUID = 0;
+ m_uiDelrissaGUID = 0;
+ m_uiVexallusDoorGUID = 0;
+ m_uiSelinDoorGUID = 0;
+ m_uiSelinEncounterDoorGUID = 0;
+ m_uiDelrissaDoorGUID = 0;
+ m_uiKaelDoorGUID = 0;
+
+ m_bInitializedItr = false;
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ return true;
+ return false;
+ }
+
+ uint32 GetData(uint32 identifier)
+ {
+ switch(identifier)
+ {
+ case DATA_SELIN_EVENT: return m_auiEncounter[0];
+ case DATA_VEXALLUS_EVENT: return m_auiEncounter[1];
+ case DATA_DELRISSA_EVENT: return m_auiEncounter[2];
+ case DATA_KAELTHAS_EVENT: return m_auiEncounter[3];
+ case DATA_DELRISSA_DEATH_COUNT: return m_uiDelrissaDeathCount;
+ case DATA_FEL_CRYSTAL_SIZE: return FelCrystals.size();
+ }
+ return 0;
+ }
+
+ void SetData(uint32 identifier, uint32 data)
+ {
+ switch(identifier)
+ {
+ case DATA_SELIN_EVENT:
+ m_auiEncounter[0] = data;
+ break;
+ case DATA_VEXALLUS_EVENT:
+ if (data == DONE)
+ DoUseDoorOrButton(m_uiVexallusDoorGUID);
+ m_auiEncounter[1] = data;
+ break;
+ case DATA_DELRISSA_EVENT:
+ if (data == DONE)
+ DoUseDoorOrButton(m_uiDelrissaDoorGUID);
+ if (data == IN_PROGRESS)
+ m_uiDelrissaDeathCount = 0;
+ m_auiEncounter[2] = data;
+ break;
+ case DATA_KAELTHAS_EVENT:
+ m_auiEncounter[3] = data;
+ break;
+ case DATA_DELRISSA_DEATH_COUNT:
+ if (data == SPECIAL)
+ ++m_uiDelrissaDeathCount;
+ else
+ m_uiDelrissaDeathCount = 0;
+ break;
+ }
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case 24723: m_uiSelinGUID = pCreature->GetGUID(); break;
+ case 24560: m_uiDelrissaGUID = pCreature->GetGUID(); break;
+ case 24722: FelCrystals.push_back(pCreature->GetGUID()); break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* go)
+ {
+ switch(go->GetEntry())
+ {
+ case 187896: m_uiVexallusDoorGUID = go->GetGUID(); break;
+ //SunwellRaid Gate 02
+ case 187979: m_uiSelinDoorGUID = go->GetGUID(); break;
+ //Assembly Chamber Door
+ case 188065: m_uiSelinEncounterDoorGUID = go->GetGUID(); break;
+ case 187770: m_uiDelrissaDoorGUID = go->GetGUID(); break;
+ case 188064: m_uiKaelDoorGUID = go->GetGUID(); break;
+ case 188165: m_auiKaelStatue[0] = go->GetGUID(); break;
+ case 188166: m_auiKaelStatue[1] = go->GetGUID(); break;
+ }
+ }
+
+ uint64 GetData64(uint32 identifier)
+ {
+ switch(identifier)
+ {
+ case DATA_SELIN: return m_uiSelinGUID;
+ case DATA_DELRISSA: return m_uiDelrissaGUID;
+ case DATA_VEXALLUS_DOOR: return m_uiVexallusDoorGUID;
+ case DATA_SELIN_DOOR: return m_uiSelinDoorGUID;
+ case DATA_SELIN_ENCOUNTER_DOOR: return m_uiSelinEncounterDoorGUID;
+ case DATA_DELRISSA_DOOR: return m_uiDelrissaDoorGUID;
+ case DATA_KAEL_DOOR: return m_uiKaelDoorGUID;
+ case DATA_KAEL_STATUE_LEFT: return m_auiKaelStatue[0];
+ case DATA_KAEL_STATUE_RIGHT: return m_auiKaelStatue[1];
+
+ case DATA_FEL_CRYSTAL:
+ {
+ if (FelCrystals.empty())
+ {
+ error_log("SD2: Magisters Terrace: No Fel Crystals loaded in Inst Data");
+ return 0;
+ }
+
+ if (!m_bInitializedItr)
+ {
+ CrystalItr = FelCrystals.begin();
+ m_bInitializedItr = true;
+ }
+
+ uint64 guid = *CrystalItr;
+ ++CrystalItr;
+ return guid;
+ }
+ }
+ return 0;
+ }
+};
+
+InstanceData* GetInstanceData_instance_magisters_terrace(Map* pMap)
+{
+ return new instance_magisters_terrace(pMap);
+}
+
+void AddSC_instance_magisters_terrace()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "instance_magisters_terrace";
+ newscript->GetInstanceData = &GetInstanceData_instance_magisters_terrace;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp b/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp
new file mode 100644
index 0000000..20a81a6
--- /dev/null
+++ b/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.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: Magisters_Terrace
+SD%Complete: 100
+SDComment: Quest support: 11490(post-event)
+SDCategory: Magisters Terrace
+EndScriptData */
+
+/* ContentData
+npc_kalecgos
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_kalecgos
+######*/
+
+enum
+{
+ SPELL_TRANSFORM_TO_KAEL = 44670,
+ SPELL_ORB_KILL_CREDIT = 46307,
+ NPC_KAEL = 24848, //human form entry
+ POINT_ID_LAND = 1
+};
+
+const float afKaelLandPoint[] = {225.045f, -276.236f, -5.434f};
+
+#define GOSSIP_ITEM_KAEL_1 "Who are you?"
+#define GOSSIP_ITEM_KAEL_2 "What can we do to assist you?"
+#define GOSSIP_ITEM_KAEL_3 "What brings you to the Sunwell?"
+#define GOSSIP_ITEM_KAEL_4 "You're not alone here?"
+#define GOSSIP_ITEM_KAEL_5 "What would Kil'jaeden want with a mortal woman?"
+
+// This is friendly keal that appear after used Orb.
+// If we assume DB handle summon, summon appear somewhere outside the platform where Orb is
+struct MANGOS_DLL_DECL npc_kalecgosAI : public ScriptedAI
+{
+ npc_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ uint32 m_uiTransformTimer;
+
+ void Reset()
+ {
+ m_uiTransformTimer = 0;
+
+ // we must assume he appear as dragon somewhere outside the platform of orb, and then move directly to here
+ if (m_creature->GetEntry() != NPC_KAEL)
+ m_creature->GetMotionMaster()->MovePoint(POINT_ID_LAND, afKaelLandPoint[0], afKaelLandPoint[1], afKaelLandPoint[2]);
+ }
+
+ void MovementInform(uint32 uiType, uint32 uiPointId)
+ {
+ if (uiType != POINT_MOTION_TYPE)
+ return;
+
+ if (uiPointId == POINT_ID_LAND)
+ m_uiTransformTimer = MINUTE*IN_MILLISECONDS;
+ }
+
+ // some targeting issues with the spell, so use this workaround as temporary solution
+ void DoWorkaroundForQuestCredit()
+ {
+ Map* pMap = m_creature->GetMap();
+
+ if (!pMap || !pMap->IsRegularDifficulty())
+ return;
+
+ Map::PlayerList const &lList = pMap->GetPlayers();
+
+ if (lList.isEmpty())
+ return;
+
+ SpellEntry const* pSpell = GetSpellStore()->LookupEntry(SPELL_ORB_KILL_CREDIT);
+
+ for(Map::PlayerList::const_iterator i = lList.begin(); i != lList.end(); ++i)
+ {
+ if (Player* pPlayer = i->getSource())
+ {
+ if (pSpell && pSpell->EffectMiscValue[0])
+ pPlayer->KilledMonsterCredit(pSpell->EffectMiscValue[0]);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_uiTransformTimer)
+ {
+ if (m_uiTransformTimer < uiDiff)
+ {
+ m_creature->CastSpell(m_creature,SPELL_ORB_KILL_CREDIT,false);
+ DoWorkaroundForQuestCredit();
+
+ // Transform and update entry, now ready for quest/read gossip
+ m_creature->CastSpell(m_creature,SPELL_TRANSFORM_TO_KAEL,false);
+ m_creature->UpdateEntry(NPC_KAEL);
+
+ m_uiTransformTimer = 0;
+ }else m_uiTransformTimer -= uiDiff;
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_kalecgos(Creature* pCreature)
+{
+ return new npc_kalecgosAI(pCreature);
+}
+
+bool GossipHello_npc_kalecgos(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ pPlayer->SEND_GOSSIP_MENU(12498, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_kalecgos(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(12500, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(12502, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->SEND_GOSSIP_MENU(12606, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAEL_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
+ pPlayer->SEND_GOSSIP_MENU(12607, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->SEND_GOSSIP_MENU(12608, pCreature->GetGUID());
+ break;
+ }
+
+ return true;
+}
+
+void AddSC_magisters_terrace()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_kalecgos";
+ newscript->GetAI = &GetAI_npc_kalecgos;
+ newscript->pGossipHello = &GossipHello_npc_kalecgos;
+ newscript->pGossipSelect = &GossipSelect_npc_kalecgos;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h b/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h
new file mode 100644
index 0000000..e6ac2d6
--- /dev/null
+++ b/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h
@@ -0,0 +1,30 @@
+/* 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 */
+
+#ifndef DEF_MAGISTERS_TERRACE_H
+#define DEF_MAGISTERS_TERRACE_H
+
+#define DATA_SELIN_EVENT 1
+#define DATA_VEXALLUS_EVENT 2
+#define DATA_DELRISSA_EVENT 3
+#define DATA_KAELTHAS_EVENT 4
+
+#define DATA_SELIN 5
+#define DATA_FEL_CRYSTAL 6
+#define DATA_FEL_CRYSTAL_SIZE 7
+
+#define DATA_VEXALLUS_DOOR 8
+#define DATA_SELIN_DOOR 9
+#define DATA_DELRISSA 10
+#define DATA_DELRISSA_DOOR 11
+#define DATA_SELIN_ENCOUNTER_DOOR 12
+
+#define DATA_KAEL_DOOR 13
+#define DATA_KAEL_STATUE_LEFT 14
+#define DATA_KAEL_STATUE_RIGHT 15
+
+#define DATA_DELRISSA_DEATH_COUNT 16
+
+#define ERROR_INST_DATA "SD2 Error: Instance Data not set properly for Magister's Terrace instance (map 585). Encounters will be buggy."
+#endif
diff --git a/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp b/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp
new file mode 100644
index 0000000..6b0c87d
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp
@@ -0,0 +1,104 @@
+/* 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_Baron_Geddon
+SD%Complete: 100
+SDComment:
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+
+#define EMOTE_SERVICE -1409000
+
+#define SPELL_INFERNO 19695
+#define SPELL_IGNITEMANA 19659
+#define SPELL_LIVINGBOMB 20475
+#define SPELL_ARMAGEDDOM 20479
+
+struct MANGOS_DLL_DECL boss_baron_geddonAI : public ScriptedAI
+{
+ boss_baron_geddonAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Inferno_Timer;
+ uint32 IgniteMana_Timer;
+ uint32 LivingBomb_Timer;
+
+ void Reset()
+ {
+ Inferno_Timer = 45000; //These times are probably wrong
+ IgniteMana_Timer = 30000;
+ LivingBomb_Timer = 35000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //If we are <2% hp cast Armageddom
+ if (m_creature->GetHealthPercent() <= 2.0f)
+ {
+ m_creature->InterruptNonMeleeSpells(true);
+
+ DoCastSpellIfCan(m_creature,SPELL_ARMAGEDDOM);
+ DoScriptText(EMOTE_SERVICE, m_creature);
+ return;
+ }
+
+ //Inferno_Timer
+ if (Inferno_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_INFERNO);
+ Inferno_Timer = 45000;
+ }else Inferno_Timer -= diff;
+
+ //IgniteMana_Timer
+ if (IgniteMana_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_IGNITEMANA);
+
+ IgniteMana_Timer = 30000;
+ }else IgniteMana_Timer -= diff;
+
+ //LivingBomb_Timer
+ if (LivingBomb_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_LIVINGBOMB);
+
+ LivingBomb_Timer = 35000;
+ }else LivingBomb_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_baron_geddon(Creature* pCreature)
+{
+ return new boss_baron_geddonAI(pCreature);
+}
+
+void AddSC_boss_baron_geddon()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_baron_geddon";
+ newscript->GetAI = &GetAI_boss_baron_geddon;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_garr.cpp b/scripts/eastern_kingdoms/molten_core/boss_garr.cpp
new file mode 100644
index 0000000..fd371d2
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_garr.cpp
@@ -0,0 +1,134 @@
+/* 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_Garr
+SD%Complete: 50
+SDComment: Adds NYI
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+
+// Garr spells
+#define SPELL_ANTIMAGICPULSE 19492
+#define SPELL_MAGMASHACKLES 19496
+#define SPELL_ENRAGE 19516 //Stacking enrage (stacks to 10 times)
+
+//Add spells
+#define SPELL_ERUPTION 19497
+#define SPELL_IMMOLATE 20294
+
+struct MANGOS_DLL_DECL boss_garrAI : public ScriptedAI
+{
+ boss_garrAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 AntiMagicPulse_Timer;
+ uint32 MagmaShackles_Timer;
+ uint32 CheckAdds_Timer;
+ uint64 Add[8];
+ bool Enraged[8];
+
+ void Reset()
+ {
+ AntiMagicPulse_Timer = 25000; //These times are probably wrong
+ MagmaShackles_Timer = 15000;
+ CheckAdds_Timer = 2000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //AntiMagicPulse_Timer
+ if (AntiMagicPulse_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_ANTIMAGICPULSE);
+ AntiMagicPulse_Timer = urand(10000, 15000);
+ }else AntiMagicPulse_Timer -= diff;
+
+ //MagmaShackles_Timer
+ if (MagmaShackles_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_MAGMASHACKLES);
+ MagmaShackles_Timer = urand(8000, 12000);
+ }else MagmaShackles_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL mob_fireswornAI : public ScriptedAI
+{
+ mob_fireswornAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Immolate_Timer;
+
+ void Reset()
+ {
+ Immolate_Timer = 4000; //These times are probably wrong
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Immolate_Timer
+ if (Immolate_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_IMMOLATE);
+
+ Immolate_Timer = urand(5000, 10000);
+ }else Immolate_Timer -= diff;
+
+ //Cast Erruption and let them die
+ if (m_creature->GetHealthPercent() <= 10.0f)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ERUPTION);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->RemoveCorpse();
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_garr(Creature* pCreature)
+{
+ return new boss_garrAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_firesworn(Creature* pCreature)
+{
+ return new mob_fireswornAI(pCreature);
+}
+
+void AddSC_boss_garr()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_garr";
+ newscript->GetAI = &GetAI_boss_garr;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_firesworn";
+ newscript->GetAI = &GetAI_mob_firesworn;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp b/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp
new file mode 100644
index 0000000..9387ff9
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp
@@ -0,0 +1,89 @@
+/* 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_Gehennas
+SD%Complete: 90
+SDComment: Adds MC NYI
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_SHADOWBOLT 19728
+#define SPELL_RAINOFFIRE 19717
+#define SPELL_GEHENNASCURSE 19716
+
+struct MANGOS_DLL_DECL boss_gehennasAI : public ScriptedAI
+{
+ boss_gehennasAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ShadowBolt_Timer;
+ uint32 RainOfFire_Timer;
+ uint32 GehennasCurse_Timer;
+
+ void Reset()
+ {
+ ShadowBolt_Timer = 6000;
+ RainOfFire_Timer = 10000;
+ GehennasCurse_Timer = 12000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowBolt_Timer
+ if (ShadowBolt_Timer < diff)
+ {
+ if (Unit* bTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1))
+ DoCastSpellIfCan(bTarget,SPELL_SHADOWBOLT);
+ ShadowBolt_Timer = 7000;
+ }else ShadowBolt_Timer -= diff;
+
+ //RainOfFire_Timer
+ if (RainOfFire_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_RAINOFFIRE);
+
+ RainOfFire_Timer = urand(4000, 12000);
+ }else RainOfFire_Timer -= diff;
+
+ //GehennasCurse_Timer
+ if (GehennasCurse_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_GEHENNASCURSE);
+ GehennasCurse_Timer = urand(22000, 30000);
+ }else GehennasCurse_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_gehennas(Creature* pCreature)
+{
+ return new boss_gehennasAI(pCreature);
+}
+
+void AddSC_boss_gehennas()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_gehennas";
+ newscript->GetAI = &GetAI_boss_gehennas;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp b/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp
new file mode 100644
index 0000000..120efdf
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp
@@ -0,0 +1,198 @@
+/* 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_Golemagg
+SD%Complete: 75
+SDComment: Timers need to be confirmed, Golemagg's Trust need to be checked
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+#include "molten_core.h"
+
+enum
+{
+ SPELL_MAGMASPLASH = 13879,
+ SPELL_PYROBLAST = 20228,
+ SPELL_EARTHQUAKE = 19798,
+ SPELL_ENRAGE = 19953,
+ SPELL_GOLEMAGG_TRUST = 20553,
+
+ // Core Rager
+ EMOTE_LOWHP = -1409002,
+ SPELL_MANGLE = 19820
+};
+
+struct MANGOS_DLL_DECL boss_golemaggAI : public ScriptedAI
+{
+ boss_golemaggAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiPyroblastTimer;
+ uint32 m_uiEarthquakeTimer;
+ uint32 m_uiBuffTimer;
+ bool m_bEnraged;
+
+ void Reset()
+ {
+ m_uiPyroblastTimer = 7*IN_MILLISECONDS; // These timers are probably wrong
+ m_uiEarthquakeTimer = 3*IN_MILLISECONDS;
+ m_uiBuffTimer = 2.5*IN_MILLISECONDS;
+ m_bEnraged = false;
+
+ m_creature->CastSpell(m_creature, SPELL_MAGMASPLASH, true);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_GOLEMAGG, DONE);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Pyroblast
+ if (m_uiPyroblastTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_PYROBLAST);
+
+ m_uiPyroblastTimer = 7*IN_MILLISECONDS;
+ }
+ else
+ m_uiPyroblastTimer -= uiDiff;
+
+ // Enrage
+ if (!m_bEnraged && m_creature->GetHealthPercent() < 10.0f)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ m_bEnraged = true;
+ }
+
+ // Earthquake
+ if (m_bEnraged)
+ {
+ if (m_uiEarthquakeTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_EARTHQUAKE);
+ m_uiEarthquakeTimer = 3*IN_MILLISECONDS;
+ }
+ else
+ m_uiEarthquakeTimer -= uiDiff;
+ }
+
+ /*
+ // Golemagg's Trust
+ if (m_uiBuffTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_GOLEMAGG_TRUST);
+ m_uiBuffTimer = 2.5*IN_MILLISECONDS;
+ }
+ else
+ m_uiBuffTimer -= uiDiff;
+ */
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL mob_core_ragerAI : public ScriptedAI
+{
+ mob_core_ragerAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ uint32 m_uiMangleTimer;
+
+ void Reset()
+ {
+ m_uiMangleTimer = 7*IN_MILLISECONDS; // These times are probably wrong
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32& uiDamage)
+ {
+ if (m_creature->GetHealthPercent() < 50.0f)
+ {
+ if (m_pInstance)
+ {
+ if (Creature* pGolemagg = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_GOLEMAGG)))
+ {
+ if (pGolemagg->isAlive())
+ {
+ DoScriptText(EMOTE_LOWHP, m_creature);
+ m_creature->SetHealth(m_creature->GetMaxHealth());
+ }
+ else
+ uiDamage = m_creature->GetHealth();
+ }
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Mangle
+ if (m_uiMangleTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MANGLE);
+ m_uiMangleTimer = 10*IN_MILLISECONDS;
+ }
+ else
+ m_uiMangleTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_golemagg(Creature* pCreature)
+{
+ return new boss_golemaggAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_core_rager(Creature* pCreature)
+{
+ return new mob_core_ragerAI(pCreature);
+}
+
+void AddSC_boss_golemagg()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_golemagg";
+ newscript->GetAI = &GetAI_boss_golemagg;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_core_rager";
+ newscript->GetAI = &GetAI_mob_core_rager;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp b/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp
new file mode 100644
index 0000000..1d8cd72
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp
@@ -0,0 +1,86 @@
+/* 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_Lucifron
+SD%Complete: 100
+SDComment:
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_IMPENDINGDOOM 19702
+#define SPELL_LUCIFRONCURSE 19703
+#define SPELL_SHADOWSHOCK 20603
+
+struct MANGOS_DLL_DECL boss_lucifronAI : public ScriptedAI
+{
+ boss_lucifronAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ImpendingDoom_Timer;
+ uint32 LucifronCurse_Timer;
+ uint32 ShadowShock_Timer;
+
+ void Reset()
+ {
+ ImpendingDoom_Timer = 10000; //Initial cast after 10 seconds so the debuffs alternate
+ LucifronCurse_Timer = 20000; //Initial cast after 20 seconds
+ ShadowShock_Timer = 6000; //6 seconds
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Impending doom timer
+ if (ImpendingDoom_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_IMPENDINGDOOM);
+ ImpendingDoom_Timer = 20000;
+ }else ImpendingDoom_Timer -= diff;
+
+ //Lucifron's curse timer
+ if (LucifronCurse_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_LUCIFRONCURSE);
+ LucifronCurse_Timer = 15000;
+ }else LucifronCurse_Timer -= diff;
+
+ //Shadowshock
+ if (ShadowShock_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWSHOCK);
+ ShadowShock_Timer = 6000;
+ }else ShadowShock_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_lucifron(Creature* pCreature)
+{
+ return new boss_lucifronAI(pCreature);
+}
+
+void AddSC_boss_lucifron()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_lucifron";
+ newscript->GetAI = &GetAI_boss_lucifron;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp b/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp
new file mode 100644
index 0000000..9be5fc7
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp
@@ -0,0 +1,99 @@
+/* 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_Magmadar
+SD%Complete: 75
+SDComment: Conflag on ground nyi, fear causes issues without VMAPs
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ EMOTE_GENERIC_FRENZY_KILL = -1000001,
+
+ SPELL_FRENZY = 19451,
+ SPELL_MAGMASPIT = 19449, //This is actually a buff he gives himself
+ SPELL_PANIC = 19408,
+ SPELL_LAVABOMB = 19411, //This calls a dummy server side effect that isn't implemented yet
+ SPELL_LAVABOMB_ALT = 19428 //This is the spell that the lava bomb casts
+};
+
+struct MANGOS_DLL_DECL boss_magmadarAI : public ScriptedAI
+{
+ boss_magmadarAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Frenzy_Timer;
+ uint32 Panic_Timer;
+ uint32 Lavabomb_Timer;
+
+ void Reset()
+ {
+ Frenzy_Timer = 30000;
+ Panic_Timer = 20000;
+ Lavabomb_Timer = 12000;
+
+ m_creature->CastSpell(m_creature,SPELL_MAGMASPIT,true);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Frenzy_Timer
+ if (Frenzy_Timer < diff)
+ {
+ DoScriptText(EMOTE_GENERIC_FRENZY_KILL, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_FRENZY);
+ Frenzy_Timer = 15000;
+ }else Frenzy_Timer -= diff;
+
+ //Panic_Timer
+ if (Panic_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_PANIC);
+ Panic_Timer = 35000;
+ }else Panic_Timer -= diff;
+
+ //Lavabomb_Timer
+ if (Lavabomb_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_LAVABOMB_ALT);
+
+ Lavabomb_Timer = 12000;
+ }else Lavabomb_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_magmadar(Creature* pCreature)
+{
+ return new boss_magmadarAI(pCreature);
+}
+
+void AddSC_boss_magmadar()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_magmadar";
+ newscript->GetAI = &GetAI_boss_magmadar;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp b/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp
new file mode 100644
index 0000000..b6c8ae6
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp
@@ -0,0 +1,138 @@
+/* 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_Majordomo_Executus
+SD%Complete: 30
+SDComment: Correct spawning and Event NYI
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_AGGRO -1409003
+#define SAY_SPAWN -1409004
+#define SAY_SLAY -1409005
+#define SAY_SPECIAL -1409006
+#define SAY_DEFEAT -1409007
+
+#define SAY_SUMMON_MAJ -1409008
+#define SAY_ARRIVAL1_RAG -1409009
+#define SAY_ARRIVAL2_MAJ -1409010
+#define SAY_ARRIVAL3_RAG -1409011
+#define SAY_ARRIVAL5_RAG -1409012
+
+#define SPAWN_RAG_X 838.51
+#define SPAWN_RAG_Y -829.84
+#define SPAWN_RAG_Z -232.00
+#define SPAWN_RAG_O 1.70
+
+#define SPELL_MAGIC_REFLECTION 20619
+#define SPELL_DAMAGE_REFLECTION 21075
+#define SPELL_BLASTWAVE 20229
+#define SPELL_AEGIS 20620 //This is self casted whenever we are below 50%
+#define SPELL_TELEPORT 20618
+#define SPELL_SUMMON_RAGNAROS 19774
+
+#define ENTRY_FLAMEWALKER_HEALER 11663
+#define ENTRY_FLAMEWALKER_ELITE 11664
+
+struct MANGOS_DLL_DECL boss_majordomoAI : public ScriptedAI
+{
+ boss_majordomoAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 MagicReflection_Timer;
+ uint32 DamageReflection_Timer;
+ uint32 Blastwave_Timer;
+
+ void Reset()
+ {
+ MagicReflection_Timer = 30000; //Damage reflection first so we alternate
+ DamageReflection_Timer = 15000;
+ Blastwave_Timer = 10000;
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (urand(0, 4))
+ return;
+
+ DoScriptText(SAY_SLAY, m_creature);
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Cast Ageis if less than 50% hp
+ if (m_creature->GetHealthPercent() < 50.0f)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_AEGIS);
+ }
+
+ //MagicReflection_Timer
+ // if (MagicReflection_Timer < diff)
+ // {
+ // DoCastSpellIfCan(m_creature, SPELL_MAGICREFLECTION);
+
+ //60 seconds until we should cast this agian
+ // MagicReflection_Timer = 30000;
+ // }else MagicReflection_Timer -= diff;
+
+ //DamageReflection_Timer
+ // if (DamageReflection_Timer < diff)
+ // {
+ // DoCastSpellIfCan(m_creature, SPELL_DAMAGEREFLECTION);
+
+ //60 seconds until we should cast this agian
+ // DamageReflection_Timer = 30000;
+ // }else DamageReflection_Timer -= diff;
+
+ //Blastwave_Timer
+ if (Blastwave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BLASTWAVE);
+ Blastwave_Timer = 10000;
+ }else Blastwave_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_majordomo(Creature* pCreature)
+{
+ return new boss_majordomoAI(pCreature);
+}
+
+void AddSC_boss_majordomo()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_majordomo";
+ newscript->GetAI = &GetAI_boss_majordomo;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp b/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp
new file mode 100644
index 0000000..17ed94a
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp
@@ -0,0 +1,291 @@
+/* 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_Ragnaros
+SD%Complete: 75
+SDComment: Intro Dialog and event NYI
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_REINFORCEMENTS1 -1409013
+#define SAY_REINFORCEMENTS2 -1409014
+#define SAY_HAND -1409015
+#define SAY_WRATH -1409016
+#define SAY_KILL -1409017
+#define SAY_MAGMABURST -1409018
+
+#define SPELL_HANDOFRAGNAROS 19780
+#define SPELL_WRATHOFRAGNAROS 20566
+#define SPELL_LAVABURST 21158
+
+#define SPELL_MAGMABURST 20565 //Ranged attack
+
+#define SPELL_SONSOFFLAME_DUMMY 21108 //Server side effect
+#define SPELL_RAGSUBMERGE 21107 //Stealth aura
+#define SPELL_RAGEMERGE 20568
+#define SPELL_MELTWEAPON 21388
+#define SPELL_ELEMENTALFIRE 20564
+#define SPELL_ERRUPTION 17731
+
+#define ADD_1X 848.740356
+#define ADD_1Y -816.103455
+#define ADD_1Z -229.74327
+#define ADD_1O 2.615287
+
+#define ADD_2X 852.560791
+#define ADD_2Y -849.861511
+#define ADD_2Z -228.560974
+#define ADD_2O 2.836073
+
+#define ADD_3X 808.710632
+#define ADD_3Y -852.845764
+#define ADD_3Z -227.914963
+#define ADD_3O 0.964207
+
+#define ADD_4X 786.597107
+#define ADD_4Y -821.132874
+#define ADD_4Z -226.350128
+#define ADD_4O 0.949377
+
+#define ADD_5X 796.219116
+#define ADD_5Y -800.948059
+#define ADD_5Z -226.010361
+#define ADD_5O 0.560603
+
+#define ADD_6X 821.602539
+#define ADD_6Y -782.744109
+#define ADD_6Z -226.023575
+#define ADD_6O 6.157440
+
+#define ADD_7X 844.924744
+#define ADD_7Y -769.453735
+#define ADD_7Z -225.521698
+#define ADD_7O 4.4539958
+
+#define ADD_8X 839.823364
+#define ADD_8Y -810.869385
+#define ADD_8Z -229.683182
+#define ADD_8O 4.693108
+
+struct MANGOS_DLL_DECL boss_ragnarosAI : public ScriptedAI
+{
+ boss_ragnarosAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ SetCombatMovement(false);
+ Reset();
+ }
+
+ uint32 WrathOfRagnaros_Timer;
+ uint32 HandOfRagnaros_Timer;
+ uint32 LavaBurst_Timer;
+ uint32 MagmaBurst_Timer;
+ uint32 ElementalFire_Timer;
+ uint32 Erruption_Timer;
+ uint32 Submerge_Timer;
+ uint32 Attack_Timer;
+ Creature *Summoned;
+ bool HasYelledMagmaBurst;
+ bool HasSubmergedOnce;
+ bool WasBanished;
+ bool HasAura;
+
+ void Reset()
+ {
+ WrathOfRagnaros_Timer = 30000;
+ HandOfRagnaros_Timer = 25000;
+ LavaBurst_Timer = 10000;
+ MagmaBurst_Timer = 2000;
+ Erruption_Timer = 15000;
+ ElementalFire_Timer = 3000;
+ Submerge_Timer = 180000;
+ Attack_Timer = 90000;
+ HasYelledMagmaBurst = false;
+ HasSubmergedOnce = false;
+ WasBanished = false;
+
+ m_creature->CastSpell(m_creature,SPELL_MELTWEAPON,true);
+ HasAura = true;
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ if (urand(0, 4))
+ return;
+
+ DoScriptText(SAY_KILL, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (WasBanished && Attack_Timer < diff)
+ {
+ //Become unbanished again
+ m_creature->setFaction(14);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ DoCastSpellIfCan(m_creature,SPELL_RAGEMERGE);
+ WasBanished = false;
+ } else if (WasBanished)
+ {
+ Attack_Timer -= diff;
+ //Do nothing while banished
+ return;
+ }
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //WrathOfRagnaros_Timer
+ if (WrathOfRagnaros_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_WRATHOFRAGNAROS);
+
+ if (urand(0, 1))
+ DoScriptText(SAY_WRATH, m_creature);
+
+ WrathOfRagnaros_Timer = 30000;
+ }else WrathOfRagnaros_Timer -= diff;
+
+ //HandOfRagnaros_Timer
+ if (HandOfRagnaros_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_HANDOFRAGNAROS);
+
+ if (urand(0, 1))
+ DoScriptText(SAY_HAND, m_creature);
+
+ HandOfRagnaros_Timer = 25000;
+ }else HandOfRagnaros_Timer -= diff;
+
+ //LavaBurst_Timer
+ if (LavaBurst_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_LAVABURST);
+ LavaBurst_Timer = 10000;
+ }else LavaBurst_Timer -= diff;
+
+ //Erruption_Timer
+ if (LavaBurst_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ERRUPTION);
+ Erruption_Timer = urand(20000, 45000);
+ }else Erruption_Timer -= diff;
+
+ //ElementalFire_Timer
+ if (ElementalFire_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ELEMENTALFIRE);
+ ElementalFire_Timer = urand(10000, 14000);
+ }else ElementalFire_Timer -= diff;
+
+ //Submerge_Timer
+ if (!WasBanished && Submerge_Timer < diff)
+ {
+ //Creature spawning and ragnaros becomming unattackable
+ //is not very well supported in the core
+ //so added normaly spawning and banish workaround and attack again after 90 secs.
+
+ m_creature->InterruptNonMeleeSpells(false);
+ //Root self
+ DoCastSpellIfCan(m_creature,23973);
+ m_creature->setFaction(35);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->HandleEmote(EMOTE_ONESHOT_SUBMERGE);
+
+ if (!HasSubmergedOnce)
+ {
+ DoScriptText(SAY_REINFORCEMENTS1, m_creature);
+
+ // summon 10 elementals
+ for(int i = 0; i < 9; ++i)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ if (Creature* pSummoned = m_creature->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000))
+ pSummoned->AI()->AttackStart(pTarget);
+ }
+ }
+
+ HasSubmergedOnce = true;
+ WasBanished = true;
+ DoCastSpellIfCan(m_creature,SPELL_RAGSUBMERGE);
+ Attack_Timer = 90000;
+ }
+ else
+ {
+ DoScriptText(SAY_REINFORCEMENTS2, m_creature);
+
+ for(int i = 0; i < 9; ++i)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ if (Creature* pSummoned = m_creature->SummonCreature(12143,pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(),0.0f,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,900000))
+ pSummoned->AI()->AttackStart(pTarget);
+ }
+ }
+
+ WasBanished = true;
+ DoCastSpellIfCan(m_creature,SPELL_RAGSUBMERGE);
+ Attack_Timer = 90000;
+ }
+
+ Submerge_Timer = 180000;
+ }else Submerge_Timer -= diff;
+
+ //If we are within range melee the target
+ if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
+ {
+ //Make sure our attack is ready and we arn't currently casting
+ if (m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false))
+ {
+ m_creature->AttackerStateUpdate(m_creature->getVictim());
+ m_creature->resetAttackTimer();
+ }
+ }
+ else
+ {
+ //MagmaBurst_Timer
+ if (MagmaBurst_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MAGMABURST);
+
+ if (!HasYelledMagmaBurst)
+ {
+ DoScriptText(SAY_MAGMABURST, m_creature);
+ HasYelledMagmaBurst = true;
+ }
+
+ MagmaBurst_Timer = 2500;
+ }else MagmaBurst_Timer -= diff;
+ }
+ }
+};
+CreatureAI* GetAI_boss_ragnaros(Creature* pCreature)
+{
+ return new boss_ragnarosAI(pCreature);
+}
+
+void AddSC_boss_ragnaros()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_ragnaros";
+ newscript->GetAI = &GetAI_boss_ragnaros;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp b/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp
new file mode 100644
index 0000000..a13a463
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp
@@ -0,0 +1,122 @@
+/* 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_Shazzrah
+SD%Complete: 75
+SDComment: Teleport NYI
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_ARCANEEXPLOSION = 19712,
+ SPELL_SHAZZRAHCURSE = 19713,
+ SPELL_DEADENMAGIC = 19714,
+ SPELL_COUNTERSPELL = 19715,
+ SPELL_GATE_DUMMY = 23138 // effect spell: 23139
+};
+
+struct MANGOS_DLL_DECL boss_shazzrahAI : public ScriptedAI
+{
+ boss_shazzrahAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ArcaneExplosion_Timer;
+ uint32 ShazzrahCurse_Timer;
+ uint32 DeadenMagic_Timer;
+ uint32 Countspell_Timer;
+ uint32 Blink_Timer;
+
+ void Reset()
+ {
+ ArcaneExplosion_Timer = 6000; //These times are probably wrong
+ ShazzrahCurse_Timer = 10000;
+ DeadenMagic_Timer = 24000;
+ Countspell_Timer = 15000;
+ Blink_Timer = 30000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ArcaneExplosion_Timer
+ if (ArcaneExplosion_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ARCANEEXPLOSION);
+ ArcaneExplosion_Timer = urand(5000, 9000);
+ }else ArcaneExplosion_Timer -= diff;
+
+ //ShazzrahCurse_Timer
+ if (ShazzrahCurse_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_SHAZZRAHCURSE);
+
+ ShazzrahCurse_Timer = urand(25000, 30000);
+ }else ShazzrahCurse_Timer -= diff;
+
+ //DeadenMagic_Timer
+ if (DeadenMagic_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_DEADENMAGIC);
+ DeadenMagic_Timer = 35000;
+ }else DeadenMagic_Timer -= diff;
+
+ //Countspell_Timer
+ if (Countspell_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_COUNTERSPELL);
+ Countspell_Timer = urand(16000, 20000);
+ }else Countspell_Timer -= diff;
+
+ //Blink_Timer
+ if (Blink_Timer < diff)
+ {
+ // Teleporting him to a random gamer and casting Arcane Explosion after that.
+ DoCastSpellIfCan(m_creature, SPELL_GATE_DUMMY, CAST_TRIGGERED);
+
+ // manual, until added effect of dummy properly
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1))
+ m_creature->NearTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), m_creature->GetOrientation());
+
+ DoCastSpellIfCan(m_creature, SPELL_ARCANEEXPLOSION);
+
+ DoResetThreat();
+
+ Blink_Timer = 45000;
+ }else Blink_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_shazzrah(Creature* pCreature)
+{
+ return new boss_shazzrahAI(pCreature);
+}
+
+void AddSC_boss_shazzrah()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_shazzrah";
+ newscript->GetAI = &GetAI_boss_shazzrah;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp b/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp
new file mode 100644
index 0000000..7451653
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp
@@ -0,0 +1,207 @@
+/* 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_Sulfuron_Harbringer
+SD%Complete: 80
+SDComment: Adds NYI
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+#include "molten_core.h"
+
+#define SPELL_DARKSTRIKE 19777
+#define SPELL_DEMORALIZINGSHOUT 19778
+#define SPELL_INSPIRE 19779
+#define SPELL_KNOCKDOWN 19780
+#define SPELL_FLAMESPEAR 19781
+
+//Adds Spells
+#define SPELL_HEAL 19775
+#define SPELL_SHADOWWORDPAIN 19776
+#define SPELL_IMMOLATE 20294
+
+struct MANGOS_DLL_DECL boss_sulfuronAI : public ScriptedAI
+{
+ boss_sulfuronAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ uint32 Darkstrike_Timer;
+ uint32 DemoralizingShout_Timer;
+ uint32 Inspire_Timer;
+ uint32 Knockdown_Timer;
+ uint32 Flamespear_Timer;
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ Darkstrike_Timer=10000; //These times are probably wrong
+ DemoralizingShout_Timer = 15000;
+ Inspire_Timer = 13000;
+ Knockdown_Timer = 6000;
+ Flamespear_Timer = 2000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //DemoralizingShout_Timer
+ if (DemoralizingShout_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_DEMORALIZINGSHOUT);
+ DemoralizingShout_Timer = urand(15000, 20000);
+ }else DemoralizingShout_Timer -= diff;
+
+ //Inspire_Timer
+ if (Inspire_Timer < diff)
+ {
+ Creature* target = NULL;
+ std::list pList = DoFindFriendlyMissingBuff(45.0f,SPELL_INSPIRE);
+ if (!pList.empty())
+ {
+ std::list::iterator i = pList.begin();
+ advance(i, (rand()%pList.size()));
+ target = (*i);
+ }
+
+ if (target)
+ DoCastSpellIfCan(target,SPELL_INSPIRE);
+
+ DoCastSpellIfCan(m_creature,SPELL_INSPIRE);
+
+ Inspire_Timer = urand(20000, 26000);
+ }else Inspire_Timer -= diff;
+
+ //Knockdown_Timer
+ if (Knockdown_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KNOCKDOWN);
+ Knockdown_Timer = urand(12000, 15000);
+ }else Knockdown_Timer -= diff;
+
+ //Flamespear_Timer
+ if (Flamespear_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_FLAMESPEAR);
+
+ Flamespear_Timer = urand(12000, 16000);
+ }else Flamespear_Timer -= diff;
+
+ //DarkStrike_Timer
+ if (Darkstrike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_DARKSTRIKE);
+ Darkstrike_Timer = urand(15000, 18000);
+ }else Darkstrike_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL mob_flamewaker_priestAI : public ScriptedAI
+{
+ mob_flamewaker_priestAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ uint32 Heal_Timer;
+ uint32 ShadowWordPain_Timer;
+ uint32 Immolate_Timer;
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ Heal_Timer = urand(15000, 30000);
+ ShadowWordPain_Timer = 2000;
+ Immolate_Timer = 8000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Casting Heal to Sulfuron or other Guards.
+ if (Heal_Timer < diff)
+ {
+ Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1);
+ if (!pUnit)
+ return;
+
+ DoCastSpellIfCan(pUnit, SPELL_HEAL);
+
+ Heal_Timer = urand(15000, 20000);
+ }else Heal_Timer -= diff;
+
+ //ShadowWordPain_Timer
+ if (ShadowWordPain_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_SHADOWWORDPAIN);
+
+ ShadowWordPain_Timer = urand(18000, 26000);
+ }else ShadowWordPain_Timer -= diff;
+
+ //Immolate_Timer
+ if (Immolate_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_IMMOLATE);
+
+ Immolate_Timer = urand(15000, 25000);
+ }else Immolate_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_sulfuron(Creature* pCreature)
+{
+ return new boss_sulfuronAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_flamewaker_priest(Creature* pCreature)
+{
+ return new mob_flamewaker_priestAI(pCreature);
+}
+
+void AddSC_boss_sulfuron()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_sulfuron";
+ newscript->GetAI = &GetAI_boss_sulfuron;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_flamewaker_priest";
+ newscript->GetAI = &GetAI_mob_flamewaker_priest;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp b/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp
new file mode 100644
index 0000000..046af55
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp
@@ -0,0 +1,287 @@
+/* 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_Molten_Core
+SD%Complete: 0
+SDComment: Place Holder
+SDCategory: Molten Core
+EndScriptData */
+
+#include "precompiled.h"
+#include "molten_core.h"
+
+struct MANGOS_DLL_DECL instance_molten_core : public ScriptedInstance
+{
+ instance_molten_core(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint64 m_uiLucifronGUID, m_uiMagmadarGUID, m_uiGehennasGUID, m_uiGarrGUID, m_uiGeddonGUID, m_uiShazzrahGUID, m_uiSulfuronGUID, m_uiGolemaggGUID, m_uiMajorDomoGUID, m_uiRagnarosGUID, m_uiFlamewakerPriestGUID;
+ uint64 m_uiRuneKoroGUID, m_uiRuneZethGUID, m_uiRuneMazjGUID, m_uiRuneTheriGUID, m_uiRuneBlazGUID, m_uiRuneKressGUID, m_uiRuneMohnGUID, m_uiFirelordCacheGUID;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiLucifronGUID = 0;
+ m_uiMagmadarGUID = 0;
+ m_uiGehennasGUID = 0;
+ m_uiGarrGUID = 0;
+ m_uiGeddonGUID = 0;
+ m_uiShazzrahGUID = 0;
+ m_uiSulfuronGUID = 0;
+ m_uiGolemaggGUID = 0;
+ m_uiMajorDomoGUID = 0;
+ m_uiRagnarosGUID = 0;
+ m_uiFlamewakerPriestGUID = 0;
+
+ m_uiRuneKoroGUID = 0;
+ m_uiRuneZethGUID = 0;
+ m_uiRuneMazjGUID = 0;
+ m_uiRuneTheriGUID = 0;
+ m_uiRuneBlazGUID = 0;
+ m_uiRuneKressGUID = 0;
+ m_uiRuneMohnGUID = 0;
+
+ m_uiFirelordCacheGUID = 0;
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ return false;
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case 176951: //Sulfuron
+ m_uiRuneKoroGUID = pGo->GetGUID();
+ break;
+ case 176952: //Geddon
+ m_uiRuneZethGUID = pGo->GetGUID();
+ break;
+ case 176953: //Shazzrah
+ m_uiRuneMazjGUID = pGo->GetGUID();
+ break;
+ case 176954: //Golemagg
+ m_uiRuneTheriGUID = pGo->GetGUID();
+ break;
+ case 176955: //Garr
+ m_uiRuneBlazGUID = pGo->GetGUID();
+ break;
+ case 176956: //Magmadar
+ m_uiRuneKressGUID = pGo->GetGUID();
+ break;
+ case 176957: //Gehennas
+ m_uiRuneMohnGUID = pGo->GetGUID();
+ break;
+ case 179703:
+ m_uiFirelordCacheGUID = pGo->GetGUID(); //majordomo event chest
+ break;
+ }
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case NPC_LUCIFRON:
+ m_uiLucifronGUID = pCreature->GetGUID();
+ break;
+ case NPC_MAGMADAR:
+ m_uiMagmadarGUID = pCreature->GetGUID();
+ break;
+ case NPC_GEHENNAS:
+ m_uiGehennasGUID = pCreature->GetGUID();
+ break;
+ case NPC_GARR:
+ m_uiGarrGUID = pCreature->GetGUID();
+ break;
+ case NPC_GEDDON:
+ m_uiGeddonGUID = pCreature->GetGUID();
+ break;
+ case NPC_SHAZZRAH:
+ m_uiShazzrahGUID = pCreature->GetGUID();
+ break;
+ case NPC_SULFURON:
+ m_uiSulfuronGUID = pCreature->GetGUID();
+ break;
+ case NPC_GOLEMAGG:
+ m_uiGolemaggGUID = pCreature->GetGUID();
+ break;
+ case NPC_DOMO:
+ m_uiMajorDomoGUID = pCreature->GetGUID();
+ break;
+ case NPC_RAGNAROS:
+ m_uiRagnarosGUID = pCreature->GetGUID();
+ break;
+ case NPC_FLAMEWAKERPRIEST:
+ m_uiFlamewakerPriestGUID = pCreature->GetGUID();
+ break;
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_SULFURON:
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_GEDDON:
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_SHAZZRAH:
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_GOLEMAGG:
+ m_auiEncounter[3] = uiData;
+ break;
+ case TYPE_GARR:
+ m_auiEncounter[4] = uiData;
+ break;
+ case TYPE_MAGMADAR:
+ m_auiEncounter[5] = uiData;
+ break;
+ case TYPE_GEHENNAS:
+ m_auiEncounter[6] = uiData;
+ break;
+ case TYPE_LUCIFRON:
+ m_auiEncounter[7] = uiData;
+ break;
+ case TYPE_MAJORDOMO:
+ if (uiData == DONE)
+ DoRespawnGameObject(m_uiFirelordCacheGUID);
+ m_auiEncounter[8] = uiData;
+ break;
+ case TYPE_RAGNAROS:
+ m_auiEncounter[9] = 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] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " "
+ << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8] << " "
+ << m_auiEncounter[9];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ const char* Save()
+ {
+ return strInstData.c_str();
+ }
+
+ bool CanSpawnMajorDomo()
+ {
+ return m_auiEncounter[0] && m_auiEncounter[1] && m_auiEncounter[2] && m_auiEncounter[3] &&
+ m_auiEncounter[4] && m_auiEncounter[5] && m_auiEncounter[6];
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_SULFURON:
+ return m_auiEncounter[0];
+ case TYPE_GEDDON:
+ return m_auiEncounter[1];
+ case TYPE_SHAZZRAH:
+ return m_auiEncounter[2];
+ case TYPE_GOLEMAGG:
+ return m_auiEncounter[3];
+ case TYPE_GARR:
+ return m_auiEncounter[4];
+ case TYPE_MAGMADAR:
+ return m_auiEncounter[5];
+ case TYPE_GEHENNAS:
+ return m_auiEncounter[6];
+ case TYPE_LUCIFRON:
+ return m_auiEncounter[7];
+ case TYPE_MAJORDOMO:
+ return m_auiEncounter[8];
+ case TYPE_RAGNAROS:
+ return m_auiEncounter[9];
+ }
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_SULFURON:
+ return m_uiSulfuronGUID;
+ case DATA_GOLEMAGG:
+ return m_uiGolemaggGUID;
+ case DATA_GARR:
+ return m_uiGarrGUID;
+ case DATA_MAJORDOMO:
+ return m_uiMajorDomoGUID;
+ }
+
+ return 0;
+ }
+
+ void Load(const char* chrIn)
+ {
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
+ >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7]
+ >> m_auiEncounter[8] >> m_auiEncounter[9];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as "In Progress" - reset it instead.
+ m_auiEncounter[i] = NOT_STARTED;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstance_instance_molten_core(Map* pMap)
+{
+ return new instance_molten_core(pMap);
+}
+
+void AddSC_instance_molten_core()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_molten_core";
+ newscript->GetInstanceData = &GetInstance_instance_molten_core;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/molten_core/molten_core.cpp b/scripts/eastern_kingdoms/molten_core/molten_core.cpp
new file mode 100644
index 0000000..564566c
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/molten_core.cpp
@@ -0,0 +1,31 @@
+/* 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: Molten_Core
+SD%Complete:
+SDComment:
+SDCategory: Molten Core
+EndScriptData */
+
+/* ContentData
+EndContentData */
+
+#include "precompiled.h"
+
+void AddSC_molten_core()
+{
+}
diff --git a/scripts/eastern_kingdoms/molten_core/molten_core.h b/scripts/eastern_kingdoms/molten_core/molten_core.h
new file mode 100644
index 0000000..0cd1f35
--- /dev/null
+++ b/scripts/eastern_kingdoms/molten_core/molten_core.h
@@ -0,0 +1,43 @@
+/* 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 */
+
+#ifndef DEF_MOLTEN_CORE_H
+#define DEF_MOLTEN_CORE_H
+
+enum
+{
+ MAX_ENCOUNTER = 10,
+
+ NPC_LUCIFRON = 12118,
+ NPC_MAGMADAR = 11982,
+ NPC_GEHENNAS = 12259,
+ NPC_GARR = 12057,
+ NPC_GEDDON = 12056,
+ NPC_SHAZZRAH = 12264,
+ NPC_GOLEMAGG = 11988,
+ NPC_SULFURON = 12098,
+ NPC_DOMO = 12018,
+ NPC_RAGNAROS = 11502,
+ NPC_FLAMEWAKERPRIEST = 11662,
+
+ TYPE_SULFURON = 1,
+ TYPE_GEDDON = 2,
+ TYPE_SHAZZRAH = 3,
+ TYPE_GOLEMAGG = 4,
+ TYPE_GARR = 5,
+ TYPE_MAGMADAR = 6,
+ TYPE_GEHENNAS = 7,
+ TYPE_LUCIFRON = 8,
+ TYPE_MAJORDOMO = 9,
+ TYPE_RAGNAROS = 10,
+
+ DATA_SULFURON = 11,
+ DATA_GOLEMAGG = 12,
+ DATA_GARR = 13,
+ DATA_MAJORDOMO = 14,
+
+ DATA_BOSSES_DEAD_CHECK = 15
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/redridge_mountains.cpp b/scripts/eastern_kingdoms/redridge_mountains.cpp
new file mode 100644
index 0000000..07f4f40
--- /dev/null
+++ b/scripts/eastern_kingdoms/redridge_mountains.cpp
@@ -0,0 +1,145 @@
+/* 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: redridge_mountains
+SD%Complete: 100%
+SDComment: Quest support: 219
+SDCategory: Redridge Mountains
+EndScriptData */
+
+/* ContentData
+npc_corporal_keeshan */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_corporal_leehsan
+######*/
+
+enum
+{
+ QUEST_MISSING_IN_ACTION = 219,
+
+ SPELL_MOCKING_BLOW = 21008,
+ SPELL_SHIELD_BASH = 11972,
+
+ SAY_CORPORAL_KEESHAN_1 = -1000561,
+ SAY_CORPORAL_KEESHAN_2 = -1000562,
+ SAY_CORPORAL_KEESHAN_3 = -1000563,
+ SAY_CORPORAL_KEESHAN_4 = -1000564,
+ SAY_CORPORAL_KEESHAN_5 = -1000565,
+};
+
+struct MANGOS_DLL_DECL npc_corporal_keeshan_escortAI : public npc_escortAI
+{
+ npc_corporal_keeshan_escortAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ uint32 m_uiMockingBlowTimer;
+ uint32 m_uiShieldBashTimer;
+
+ void Reset()
+ {
+ m_uiMockingBlowTimer = 5000;
+ m_uiShieldBashTimer = 8000;
+ }
+
+ void WaypointStart(uint32 uiWP)
+ {
+ switch (uiWP)
+ {
+ case 27: //break outside
+ DoScriptText(SAY_CORPORAL_KEESHAN_3, m_creature);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ break;
+ case 54: //say goodbye
+ DoScriptText(SAY_CORPORAL_KEESHAN_5, m_creature);
+ break;
+ }
+ }
+
+ void WaypointReached(uint32 uiWP)
+ {
+ switch (uiWP)
+ {
+ case 26: //break outside
+ m_creature->SetStandState(UNIT_STAND_STATE_SIT);
+ DoScriptText(SAY_CORPORAL_KEESHAN_2, m_creature);
+ break;
+ case 53: //quest_complete
+ DoScriptText(SAY_CORPORAL_KEESHAN_4, m_creature);
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_MISSING_IN_ACTION, m_creature);
+ break;
+ }
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ //Combat check
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiMockingBlowTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MOCKING_BLOW);
+ m_uiMockingBlowTimer = 5000;
+ }
+ else
+ m_uiMockingBlowTimer -= uiDiff;
+
+ if (m_uiShieldBashTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHIELD_BASH);
+ m_uiShieldBashTimer = 8000;
+ }
+ else
+ m_uiShieldBashTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_corporal_keeshan(Creature* pCreature)
+{
+ return new npc_corporal_keeshan_escortAI(pCreature);
+}
+
+bool QuestAccept_npc_corporal_keeshan(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_MISSING_IN_ACTION)
+ {
+ if (npc_corporal_keeshan_escortAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ {
+ DoScriptText(SAY_CORPORAL_KEESHAN_1, pCreature);
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ }
+
+ return true;
+}
+
+void AddSC_redridge_mountains()
+{
+ Script* NewScript;
+
+ NewScript = new Script;
+ NewScript->Name = "npc_corporal_keeshan";
+ NewScript->GetAI = &GetAI_npc_corporal_keeshan;
+ NewScript->pQuestAccept = &QuestAccept_npc_corporal_keeshan;
+ NewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp b/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp
new file mode 100644
index 0000000..34f9c62
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_enclave/ebon_hold.cpp
@@ -0,0 +1,3591 @@
+/* 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: Ebon_Hold
+SD%Complete: 80
+SDComment: Quest support: 12848, 12733, 12739(and 12742 to 12750), 12727
+SDCategory: Ebon Hold
+EndScriptData */
+
+/* ContentData
+npc_a_special_surprise
+npc_death_knight_initiate
+npc_unworthy_initiate_anchor
+npc_unworthy_initiate
+go_acherus_soul_prison
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+#include "WorldPacket.h"
+#include "follower_ai.h"
+
+/*######
+## npc_a_special_surprise
+######*/
+
+enum SpecialSurprise
+{
+ SAY_EXEC_START_1 = -1609025, // speech for all
+ SAY_EXEC_START_2 = -1609026,
+ SAY_EXEC_START_3 = -1609027,
+ SAY_EXEC_PROG_1 = -1609028,
+ SAY_EXEC_PROG_2 = -1609029,
+ SAY_EXEC_PROG_3 = -1609030,
+ SAY_EXEC_PROG_4 = -1609031,
+ SAY_EXEC_PROG_5 = -1609032,
+ SAY_EXEC_PROG_6 = -1609033,
+ SAY_EXEC_PROG_7 = -1609034,
+ SAY_EXEC_NAME_1 = -1609035,
+ SAY_EXEC_NAME_2 = -1609036,
+ SAY_EXEC_RECOG_1 = -1609037,
+ SAY_EXEC_RECOG_2 = -1609038,
+ SAY_EXEC_RECOG_3 = -1609039,
+ SAY_EXEC_RECOG_4 = -1609040,
+ SAY_EXEC_RECOG_5 = -1609041,
+ SAY_EXEC_RECOG_6 = -1609042,
+ SAY_EXEC_NOREM_1 = -1609043,
+ SAY_EXEC_NOREM_2 = -1609044,
+ SAY_EXEC_NOREM_3 = -1609045,
+ SAY_EXEC_NOREM_4 = -1609046,
+ SAY_EXEC_NOREM_5 = -1609047,
+ SAY_EXEC_NOREM_6 = -1609048,
+ SAY_EXEC_NOREM_7 = -1609049,
+ SAY_EXEC_NOREM_8 = -1609050,
+ SAY_EXEC_NOREM_9 = -1609051,
+ SAY_EXEC_THINK_1 = -1609052,
+ SAY_EXEC_THINK_2 = -1609053,
+ SAY_EXEC_THINK_3 = -1609054,
+ SAY_EXEC_THINK_4 = -1609055,
+ SAY_EXEC_THINK_5 = -1609056,
+ SAY_EXEC_THINK_6 = -1609057,
+ SAY_EXEC_THINK_7 = -1609058,
+ SAY_EXEC_THINK_8 = -1609059,
+ SAY_EXEC_THINK_9 = -1609060,
+ SAY_EXEC_THINK_10 = -1609061,
+ SAY_EXEC_LISTEN_1 = -1609062,
+ SAY_EXEC_LISTEN_2 = -1609063,
+ SAY_EXEC_LISTEN_3 = -1609064,
+ SAY_EXEC_LISTEN_4 = -1609065,
+ SAY_PLAGUEFIST = -1609066,
+ SAY_EXEC_TIME_1 = -1609067,
+ SAY_EXEC_TIME_2 = -1609068,
+ SAY_EXEC_TIME_3 = -1609069,
+ SAY_EXEC_TIME_4 = -1609070,
+ SAY_EXEC_TIME_5 = -1609071,
+ SAY_EXEC_TIME_6 = -1609072,
+ SAY_EXEC_TIME_7 = -1609073,
+ SAY_EXEC_TIME_8 = -1609074,
+ SAY_EXEC_TIME_9 = -1609075,
+ SAY_EXEC_TIME_10 = -1609076,
+ SAY_EXEC_WAITING = -1609077,
+ EMOTE_DIES = -1609078,
+
+ NPC_PLAGUEFIST = 29053
+};
+
+struct MANGOS_DLL_DECL npc_a_special_surpriseAI : public ScriptedAI
+{
+ npc_a_special_surpriseAI(Creature *pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ uint32 m_uiExecuteSpeech_Timer;
+ uint32 m_uiExecuteSpeech_Counter;
+ uint64 m_uiPlayerGUID;
+
+ void Reset()
+ {
+ m_uiExecuteSpeech_Timer = 0;
+ m_uiExecuteSpeech_Counter = 0;
+ m_uiPlayerGUID = 0;
+ }
+
+ bool MeetQuestCondition(Player* pPlayer)
+ {
+ switch(m_creature->GetEntry())
+ {
+ case 29061: // Ellen Stanbridge
+ if (pPlayer->GetQuestStatus(12742) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29072: // Kug Ironjaw
+ if (pPlayer->GetQuestStatus(12748) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29067: // Donovan Pulfrost
+ if (pPlayer->GetQuestStatus(12744) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29065: // Yazmina Oakenthorn
+ if (pPlayer->GetQuestStatus(12743) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29071: // Antoine Brack
+ if (pPlayer->GetQuestStatus(12750) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29032: // Malar Bravehorn
+ if (pPlayer->GetQuestStatus(12739) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29068: // Goby Blastenheimer
+ if (pPlayer->GetQuestStatus(12745) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29073: // Iggy Darktusk
+ if (pPlayer->GetQuestStatus(12749) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29074: // Lady Eonys
+ if (pPlayer->GetQuestStatus(12747) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ case 29070: // Valok the Righteous
+ if (pPlayer->GetQuestStatus(12746) == QUEST_STATUS_INCOMPLETE)
+ return true;
+ break;
+ }
+
+ return false;
+ }
+
+ void MoveInLineOfSight(Unit* pWho)
+ {
+ if (m_uiPlayerGUID || pWho->GetTypeId() != TYPEID_PLAYER || !pWho->IsWithinDist(m_creature, INTERACTION_DISTANCE))
+ return;
+
+ if (MeetQuestCondition((Player*)pWho))
+ m_uiPlayerGUID = pWho->GetGUID();
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_uiPlayerGUID && !m_creature->getVictim() && m_creature->isAlive())
+ {
+ if (m_uiExecuteSpeech_Timer < uiDiff)
+ {
+ Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID);
+
+ if (!pPlayer)
+ {
+ Reset();
+ return;
+ }
+
+ //TODO: simplify text's selection
+
+ switch(pPlayer->getRace())
+ {
+ case RACE_HUMAN:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_1, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_5, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_1, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_5, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_7, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_1, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_6, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_ORC:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_1, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_6, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_1, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_7, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_8, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_1, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_8, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_DWARF:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_2, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_2, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_3, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_2, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_5, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_2, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_3, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_NIGHTELF:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_1, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_5, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_1, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_6, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_2, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_1, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_7, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_UNDEAD_PLAYER:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_1, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_3, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_4, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_3, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_1, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_3, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_4, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_TAUREN:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_1, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_1, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_5, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_8, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_9, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_1, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_9, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_GNOME:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_1, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_4, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_1, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_4, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_6, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_1, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_5, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_TROLL:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_3, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_7, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_2, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_6, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_9, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_10, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_4, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_10, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_BLOODELF:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_1, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_1, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_1, m_creature, pPlayer); break;
+ //case 5: //unknown
+ case 6: DoScriptText(SAY_EXEC_THINK_3, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_1, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_1, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ case RACE_DRAENEI:
+ switch(m_uiExecuteSpeech_Counter)
+ {
+ case 0: DoScriptText(SAY_EXEC_START_1, m_creature, pPlayer); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_STAND); break;
+ case 2: DoScriptText(SAY_EXEC_PROG_1, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_EXEC_NAME_1, m_creature, pPlayer); break;
+ case 4: DoScriptText(SAY_EXEC_RECOG_2, m_creature, pPlayer); break;
+ case 5: DoScriptText(SAY_EXEC_NOREM_1, m_creature, pPlayer); break;
+ case 6: DoScriptText(SAY_EXEC_THINK_4, m_creature, pPlayer); break;
+ case 7: DoScriptText(SAY_EXEC_LISTEN_1, m_creature, pPlayer); break;
+ case 8:
+ if (Creature* pPlaguefist = GetClosestCreatureWithEntry(m_creature, NPC_PLAGUEFIST, 85.0f))
+ DoScriptText(SAY_PLAGUEFIST, pPlaguefist, pPlayer);
+ break;
+ case 9:
+ DoScriptText(SAY_EXEC_TIME_2, m_creature, pPlayer);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ break;
+ case 10: DoScriptText(SAY_EXEC_WAITING, m_creature, pPlayer); break;
+ case 11:
+ DoScriptText(EMOTE_DIES, m_creature);
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->SetHealth(0);
+ return;
+ }
+ break;
+ }
+
+ if (m_uiExecuteSpeech_Counter >= 9)
+ m_uiExecuteSpeech_Timer = 15000;
+ else
+ m_uiExecuteSpeech_Timer = 7000;
+
+ ++m_uiExecuteSpeech_Counter;
+ }
+ else
+ m_uiExecuteSpeech_Timer -= uiDiff;
+ }
+ }
+};
+
+/*######
+## npc_death_knight_initiate
+######*/
+
+enum npc_death_knight_initiate
+{
+ SAY_DUEL_A = -1609016,
+ SAY_DUEL_B = -1609017,
+ SAY_DUEL_C = -1609018,
+ SAY_DUEL_D = -1609019,
+ SAY_DUEL_E = -1609020,
+ SAY_DUEL_F = -1609021,
+ SAY_DUEL_G = -1609022,
+ SAY_DUEL_H = -1609023,
+ SAY_DUEL_I = -1609024,
+
+ SPELL_BLOOD_STRIKE = 52374,
+ SPELL_DEATH_COIL = 52375,
+ SPELL_ICY_TOUCH = 52372,
+ SPELL_PLAGUE_STRIKE = 52373,
+
+ SPELL_DUEL = 52996,
+ SPELL_DUEL_TRIGGERED = 52990,
+ SPELL_DUEL_VICTORY = 52994,
+ SPELL_DUEL_FLAG = 52991,
+
+ QUEST_DEATH_CHALLENGE = 12733,
+ FACTION_HOSTILE = 2068
+};
+
+int32 m_auiRandomSay[] =
+{
+ SAY_DUEL_A, SAY_DUEL_B, SAY_DUEL_C, SAY_DUEL_D, SAY_DUEL_E, SAY_DUEL_F, SAY_DUEL_G, SAY_DUEL_H, SAY_DUEL_I
+};
+
+#define GOSSIP_ACCEPT_DUEL "I challenge you, death knight!"
+
+struct MANGOS_DLL_DECL npc_death_knight_initiateAI : public ScriptedAI
+{
+ npc_death_knight_initiateAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ uint64 m_uiDuelerGUID;
+ uint32 m_uiDuelTimer;
+ uint32 m_uiBloodStrike_Timer;
+ uint32 m_uiDeathCoil_Timer;
+ uint32 m_uiIcyTouch_Timer;
+ uint32 m_uiPlagueStrike_Timer;
+ bool m_bIsDuelInProgress;
+
+ void Reset()
+ {
+ if (m_creature->getFaction() != m_creature->GetCreatureInfo()->faction_A)
+ m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A);
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15);
+
+ m_uiDuelerGUID = 0;
+ m_uiDuelTimer = 5000;
+ m_uiBloodStrike_Timer = 4000;
+ m_uiDeathCoil_Timer = 5000;
+ m_uiIcyTouch_Timer = 2000;
+ m_uiPlagueStrike_Timer = 3000;
+ m_bIsDuelInProgress = false;
+ }
+
+ void AttackedBy(Unit* pAttacker)
+ {
+ if (m_creature->getVictim())
+ return;
+
+ if (m_creature->IsFriendlyTo(pAttacker))
+ return;
+
+ AttackStart(pAttacker);
+ }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (!m_bIsDuelInProgress && pSpell->Id == SPELL_DUEL_TRIGGERED && pCaster->GetTypeId() == TYPEID_PLAYER)
+ {
+ m_uiDuelerGUID = pCaster->GetGUID();
+ m_bIsDuelInProgress = true;
+ }
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (m_bIsDuelInProgress && uiDamage > m_creature->GetHealth())
+ {
+ uiDamage = 0;
+
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiDuelerGUID))
+ m_creature->CastSpell(pPlayer, SPELL_DUEL_VICTORY, true);
+
+ //possibly not evade, but instead have end sequenze
+ EnterEvadeMode();
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ if (m_bIsDuelInProgress)
+ {
+ if (m_uiDuelTimer < uiDiff)
+ {
+ m_creature->setFaction(FACTION_HOSTILE);
+
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiDuelerGUID))
+ AttackStart(pPlayer);
+ }
+ else
+ m_uiDuelTimer -= uiDiff;
+ }
+ return;
+ }
+
+ if (m_uiIcyTouch_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ICY_TOUCH);
+ m_uiIcyTouch_Timer = 8000;
+ }
+ else
+ m_uiIcyTouch_Timer -= uiDiff;
+
+ if (m_uiPlagueStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_PLAGUE_STRIKE);
+ m_uiPlagueStrike_Timer = 8000;
+ }
+ else
+ m_uiPlagueStrike_Timer -= uiDiff;
+
+ if (m_uiBloodStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BLOOD_STRIKE);
+ m_uiBloodStrike_Timer = 8000;
+ }
+ else
+ m_uiBloodStrike_Timer -= uiDiff;
+
+ if (m_uiDeathCoil_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_DEATH_COIL);
+ m_uiDeathCoil_Timer = 8000;
+ }
+ else
+ m_uiDeathCoil_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_death_knight_initiate(Creature* pCreature)
+{
+ return new npc_death_knight_initiateAI(pCreature);
+}
+
+bool GossipHello_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(QUEST_DEATH_CHALLENGE) == QUEST_STATUS_INCOMPLETE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ACCEPT_DUEL, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(13433, pCreature->GetGUID());
+ return true;
+ }
+ return false;
+}
+
+bool GossipSelect_npc_death_knight_initiate(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (npc_death_knight_initiateAI* pInitiateAI = dynamic_cast(pCreature->AI()))
+ {
+ if (pInitiateAI->m_bIsDuelInProgress)
+ return true;
+ }
+
+ pCreature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_15);
+
+ int32 uiSayId = rand()% (sizeof(m_auiRandomSay)/sizeof(int32));
+ DoScriptText(m_auiRandomSay[uiSayId], pCreature, pPlayer);
+
+ pCreature->CastSpell(pPlayer, SPELL_DUEL, false);
+ pCreature->CastSpell(pPlayer, SPELL_DUEL_FLAG, true);
+ }
+ return true;
+}
+
+/*######
+## npc_koltira_deathweaver
+######*/
+
+enum eKoltira
+{
+ SAY_BREAKOUT1 = -1609079,
+ SAY_BREAKOUT2 = -1609080,
+ SAY_BREAKOUT3 = -1609081,
+ SAY_BREAKOUT4 = -1609082,
+ SAY_BREAKOUT5 = -1609083,
+ SAY_BREAKOUT6 = -1609084,
+ SAY_BREAKOUT7 = -1609085,
+ SAY_BREAKOUT8 = -1609086,
+ SAY_BREAKOUT9 = -1609087,
+ SAY_BREAKOUT10 = -1609088,
+
+ SPELL_KOLTIRA_TRANSFORM = 52899,
+ SPELL_ANTI_MAGIC_ZONE = 52894,
+
+ QUEST_BREAKOUT = 12727,
+
+ NPC_CRIMSON_ACOLYTE = 29007,
+ NPC_HIGH_INQUISITOR_VALROTH = 29001,
+ NPC_KOLTIRA_ALT = 28447,
+
+ MODEL_DEATH_KNIGHT_MOUNT = 25278
+};
+
+struct MANGOS_DLL_DECL npc_koltira_deathweaverAI : public npc_escortAI
+{
+ npc_koltira_deathweaverAI(Creature *pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ uint32 m_uiWave;
+ uint32 m_uiWave_Timer;
+ uint64 m_uiValrothGUID;
+
+ void Reset()
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ m_uiWave = 0;
+ m_uiWave_Timer = 3000;
+ m_uiValrothGUID = 0;
+ }
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 0:
+ DoScriptText(SAY_BREAKOUT1, m_creature);
+ break;
+ case 1:
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ break;
+ case 2:
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ 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
+ SetEscortPaused(true);
+ m_creature->SetStandState(UNIT_STAND_STATE_KNEEL);
+ //m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ DoScriptText(SAY_BREAKOUT2, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_ANTI_MAGIC_ZONE);
+ break;
+ case 4: // Valroth dead, he runs away
+ {
+ //m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ // 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);
+ DoCastSpellIfCan(m_creature, SPELL_KOLTIRA_TRANSFORM); // Somehow he gets naked
+ SetRun(true);
+ break;
+ }
+ case 9:
+ m_creature->Mount(MODEL_DEATH_KNIGHT_MOUNT);
+ break;
+ case 10:
+ m_creature->Unmount();
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ pSummoned->AI()->AttackStart(pPlayer);
+ pSummoned->AddThreat(pPlayer);
+ }
+
+ if (pSummoned->GetEntry() == NPC_HIGH_INQUISITOR_VALROTH)
+ m_uiValrothGUID = pSummoned->GetGUID();
+ }
+
+ void SummonAcolyte(uint32 uiAmount)
+ {
+ for(uint32 i = 0; i < uiAmount; ++i)
+ m_creature->SummonCreature(NPC_CRIMSON_ACOLYTE, 1642.329f, -6045.818f, 127.583f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (HasEscortState(STATE_ESCORT_PAUSED))
+ {
+ if (m_uiWave_Timer < uiDiff)
+ {
+ switch(m_uiWave)
+ {
+ case 0:
+ DoScriptText(SAY_BREAKOUT3, m_creature);
+ SummonAcolyte(3);
+ m_uiWave_Timer = 20000;
+ break;
+ case 1:
+ DoScriptText(SAY_BREAKOUT4, m_creature);
+ SummonAcolyte(3);
+ m_uiWave_Timer = 20000;
+ break;
+ case 2:
+ DoScriptText(SAY_BREAKOUT5, m_creature);
+ SummonAcolyte(4);
+ m_uiWave_Timer = 20000;
+ break;
+ case 3:
+ DoScriptText(SAY_BREAKOUT6, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_ANTI_MAGIC_ZONE);
+ m_creature->SummonCreature(NPC_HIGH_INQUISITOR_VALROTH, 1642.329f, -6045.818f, 127.583f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000);
+ m_uiWave_Timer = 1000;
+ break;
+ case 4:
+ {
+ Creature* pTemp = m_creature->GetMap()->GetCreature(m_uiValrothGUID);
+
+ if (!pTemp || !pTemp->isAlive())
+ {
+ DoScriptText(SAY_BREAKOUT8, m_creature);
+ m_uiWave_Timer = 5000;
+ }
+ else
+ {
+ m_uiWave_Timer = 2500;
+ return; //return, we don't want m_uiWave to increment now
+ }
+ break;
+ }
+ case 5:
+ DoScriptText(SAY_BREAKOUT9, m_creature);
+ m_creature->RemoveAurasDueToSpell(SPELL_ANTI_MAGIC_ZONE);
+ m_uiWave_Timer = 2500;
+ break;
+ case 6:
+ DoScriptText(SAY_BREAKOUT10, m_creature);
+ SetEscortPaused(false);
+ break;
+ }
+
+ ++m_uiWave;
+ }
+ else
+ m_uiWave_Timer -= uiDiff;
+ }
+ else
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_koltira_deathweaver(Creature* pCreature)
+{
+ return new npc_koltira_deathweaverAI(pCreature);
+}
+
+bool QuestAccept_npc_koltira_deathweaver(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_BREAKOUT)
+ {
+ pCreature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ if (npc_koltira_deathweaverAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+/*######
+## Mob High Inquisitor Valroth
+######*/
+enum valroth
+{
+ SAY_VALROTH1 = -1609082,
+ SAY_VALROTH2 = -1609083,
+ SAY_VALROTH3 = -1609084,
+ SAY_VALROTH4 = -1609085,
+ SAY_VALROTH5 = -1609086,
+ SAY_VALROTH6 = -1609087,
+ 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 = 1000;
+ uiInquisitor_Penance_timer = 2000;
+ uiValroth_Smite_timer = 1000;
+ }
+
+ 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 = 1000 + 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()%20)
+ {
+ case 0: DoScriptText(SAY_VALROTH3, m_creature);break;
+ case 1: DoScriptText(SAY_VALROTH4, m_creature);break;
+ case 2: DoScriptText(SAY_VALROTH5, m_creature);break;
+ }
+ }
+
+ void JustDied(Unit* killer)
+ {
+ DoScriptText(SAY_VALROTH6, m_creature);
+ killer->CastSpell(m_creature, SPELL_SUMMON_VALROTH_REMAINS, true);
+ }
+};
+
+/*######
+## Quest: The Endless Hunger
+######*/
+
+enum npc_unworthy_initiate
+{
+ 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
+
+ //SPELL_CHAINED_PESANT_LH = 54602, // not used. possible it determine side, where to go get "weapon"
+ //SPELL_CHAINED_PESANT_RH = 54610,
+ SPELL_CHAINED_PESANT_CHEST = 54612,
+ 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,
+
+ PHASE_INACTIVE_OR_COMBAT = 0,
+ PHASE_DRESSUP = 1,
+ PHASE_ACTIVATE = 2
+};
+
+struct DisplayToSpell
+{
+ uint32 m_uiDisplayId;
+ uint32 m_uiSpellToNewDisplay;
+};
+
+DisplayToSpell m_aDisplayToSpell[] =
+{
+ {25354, 51520}, // human M
+ {25355, 51534}, // human F
+ {25356, 51538}, // dwarf M
+ {25357, 51541}, // draenei M
+ {25358, 51535}, // nelf M
+ {25359, 51539}, // gnome M
+ {25360, 51536}, // nelf F
+ {25361, 51537}, // dwarf F
+ {25362, 51540}, // gnome F
+ {25363, 51542}, // draenei F
+ {25364, 51543}, // orc M
+ {25365, 51546}, // troll M
+ {25366, 51547}, // tauren M
+ {25367, 51549}, // forsaken M
+ {25368, 51544}, // orc F
+ {25369, 51552}, // belf F
+ {25370, 51545}, // troll F
+ {25371, 51548}, // tauren F
+ {25372, 51550}, // forsaken F
+ {25373, 51551} // belf M
+};
+
+/*######
+## npc_unworthy_initiate_anchor
+######*/
+
+struct MANGOS_DLL_DECL npc_unworthy_initiate_anchorAI : public ScriptedAI
+{
+ npc_unworthy_initiate_anchorAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiMyInitiate = 0;
+ Reset();
+ }
+
+ uint64 m_uiMyInitiate;
+ uint64 m_uiMyPrisonGUID;
+
+ void Reset() { }
+
+ void NotifyMe(Unit* pSource, uint64 uiPrisonGuid)
+ {
+ m_uiMyPrisonGUID = uiPrisonGuid;
+ Creature* pInitiate = m_creature->GetMap()->GetCreature(m_uiMyInitiate);
+
+ if (pInitiate && pSource)
+ {
+ pInitiate->SetLootRecipient(pSource);
+ m_creature->CastSpell(pInitiate,SPELL_CHAINED_PESANT_BREATH,true);
+ }
+ }
+
+ void RegisterCloseInitiate(uint64 uiGuid)
+ {
+ m_uiMyInitiate = uiGuid;
+ }
+
+ void ResetPrison()
+ {
+ if (GameObject* pPrison = m_creature->GetMap()->GetGameObject(m_uiMyPrisonGUID))
+ pPrison->ResetDoorOrButton();
+ }
+};
+
+/*######
+## npc_unworthy_initiate
+######*/
+
+struct MANGOS_DLL_DECL npc_unworthy_initiateAI : public ScriptedAI
+{
+ npc_unworthy_initiateAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pToTransform = NULL;
+
+ uint32 uiDisplayCount = sizeof(m_aDisplayToSpell)/sizeof(DisplayToSpell);
+
+ for (uint8 i=0; iGetDisplayId())
+ {
+ m_pToTransform = &m_aDisplayToSpell[i];
+ break;
+ }
+ }
+
+ m_uiNormFaction = pCreature->getFaction();
+ Reset();
+ }
+
+ DisplayToSpell* m_pToTransform;
+
+ uint64 m_uiMyAnchorGUID;
+ uint32 m_uiNormFaction;
+ uint32 m_uiAnchorCheckTimer;
+ uint32 m_uiPhase;
+ uint32 m_uiPhaseTimer;
+ uint32 m_uiBloodStrike_Timer;
+ uint32 m_uiDeathCoil_Timer;
+ uint32 m_uiIcyTouch_Timer;
+ uint32 m_uiPlagueStrike_Timer;
+
+ void Reset()
+ {
+ if (m_creature->getFaction() != m_uiNormFaction)
+ m_creature->setFaction(m_uiNormFaction);
+
+ m_uiMyAnchorGUID = 0;
+ m_uiAnchorCheckTimer = 5000;
+ m_uiPhase = PHASE_INACTIVE_OR_COMBAT;
+ m_uiPhaseTimer = 7500;
+ m_uiBloodStrike_Timer = 4000;
+ m_uiDeathCoil_Timer = 6000;
+ m_uiIcyTouch_Timer = 2000;
+ m_uiPlagueStrike_Timer = 5000;
+ }
+
+ void JustReachedHome()
+ {
+ SetAnchor();
+ }
+
+ void JustRespawned()
+ {
+ if (Creature* pAnchor = GetAnchor())
+ {
+ if (npc_unworthy_initiate_anchorAI* pAnchorAI = dynamic_cast(pAnchor->AI()))
+ pAnchorAI->ResetPrison();
+ }
+
+ Reset();
+ }
+
+ int32 GetTextId()
+ {
+ return m_uiPhase == PHASE_DRESSUP ? SAY_START-rand()%8 : SAY_AGGRO-rand()%8;
+ }
+
+ Creature* GetAnchor()
+ {
+ if (m_uiMyAnchorGUID)
+ return m_creature->GetMap()->GetCreature(m_uiMyAnchorGUID);
+ else
+ return GetClosestCreatureWithEntry(m_creature, NPC_ANCHOR, INTERACTION_DISTANCE*2);
+ }
+
+ void SetAnchor()
+ {
+ if (Creature* pAnchor = GetAnchor())
+ {
+ if (npc_unworthy_initiate_anchorAI* pAnchorAI = dynamic_cast(pAnchor->AI()))
+ pAnchorAI->RegisterCloseInitiate(m_creature->GetGUID());
+
+ pAnchor->CastSpell(m_creature, SPELL_CHAINED_PESANT_CHEST, false);
+
+ m_uiAnchorCheckTimer = 0;
+ return;
+ }
+
+ m_uiAnchorCheckTimer = 5000;
+ }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (pSpell->Id == SPELL_CHAINED_PESANT_BREATH)
+ {
+ pCaster->InterruptNonMeleeSpells(true);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ m_uiPhase = PHASE_DRESSUP;
+
+ if (Player* pSource = m_creature->GetLootRecipient())
+ DoScriptText(GetTextId(), m_creature, pSource);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_uiAnchorCheckTimer)
+ {
+ if (m_uiAnchorCheckTimer <= uiDiff)
+ SetAnchor();
+ else
+ m_uiAnchorCheckTimer -= uiDiff;
+ }
+
+ if (m_uiPhase == PHASE_INACTIVE_OR_COMBAT)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiBloodStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BLOOD_STRIKE);
+ m_uiBloodStrike_Timer = 9000;
+ }
+ else
+ m_uiBloodStrike_Timer -= uiDiff;
+
+ if (m_uiDeathCoil_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_DEATH_COIL);
+ m_uiDeathCoil_Timer = 8000;
+ }
+ else
+ m_uiDeathCoil_Timer -= uiDiff;
+
+ if (m_uiIcyTouch_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ICY_TOUCH);
+ m_uiIcyTouch_Timer = 8000;
+ }
+ else
+ m_uiIcyTouch_Timer -= uiDiff;
+
+ if (m_uiPlagueStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_PLAGUE_STRIKE);
+ m_uiPlagueStrike_Timer = 8000;
+ }
+ else
+ m_uiPlagueStrike_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+ else
+ {
+ if (m_uiPhaseTimer < uiDiff)
+ {
+ if (m_uiPhase == PHASE_DRESSUP)
+ {
+ if (m_pToTransform)
+ {
+ m_creature->CastSpell(m_creature, m_pToTransform->m_uiSpellToNewDisplay, true);
+ m_creature->CastSpell(m_creature, SPELL_INITIATE_VISUAL, false);
+ }
+ else
+ error_log("SD2: npc_unworthy_initiate does not have any spell associated with model");
+
+ m_uiPhase = PHASE_ACTIVATE;
+ }
+ else
+ {
+ m_creature->setFaction(FACTION_MONSTER);
+
+ m_uiPhase = PHASE_INACTIVE_OR_COMBAT;
+
+ if (Player* pTarget = m_creature->GetLootRecipient())
+ {
+ DoScriptText(GetTextId(), m_creature, pTarget);
+ AttackStart(pTarget);
+ }
+ }
+
+ m_uiPhaseTimer = 5000;
+ }
+ else
+ m_uiPhaseTimer -= uiDiff;
+ }
+ }
+};
+
+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
+######*/
+
+bool GOHello_go_acherus_soul_prison(Player* pPlayer, GameObject* pGo)
+{
+ if (Creature* pAnchor = GetClosestCreatureWithEntry(pGo, NPC_ANCHOR, INTERACTION_DISTANCE))
+ {
+ if (npc_unworthy_initiate_anchorAI* pAnchorAI = dynamic_cast(pAnchor->AI()))
+ pAnchorAI->NotifyMe(pPlayer, pGo->GetGUID());
+ }
+
+ return false;
+}
+
+/*######
+## npc_eye_of_acherus
+######*/
+
+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;
+ }
+
+ uint32 StartTimer;
+ bool Active;
+
+ void Reset(){}
+ void AttackStart(Unit *) {}
+ void MoveInLineOfSight(Unit*) {}
+
+ void JustDied(Unit*u)
+ {
+ if(!m_creature || m_creature->GetTypeId() != TYPEID_UNIT)
+ return;
+
+ Unit *target = m_creature->GetCharmer();
+
+ if(!target || target->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ m_creature->SetCharmerGUID(0);
+ target->RemoveAurasDueToSpell(51852);
+ target->SetCharm(NULL);
+
+ ((Player*)target)->GetCamera().ResetView();
+ ((Player*)target)->SetClientControl(m_creature,0);
+ ((Player*)target)->SetMover(NULL);
+
+ m_creature->CleanupsBeforeDelete();
+ m_creature->AddObjectToRemoveList();
+ //m_creature->ForcedDespawn();
+ return;
+ }
+
+ void MovementInform(uint32 uiType, uint32 uiPointId)
+ {
+ 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);
+ m_creature->CastSpell(m_creature, 51890, true);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if(m_creature->isCharmed())
+ {
+ 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->GetMotionMaster()->MovePoint(0, 1750.8276f, -5873.788f, 147.2266f);
+ Active = true;
+ }
+ else StartTimer -= uiDiff;
+ }
+ else
+ {
+ m_creature->CleanupsBeforeDelete();
+ m_creature->AddObjectToRemoveList();
+ }
+ }
+};
+
+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,
+ 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_crusade_persuaded - Quest: How To Win Friends And Influence Enemies
+######*/
+
+enum win_friends
+{
+ SAY_PERSUADE1 = -1609051,
+ SAY_PERSUADE2 = -1609052,
+ SAY_PERSUADE3 = -1609053,
+ SAY_PERSUADE4 = -1609054,
+ SAY_PERSUADE5 = -1609055,
+ SAY_PERSUADE6 = -1609056,
+ SAY_PERSUADE7 = -1609057,
+ SAY_CRUSADER1 = -1609058,
+ SAY_CRUSADER2 = -1609059,
+ SAY_CRUSADER3 = -1609060,
+ SAY_CRUSADER4 = -1609061,
+ SAY_CRUSADER5 = -1609062,
+ SAY_CRUSADER6 = -1609063,
+ SAY_PERSUADED1 = -1609064,
+ SAY_PERSUADED2 = -1609065,
+ SAY_PERSUADED3 = -1609066,
+ SAY_PERSUADED4 = -1609067,
+ SAY_PERSUADED5 = -1609068,
+ SAY_PERSUADED6 = -1609069,
+ SPELL_PERSUASIVE_STRIKE = 52781
+};
+
+struct MANGOS_DLL_DECL npc_crusade_persuadedAI : public ScriptedAI
+{
+ npc_crusade_persuadedAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ Reset();
+ }
+
+ uint32 uiSpeech_timer;
+ uint32 uiSpeech_counter;
+ uint32 uiCrusade_faction;
+ uint64 uiPlayerGUID;
+
+ void Reset()
+ {
+ uiSpeech_timer = 0;
+ uiSpeech_counter = 0;
+ uiCrusade_faction = 0;
+ uiPlayerGUID = 0;
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER && m_creature->isAlive() && spell->Id == SPELL_PERSUASIVE_STRIKE && uiSpeech_counter == 0)
+ {
+ if(((Player*)caster)->GetQuestStatus(12720) == QUEST_STATUS_INCOMPLETE)
+ {
+ if (rand()%100 > 90) // chance
+ {
+ uiPlayerGUID = ((Player*)caster)->GetGUID();
+ uiCrusade_faction = m_creature->getFaction();
+ uiSpeech_timer = 1000;
+ uiSpeech_counter = 1;
+ m_creature->setFaction(35);
+ }
+ else if (uiSpeech_counter == 0)
+ {
+ switch(rand()%6)
+ {
+ case 0: DoScriptText(SAY_PERSUADE1, caster);break;
+ case 1: DoScriptText(SAY_PERSUADE2, caster);break;
+ case 2: DoScriptText(SAY_PERSUADE3, caster);break;
+ case 3: DoScriptText(SAY_PERSUADE4, caster);break;
+ case 4: DoScriptText(SAY_PERSUADE5, caster);break;
+ case 5: DoScriptText(SAY_PERSUADE6, caster);break;
+ case 6: DoScriptText(SAY_PERSUADE7, caster);break;
+ }
+ switch(rand()%5)
+ {
+ case 0: DoScriptText(SAY_CRUSADER1, m_creature);break;
+ case 1: DoScriptText(SAY_CRUSADER2, m_creature);break;
+ case 2: DoScriptText(SAY_CRUSADER3, m_creature);break;
+ case 3: DoScriptText(SAY_CRUSADER4, m_creature);break;
+ case 4: DoScriptText(SAY_CRUSADER5, m_creature);break;
+ case 5: DoScriptText(SAY_CRUSADER6, m_creature);break;
+ }
+ }
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (uiSpeech_counter >= 1 && uiSpeech_counter <= 6)
+ if (uiSpeech_timer < diff)
+ {
+ m_creature->CombatStop(true);
+ m_creature->StopMoving();
+ Unit* pPlayer = m_creature->GetMap()->GetUnit(uiPlayerGUID);
+
+ switch(uiSpeech_counter)
+ {
+ case 1: DoScriptText(SAY_PERSUADED1, m_creature); uiSpeech_timer = 8000; uiSpeech_counter++; break;
+ case 2: DoScriptText(SAY_PERSUADED2, m_creature); uiSpeech_timer = 8000; uiSpeech_counter++; break;
+ case 3: DoScriptText(SAY_PERSUADED3, m_creature); uiSpeech_timer = 8000; uiSpeech_counter++; break;
+ case 4: DoScriptText(SAY_PERSUADED4, m_creature); uiSpeech_timer = 8000; uiSpeech_counter++; break;
+ case 5: DoScriptText(SAY_PERSUADED5, pPlayer); uiSpeech_timer = 8000; uiSpeech_counter++; break;
+ case 6:
+ DoScriptText(SAY_PERSUADED6, m_creature);
+ m_creature->setFaction(uiCrusade_faction);
+ //m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ //m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ uiSpeech_timer = 0;
+ uiCrusade_faction = 0;
+ uiSpeech_counter++;
+ AttackStart(pPlayer);
+ if(((Player*)pPlayer)->GetQuestStatus(12720) == QUEST_STATUS_INCOMPLETE)
+ ((Player*)pPlayer)->AreaExploredOrEventHappens(12720);
+ break;
+ }
+ }else uiSpeech_timer -= diff;
+ else
+ DoMeleeAttackIfReady();
+ }
+};
+
+/*######
+## npc_palomino - Quest: Grand Theft Palomino - Vehicle HACK
+######*/
+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)
+{
+
+ 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)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (npc_palominoAI* ppalominoAI = dynamic_cast(pCreature->AI()))
+ ppalominoAI->StartFollow(pPlayer, FACTION_ESCORT_N_FRIEND_PASSIVE);
+ }
+ 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());
+
+ return true;
+}
+
+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;
+}
+
+/*######
+## 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}
+};
+
+// 52693
+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();
+ }
+
+ 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;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ 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_uiWalkTimer <= diff)
+ {
+ m_creature->GetMotionMaster()->MovePoint(id,DarkriderWP[id].x, DarkriderWP[id].y, DarkriderWP[id].z);
+ m_uiWalkTimer = 0;
+
+ }else m_uiWalkTimer -= diff;
+ }
+
+ 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;
+ }
+
+ ++id;
+ m_uiWalkTimer = 200;
+ }
+};
+// Hack untill 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 scarletminer
+{
+ NPC_SCARLET_GHOUL = 28845,
+ SPELL_GIFT_OF_THE_HARVESTER = 52479, // only works, when ghouls attack you
+ SPELL_GIFT_OF_THE_HARVESTER_MISSILE = 52481,
+ SPELL_SCARLET_MINER_GHOUL_TRANSFORM = 52490, // approx 35%
+ 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
+
+};
+
+struct MANGOS_DLL_DECL mob_scarlet_minerAI : public ScriptedAI
+{
+ mob_scarlet_minerAI(Creature *pCreature) : ScriptedAI(pCreature)
+ {
+ // hack spell 52481
+ SpellEntry *TempSpell = (SpellEntry*)GetSpellStore()->LookupEntry(SPELL_GIFT_OF_THE_HARVESTER_MISSILE);
+ if (TempSpell && TempSpell->EffectImplicitTargetB[0] != 16)
+ {
+ TempSpell->EffectImplicitTargetB[0] = 16;
+ TempSpell->EffectImplicitTargetB[1] = 87;
+ TempSpell->EffectImplicitTargetB[2] = 16;
+ }
+ }
+
+ 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(((Player*)pCaster)->GetQuestStatus(12698) == QUEST_STATUS_INCOMPLETE)
+ {
+ if (rand()%100 < 35)
+ {
+ 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());
+
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->RemoveCorpse();
+ }
+ }
+ }
+};
+
+/*######
+## 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 = 10, // how many of defender
+ ENCOUNTER_EARTHSHATTER_NUMBER = 10, // 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_WARRIOR_NUMBER = 2, // how many of warrior
+ ENCOUNTER_TOTAL_DAWN = 300, // Total number
+ ENCOUNTER_TOTAL_SCOURGE = 10000,
+
+ WORLD_STATE_REMAINS = 3592,
+ WORLD_STATE_COUNTDOWN = 3603,
+ WORLD_STATE_EVENT_BEGIN = 3605,
+
+ SAY_LIGHT_OF_DAWN01 = -1609201, // pre text
+ SAY_LIGHT_OF_DAWN02 = -1609202,
+ SAY_LIGHT_OF_DAWN03 = -1609203,
+ SAY_LIGHT_OF_DAWN04 = -1609204, // intro
+ SAY_LIGHT_OF_DAWN05 = -1609205,
+ SAY_LIGHT_OF_DAWN06 = -1609206,
+ SAY_LIGHT_OF_DAWN07 = -1609207, // During the fight - Korfax, Champion of the Light
+ SAY_LIGHT_OF_DAWN08 = -1609208, // Lord Maxwell Tyrosus
+ SAY_LIGHT_OF_DAWN09 = -1609209, // Highlord Darion Mograine
+ SAY_LIGHT_OF_DAWN10 = -1609210,
+ SAY_LIGHT_OF_DAWN11 = -1609211,
+ SAY_LIGHT_OF_DAWN12 = -1609212,
+ SAY_LIGHT_OF_DAWN13 = -1609213,
+ SAY_LIGHT_OF_DAWN14 = -1609214,
+ SAY_LIGHT_OF_DAWN15 = -1609215,
+ SAY_LIGHT_OF_DAWN16 = -1609216,
+ SAY_LIGHT_OF_DAWN17 = -1609217,
+ SAY_LIGHT_OF_DAWN18 = -1609218,
+ SAY_LIGHT_OF_DAWN19 = -1609219,
+ SAY_LIGHT_OF_DAWN20 = -1609220,
+ SAY_LIGHT_OF_DAWN21 = -1609221,
+ SAY_LIGHT_OF_DAWN22 = -1609222,
+ SAY_LIGHT_OF_DAWN23 = -1609223,
+ SAY_LIGHT_OF_DAWN24 = -1609224,
+ SAY_LIGHT_OF_DAWN25 = -1609225, // After the fight
+ SAY_LIGHT_OF_DAWN26 = -1609226, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN27 = -1609227, // Highlord Darion Mograine
+ SAY_LIGHT_OF_DAWN28 = -1609228, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN29 = -1609229, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN30 = -1609230, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN31 = -1609231, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN32 = -1609232, // Highlord Alexandros Mograine
+ SAY_LIGHT_OF_DAWN33 = -1609233, // Highlord Darion Mograine
+ SAY_LIGHT_OF_DAWN34 = -1609234, // Highlord Darion Mograine
+ SAY_LIGHT_OF_DAWN35 = -1609235, // Darion Mograine
+ SAY_LIGHT_OF_DAWN36 = -1609236, // Darion Mograine
+ SAY_LIGHT_OF_DAWN37 = -1609237, // Highlord Alexandros Mograine
+ SAY_LIGHT_OF_DAWN38 = -1609238, // Darion Mograine
+ SAY_LIGHT_OF_DAWN39 = -1609239, // Highlord Alexandros Mograine
+ SAY_LIGHT_OF_DAWN40 = -1609240, // Darion Mograine
+ SAY_LIGHT_OF_DAWN41 = -1609241, // Highlord Alexandros Mograine
+ SAY_LIGHT_OF_DAWN42 = -1609242, // Highlord Alexandros Mograine
+ SAY_LIGHT_OF_DAWN43 = -1609243, // The Lich King
+ SAY_LIGHT_OF_DAWN44 = -1609244, // Highlord Darion Mograine
+ SAY_LIGHT_OF_DAWN45 = -1609245, // The Lich King
+ SAY_LIGHT_OF_DAWN46 = -1609246, // The Lich King
+ SAY_LIGHT_OF_DAWN47 = -1609247, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN48 = -1609248, // The Lich King
+ SAY_LIGHT_OF_DAWN49 = -1609249, // The Lich King
+ SAY_LIGHT_OF_DAWN50 = -1609250, // Lord Maxwell Tyrosus
+ SAY_LIGHT_OF_DAWN51 = -1609251, // The Lich King
+ SAY_LIGHT_OF_DAWN52 = -1609252, // Highlord Darion Mograine
+ SAY_LIGHT_OF_DAWN53 = -1609253, // Highlord Darion Mograine
+ SAY_LIGHT_OF_DAWN54 = -1609254, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN55 = -1609255, // The Lich King
+ SAY_LIGHT_OF_DAWN56 = -1609256, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN57 = -1609257, // The Lich King
+ SAY_LIGHT_OF_DAWN58 = -1609258, // The Lich King
+ SAY_LIGHT_OF_DAWN59 = -1609259, // The Lich King
+ SAY_LIGHT_OF_DAWN60 = -1609260, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN61 = -1609261, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN62 = -1609262, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN63 = -1609263, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN64 = -1609264, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN65 = -1609265, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN66 = -1609266, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN67 = -1609267, // Highlord Tirion Fordring
+ SAY_LIGHT_OF_DAWN68 = -1609268, // Highlord Darion Mograine
+
+ EMOTE_LIGHT_OF_DAWN01 = -1609269, // Emotes
+ EMOTE_LIGHT_OF_DAWN02 = -1609270,
+ EMOTE_LIGHT_OF_DAWN03 = -1609271,
+ EMOTE_LIGHT_OF_DAWN04 = -1609272,
+ EMOTE_LIGHT_OF_DAWN05 = -1609273,
+ EMOTE_LIGHT_OF_DAWN06 = -1609274,
+ EMOTE_LIGHT_OF_DAWN07 = -1609275,
+ EMOTE_LIGHT_OF_DAWN08 = -1609276,
+ EMOTE_LIGHT_OF_DAWN09 = -1609277,
+ EMOTE_LIGHT_OF_DAWN10 = -1609278,
+ EMOTE_LIGHT_OF_DAWN11 = -1609279,
+ EMOTE_LIGHT_OF_DAWN12 = -1609280,
+ EMOTE_LIGHT_OF_DAWN13 = -1609281,
+ EMOTE_LIGHT_OF_DAWN14 = -1609282,
+ EMOTE_LIGHT_OF_DAWN15 = -1609283,
+ EMOTE_LIGHT_OF_DAWN16 = -1609284,
+ EMOTE_LIGHT_OF_DAWN17 = -1609285,
+ EMOTE_LIGHT_OF_DAWN18 = -1609286,
+
+ GO_LIGHT_OF_DAWN = 191330,
+ SPELL_THE_LIGHT_OF_DAWN_Q = 53606, // quest credit
+
+ // ---- Dark Knight npc --------------------
+ // Highlord Darion Mograine
+ NPC_HIGHLORD_DARION_MOGRAINE = 29173,
+ SPELL_ANTI_MAGIC_ZONE1 = 52893,
+ SPELL_DEATH_STRIKE = 53639,
+ SPELL_DEATH_EMBRACE = 53635,
+ SPELL_ICY_TOUCH1 = 49723,
+ SPELL_THE_LIGHT_OF_DAWN = 53658,
+ SPELL_THE_MIGHT_OF_MOGRAINE = 53642, // on players when begins
+ SPELL_UNHOLY_BLIGHT = 53640,
+ SPELL_ALEXANDROS_MOGRAINE_SPAWN = 53667,
+ SPELL_MOGRAINE_CHARGE = 53679,
+ SPELL_ASHBRINGER = 53701,
+
+ // Koltira Deathweaver & Orbaz Bloodbane are using the same abilities
+ NPC_KOLTIRA_DEATHWEAVER = 29199,
+ NPC_ORBAZ_BLOODBANE = 29204, // this guy fleed
+ NPC_THASSARIAN = 29200, // he also does SPELL_THE_LIGHT_OF_DAWN 53658
+ //SPELL_BLOOD_STRIKE = 52374,
+ SPELL_DEATH_GRIP = 49576,
+ //SPELL_ICY_TOUCH = 52372,
+ SPELL_PLAGUE_STRIKE1 = 50668,
+ // all do SPELL_HERO_AGGRO_AURA 53627
+
+ // Lich King
+ NPC_THE_LICH_KING = 29183, // show up at end
+ SPELL_APOCALYPSE = 53210,
+ SPELL_TELEPORT_VISUAL = 52233,
+ SPELL_SOUL_FEAST_ALEX = 53677, // on Alexandros
+ SPELL_SOUL_FEAST_TIRION = 53685, // on Tirion
+ SPELL_ICEBOUND_VISAGE = 53274, // not sure what is it for
+ SPELL_REBUKE = 53680,
+
+ // others
+ NPC_RAMPAGING_ABOMINATION = 29186,
+ SPELL_CLEAVE1 = 53633,
+ SPELL_SCOURGE_HOOK = 50335,
+ SPELL_SCOURGE_AGGRO_AURA = 53624,
+
+ NPC_FLESH_BEHEMOTH = 29190, // giant guy
+ SPELL_STOMP = 53634,
+ SPELL_THUNDERCLAP = 36706,
+ SPELL_HERO_AGGRO_AURA = 53627,
+
+ NPC_ACHERUS_GHOUL = 29219, // just ghoul....
+ SPELL_GHOULPLOSION = 53632,
+
+ NPC_WARRIOR_OF_THE_FROZEN_WASTES = 29206, // use SPELL_CLEAVE 53631
+
+ NPC_HIGHLORD_ALEXANDROS_MOGRAINE = 29227, // ghost
+ NPC_DARION_MOGRAINE = 29228, // ghost
+
+ // ---- Dawn npc --------------------
+ // Highlord Tirion Fordring
+ NPC_HIGHLORD_TIRION_FORDRING = 29175,
+ EQUIP_HIGHLORD_TIRION_FORDRING = 13262,
+ SPELL_LAY_ON_HANDS = 53778,
+ SPELL_REBIRTH_OF_THE_ASHBRINGER = 53702,
+ SPELL_TIRION_CHARGE = 53705,
+ SPELL_TIRION_CHARGE_VISUAL = 53706,
+
+ // others
+ NPC_KORFAX_CHAMPION_OF_THE_LIGHT = 29176,
+ SPELL_CLEAVE = 53631,
+ SPELL_HEROIC_LEAP = 53625,
+
+ NPC_LORD_MAXWELL_TYROSUS = 29178,
+ NPC_LEONID_BARTHALOMEW_THE_REVERED = 29179,
+ NPC_DUKE_NICHOLAS_ZVERENHOFF = 29180,
+
+ NPC_COMMANDER_ELIGOR_DAWNBRINGER = 29177,
+ SPELL_HOLY_LIGHT2 = 37979,
+
+ NPC_RAYNE = 29181,
+ SPELL_REJUVENATION = 20664,
+ SPELL_STARFALL = 20678,
+ SPELL_TRANQUILITY = 25817,
+ SPELL_WRATH = 21807,
+
+ NPC_DEFENDER_OF_THE_LIGHT = 29174, // also does SPELL_HEROIC_LEAP 53625
+ SPELL_HOLY_LIGHT1 = 29427,
+ SPELL_HOLY_STRIKE = 53643,
+ SPELL_HOLY_WRATH = 53638,
+ SPELL_UPPERCUT = 53629,
+
+ NPC_RIMBLAT_EARTHSHATTER = 29182,
+ SPELL_CHAIN_HEAL = 33642,
+ //SPELL_THUNDER = 53630 //spell is annoying and kicking units around
+};
+
+struct Locations
+{
+ float x, y, z, o;
+ uint32 id;
+};
+
+static Locations LightofDawnLoc[]=
+{
+ {2281.335f, -5300.409f, 85.170f, 0}, // 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
+};
+
+struct MANGOS_DLL_DECL npc_highlord_darion_mograineAI : public npc_escortAI
+{
+ npc_highlord_darion_mograineAI(Creature *pCreature) : npc_escortAI(pCreature)
+ {
+ Reset();
+ }
+
+ bool bIsBattle;
+ uint32 uiStep;
+ uint32 uiPhase_timer;
+ uint32 uiFight_duration;
+ uint32 uiTotal_dawn;
+ uint32 uiTotal_scourge;
+ uint32 uiSummon_counter;
+
+ // Darion Mograine
+ uint32 uiAnti_magic_zone;
+ uint32 uiDeath_strike;
+ uint32 uiDeath_embrace;
+ uint32 uiIcy_touch;
+ uint32 uiUnholy_blight;
+ uint32 uiFight_speech;
+ uint32 uiSpawncheck;
+ uint32 uiTargetcheck;
+
+ // Dawn
+ uint64 uiTirionGUID;
+ uint64 uiAlexandrosGUID;
+ uint64 uiDarionGUID;
+ uint64 uiKorfaxGUID;
+ uint64 uiMaxwellGUID;
+ uint64 uiEligorGUID;
+ uint64 uiRayneGUID;
+ uint64 uiDefenderGUID[ENCOUNTER_DEFENDER_NUMBER];
+ uint64 uiEarthshatterGUID[ENCOUNTER_EARTHSHATTER_NUMBER];
+
+ // Death
+ uint64 uiKoltiraGUID;
+ uint64 uiOrbazGUID;
+ uint64 uiThassarianGUID;
+ uint64 uiLichKingGUID;
+ uint64 uiAbominationGUID[ENCOUNTER_ABOMINATION_NUMBER];
+ uint64 uiBehemothGUID[ENCOUNTER_BEHEMOTH_NUMBER];
+ uint64 uiGhoulGUID[ENCOUNTER_GHOUL_NUMBER];
+ uint64 uiWarriorGUID[ENCOUNTER_WARRIOR_NUMBER];
+
+ // Misc
+ uint64 uiDawnofLightGUID;
+
+ void Reset()
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ bIsBattle = false;
+ uiStep = 0;
+ uiPhase_timer = 3000;
+ uiFight_duration = 300000; // 5 minutes
+ uiTotal_dawn = ENCOUNTER_TOTAL_DAWN;
+ uiTotal_scourge = ENCOUNTER_TOTAL_SCOURGE;
+ uiSummon_counter = 0;
+
+ uiDawnofLightGUID = 0;
+
+ uiAnti_magic_zone = 1000 + rand()%5000;
+ uiDeath_strike = 5000 + rand()%5000;
+ uiDeath_embrace = 5000 + rand()%5000;
+ uiIcy_touch = 5000 + rand()%5000;
+ uiUnholy_blight = 5000 + rand()%5000;
+
+ uiFight_speech = 15000;
+ uiSpawncheck = 1000;
+ uiTargetcheck = 10000;
+
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->Mount(25279);
+
+ UpdateWorldState(m_creature->GetMap(), WORLD_STATE_REMAINS, 0);
+ //UpdateWorldState(m_creature->GetMap(), WORLD_STATE_COUNTDOWN, 0);
+ UpdateWorldState(m_creature->GetMap(), WORLD_STATE_EVENT_BEGIN, 0);
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ pTemp->SetDeathState(JUST_DIED);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKorfaxGUID))
+ pTemp->SetDeathState(JUST_DIED);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiMaxwellGUID))
+ pTemp->SetDeathState(JUST_DIED);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEligorGUID))
+ pTemp->SetDeathState(JUST_DIED);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiRayneGUID))
+ pTemp->SetDeathState(JUST_DIED);
+
+ uiTirionGUID = NULL;
+ uiKorfaxGUID = NULL;
+ uiMaxwellGUID = NULL;
+ uiEligorGUID = NULL;
+ uiRayneGUID = NULL;
+
+ 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)
+ {
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEarthshatterGUID[i]))
+ pTemp->SetDeathState(JUST_DIED);
+ uiEarthshatterGUID[i] = 0;
+ }
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKoltiraGUID))
+ pTemp->SetDeathState(JUST_DIED);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiOrbazGUID))
+ pTemp->SetDeathState(JUST_DIED);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiThassarianGUID))
+ pTemp->SetDeathState(JUST_DIED);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ pTemp->SetDeathState(JUST_DIED);
+
+ uiKoltiraGUID = NULL;
+ uiOrbazGUID = NULL;
+ uiThassarianGUID = NULL;
+ uiLichKingGUID = NULL;
+ for(uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i)
+ {
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiAbominationGUID[i]))
+ pTemp->SetDeathState(JUST_DIED);
+ uiAbominationGUID[i] = 0;
+ }
+ for(uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i)
+ {
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiBehemothGUID[i]))
+ pTemp->SetDeathState(JUST_DIED);
+ uiBehemothGUID[i] = 0;
+ }
+ for(uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i)
+ {
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiGhoulGUID[i]))
+ pTemp->SetDeathState(JUST_DIED);
+ uiGhoulGUID[i] = 0;
+ }
+ for(uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i)
+ {
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiWarriorGUID[i]))
+ pTemp->SetDeathState(JUST_DIED);
+ uiWarriorGUID[i] = 0;
+ }
+ }
+ }
+
+ void AttackStart(Unit* who)
+ {
+ if (!who)
+ return;
+
+ if (who == m_creature)
+ return;
+
+ if (m_creature->Attack(who, true))
+ {
+ m_creature->AddThreat(who, 0.0f);
+ m_creature->SetInCombatWith(who);
+ who->SetInCombatWith(m_creature);
+ DoStartMovement(who);
+ }
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ if (!who)
+ return;
+
+ if (who->isTargetableForAttack() && m_creature->IsHostileTo(who))
+ if (m_creature->IsWithinDistInMap(who, 20) && m_creature->IsWithinLOSInMap(who))
+ AttackStart(who);
+ }
+
+ void SetHoldState(bool bOnHold)
+ {
+ SetEscortPaused(bOnHold);
+ }
+
+ void WaypointReached(uint32 i)
+ {
+ switch(i)
+ {
+ case 0:
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ SetHoldState(true);
+ break;
+ case 1:
+ SetHoldState(true);
+
+ if (GameObject* pGo = GetClosestGameObjectWithEntry(m_creature, GO_LIGHT_OF_DAWN, 100.0f)) // make dawn of light effect off
+ {
+ uiDawnofLightGUID = pGo->GetGUID();
+ pGo->SetPhaseMask(0, true);
+ }
+
+ SpawnNPC();
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKorfaxGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN07, pTemp);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiMaxwellGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN08, pTemp);
+
+ for(uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i)
+ NPCChangeTarget(uiGhoulGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i)
+ NPCChangeTarget(uiWarriorGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i)
+ NPCChangeTarget(uiAbominationGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i)
+ NPCChangeTarget(uiBehemothGUID[i]);
+ NPCChangeTarget(uiKoltiraGUID);
+ NPCChangeTarget(uiOrbazGUID);
+ NPCChangeTarget(uiThassarianGUID);
+
+ m_creature->Unmount();
+ 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();
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiThassarianGUID))
+ pTemp->Unmount();
+
+ bIsBattle = true;
+ break;
+ case 2:
+ m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE);
+ DoCast(m_creature, SPELL_THE_LIGHT_OF_DAWN);
+ break;
+ case 3:
+ {
+ Unit* pTirion = m_creature->GetMap()->GetUnit(uiTirionGUID);
+
+ DoScriptText(EMOTE_LIGHT_OF_DAWN05, m_creature);
+ if (m_creature->HasAura(SPELL_THE_LIGHT_OF_DAWN, EFFECT_INDEX_0))
+ 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))
+ 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))
+ pTemp->RemoveAurasDueToSpell(SPELL_THE_LIGHT_OF_DAWN);
+ pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[21].x, LightofDawnLoc[21].y, LightofDawnLoc[21].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKorfaxGUID))
+ {
+ pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[10].x, LightofDawnLoc[10].y, LightofDawnLoc[10].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiMaxwellGUID))
+ {
+ pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[13].x, LightofDawnLoc[13].y, LightofDawnLoc[13].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEligorGUID))
+ {
+ pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[16].x, LightofDawnLoc[16].y, LightofDawnLoc[16].z);
+ }
+ JumpToNextStep(10000);
+ } break;
+ case 4:
+ DoScriptText(SAY_LIGHT_OF_DAWN27, m_creature);
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_KNEEL);
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKoltiraGUID))
+ pTemp->SetStandState(UNIT_STAND_STATE_KNEEL);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiThassarianGUID))
+ pTemp->SetStandState(UNIT_STAND_STATE_KNEEL);
+ SetHoldState(true);
+ break;
+ case 5:
+ DoScriptText(SAY_LIGHT_OF_DAWN33, m_creature);
+ SetHoldState(true);
+ break;
+ case 6:
+ SetHoldState(true);
+ m_creature->HandleEmoteCommand(EMOTE_ONESHOT_SPECIALATTACK1H);
+ JumpToNextStep(1000);
+ break;
+ case 7:
+ SetHoldState(true);
+ JumpToNextStep(2000);
+ break;
+ case 8:
+ m_creature->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP));
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ m_creature->CastSpell(pTemp, SPELL_ASHBRINGER, true);
+ DoScriptText(EMOTE_LIGHT_OF_DAWN14, m_creature);
+ SetHoldState(true);
+ break;
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ npc_escortAI::UpdateAI(diff);
+
+ if (!bIsBattle)
+ {
+ if (uiPhase_timer < diff)
+ {
+ // ******* Before battle *****************************************************************
+ switch(uiStep)
+ {
+ case 0: // countdown
+ //UpdateWorldState(m_creature->GetMap(), WORLD_STATE_COUNTDOWN, 1);
+ 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_EVENT_BEGIN, 1);
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ JumpToNextStep(3000);
+ break;
+
+ case 2:
+ DoScriptText(SAY_LIGHT_OF_DAWN04, m_creature);
+ if (Creature* pKoltira = GetClosestCreatureWithEntry(m_creature, NPC_KOLTIRA_DEATHWEAVER, 50.0f))
+ uiKoltiraGUID = pKoltira->GetGUID();
+ if (Creature* pOrbaz = GetClosestCreatureWithEntry(m_creature, NPC_ORBAZ_BLOODBANE, 50.0f))
+ uiOrbazGUID = pOrbaz->GetGUID();
+ if (Creature* pThassarian = GetClosestCreatureWithEntry(m_creature, NPC_THASSARIAN, 50.0f))
+ uiThassarianGUID = pThassarian->GetGUID();
+ JumpToNextStep(10000);
+ break;
+
+ case 3: // rise
+ DoScriptText(SAY_LIGHT_OF_DAWN05, m_creature);
+ JumpToNextStep(3000);
+ break;
+
+ case 4: // summon ghoul
+ // Dunno whats the summon spell, so workaround
+ DoCast(m_creature, 33271); // shack effect
+ uiPhase_timer = 500;
+ if (uiSummon_counter < ENCOUNTER_GHOUL_NUMBER)
+ {
+ if (Creature* pTemp = m_creature->SummonCreature(NPC_ACHERUS_GHOUL, (m_creature->GetPositionX()-20)+rand()%40, (m_creature->GetPositionY()-20)+rand()%40, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000))
+ {
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->setFaction(2084);
+ uiGhoulGUID[uiSummon_counter] = pTemp->GetGUID();
+ uiSummon_counter++;
+ }
+ }
+ else
+ {
+ uiSummon_counter = 0;
+ uiStep++;
+ }
+ break;
+
+ case 5: // summon abomination
+ DoCast(m_creature, 33271); // shack effect
+ uiPhase_timer = 500;
+ if (uiSummon_counter < ENCOUNTER_ABOMINATION_NUMBER)
+ {
+ if (Creature* pTemp = m_creature->SummonCreature(NPC_RAMPAGING_ABOMINATION, (m_creature->GetPositionX()-20)+rand()%40, (m_creature->GetPositionY()-20)+rand()%40, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000))
+ {
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->setFaction(2084);
+ uiAbominationGUID[uiSummon_counter] = pTemp->GetGUID();
+ uiSummon_counter++;
+ }
+ }
+ else
+ {
+ uiSummon_counter = 0;
+ uiStep++;
+ }
+ break;
+
+ case 6: // summon warrior
+ DoCast(m_creature, 33271); // shack effect
+ uiPhase_timer = 500;
+ if (uiSummon_counter < ENCOUNTER_WARRIOR_NUMBER)
+ {
+ if (Creature* pTemp = m_creature->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, (m_creature->GetPositionX()-20)+rand()%40, (m_creature->GetPositionY()-20)+rand()%40, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000))
+ {
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->setFaction(2084);
+ uiWarriorGUID[uiSummon_counter] = pTemp->GetGUID();
+ uiSummon_counter++;
+ }
+ }
+ else
+ {
+ uiSummon_counter = 0;
+ uiStep++;
+ }
+ break;
+
+ case 7: // summon warrior
+ DoCast(m_creature, 33271); // shack effect
+ uiPhase_timer = 500;
+ if (uiSummon_counter < ENCOUNTER_BEHEMOTH_NUMBER)
+ {
+ if (Creature* pTemp = m_creature->SummonCreature(NPC_FLESH_BEHEMOTH, (m_creature->GetPositionX()-20)+rand()%40, (m_creature->GetPositionY()-20)+rand()%40, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000))
+ {
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->setFaction(2084);
+ uiBehemothGUID[uiSummon_counter] = pTemp->GetGUID();
+ uiSummon_counter++;
+ }
+ }
+ else
+ {
+ uiSummon_counter = 0;
+ uiStep++;
+ }
+ break;
+
+ 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);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKoltiraGUID))
+ {
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiOrbazGUID))
+ {
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiThassarianGUID))
+ {
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z);
+ }
+ for(uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i)
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiAbominationGUID[i]))
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z);
+ for(uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i)
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiBehemothGUID[i]))
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z);
+ for(uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i)
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiGhoulGUID[i]))
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z);
+ for(uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i)
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiWarriorGUID[i]))
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z);
+ JumpToNextStep(5000);
+ break;
+
+ // ******* After battle *****************************************************************
+ case 11: // Tirion starts to speak
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN28, pTemp);
+ JumpToNextStep(21000);
+ break;
+
+ case 12:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN29, pTemp);
+ JumpToNextStep(13000);
+ break;
+
+ case 13:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN30, pTemp);
+ JumpToNextStep(13000);
+ break;
+
+ case 14:
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_STAND);
+ DoScriptText(SAY_LIGHT_OF_DAWN31, m_creature);
+ JumpToNextStep(7000);
+ break;
+
+ case 15: // summon gate
+ if (Creature* pTemp = m_creature->SummonCreature(NPC_HIGHLORD_ALEXANDROS_MOGRAINE, LightofDawnLoc[22].x, LightofDawnLoc[22].y, LightofDawnLoc[22].z, LightofDawnLoc[22].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000))
+ {
+ pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pTemp->CastSpell(pTemp, SPELL_ALEXANDROS_MOGRAINE_SPAWN, true);
+ DoScriptText(EMOTE_LIGHT_OF_DAWN06, pTemp);
+ uiAlexandrosGUID = pTemp->GetGUID();
+ }
+ JumpToNextStep(4000);
+ break;
+
+ case 16: // Alexandros out
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiAlexandrosGUID))
+ {
+ pTemp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ 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
+ JumpToNextStep(5000);
+ break;
+
+ case 17:
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_KNEEL);
+ DoScriptText(SAY_LIGHT_OF_DAWN34, m_creature);
+ JumpToNextStep(5000);
+ break;
+
+ case 18: // Darion's spirit out
+ if (Creature* pTemp = m_creature->SummonCreature(NPC_DARION_MOGRAINE, LightofDawnLoc[24].x, LightofDawnLoc[24].y, LightofDawnLoc[24].z, LightofDawnLoc[24].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000))
+ {
+ DoScriptText(SAY_LIGHT_OF_DAWN35, pTemp);
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ uiDarionGUID = pTemp->GetGUID();
+ }
+ JumpToNextStep(4000);
+ break;
+
+ case 19: // runs to father
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiDarionGUID))
+ {
+ DoScriptText(EMOTE_LIGHT_OF_DAWN07, pTemp);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[25].x, LightofDawnLoc[25].y, LightofDawnLoc[25].z);
+ }
+ JumpToNextStep(4000);
+ break;
+
+ case 20:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiDarionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN36, pTemp);
+ JumpToNextStep(4000);
+ break;
+
+ case 21:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiDarionGUID))
+ DoScriptText(EMOTE_LIGHT_OF_DAWN08, pTemp);
+ JumpToNextStep(4000);
+ break;
+
+ case 22:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiAlexandrosGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN37, pTemp);
+ JumpToNextStep(8000);
+ break;
+
+ case 23:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiDarionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN38, pTemp);
+ JumpToNextStep(8000);
+ break;
+
+ case 24:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiAlexandrosGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN39, pTemp);
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID)) // Tirion moves forward here
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[1].x, LightofDawnLoc[1].y, LightofDawnLoc[1].z);
+
+ JumpToNextStep(15000);
+ break;
+
+ case 25:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiDarionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN40, pTemp);
+ JumpToNextStep(11000);
+ break;
+
+ case 26:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiAlexandrosGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN41, pTemp);
+ JumpToNextStep(5000);
+ break;
+
+ case 27:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiDarionGUID))
+ pTemp->SetDeathState(JUST_DIED);
+ JumpToNextStep(24000);
+ break;
+
+ case 28:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiAlexandrosGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN42, pTemp);
+ JumpToNextStep(6000);
+ break;
+
+ case 29: // lich king spawns
+ if (Creature* pTemp = m_creature->SummonCreature(NPC_THE_LICH_KING, LightofDawnLoc[26].x, LightofDawnLoc[26].y, LightofDawnLoc[26].z, LightofDawnLoc[26].o, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000))
+ {
+ DoScriptText(SAY_LIGHT_OF_DAWN43, pTemp);
+ uiLichKingGUID = pTemp->GetGUID();
+ if (Unit* pAlex = m_creature->GetMap()->GetUnit(uiAlexandrosGUID))
+ pTemp->CastSpell(pAlex, SPELL_SOUL_FEAST_ALEX, false);
+ }
+ JumpToNextStep(2000);
+ break;
+
+ case 30:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiAlexandrosGUID)) // remove him
+ {
+ DoScriptText(EMOTE_LIGHT_OF_DAWN09, pTemp);
+ pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ {
+ pTemp->InterruptNonMeleeSpells(false);
+ DoScriptText(SAY_LIGHT_OF_DAWN45, pTemp);
+ }
+ JumpToNextStep(3000);
+ break;
+
+ case 31:
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_STAND);
+ DoScriptText(EMOTE_LIGHT_OF_DAWN10, m_creature);
+ DoScriptText(SAY_LIGHT_OF_DAWN44, m_creature);
+ JumpToNextStep(3000);
+ break;
+
+ case 32:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[27].x, LightofDawnLoc[27].y, LightofDawnLoc[27].z);
+ JumpToNextStep(6000);
+ break;
+
+ case 33: // Darion supports to jump to lich king here
+// disable if (Creature* pTemp = m_creature->GetMap()->GetCreature(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);
+ JumpToNextStep(0);
+ break;
+
+ case 35: // Lich king counterattacks
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ {
+ pTemp->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
+ DoScriptText(SAY_LIGHT_OF_DAWN46, pTemp);
+ }
+ m_creature->SetSpeedRate(MOVE_RUN, 6.0f);
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_DEAD);
+ SetHoldState(false); // Darion got kicked by lich king
+ JumpToNextStep(0);
+ break;
+
+ case 37: // Lich king counterattacks
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_KNEEL);
+ JumpToNextStep(3000);
+ break;
+
+ case 38:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN47, pTemp);
+ JumpToNextStep(8000);
+ break;
+
+ case 39:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN48, pTemp);
+ JumpToNextStep(15000);
+ break;
+
+ case 40:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN49, pTemp);
+ JumpToNextStep(17000);
+ break;
+
+ case 41: // Lich king - Apocalypse
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ {
+ DoScriptText(EMOTE_LIGHT_OF_DAWN11, pTemp);
+ DoScriptText(SAY_LIGHT_OF_DAWN51, pTemp);
+ if (Creature* pTirion = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ {
+ ((Unit*)pTirion)->SetStandState(UNIT_STAND_STATE_KNEEL);
+ //pTemp->CastSpell(pTirion, SPELL_APOCALYPSE, false); // not working
+ pTemp->CastSpell(pTirion, SPELL_SOUL_FEAST_TIRION, false);
+ DoScriptText(EMOTE_LIGHT_OF_DAWN12, pTirion);
+ }
+ }
+ JumpToNextStep(2000);
+ break;
+
+ case 42: // Maxwell yells for attack
+ {
+ float fLichPositionX, fLichPositionY, fLichPositionZ;
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ {
+ fLichPositionX = pTemp->GetPositionX();
+ fLichPositionY = pTemp->GetPositionY();
+ fLichPositionZ = pTemp->GetPositionZ();
+ }
+
+ if (fLichPositionX && fLichPositionY)
+ {
+ Creature* pTemp;
+ if (pTemp = m_creature->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000))
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->SetSpeedRate(MOVE_RUN, 2.0f);
+ pTemp->setFaction(m_creature->getFaction());
+ pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
+ uiDefenderGUID[0] = pTemp->GetGUID();
+ }
+
+ if (pTemp = m_creature->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000))
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->SetSpeedRate(MOVE_RUN, 2.0f);
+ pTemp->setFaction(m_creature->getFaction());
+ pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
+ uiEarthshatterGUID[0] = pTemp->GetGUID();
+ }
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiMaxwellGUID))
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->SetSpeedRate(MOVE_RUN, 2.0f);
+ pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
+ DoScriptText(SAY_LIGHT_OF_DAWN50, pTemp);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKorfaxGUID))
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->SetSpeedRate(MOVE_RUN, 2.0f);
+ pTemp->HandleEmoteCommand(EMOTE_STATE_ATTACK_UNARMED);
+ pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEligorGUID))
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->SetSpeedRate(MOVE_RUN, 2.0f);
+ pTemp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
+ }
+ }
+ JumpToNextStep(4500);
+ break;
+
+ case 43: // They all got kicked
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ DoScriptText(EMOTE_LIGHT_OF_DAWN13, pTemp);
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiMaxwellGUID))
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
+ pTemp->SetSpeedRate(MOVE_RUN, 6.0f);
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_DEAD);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[14].x, LightofDawnLoc[14].y, LightofDawnLoc[14].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKorfaxGUID))
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
+ pTemp->SetSpeedRate(MOVE_RUN, 6.0f);
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_DEAD);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[11].x, LightofDawnLoc[11].y, LightofDawnLoc[11].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEligorGUID))
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
+ pTemp->SetSpeedRate(MOVE_RUN, 6.0f);
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_DEAD);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[17].x, LightofDawnLoc[17].y, LightofDawnLoc[17].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiDefenderGUID[0]))
+ {
+ pTemp->SetSpeedRate(MOVE_RUN, 6.0f);
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_DEAD);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEarthshatterGUID[0]))
+ {
+ pTemp->SetSpeedRate(MOVE_RUN, 6.0f);
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_DEAD);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].x+rand()%10, LightofDawnLoc[0].y+rand()%10, LightofDawnLoc[0].z);
+ }
+ JumpToNextStep(3000);
+ break;
+
+ case 44: // make them stand up
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiMaxwellGUID))
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_STAND);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKorfaxGUID))
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_STAND);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEligorGUID))
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_STAND);
+ JumpToNextStep(1000);
+ break;
+
+ case 45:
+ DoScriptText(SAY_LIGHT_OF_DAWN52, m_creature);
+ JumpToNextStep(5000);
+ break;
+
+ case 46: // Darion stand up, "not today"
+ m_creature->SetSpeedRate(MOVE_RUN, 1.0f);
+ 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
+ JumpToNextStep(7000);
+ break;
+
+ case 47: // Ashbringer rebirth
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_KNEEL);
+ DoScriptText(EMOTE_LIGHT_OF_DAWN15, m_creature);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ {
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_STAND);
+ pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_HIGHLORD_TIRION_FORDRING));
+ pTemp->CastSpell(pTemp, SPELL_REBIRTH_OF_THE_ASHBRINGER, false);
+ }
+ JumpToNextStep(1000);
+ break;
+
+ case 48: // Show the cleansing effect (dawn of light)
+ if (GameObject* pGo = m_creature->GetMap()->GetGameObject(uiDawnofLightGUID))
+ pGo->SetPhaseMask(128, true);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ {
+ if (pTemp->HasAura(SPELL_REBIRTH_OF_THE_ASHBRINGER, EFFECT_INDEX_0))
+ pTemp->RemoveAurasDueToSpell(SPELL_REBIRTH_OF_THE_ASHBRINGER);
+ pTemp->CastSpell(pTemp, 41542, false); // workarounds, light expoded, makes it cool
+ pTemp->HandleEmoteCommand(EMOTE_ONESHOT_ROAR);
+ }
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ pTemp->InterruptNonMeleeSpells(false);
+ JumpToNextStep(2500);
+ break;
+
+ case 49:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN54, pTemp);
+ JumpToNextStep(4000);
+ break;
+
+ case 50:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN55, pTemp);
+ JumpToNextStep(5000);
+ break;
+
+ case 51:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN56, pTemp);
+ JumpToNextStep(1000);
+ break;
+
+ case 52: // Tiron charges
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ {
+ DoScriptText(EMOTE_LIGHT_OF_DAWN16, pTemp);
+ pTemp->CastSpell(pTemp, SPELL_TIRION_CHARGE, false); // jumping charge
+ 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, 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;
+
+ case 53:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN57, pTemp);
+ JumpToNextStep(1000);
+ 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(4000);
+ break;
+
+ case 55:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_KNEEL);
+ JumpToNextStep(2000);
+ break;
+
+ case 56:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ ((Unit*)pTemp)->SetStandState(UNIT_STAND_STATE_STAND);
+ JumpToNextStep(1500);
+ break;
+
+ case 57:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN58, pTemp);
+ JumpToNextStep(10000);
+ break;
+
+ case 58:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN59, pTemp);
+ JumpToNextStep(10000);
+ break;
+
+ case 59:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID))
+ pTemp->CastSpell(pTemp, SPELL_TELEPORT_VISUAL, false);
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID)) // Tirion runs to Darion
+ {
+ pTemp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
+ pTemp->SetSpeedRate(MOVE_RUN, 1.0f);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[6].x, LightofDawnLoc[6].y, LightofDawnLoc[6].z);
+ }
+ JumpToNextStep(2500);
+ break;
+
+ case 60:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiLichKingGUID)) // Lich king disappears here
+ {
+ DoScriptText(EMOTE_LIGHT_OF_DAWN17, pTemp);
+ pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ JumpToNextStep(10000);
+ break;
+
+ case 61:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN60, pTemp);
+ JumpToNextStep(3000);
+ break;
+
+ case 62:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ {
+ pTemp->AddSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[7].x, LightofDawnLoc[7].y, LightofDawnLoc[7].z);
+ }
+ JumpToNextStep(5500);
+ break;
+
+ case 63:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ {
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[8].x, LightofDawnLoc[8].y, LightofDawnLoc[8].z);
+ DoScriptText(SAY_LIGHT_OF_DAWN61, pTemp);
+ }
+ JumpToNextStep(15000);
+ break;
+
+ case 64:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN62, pTemp);
+ JumpToNextStep(7000);
+ break;
+
+ case 65:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN63, pTemp);
+ JumpToNextStep(10000);
+ break;
+
+ case 66:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN64, pTemp);
+ JumpToNextStep(11000);
+ break;
+
+ case 67:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN65, pTemp);
+ JumpToNextStep(10000);
+ break;
+
+ case 68:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN66, pTemp);
+ JumpToNextStep(8000);
+ break;
+
+ case 69:
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN67, pTemp);
+ JumpToNextStep(10000);
+ break;
+
+ case 70:
+ ((Unit*)m_creature)->SetStandState(UNIT_STAND_STATE_STAND);
+ DoScriptText(SAY_LIGHT_OF_DAWN68, m_creature);
+ JumpToNextStep(10000);
+ break;
+
+ case 71:
+ if (GameObject* pGo = m_creature->GetMap()->GetGameObject(uiDawnofLightGUID)) // Turn off dawn of light
+ pGo->SetPhaseMask(0, true);
+
+ {
+ Map *map = m_creature->GetMap(); // search players with in 50 yards for quest credit
+ Map::PlayerList const &PlayerList = map->GetPlayers();
+ if (!PlayerList.isEmpty())
+ {
+ for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
+ if (i->getSource()->isAlive() && m_creature->IsWithinDistInMap(i->getSource(), 50))
+ i->getSource()->CastSpell(i->getSource(), SPELL_THE_LIGHT_OF_DAWN_Q, false);
+ }
+ }
+ m_creature->SetVisibility(VISIBILITY_OFF); // respawns another Darion for quest turn in
+ m_creature->SummonCreature(NPC_HIGHLORD_DARION_MOGRAINE, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000);
+ JumpToNextStep(1000);
+ break;
+
+ case 72:
+ SetHoldState(false); // Escort ends
+ JumpToNextStep(0);
+ break;
+ }
+
+ }else uiPhase_timer -= diff;
+ }
+
+ // ******* During battle *****************************************************************
+ else
+ {
+ if (uiAnti_magic_zone < diff)
+ {
+ DoCast(m_creature, SPELL_ANTI_MAGIC_ZONE1);
+ uiAnti_magic_zone = 25000 + rand()%5000;
+ }else uiAnti_magic_zone -= diff;
+
+ if (uiDeath_strike < diff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_DEATH_STRIKE);
+ uiDeath_strike = 5000 + rand()%5000;
+ }else uiDeath_strike -= diff;
+
+ if (uiDeath_embrace < diff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_DEATH_EMBRACE);
+ uiDeath_embrace = 5000 + rand()%5000;
+ }else uiDeath_embrace -= diff;
+
+ if (uiIcy_touch < diff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_ICY_TOUCH1);
+ uiIcy_touch = 5000 + rand()%5000;
+ }else uiIcy_touch -= diff;
+
+ if (uiUnholy_blight < diff)
+ {
+ DoCast(m_creature->getVictim(), SPELL_UNHOLY_BLIGHT);
+ uiUnholy_blight = 5000 + rand()%5000;
+ }else uiUnholy_blight -= diff;
+
+ if (uiFight_speech < diff)
+ {
+ switch(rand()%15)
+ {
+ case 0: DoScriptText(SAY_LIGHT_OF_DAWN09, m_creature);break;
+ case 1: DoScriptText(SAY_LIGHT_OF_DAWN10, m_creature);break;
+ case 2: DoScriptText(SAY_LIGHT_OF_DAWN11, m_creature);break;
+ case 3: DoScriptText(SAY_LIGHT_OF_DAWN12, m_creature);break;
+ case 4: DoScriptText(SAY_LIGHT_OF_DAWN13, m_creature);break;
+ case 5: DoScriptText(SAY_LIGHT_OF_DAWN14, m_creature);break;
+ case 6: DoScriptText(SAY_LIGHT_OF_DAWN15, m_creature);break;
+ case 7: DoScriptText(SAY_LIGHT_OF_DAWN16, m_creature);break;
+ case 8: DoScriptText(SAY_LIGHT_OF_DAWN17, m_creature);break;
+ case 9: DoScriptText(SAY_LIGHT_OF_DAWN18, m_creature);break;
+ case 10: DoScriptText(SAY_LIGHT_OF_DAWN19, m_creature);break;
+ case 11: DoScriptText(SAY_LIGHT_OF_DAWN20, m_creature);break;
+ case 12: DoScriptText(SAY_LIGHT_OF_DAWN21, m_creature);break;
+ case 13: DoScriptText(SAY_LIGHT_OF_DAWN22, m_creature);break;
+ case 14: DoScriptText(SAY_LIGHT_OF_DAWN23, m_creature);break;
+ case 15: DoScriptText(SAY_LIGHT_OF_DAWN24, m_creature);break;
+ }
+ uiFight_speech = 15000 + rand()%5000;
+ }else uiFight_speech -= diff;
+
+ // Check spawns
+ if (uiSpawncheck < diff)
+ {
+ SpawnNPC();
+ uiSpawncheck = 1000;
+ }else uiSpawncheck -= diff;
+
+ // Check targets
+ if (uiTargetcheck < diff)
+ {
+ for(uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i)
+ NPCChangeTarget(uiGhoulGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i)
+ NPCChangeTarget(uiWarriorGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i)
+ NPCChangeTarget(uiAbominationGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i)
+ NPCChangeTarget(uiBehemothGUID[i]);
+ NPCChangeTarget(uiKoltiraGUID);
+ NPCChangeTarget(uiOrbazGUID);
+ NPCChangeTarget(uiThassarianGUID);
+
+ uiTargetcheck = 10000;
+ }else uiTargetcheck -= diff;
+
+ // Battle end
+ if (uiFight_duration < diff + 5000)
+ {
+ if (!uiTirionGUID)
+ if (Creature* pTemp = m_creature->SummonCreature(NPC_HIGHLORD_TIRION_FORDRING, LightofDawnLoc[0].x, LightofDawnLoc[0].y, LightofDawnLoc[0].z, 1.528f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000))
+ {
+ pTemp->setFaction(m_creature->getFaction());
+ pTemp->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 0, uint32(EQUIP_UNEQUIP));
+ DoScriptText(SAY_LIGHT_OF_DAWN25, pTemp);
+ uiTirionGUID = pTemp->GetGUID();
+ }
+ }
+ if (uiFight_duration < diff)
+ {
+ bIsBattle = false;
+ uiFight_duration = 300000;
+
+ if (m_creature->HasAura(SPELL_THE_MIGHT_OF_MOGRAINE, EFFECT_INDEX_0))
+ m_creature->RemoveAurasDueToSpell(SPELL_THE_MIGHT_OF_MOGRAINE);
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(true);
+ m_creature->InterruptNonMeleeSpells(false);
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+
+ for(uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i)
+ DespawnNPC(uiDefenderGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i)
+ DespawnNPC(uiEarthshatterGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i)
+ DespawnNPC(uiAbominationGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i)
+ DespawnNPC(uiBehemothGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_GHOUL_NUMBER; ++i)
+ DespawnNPC(uiGhoulGUID[i]);
+ for(uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i)
+ DespawnNPC(uiWarriorGUID[i]);
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKorfaxGUID))
+ {
+ pTemp->RemoveAllAuras();
+ pTemp->DeleteThreatList();
+ pTemp->CombatStop(true);
+ pTemp->AttackStop();
+ pTemp->setFaction(m_creature->getFaction());
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[9].x, LightofDawnLoc[9].y, LightofDawnLoc[9].z);
+ }
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiMaxwellGUID))
+ {
+ pTemp->RemoveAllAuras();
+ pTemp->DeleteThreatList();
+ pTemp->CombatStop(true);
+ pTemp->AttackStop();
+ pTemp->setFaction(m_creature->getFaction());
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[12].x, LightofDawnLoc[12].y, LightofDawnLoc[12].z);
+ }
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiEligorGUID))
+ {
+ pTemp->RemoveAllAuras();
+ pTemp->DeleteThreatList();
+ pTemp->CombatStop(true);
+ pTemp->AttackStop();
+ pTemp->setFaction(m_creature->getFaction());
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[15].x, LightofDawnLoc[15].y, LightofDawnLoc[15].z);
+ }
+ DespawnNPC(uiRayneGUID);
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiKoltiraGUID))
+ {
+ pTemp->RemoveAllAuras();
+ pTemp->DeleteThreatList();
+ pTemp->CombatStop(true);
+ pTemp->AttackStop();
+ pTemp->setFaction(m_creature->getFaction());
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[18].x, LightofDawnLoc[18].y, LightofDawnLoc[18].z);
+ pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false);
+ }
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiOrbazGUID))
+ DoScriptText(EMOTE_LIGHT_OF_DAWN04, pTemp);
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiThassarianGUID))
+ {
+ pTemp->RemoveAllAuras();
+ pTemp->DeleteThreatList();
+ pTemp->CombatStop(true);
+ pTemp->AttackStop();
+ pTemp->setFaction(m_creature->getFaction());
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[20].x, LightofDawnLoc[20].y, LightofDawnLoc[20].z);
+ pTemp->CastSpell(pTemp, SPELL_THE_LIGHT_OF_DAWN, false);
+ }
+
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(uiTirionGUID))
+ DoScriptText(SAY_LIGHT_OF_DAWN26, pTemp);
+
+ SetHoldState(false);
+
+ }else uiFight_duration -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+ }
+
+ void JumpToNextStep(uint32 uiTimer)
+ {
+ uiPhase_timer = uiTimer;
+ uiStep++;
+ }
+
+ void NPCChangeTarget(uint64 ui_GUID)
+ {
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(ui_GUID))
+ if (pTemp->isAlive())
+ if (Unit* pTarger = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ if (pTarger->isAlive())
+ {
+ ((Creature*)pTemp)->AddThreat(pTarger, 0.0f);
+ ((Creature*)pTemp)->AI()->AttackStart(pTarger);
+ ((Creature*)pTemp)->SetInCombatWith(pTarger);
+ pTarger->SetInCombatWith(pTemp);
+ }
+ }
+
+ void SpawnNPC()
+ {
+ Creature* pTemp = NULL;
+
+ // Death
+ 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();
+ }
+ }
+ for(uint8 i = 0; i < ENCOUNTER_ABOMINATION_NUMBER; ++i)
+ {
+ if (!(pTemp = m_creature->GetMap()->GetCreature(uiAbominationGUID[i])))
+ {
+ pTemp = m_creature->SummonCreature(NPC_WARRIOR_OF_THE_FROZEN_WASTES, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000);
+ pTemp->setFaction(2084);
+ uiAbominationGUID[i] = pTemp->GetGUID();
+ }
+ }
+ for(uint8 i = 0; i < ENCOUNTER_WARRIOR_NUMBER; ++i)
+ {
+ if (!(pTemp = m_creature->GetMap()->GetCreature(uiWarriorGUID[i])))
+ {
+ pTemp = m_creature->SummonCreature(NPC_RAMPAGING_ABOMINATION, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000);
+ pTemp->setFaction(2084);
+ uiWarriorGUID[i] = pTemp->GetGUID();
+ }
+ }
+ for(uint8 i = 0; i < ENCOUNTER_BEHEMOTH_NUMBER; ++i)
+ {
+ if (!(pTemp = m_creature->GetMap()->GetCreature(uiBehemothGUID[i])))
+ {
+ pTemp = m_creature->SummonCreature(NPC_FLESH_BEHEMOTH, LightofDawnLoc[0].x+rand()%30, LightofDawnLoc[0].y+rand()%30, LightofDawnLoc[0].z, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000);
+ pTemp->setFaction(2084);
+ uiBehemothGUID[i] = pTemp->GetGUID();
+ }
+ }
+
+ // Dawn
+ for(uint8 i = 0; i < ENCOUNTER_DEFENDER_NUMBER; ++i)
+ {
+ if (!(pTemp = m_creature->GetMap()->GetCreature(uiDefenderGUID[i])))
+ {
+ 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);
+ uiDefenderGUID[i] = pTemp->GetGUID();
+ }
+ }
+ for(uint8 i = 0; i < ENCOUNTER_EARTHSHATTER_NUMBER; ++i)
+ {
+ if (!(pTemp = m_creature->GetMap()->GetCreature(uiEarthshatterGUID[i])))
+ {
+ 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);
+ uiEarthshatterGUID[i] = pTemp->GetGUID();
+ }
+ }
+ if (!(pTemp = m_creature->GetMap()->GetCreature(uiKorfaxGUID)))
+ {
+ 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);
+ 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);
+ 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);
+ 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);
+ uiRayneGUID = pTemp->GetGUID();
+ }
+ }
+
+ void DespawnNPC(uint64 pGUID)
+ {
+ if (Creature* pTemp = m_creature->GetMap()->GetCreature(pGUID))
+ if (pTemp->isAlive())
+ {
+ pTemp->SetVisibility(VISIBILITY_OFF);
+ pTemp->DealDamage(pTemp, pTemp->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ }
+};
+bool GossipHello_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu( pCreature->GetGUID() );
+
+ if (pPlayer->GetQuestStatus(12801) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM( 0, "I am ready.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_highlord_darion_mograine(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch (uiAction)
+ {
+ 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());
+ break;
+ }
+ return true;
+}
+/*######
+## npc the lich king in dawn of light
+######*/
+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 sample, just don't make them aggreesive
+ void UpdateAI(const uint32 diff) { return; }
+ void JustDied(Unit* killer) {}
+};
+
+CreatureAI* GetAI_npc_crusade_persuaded(Creature* pCreature)
+{
+ return new npc_crusade_persuadedAI (pCreature);
+}
+
+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);
+}
+
+//CreatureAI* GetAI_mob_scarlet_courier_controller(Creature* pCreature)
+//{
+// return new mob_scarlet_courier_controllerAI (pCreature);
+//}
+//
+//CreatureAI* GetAI_mob_scarlet_courier(Creature* pCreature)
+//{
+// return new mob_scarlet_courierAI (pCreature);
+//}
+
+CreatureAI* GetAI_mob_high_inquisitor_valroth(Creature* pCreature)
+{
+ return new mob_high_inquisitor_valrothAI (pCreature);
+}
+
+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);
+}
+
+// Hack until Vehicle Support
+bool GossipHello_scarlet_cannon(Player* pPlayer, 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;
+}
+
+void AddSC_ebon_hold()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_a_special_surprise";
+ pNewScript->GetAI = &GetAI_npc_a_special_surprise;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_death_knight_initiate";
+ pNewScript->GetAI = &GetAI_npc_death_knight_initiate;
+ pNewScript->pGossipHello = &GossipHello_npc_death_knight_initiate;
+ pNewScript->pGossipSelect = &GossipSelect_npc_death_knight_initiate;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_koltira_deathweaver";
+ pNewScript->GetAI = &GetAI_npc_koltira_deathweaver;
+ pNewScript->pQuestAccept = &QuestAccept_npc_koltira_deathweaver;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_unworthy_initiate";
+ pNewScript->GetAI = &GetAI_npc_unworthy_initiate;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_unworthy_initiate_anchor";
+ pNewScript->GetAI = &GetAI_npc_unworthy_initiate_anchor;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "go_acherus_soul_prison";
+ pNewScript->pGOHello = &GOHello_go_acherus_soul_prison;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_eye_of_acherus";
+ pNewScript->GetAI = &GetAI_npc_eye_of_acherus;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_crusade_persuaded";
+ pNewScript->GetAI = &GetAI_npc_crusade_persuaded;
+ 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_controller";
+ pNewScript->GetAI = &GetAI_mob_scarlet_courier_controller;
+ 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->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_highlord_darion_mograine";
+ pNewScript->GetAI = &GetAI_npc_highlord_darion_mograine;
+ pNewScript->pGossipHello = &GossipHello_npc_highlord_darion_mograine;
+ pNewScript->pGossipSelect = &GossipSelect_npc_highlord_darion_mograine;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_the_lich_king_tirion_dawn";
+ pNewScript->GetAI = &GetAI_npc_the_lich_king_tirion_dawn;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "scarlet_cannon";
+ pNewScript->pGossipHello = &GossipHello_scarlet_cannon;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_acherus_deathcharger";
+ pNewScript->pGossipHello = &GossipHello_npc_acherus_deathcharger;
+ 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->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp
new file mode 100644
index 0000000..a8a5d12
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp
@@ -0,0 +1,127 @@
+/* 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_Arcanist_Doan
+SD%Complete: 100
+SDComment:
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_AGGRO = -1189019,
+ SAY_SPECIALAE = -1189020,
+
+ SPELL_POLYMORPH = 13323,
+ SPELL_AOESILENCE = 8988,
+ SPELL_ARCANEEXPLOSION = 9433,
+ SPELL_FIREAOE = 9435,
+ SPELL_ARCANEBUBBLE = 9438,
+};
+
+struct MANGOS_DLL_DECL boss_arcanist_doanAI : public ScriptedAI
+{
+ boss_arcanist_doanAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Polymorph_Timer;
+ uint32 AoESilence_Timer;
+ uint32 ArcaneExplosion_Timer;
+ bool bCanDetonate;
+ bool bShielded;
+
+ void Reset()
+ {
+ Polymorph_Timer = 20000;
+ AoESilence_Timer = 15000;
+ ArcaneExplosion_Timer = 3000;
+ bCanDetonate = false;
+ bShielded = false;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (bShielded && bCanDetonate)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_FIREAOE);
+ bCanDetonate = false;
+ }
+
+ if (m_creature->HasAura(SPELL_ARCANEBUBBLE))
+ return;
+
+ //If we are <50% hp cast Arcane Bubble
+ if (!bShielded && m_creature->GetHealthPercent() <= 50.0f)
+ {
+ //wait if we already casting
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ return;
+
+ DoScriptText(SAY_SPECIALAE, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_ARCANEBUBBLE);
+
+ bCanDetonate = true;
+ bShielded = true;
+ }
+
+ if (Polymorph_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1))
+ DoCastSpellIfCan(target,SPELL_POLYMORPH);
+
+ Polymorph_Timer = 20000;
+ }else Polymorph_Timer -= diff;
+
+ //AoESilence_Timer
+ if (AoESilence_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_AOESILENCE);
+ AoESilence_Timer = urand(15000, 20000);
+ }else AoESilence_Timer -= diff;
+
+ //ArcaneExplosion_Timer
+ if (ArcaneExplosion_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ARCANEEXPLOSION);
+ ArcaneExplosion_Timer = 8000;
+ }else ArcaneExplosion_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_arcanist_doan(Creature* pCreature)
+{
+ return new boss_arcanist_doanAI(pCreature);
+}
+
+void AddSC_boss_arcanist_doan()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_arcanist_doan";
+ newscript->GetAI = &GetAI_boss_arcanist_doan;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp
new file mode 100644
index 0000000..a323c1a
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp
@@ -0,0 +1,93 @@
+/* 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_Azshir_the_Sleepless
+SD%Complete: 80
+SDComment:
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_CALLOFTHEGRAVE 17831
+#define SPELL_TERRIFY 7399
+#define SPELL_SOULSIPHON 7290
+
+struct MANGOS_DLL_DECL boss_azshir_the_sleeplessAI : public ScriptedAI
+{
+ boss_azshir_the_sleeplessAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 SoulSiphon_Timer;
+ uint32 CallOftheGrave_Timer;
+ uint32 Terrify_Timer;
+
+ void Reset()
+ {
+ SoulSiphon_Timer = 1;
+ CallOftheGrave_Timer = 30000;
+ Terrify_Timer = 20000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //If we are <50% hp cast Soul Siphon rank 1
+ if (m_creature->GetHealthPercent() <= 50.0f && !m_creature->IsNonMeleeSpellCasted(false))
+ {
+ //SoulSiphon_Timer
+ if (SoulSiphon_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SOULSIPHON);
+ return;
+
+ SoulSiphon_Timer = 20000;
+ }else SoulSiphon_Timer -= diff;
+ }
+
+ //CallOfTheGrave_Timer
+ if (CallOftheGrave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CALLOFTHEGRAVE);
+ CallOftheGrave_Timer = 30000;
+ }else CallOftheGrave_Timer -= diff;
+
+ //Terrify_Timer
+ if (Terrify_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_TERRIFY);
+ Terrify_Timer = 20000;
+ }else Terrify_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_azshir_the_sleepless(Creature* pCreature)
+{
+ return new boss_azshir_the_sleeplessAI(pCreature);
+}
+
+void AddSC_boss_azshir_the_sleepless()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_azshir_the_sleepless";
+ newscript->GetAI = &GetAI_boss_azshir_the_sleepless;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp
new file mode 100644
index 0000000..d2cc372
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp
@@ -0,0 +1,123 @@
+/* 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_Bloodmage_Thalnos
+SD%Complete: 100
+SDComment:
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_AGGRO = -1189016,
+ SAY_HEALTH = -1189017,
+ SAY_KILL = -1189018,
+
+ SPELL_FLAMESHOCK = 8053,
+ SPELL_SHADOWBOLT = 1106,
+ SPELL_FLAMESPIKE = 8814,
+ SPELL_FIRENOVA = 16079,
+};
+
+struct MANGOS_DLL_DECL boss_bloodmage_thalnosAI : public ScriptedAI
+{
+ boss_bloodmage_thalnosAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ bool HpYell;
+ uint32 FlameShock_Timer;
+ uint32 ShadowBolt_Timer;
+ uint32 FlameSpike_Timer;
+ uint32 FireNova_Timer;
+
+ void Reset()
+ {
+ HpYell = false;
+ FlameShock_Timer = 10000;
+ ShadowBolt_Timer = 2000;
+ FlameSpike_Timer = 8000;
+ FireNova_Timer = 40000;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void KilledUnit(Unit* Victim)
+ {
+ DoScriptText(SAY_KILL, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //If we are <35% hp
+ if (!HpYell && m_creature->GetHealthPercent() <= 35.0f)
+ {
+ DoScriptText(SAY_HEALTH, m_creature);
+ HpYell = true;
+ }
+
+ //FlameShock_Timer
+ if (FlameShock_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FLAMESHOCK);
+ FlameShock_Timer = urand(10000, 15000);
+ }else FlameShock_Timer -= diff;
+
+ //FlameSpike_Timer
+ if (FlameSpike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FLAMESPIKE);
+ FlameSpike_Timer = 30000;
+ }else FlameSpike_Timer -= diff;
+
+ //FireNova_Timer
+ if (FireNova_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FIRENOVA);
+ FireNova_Timer = 40000;
+ }else FireNova_Timer -= diff;
+
+ //ShadowBolt_Timer
+ if (ShadowBolt_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWBOLT);
+ ShadowBolt_Timer = 2000;
+ }else ShadowBolt_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_bloodmage_thalnos(Creature* pCreature)
+{
+ return new boss_bloodmage_thalnosAI(pCreature);
+}
+
+void AddSC_boss_bloodmage_thalnos()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_bloodmage_thalnos";
+ newscript->GetAI = &GetAI_boss_bloodmage_thalnos;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp
new file mode 100644
index 0000000..28cb350
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp
@@ -0,0 +1,90 @@
+/* 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_headless_horseman
+SD%Complete: 0
+SDComment: Place Holder
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_ENTRANCE = -1189022,
+ SAY_REJOINED = -1189023,
+ SAY_BODY_DEFEAT = -1189024,
+ SAY_LOST_HEAD = -1189025,
+ SAY_CONFLAGRATION = -1189026,
+ SAY_SPROUTING_PUMPKINS = -1189027,
+ SAY_SLAY = -1189028,
+ SAY_DEATH = -1189029,
+
+ EMOTE_LAUGH = -1189030,
+
+ SAY_PLAYER1 = -1189031,
+ SAY_PLAYER2 = -1189032,
+ SAY_PLAYER3 = -1189033,
+ SAY_PLAYER4 = -1189034
+};
+
+struct MANGOS_DLL_DECL boss_headless_horsemanAI : public ScriptedAI
+{
+ boss_headless_horsemanAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(SAY_SLAY, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_headless_horseman(Creature* pCreature)
+{
+ return new boss_headless_horsemanAI(pCreature);
+}
+
+void AddSC_boss_headless_horseman()
+{
+ Script* NewScript;
+
+ NewScript = new Script;
+ NewScript->Name = "boss_headless_horseman";
+ NewScript->GetAI = GetAI_boss_headless_horseman;
+ NewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp
new file mode 100644
index 0000000..2dc4e87
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp
@@ -0,0 +1,187 @@
+/* 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_Herod
+SD%Complete: 95
+SDComment: Should in addition spawn Myrmidons in the hallway outside
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+enum
+{
+ SAY_AGGRO = -1189000,
+ SAY_WHIRLWIND = -1189001,
+ SAY_ENRAGE = -1189002,
+ SAY_KILL = -1189003,
+ EMOTE_ENRAGE = -1189004,
+
+ SAY_TRAINEE_SPAWN = -1189036,
+
+ SPELL_RUSHINGCHARGE = 8260,
+ SPELL_CLEAVE = 15496,
+ SPELL_WHIRLWIND = 8989,
+ SPELL_FRENZY = 8269,
+
+ NPC_SCARLET_TRAINEE = 6575
+};
+
+struct MANGOS_DLL_DECL boss_herodAI : public ScriptedAI
+{
+ boss_herodAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ bool m_bEnrage;
+ bool m_bTraineeSay;
+
+ uint32 m_uiCleaveTimer;
+ uint32 m_uiWhirlwindTimer;
+
+ void Reset()
+ {
+ m_bTraineeSay = false;
+ m_bEnrage = false;
+
+ m_uiCleaveTimer = 12000;
+ m_uiWhirlwindTimer = 45000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_RUSHINGCHARGE);
+ }
+
+ void SummonedCreature(Creature* pSummoned)
+ {
+ // make first Scarlet Trainee say text
+ if (pSummoned->GetEntry() == NPC_SCARLET_TRAINEE && !m_bTraineeSay)
+ {
+ DoScriptText(SAY_TRAINEE_SPAWN, pSummoned);
+ m_bTraineeSay = true;
+ }
+
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(SAY_KILL, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ for(uint8 i = 0; i < 20; ++i)
+ m_creature->SummonCreature(NPC_SCARLET_TRAINEE, 1939.18f, -431.58f, 17.09f, 6.22f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // If we are < 30% hp enrage
+ if (!m_bEnrage && m_creature->GetHealthPercent() <= 30.0f && !m_creature->IsNonMeleeSpellCasted(false))
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK)
+ {
+ DoScriptText(EMOTE_ENRAGE, m_creature);
+ DoScriptText(SAY_ENRAGE, m_creature);
+ m_bEnrage = true;
+ }
+ }
+
+ // Cleave
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleaveTimer = 12000;
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ if (m_uiWhirlwindTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_WHIRLWIND) == CAST_OK)
+ {
+ DoScriptText(SAY_WHIRLWIND, m_creature);
+ m_uiWhirlwindTimer = 30000;
+ }
+ }
+ else
+ m_uiWhirlwindTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_herod(Creature* pCreature)
+{
+ return new boss_herodAI(pCreature);
+}
+
+struct MANGOS_DLL_DECL mob_scarlet_traineeAI : public npc_escortAI
+{
+ mob_scarlet_traineeAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_uiStartTimer = urand(1000, 6000);
+ Reset();
+ }
+
+ uint32 m_uiStartTimer;
+
+ void Reset() { }
+ void WaypointReached(uint32 /*uiPointId*/) {}
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (m_uiStartTimer)
+ {
+ if (m_uiStartTimer <= uiDiff)
+ {
+ Start(true);
+ m_uiStartTimer = 0;
+ }
+ else
+ m_uiStartTimer -= uiDiff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_scarlet_trainee(Creature* pCreature)
+{
+ return new mob_scarlet_traineeAI(pCreature);
+}
+
+void AddSC_boss_herod()
+{
+ Script* pNewScript;
+ pNewScript = new Script;
+ pNewScript->Name = "boss_herod";
+ pNewScript->GetAI = &GetAI_boss_herod;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "mob_scarlet_trainee";
+ pNewScript->GetAI = &GetAI_mob_scarlet_trainee;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp
new file mode 100644
index 0000000..73c1421
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp
@@ -0,0 +1,128 @@
+/* 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_High_Inquisitor_Fairbanks
+SD%Complete: 100
+SDComment: TODO: if this guy not involved in some special event, remove (and let ACID script)
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_CURSEOFBLOOD = 8282,
+ SPELL_DISPELMAGIC = 15090,
+ SPELL_FEAR = 12096,
+ SPELL_HEAL = 12039,
+ SPELL_POWERWORDSHIELD = 11647,
+ SPELL_SLEEP = 8399
+};
+
+struct MANGOS_DLL_DECL boss_high_inquisitor_fairbanksAI : public ScriptedAI
+{
+ boss_high_inquisitor_fairbanksAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 CurseOfBlood_Timer;
+ uint32 DispelMagic_Timer;
+ uint32 Fear_Timer;
+ uint32 Heal_Timer;
+ uint32 Sleep_Timer;
+ uint32 Dispel_Timer;
+ bool PowerWordShield;
+
+ void Reset()
+ {
+ CurseOfBlood_Timer = 10000;
+ DispelMagic_Timer = 30000;
+ Fear_Timer = 40000;
+ Heal_Timer = 30000;
+ Sleep_Timer = 30000;
+ Dispel_Timer = 20000;
+ PowerWordShield = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //If we are <25% hp cast Heal
+ if (m_creature->GetHealthPercent() <= 25.0f && !m_creature->IsNonMeleeSpellCasted(false) && Heal_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_HEAL);
+ Heal_Timer = 30000;
+ }else Heal_Timer -= diff;
+
+ //Fear_Timer
+ if (Fear_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1))
+ DoCastSpellIfCan(target,SPELL_FEAR);
+
+ Fear_Timer = 40000;
+ }else Fear_Timer -= diff;
+
+ //Sleep_Timer
+ if (Sleep_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO,0))
+ DoCastSpellIfCan(target,SPELL_SLEEP);
+
+ Sleep_Timer = 30000;
+ }else Sleep_Timer -= diff;
+
+ //PowerWordShield_Timer
+ if (!PowerWordShield && m_creature->GetHealthPercent() <= 25.0f)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_POWERWORDSHIELD);
+ PowerWordShield = true;
+ }
+
+ //Dispel_Timer
+ if (Dispel_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target, SPELL_DISPELMAGIC);
+
+ DispelMagic_Timer = 30000;
+ }else DispelMagic_Timer -= diff;
+
+ //CurseOfBlood_Timer
+ if (CurseOfBlood_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CURSEOFBLOOD);
+ CurseOfBlood_Timer = 25000;
+ }else CurseOfBlood_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_high_inquisitor_fairbanks(Creature* pCreature)
+{
+ return new boss_high_inquisitor_fairbanksAI(pCreature);
+}
+
+void AddSC_boss_high_inquisitor_fairbanks()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_high_inquisitor_fairbanks";
+ newscript->GetAI = &GetAI_boss_high_inquisitor_fairbanks;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp
new file mode 100644
index 0000000..819ff45
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp
@@ -0,0 +1,77 @@
+/* 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_Houndmaster_Loksey
+SD%Complete: 100
+SDComment: TODO: if this guy not involved in some special event, remove (and let ACID script)
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_AGGRO = -1189021,
+ SPELL_SUMMONSCARLETHOUND = 17164,
+ SPELL_BLOODLUST = 6742
+};
+
+struct MANGOS_DLL_DECL boss_houndmaster_lokseyAI : public ScriptedAI
+{
+ boss_houndmaster_lokseyAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 BloodLust_Timer;
+
+ void Reset()
+ {
+ BloodLust_Timer = 20000;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_SUMMONSCARLETHOUND);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (BloodLust_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_BLOODLUST);
+ BloodLust_Timer = 20000;
+ }else BloodLust_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_houndmaster_loksey(Creature* pCreature)
+{
+ return new boss_houndmaster_lokseyAI(pCreature);
+}
+
+void AddSC_boss_houndmaster_loksey()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_houndmaster_loksey";
+ newscript->GetAI = &GetAI_boss_houndmaster_loksey;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp
new file mode 100644
index 0000000..76f13e6
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp
@@ -0,0 +1,120 @@
+/* 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_Interrogator_Vishas
+SD%Complete: 100
+SDComment:
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+#include "scarlet_monastery.h"
+
+enum
+{
+ SAY_AGGRO = -1189011,
+ SAY_HEALTH1 = -1189012,
+ SAY_HEALTH2 = -1189013,
+ SAY_KILL = -1189014,
+ SAY_TRIGGER_VORREL = -1189015,
+
+ SPELL_SHADOWWORDPAIN = 2767,
+};
+
+struct MANGOS_DLL_DECL boss_interrogator_vishasAI : public ScriptedAI
+{
+ boss_interrogator_vishasAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ bool Yell30;
+ bool Yell60;
+ uint32 ShadowWordPain_Timer;
+
+ void Reset()
+ {
+ Yell30 = false;
+ Yell60 = false;
+ ShadowWordPain_Timer = 5000;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void KilledUnit(Unit* Victim)
+ {
+ DoScriptText(SAY_KILL, m_creature);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (!m_pInstance)
+ return;
+
+ //Any other actions to do with vorrel? setStandState?
+ if (Creature *vorrel = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_VORREL)))
+ DoScriptText(SAY_TRIGGER_VORREL, vorrel);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //If we are low on hp Do sayings
+ if (!Yell60 && m_creature->GetHealthPercent() <= 60.0f)
+ {
+ DoScriptText(SAY_HEALTH1, m_creature);
+ Yell60 = true;
+ }
+
+ if (!Yell30 && m_creature->GetHealthPercent() <= 30.0f)
+ {
+ DoScriptText(SAY_HEALTH2, m_creature);
+ Yell30 = true;
+ }
+
+ //ShadowWordPain_Timer
+ if (ShadowWordPain_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWWORDPAIN);
+ ShadowWordPain_Timer = urand(5000, 15000);
+ }else ShadowWordPain_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_interrogator_vishas(Creature* pCreature)
+{
+ return new boss_interrogator_vishasAI(pCreature);
+}
+
+void AddSC_boss_interrogator_vishas()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_interrogator_vishas";
+ newscript->GetAI = &GetAI_boss_interrogator_vishas;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp
new file mode 100644
index 0000000..e204403
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp
@@ -0,0 +1,398 @@
+/* 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_Mograine_And_Whitemane
+SD%Complete: 90
+SDComment:
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+#include "scarlet_monastery.h"
+
+enum
+{
+ //Mograine says
+ SAY_MO_AGGRO = -1189005,
+ SAY_MO_KILL = -1189006,
+ SAY_MO_RESSURECTED = -1189007,
+
+ //Whitemane says
+ SAY_WH_INTRO = -1189008,
+ SAY_WH_KILL = -1189009,
+ SAY_WH_RESSURECT = -1189010,
+
+ //Mograine Spells
+ SPELL_CRUSADERSTRIKE = 14518,
+ SPELL_HAMMEROFJUSTICE = 5589,
+ SPELL_LAYONHANDS = 9257,
+ SPELL_RETRIBUTIONAURA = 8990,
+
+ //Whitemanes Spells
+ SPELL_DEEPSLEEP = 9256,
+ SPELL_SCARLETRESURRECTION = 9232,
+ SPELL_DOMINATEMIND = 14515,
+ SPELL_HOLYSMITE = 9481,
+ SPELL_HEAL = 12039,
+ SPELL_POWERWORDSHIELD = 22187
+};
+
+struct MANGOS_DLL_DECL boss_scarlet_commander_mograineAI : public ScriptedAI
+{
+ boss_scarlet_commander_mograineAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiCrusaderStrike_Timer;
+ uint32 m_uiHammerOfJustice_Timer;
+
+ bool m_bHasDied;
+ bool m_bHeal;
+ bool m_bFakeDeath;
+
+ void Reset()
+ {
+ m_uiCrusaderStrike_Timer = 10000;
+ m_uiHammerOfJustice_Timer = 10000;
+
+ //Incase wipe during phase that mograine fake death
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ m_bHasDied = false;
+ m_bHeal = false;
+ m_bFakeDeath = false;
+
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pWhitemane = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_WHITEMANE)))
+ {
+ if (m_creature->isAlive() && !pWhitemane->isAlive())
+ pWhitemane->Respawn();
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_MO_AGGRO, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_RETRIBUTIONAURA);
+
+ m_creature->CallForHelp(VISIBLE_RANGE);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(SAY_MO_KILL, m_creature);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (uiDamage < m_creature->GetHealth() || m_bHasDied)
+ return;
+
+ if (!m_pInstance)
+ return;
+
+ //On first death, fake death and open door, as well as initiate whitemane if exist
+ if (Creature* pWhitemane = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_WHITEMANE)))
+ {
+ m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, IN_PROGRESS);
+
+ pWhitemane->GetMotionMaster()->MovePoint(1, 1163.113370f, 1398.856812f, 32.527786f);
+
+ m_creature->GetMotionMaster()->MovementExpired();
+ m_creature->GetMotionMaster()->MoveIdle();
+
+ m_creature->SetHealth(0);
+
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ m_creature->ClearComboPointHolders();
+ m_creature->RemoveAllAuras();
+ m_creature->ClearAllReactives();
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ m_creature->SetStandState(UNIT_STAND_STATE_DEAD);
+
+ m_bHasDied = true;
+ m_bFakeDeath = true;
+
+ uiDamage = 0;
+ }
+ }
+
+ void SpellHit(Unit* pWho, const SpellEntry* pSpell)
+ {
+ //When hit with ressurection say text
+ if (pSpell->Id == SPELL_SCARLETRESURRECTION)
+ {
+ DoScriptText(SAY_MO_RESSURECTED, m_creature);
+ m_bFakeDeath = false;
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, SPECIAL);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_bHasDied && !m_bHeal && m_pInstance && m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == SPECIAL)
+ {
+ //On ressurection, stop fake death and heal whitemane and resume fight
+ if (Creature* pWhitemane = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_WHITEMANE)))
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ DoCastSpellIfCan(pWhitemane, SPELL_LAYONHANDS);
+
+ m_uiCrusaderStrike_Timer = 10000;
+ m_uiHammerOfJustice_Timer = 10000;
+
+ if (m_creature->getVictim())
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+
+ m_bHeal = true;
+ }
+ }
+
+ //This if-check to make sure mograine does not attack while fake death
+ if (m_bFakeDeath)
+ return;
+
+ //m_uiCrusaderStrike_Timer
+ if (m_uiCrusaderStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CRUSADERSTRIKE);
+ m_uiCrusaderStrike_Timer = 10000;
+ }
+ else
+ m_uiCrusaderStrike_Timer -= uiDiff;
+
+ //m_uiHammerOfJustice_Timer
+ if (m_uiHammerOfJustice_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_HAMMEROFJUSTICE);
+ m_uiHammerOfJustice_Timer = 60000;
+ }
+ else
+ m_uiHammerOfJustice_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_high_inquisitor_whitemaneAI : public ScriptedAI
+{
+ boss_high_inquisitor_whitemaneAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiHeal_Timer;
+ uint32 m_uiPowerWordShield_Timer;
+ uint32 m_uiHolySmite_Timer;
+ uint32 m_uiWait_Timer;
+
+ bool m_bCanResurrectCheck;
+ bool m_bCanResurrect;
+
+ void Reset()
+ {
+ m_uiWait_Timer = 7000;
+ m_uiHeal_Timer = 10000;
+ m_uiPowerWordShield_Timer = 15000;
+ m_uiHolySmite_Timer = 6000;
+
+ m_bCanResurrectCheck = false;
+ m_bCanResurrect = false;
+
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pMograine = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_MOGRAINE)))
+ {
+ if (m_creature->isAlive() && !pMograine->isAlive())
+ pMograine->Respawn();
+ }
+ }
+
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ {
+ if (!(m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED) || !(m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == FAIL))
+ m_pInstance->SetData(TYPE_MOGRAINE_AND_WHITE_EVENT, FAIL);
+ }
+ }
+
+ void MoveInLineOfSight()
+ {
+ //This needs to be empty because Whitemane should NOT aggro while fighting Mograine. Mograine will give us a target.
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (uiDamage < m_creature->GetHealth())
+ return;
+
+ if (!m_bCanResurrectCheck || m_bCanResurrect)
+ {
+ // prevent killing blow before rezzing commander
+ m_creature->SetHealth(uiDamage+1);
+ }
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (m_pInstance && (m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == NOT_STARTED || m_pInstance->GetData(TYPE_MOGRAINE_AND_WHITE_EVENT) == FAIL))
+ return;
+
+ ScriptedAI::AttackStart(pWho);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_WH_INTRO, m_creature);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(SAY_WH_KILL, m_creature);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_bCanResurrect)
+ {
+ //When casting resuruction make sure to delay so on rez when reinstate battle deepsleep runs out
+ if (m_pInstance && m_uiWait_Timer < uiDiff)
+ {
+ if (Creature* pMograine = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_MOGRAINE)))
+ {
+ DoCastSpellIfCan(pMograine, SPELL_SCARLETRESURRECTION);
+ DoScriptText(SAY_WH_RESSURECT, m_creature);
+ m_bCanResurrect = false;
+ }
+ }
+ else
+ m_uiWait_Timer -= uiDiff;
+ }
+
+ //Cast Deep sleep when health is less than 50%
+ if (!m_bCanResurrectCheck && m_creature->GetHealthPercent() <= 50.0f)
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_DEEPSLEEP);
+ m_bCanResurrectCheck = true;
+ m_bCanResurrect = true;
+ return;
+ }
+
+ //while in "resurrect-mode", don't do anything
+ if (m_bCanResurrect)
+ return;
+
+ //If we are <75% hp cast healing spells at self or Mograine
+ if (m_uiHeal_Timer < uiDiff)
+ {
+ Creature* pTarget = NULL;
+
+ if (m_creature->GetHealthPercent() <= 75.0f)
+ pTarget = m_creature;
+
+ if (m_pInstance)
+ {
+ if (Creature* pMograine = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_MOGRAINE)))
+ {
+ if (pMograine->isAlive() && pMograine->GetHealthPercent() <= 75.0f)
+ pTarget = pMograine;
+ }
+ }
+
+ if (pTarget)
+ DoCastSpellIfCan(pTarget, SPELL_HEAL);
+
+ m_uiHeal_Timer = 13000;
+ }
+ else
+ m_uiHeal_Timer -= uiDiff;
+
+ //m_uiPowerWordShield_Timer
+ if (m_uiPowerWordShield_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_POWERWORDSHIELD);
+ m_uiPowerWordShield_Timer = 15000;
+ }
+ else
+ m_uiPowerWordShield_Timer -= uiDiff;
+
+ //m_uiHolySmite_Timer
+ if (m_uiHolySmite_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_HOLYSMITE);
+ m_uiHolySmite_Timer = 6000;
+ }
+ else
+ m_uiHolySmite_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_scarlet_commander_mograine(Creature* pCreature)
+{
+ return new boss_scarlet_commander_mograineAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_high_inquisitor_whitemane(Creature* pCreature)
+{
+ return new boss_high_inquisitor_whitemaneAI(pCreature);
+}
+
+void AddSC_boss_mograine_and_whitemane()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_scarlet_commander_mograine";
+ newscript->GetAI = &GetAI_boss_scarlet_commander_mograine;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_high_inquisitor_whitemane";
+ newscript->GetAI = &GetAI_boss_high_inquisitor_whitemane;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp b/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp
new file mode 100644
index 0000000..3476d93
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp
@@ -0,0 +1,96 @@
+/* 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_Scorn
+SD%Complete: 100
+SDComment:
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_LICHSLAP 28873
+#define SPELL_FROSTBOLTVOLLEY 8398
+#define SPELL_MINDFLAY 17313
+#define SPELL_FROSTNOVA 15531
+
+struct MANGOS_DLL_DECL boss_scornAI : public ScriptedAI
+{
+ boss_scornAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 LichSlap_Timer;
+ uint32 FrostboltVolley_Timer;
+ uint32 MindFlay_Timer;
+ uint32 FrostNova_Timer;
+
+ void Reset()
+ {
+ LichSlap_Timer = 45000;
+ FrostboltVolley_Timer = 30000;
+ MindFlay_Timer = 30000;
+ FrostNova_Timer = 30000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //LichSlap_Timer
+ if (LichSlap_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_LICHSLAP);
+ LichSlap_Timer = 45000;
+ }else LichSlap_Timer -= diff;
+
+ //FrostboltVolley_Timer
+ if (FrostboltVolley_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROSTBOLTVOLLEY);
+ FrostboltVolley_Timer = 20000;
+ }else FrostboltVolley_Timer -= diff;
+
+ //MindFlay_Timer
+ if (MindFlay_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MINDFLAY);
+ MindFlay_Timer = 20000;
+ }else MindFlay_Timer -= diff;
+
+ //FrostNova_Timer
+ if (FrostNova_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROSTNOVA);
+ FrostNova_Timer = 15000;
+ }else FrostNova_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_scorn(Creature* pCreature)
+{
+ return new boss_scornAI(pCreature);
+}
+
+void AddSC_boss_scorn()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_scorn";
+ newscript->GetAI = &GetAI_boss_scorn;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp b/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp
new file mode 100644
index 0000000..a4dfad4
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp
@@ -0,0 +1,115 @@
+/* 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_Scarlet_Monastery
+SD%Complete: 50
+SDComment:
+SDCategory: Scarlet Monastery
+EndScriptData */
+
+#include "precompiled.h"
+#include "scarlet_monastery.h"
+
+struct MANGOS_DLL_DECL instance_scarlet_monastery : public ScriptedInstance
+{
+ instance_scarlet_monastery(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ uint64 m_uiMograineGUID;
+ uint64 m_uiWhitemaneGUID;
+ uint64 m_uiVorrelGUID;
+ uint64 m_uiDoorHighInquisitorGUID;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiMograineGUID = 0;
+ m_uiWhitemaneGUID = 0;
+ m_uiVorrelGUID = 0;
+ m_uiDoorHighInquisitorGUID = 0;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case 3976: m_uiMograineGUID = pCreature->GetGUID(); break;
+ case 3977: m_uiWhitemaneGUID = pCreature->GetGUID(); break;
+ case 3981: m_uiVorrelGUID = pCreature->GetGUID(); break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ if (pGo->GetEntry() == 104600)
+ m_uiDoorHighInquisitorGUID = pGo->GetGUID();
+ }
+
+ uint64 GetData64(uint32 data)
+ {
+ switch(data)
+ {
+ case DATA_MOGRAINE:
+ return m_uiMograineGUID;
+ case DATA_WHITEMANE:
+ return m_uiWhitemaneGUID;
+ case DATA_VORREL:
+ return m_uiVorrelGUID;
+ case DATA_DOOR_WHITEMANE:
+ return m_uiDoorHighInquisitorGUID;
+ }
+
+ return 0;
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ if (uiType == TYPE_MOGRAINE_AND_WHITE_EVENT)
+ {
+ if (uiData == IN_PROGRESS)
+ DoUseDoorOrButton(m_uiDoorHighInquisitorGUID);
+ if (uiData == FAIL)
+ DoUseDoorOrButton(m_uiDoorHighInquisitorGUID);
+
+ m_auiEncounter[0] = uiData;
+ }
+ }
+
+ uint32 GetData(uint32 uiData)
+ {
+ if (uiData == TYPE_MOGRAINE_AND_WHITE_EVENT)
+ return m_auiEncounter[0];
+
+ return 0;
+ }
+};
+
+InstanceData* GetInstanceData_instance_scarlet_monastery(Map* pMap)
+{
+ return new instance_scarlet_monastery(pMap);
+}
+
+void AddSC_instance_scarlet_monastery()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_scarlet_monastery";
+ newscript->GetInstanceData = &GetInstanceData_instance_scarlet_monastery;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h b/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h
new file mode 100644
index 0000000..0a48eab
--- /dev/null
+++ b/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h
@@ -0,0 +1,20 @@
+/* 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 */
+
+#ifndef DEF_SCARLETM_H
+#define DEF_SCARLETM_H
+
+enum
+{
+ MAX_ENCOUNTER = 1,
+
+ TYPE_MOGRAINE_AND_WHITE_EVENT = 1,
+
+ DATA_MOGRAINE = 2,
+ DATA_WHITEMANE = 3,
+ DATA_DOOR_WHITEMANE = 4,
+ DATA_VORREL = 5
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp b/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp
new file mode 100644
index 0000000..6730b7f
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp
@@ -0,0 +1,222 @@
+/* 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_Darkmaster_Gandling
+SD%Complete: 75
+SDComment: Doors missing
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+#include "scholomance.h"
+
+#define SPELL_ARCANEMISSILES 22272
+#define SPELL_SHADOWSHIELD 22417 //Not right ID. But 12040 is wrong either.
+#define SPELL_CURSE 18702
+
+#define ADD_1X 170.205
+#define ADD_1Y 99.413
+#define ADD_1Z 104.733
+#define ADD_1O 3.16
+
+#define ADD_2X 170.813
+#define ADD_2Y 97.857
+#define ADD_2Z 104.713
+#define ADD_2O 3.16
+
+#define ADD_3X 170.720
+#define ADD_3Y 100.900
+#define ADD_3Z 104.739
+#define ADD_3O 3.16
+
+#define ADD_4X 171.866
+#define ADD_4Y 99.373
+#define ADD_4Z 104.732
+#define ADD_4O 3.16
+
+struct MANGOS_DLL_DECL boss_darkmaster_gandlingAI : public ScriptedAI
+{
+ boss_darkmaster_gandlingAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 ArcaneMissiles_Timer;
+ uint32 ShadowShield_Timer;
+ uint32 Curse_Timer;
+ uint32 Teleport_Timer;
+
+ Creature *Summoned;
+
+ void Reset()
+ {
+ ArcaneMissiles_Timer = 4500;
+ ShadowShield_Timer = 12000;
+ Curse_Timer = 2000;
+ Teleport_Timer = 16000;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_GANDLING, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ArcaneMissiles_Timer
+ if (ArcaneMissiles_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ARCANEMISSILES);
+ ArcaneMissiles_Timer = 8000;
+ }else ArcaneMissiles_Timer -= diff;
+
+ //ShadowShield_Timer
+ if (ShadowShield_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_SHADOWSHIELD);
+ ShadowShield_Timer = urand(14000, 28000);
+ }else ShadowShield_Timer -= diff;
+
+ //Curse_Timer
+ if (Curse_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CURSE);
+ Curse_Timer = urand(15000, 27000);
+ }else Curse_Timer -= diff;
+
+ //Teleporting Random Target to one of the six pre boss rooms and spawn 3-4 skeletons near the gamer.
+ //We will only telport if gandling has more than 3% of hp so teleported gamers can always loot.
+ if (m_creature->GetHealthPercent() > 3.0f)
+ {
+ if (Teleport_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target && target->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (m_creature->getThreatManager().getThreat(target))
+ m_creature->getThreatManager().modifyThreatPercent(target, -100);
+
+ switch(urand(0, 5))
+ {
+ case 0:
+ DoTeleportPlayer(target, 250.0696f, 0.3921f, 84.8408f, 3.149f);
+ Summoned = m_creature->SummonCreature(16119, 254.2325f, 0.3417f, 84.8407f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 257.7133f, 4.0226f, 84.8407f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 258.6702f, -2.60656f, 84.8407f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ break;
+ case 1:
+ DoTeleportPlayer(target, 181.4220f, -91.9481f, 84.8410f, 1.608f);
+ Summoned = m_creature->SummonCreature(16119, 184.0519f, -73.5649f, 84.8407f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 179.5951f, -73.7045f, 84.8407f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 180.6452f, -78.2143f, 84.8407f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 283.2274f, -78.1518f, 84.8407f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ break;
+ case 2:
+ DoTeleportPlayer(target, 95.1547f, -1.8173f, 85.2289f, 0.043f);
+ Summoned = m_creature->SummonCreature(16119, 100.9404f, -1.8016f, 85.2289f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 101.3729f, 0.4882f, 85.2289f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 101.4596f, -4.4740f, 85.2289f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ break;
+ case 3:
+ DoTeleportPlayer(target, 250.0696f, 0.3921f, 72.6722f, 3.149f);
+ Summoned = m_creature->SummonCreature(16119, 240.34481f, 0.7368f, 72.6722f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 240.3633f, -2.9520f, 72.6722f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 240.6702f, 3.34949f, 72.6722f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ break;
+ case 4:
+ DoTeleportPlayer(target, 181.4220f, -91.9481f, 70.7734f, 1.608f);
+ Summoned = m_creature->SummonCreature(16119, 184.0519f, -73.5649f, 70.7734f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 179.5951f, -73.7045f, 70.7734f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 180.6452f, -78.2143f, 70.7734f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 283.2274f, -78.1518f, 70.7734f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ break;
+ case 5:
+ DoTeleportPlayer(target, 106.1541f, -1.8994f, 75.3663f, 0.043f);
+ Summoned = m_creature->SummonCreature(16119, 115.3945f, -1.5555f, 75.3663f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 257.7133f, 1.8066f, 75.3663f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ Summoned = m_creature->SummonCreature(16119, 258.6702f, -5.1001f, 75.3663f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,10000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(target);
+ break;
+ }
+ }
+ Teleport_Timer = urand(20000, 35000);
+ }else Teleport_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_darkmaster_gandling(Creature* pCreature)
+{
+ return new boss_darkmaster_gandlingAI(pCreature);
+}
+
+void AddSC_boss_darkmaster_gandling()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_darkmaster_gandling";
+ newscript->GetAI = &GetAI_boss_darkmaster_gandling;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp b/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp
new file mode 100644
index 0000000..5675e2f
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp
@@ -0,0 +1,56 @@
+/* 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_Death_knight_darkreaver
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+
+struct MANGOS_DLL_DECL boss_death_knight_darkreaverAI : public ScriptedAI
+{
+ boss_death_knight_darkreaverAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ }
+
+ void DamageTaken(Unit *done_by, uint32 &damage)
+ {
+ if (m_creature->GetHealth() <= damage)
+ {
+ m_creature->CastSpell(m_creature,23261,true); //Summon Darkreaver's Fallen Charger
+ }
+ }
+};
+
+CreatureAI* GetAI_boss_death_knight_darkreaver(Creature* pCreature)
+{
+ return new boss_death_knight_darkreaverAI(pCreature);
+}
+
+void AddSC_boss_death_knight_darkreaver()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_death_knight_darkreaver";
+ newscript->GetAI = &GetAI_boss_death_knight_darkreaver;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp b/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp
new file mode 100644
index 0000000..2600ecf
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp
@@ -0,0 +1,116 @@
+/* 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_Doctor_Theolen_Krastinov
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+#include "scholomance.h"
+
+enum
+{
+ EMOTE_GENERIC_FRENZY_KILL = -1000001,
+
+ SPELL_REND = 16509,
+ SPELL_BACKHAND = 18103,
+ SPELL_FRENZY = 8269
+};
+
+struct MANGOS_DLL_DECL boss_theolenkrastinovAI : public ScriptedAI
+{
+ boss_theolenkrastinovAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiRend_Timer;
+ uint32 m_uiBackhand_Timer;
+ uint32 m_uiFrenzy_Timer;
+
+ void Reset()
+ {
+ m_uiRend_Timer = 8000;
+ m_uiBackhand_Timer = 9000;
+ m_uiFrenzy_Timer = 1000;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)m_creature->GetInstanceData())
+ {
+ pInstance->SetData(TYPE_THEOLEN, DONE);
+
+ if (pInstance->GetData(TYPE_GANDLING) == SPECIAL)
+ m_creature->SummonCreature(1853, 180.73f, -9.43856f, 75.507f, 1.61399f, TEMPSUMMON_DEAD_DESPAWN, 0);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Rend_Timer
+ if (m_uiRend_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_REND);
+ m_uiRend_Timer = 10000;
+ }
+ else
+ m_uiRend_Timer -= uiDiff;
+
+ //m_uiBackhand_Timer
+ if (m_uiBackhand_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_BACKHAND);
+ m_uiBackhand_Timer = 10000;
+ }
+ else
+ m_uiBackhand_Timer -= uiDiff;
+
+ //Frenzy_Timer
+ if (m_creature->GetHealthPercent() < 26.0f)
+ {
+ if (m_uiFrenzy_Timer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK)
+ {
+ DoScriptText(EMOTE_GENERIC_FRENZY_KILL, m_creature);
+ m_uiFrenzy_Timer = 120000;
+ }
+ }
+ else
+ m_uiFrenzy_Timer -= uiDiff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_theolenkrastinov(Creature* pCreature)
+{
+ return new boss_theolenkrastinovAI(pCreature);
+}
+
+void AddSC_boss_theolenkrastinov()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_doctor_theolen_krastinov";
+ newscript->GetAI = &GetAI_boss_theolenkrastinov;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp b/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp
new file mode 100644
index 0000000..f5052d4
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp
@@ -0,0 +1,111 @@
+/* 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_Illucia_Barov
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+#include "scholomance.h"
+
+#define SPELL_CURSEOFAGONY 18671
+#define SPELL_SHADOWSHOCK 20603
+#define SPELL_SILENCE 15487
+#define SPELL_FEAR 6215
+
+struct MANGOS_DLL_DECL boss_illuciabarovAI : public ScriptedAI
+{
+ boss_illuciabarovAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 CurseOfAgony_Timer;
+ uint32 ShadowShock_Timer;
+ uint32 Silence_Timer;
+ uint32 Fear_Timer;
+
+ void Reset()
+ {
+ CurseOfAgony_Timer = 18000;
+ ShadowShock_Timer = 9000;
+ Silence_Timer = 5000;
+ Fear_Timer = 30000;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)m_creature->GetInstanceData())
+ {
+ pInstance->SetData(TYPE_ILLUCIABAROV, DONE);
+
+ if (pInstance->GetData(TYPE_GANDLING) == SPECIAL)
+ m_creature->SummonCreature(1853, 180.73f, -9.43856f, 75.507f, 1.61399f, TEMPSUMMON_DEAD_DESPAWN, 0);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //CurseOfAgony_Timer
+ if (CurseOfAgony_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CURSEOFAGONY);
+ CurseOfAgony_Timer = 30000;
+ }else CurseOfAgony_Timer -= diff;
+
+ //ShadowShock_Timer
+ if (ShadowShock_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_SHADOWSHOCK);
+
+ ShadowShock_Timer = 12000;
+ }else ShadowShock_Timer -= diff;
+
+ //Silence_Timer
+ if (Silence_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SILENCE);
+ Silence_Timer = 14000;
+ }else Silence_Timer -= diff;
+
+ //Fear_Timer
+ if (Fear_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FEAR);
+ Fear_Timer = 30000;
+ }else Fear_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_illuciabarov(Creature* pCreature)
+{
+ return new boss_illuciabarovAI(pCreature);
+}
+
+void AddSC_boss_illuciabarov()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_illucia_barov";
+ newscript->GetAI = &GetAI_boss_illuciabarov;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp b/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp
new file mode 100644
index 0000000..4f79a10
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp
@@ -0,0 +1,147 @@
+/* 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_instructormalicia
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+#include "scholomance.h"
+
+#define SPELL_CALLOFGRAVES 17831
+#define SPELL_CORRUPTION 11672
+#define SPELL_FLASHHEAL 10917
+#define SPELL_RENEW 10929
+#define SPELL_HEALINGTOUCH 9889
+
+struct MANGOS_DLL_DECL boss_instructormaliciaAI : public ScriptedAI
+{
+ boss_instructormaliciaAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 CallOfGraves_Timer;
+ uint32 Corruption_Timer;
+ uint32 FlashHeal_Timer;
+ uint32 Renew_Timer;
+ uint32 HealingTouch_Timer;
+ uint32 FlashCounter;
+ uint32 TouchCounter;
+
+ void Reset()
+ {
+ CallOfGraves_Timer = 4000;
+ Corruption_Timer = 8000;
+ FlashHeal_Timer = 38000;
+ Renew_Timer = 32000;
+ HealingTouch_Timer = 45000;
+ FlashCounter = 0;
+ TouchCounter = 0;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)m_creature->GetInstanceData())
+ {
+ pInstance->SetData(TYPE_MALICIA, DONE);
+
+ if (pInstance->GetData(TYPE_GANDLING) == SPECIAL)
+ m_creature->SummonCreature(1853, 180.73f, -9.43856f, 75.507f, 1.61399f, TEMPSUMMON_DEAD_DESPAWN, 0);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //CallOfGraves_Timer
+ if (CallOfGraves_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CALLOFGRAVES);
+ CallOfGraves_Timer = 65000;
+ }else CallOfGraves_Timer -= diff;
+
+ //Corruption_Timer
+ if (Corruption_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_CORRUPTION);
+
+ Corruption_Timer = 24000;
+ }else Corruption_Timer -= diff;
+
+ //Renew_Timer
+ if (Renew_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_RENEW);
+ Renew_Timer = 10000;
+ }else Renew_Timer -= diff;
+
+ //FlashHeal_Timer
+ if (FlashHeal_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_FLASHHEAL);
+
+ //5 Flashheals will be casted
+ if (FlashCounter < 2)
+ {
+ FlashHeal_Timer = 5000;
+ ++FlashCounter;
+ }
+ else
+ {
+ FlashCounter=0;
+ FlashHeal_Timer = 30000;
+ }
+ }else FlashHeal_Timer -= diff;
+
+ //HealingTouch_Timer
+ if (HealingTouch_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_HEALINGTOUCH);
+
+ //3 Healingtouchs will be casted
+ if (HealingTouch_Timer < 2)
+ {
+ HealingTouch_Timer = 5500;
+ ++TouchCounter;
+ }
+ else
+ {
+ TouchCounter=0;
+ HealingTouch_Timer = 30000;
+ }
+ }else HealingTouch_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_instructormalicia(Creature* pCreature)
+{
+ return new boss_instructormaliciaAI(pCreature);
+}
+
+void AddSC_boss_instructormalicia()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_instructor_malicia";
+ newscript->GetAI = &GetAI_boss_instructormalicia;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp b/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp
new file mode 100644
index 0000000..25750fa
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp
@@ -0,0 +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
+*/
+
+/* ScriptData
+SDName: Boss_jandicebarov
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_CURSEOFBLOOD 24673
+//#define SPELL_ILLUSION 17773
+
+//Spells of Illusion of Jandice Barov
+#define SPELL_CLEAVE 15584
+
+struct MANGOS_DLL_DECL boss_jandicebarovAI : public ScriptedAI
+{
+ boss_jandicebarovAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 CurseOfBlood_Timer;
+ uint32 Illusion_Timer;
+ //uint32 Illusioncounter;
+ uint32 Invisible_Timer;
+ bool Invisible;
+ int Rand;
+ int RandX;
+ int RandY;
+ Creature* Summoned;
+
+ void Reset()
+ {
+ CurseOfBlood_Timer = 15000;
+ Illusion_Timer = 30000;
+ Invisible_Timer = 3000; //Too much too low?
+ Invisible = false;
+ }
+
+ void SummonIllusions(Unit* victim)
+ {
+ Rand = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: RandX = 0 - Rand; break;
+ case 1: RandX = 0 + Rand; break;
+ }
+ Rand = 0;
+ Rand = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: RandY = 0 - Rand; break;
+ case 1: RandY = 0 + Rand; break;
+ }
+ Rand = 0;
+ Summoned = DoSpawnCreature(11439, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 60000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(victim);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (Invisible && Invisible_Timer < diff)
+ {
+ //Become visible again
+ m_creature->setFaction(14);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetDisplayId(11073); //Jandice Model
+ Invisible = false;
+ } else if (Invisible)
+ {
+ Invisible_Timer -= diff;
+ //Do nothing while invisible
+ return;
+ }
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //CurseOfBlood_Timer
+ if (CurseOfBlood_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CURSEOFBLOOD);
+ CurseOfBlood_Timer = 30000;
+ }else CurseOfBlood_Timer -= diff;
+
+ //Illusion_Timer
+ if (!Invisible && Illusion_Timer < diff)
+ {
+ //Inturrupt any spell casting
+ m_creature->InterruptNonMeleeSpells(false);
+ m_creature->setFaction(35);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetDisplayId(11686); // Invisible Model
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-99);
+
+ //Summon 10 Illusions attacking random gamers
+ Unit* target = NULL;
+ for(int i = 0; i < 10; ++i)
+ {
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ SummonIllusions(target);
+ }
+ Invisible = true;
+ Invisible_Timer = 3000;
+
+ //25 seconds until we should cast this agian
+ Illusion_Timer = 25000;
+ }else Illusion_Timer -= diff;
+
+ // //Illusion_Timer
+ // if (Illusion_Timer < diff)
+ // {
+ // //Cast
+ // DoCastSpellIfCan(m_creature->getVictim(),SPELL_ILLUSION);
+ // //3 Illusion will be summoned
+ // if (Illusioncounter < 3)
+ // {
+ // Illusion_Timer = 500;
+ // ++Illusioncounter;
+ // }
+ // else {
+ // //15 seconds until we should cast this again
+ // Illusion_Timer = 15000;
+ // Illusioncounter=0;
+ // }
+ // }else Illusion_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+// Illusion of Jandice Barov Script
+
+struct MANGOS_DLL_DECL mob_illusionofjandicebarovAI : public ScriptedAI
+{
+ mob_illusionofjandicebarovAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Cleave_Timer;
+
+ void Reset()
+ {
+ Cleave_Timer = urand(2000, 8000);
+ m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = urand(5000, 8000);
+ }else Cleave_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_jandicebarov(Creature* pCreature)
+{
+ return new boss_jandicebarovAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_illusionofjandicebarov(Creature* pCreature)
+{
+ return new mob_illusionofjandicebarovAI(pCreature);
+}
+
+void AddSC_boss_jandicebarov()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_jandice_barov";
+ newscript->GetAI = &GetAI_boss_jandicebarov;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_illusionofjandicebarov";
+ newscript->GetAI = &GetAI_mob_illusionofjandicebarov;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp b/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp
new file mode 100644
index 0000000..cec9bb4
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp
@@ -0,0 +1,153 @@
+/* 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_Kormok
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_SHADOWBOLTVOLLEY 20741
+#define SPELL_BONESHIELD 27688
+
+struct MANGOS_DLL_DECL boss_kormokAI : public ScriptedAI
+{
+ boss_kormokAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ShadowVolley_Timer;
+ uint32 BoneShield_Timer;
+ uint32 Minion_Timer;
+ uint32 Mage_Timer;
+ bool Mages;
+ int Rand1;
+ int Rand1X;
+ int Rand1Y;
+ int Rand2;
+ int Rand2X;
+ int Rand2Y;
+ Creature* SummonedMinions;
+ Creature* SummonedMages;
+
+ void Reset()
+ {
+ ShadowVolley_Timer = 10000;
+ BoneShield_Timer = 2000;
+ Minion_Timer = 15000;
+ Mage_Timer = 0;
+ Mages = false;
+ }
+
+ void SummonMinion(Unit* victim)
+ {
+ Rand1 = rand()%8;
+ switch(urand(0, 1))
+ {
+ case 0: Rand1X = 0 - Rand1; break;
+ case 1: Rand1X = 0 + Rand1; break;
+ }
+ Rand1 = 0;
+ Rand1 = rand()%8;
+ switch(urand(0, 1))
+ {
+ case 0: Rand1Y = 0 - Rand1; break;
+ case 1: Rand1Y = 0 + Rand1; break;
+ }
+ Rand1 = 0;
+ SummonedMinions = DoSpawnCreature(16119, Rand1X, Rand1Y, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000);
+ if (SummonedMinions)
+ SummonedMinions->AI()->AttackStart(victim);
+ }
+
+ void SummonMages(Unit* victim)
+ {
+ Rand2 = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: Rand2X = 0 - Rand2; break;
+ case 1: Rand2X = 0 + Rand2; break;
+ }
+ Rand2 = 0;
+ Rand2 = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: Rand2Y = 0 - Rand2; break;
+ case 1: Rand2Y = 0 + Rand2; break;
+ }
+ Rand2 = 0;
+ SummonedMages = DoSpawnCreature(16120, Rand2X, Rand2Y, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 120000);
+ if (SummonedMages)
+ SummonedMages->AI()->AttackStart(victim);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowVolley_Timer
+ if (ShadowVolley_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWBOLTVOLLEY);
+ ShadowVolley_Timer = 15000;
+ }else ShadowVolley_Timer -= diff;
+
+ //BoneShield_Timer
+ if (BoneShield_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BONESHIELD);
+ BoneShield_Timer = 45000;
+ }else BoneShield_Timer -= diff;
+
+ //Minion_Timer
+ if (Minion_Timer < diff)
+ {
+ //Cast
+ SummonMinion(m_creature->getVictim());
+ SummonMinion(m_creature->getVictim());
+ SummonMinion(m_creature->getVictim());
+ SummonMinion(m_creature->getVictim());
+
+ Minion_Timer = 12000;
+ }else Minion_Timer -= diff;
+
+ //Summon 2 Bone Mages
+ if (!Mages && m_creature->GetHealthPercent() < 26.0f)
+ {
+ //Cast
+ SummonMages(m_creature->getVictim());
+ SummonMages(m_creature->getVictim());
+ Mages = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_kormok(Creature* pCreature)
+{
+ return new boss_kormokAI(pCreature);
+}
+
+void AddSC_boss_kormok()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_kormok";
+ newscript->GetAI = &GetAI_boss_kormok;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp b/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp
new file mode 100644
index 0000000..17fc273
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp
@@ -0,0 +1,93 @@
+/* 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_Lord_Alexei_Barov
+SD%Complete: 100
+SDComment: aura applied/defined in database
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+#include "scholomance.h"
+
+#define SPELL_IMMOLATE 20294 // Old ID was 15570
+#define SPELL_VEILOFSHADOW 17820
+
+struct MANGOS_DLL_DECL boss_lordalexeibarovAI : public ScriptedAI
+{
+ boss_lordalexeibarovAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Immolate_Timer;
+ uint32 VeilofShadow_Timer;
+
+ void Reset()
+ {
+ Immolate_Timer = 7000;
+ VeilofShadow_Timer = 15000;
+
+ m_creature->LoadCreatureAddon();
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)m_creature->GetInstanceData())
+ {
+ pInstance->SetData(TYPE_ALEXEIBAROV, DONE);
+
+ if (pInstance->GetData(TYPE_GANDLING) == SPECIAL)
+ m_creature->SummonCreature(1853, 180.73f, -9.43856f, 75.507f, 1.61399f, TEMPSUMMON_DEAD_DESPAWN, 0);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Immolate_Timer
+ if (Immolate_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_IMMOLATE);
+
+ Immolate_Timer = 12000;
+ }else Immolate_Timer -= diff;
+
+ //VeilofShadow_Timer
+ if (VeilofShadow_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_VEILOFSHADOW);
+ VeilofShadow_Timer = 20000;
+ }else VeilofShadow_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_lordalexeibarov(Creature* pCreature)
+{
+ return new boss_lordalexeibarovAI(pCreature);
+}
+
+void AddSC_boss_lordalexeibarov()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_lord_alexei_barov";
+ newscript->GetAI = &GetAI_boss_lordalexeibarov;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp b/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp
new file mode 100644
index 0000000..f684020
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp
@@ -0,0 +1,108 @@
+/* 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_Lorekeeper_Polkelt
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+#include "scholomance.h"
+
+#define SPELL_VOLATILEINFECTION 24928
+#define SPELL_DARKPLAGUE 18270
+#define SPELL_CORROSIVEACID 23313
+#define SPELL_NOXIOUSCATALYST 18151
+
+struct MANGOS_DLL_DECL boss_lorekeeperpolkeltAI : public ScriptedAI
+{
+ boss_lorekeeperpolkeltAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 VolatileInfection_Timer;
+ uint32 Darkplague_Timer;
+ uint32 CorrosiveAcid_Timer;
+ uint32 NoxiousCatalyst_Timer;
+
+ void Reset()
+ {
+ VolatileInfection_Timer = 38000;
+ Darkplague_Timer = 8000;
+ CorrosiveAcid_Timer = 45000;
+ NoxiousCatalyst_Timer = 35000;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)m_creature->GetInstanceData())
+ {
+ pInstance->SetData(TYPE_POLKELT, DONE);
+
+ if (pInstance->GetData(TYPE_GANDLING) == SPECIAL)
+ m_creature->SummonCreature(1853, 180.73f, -9.43856f, 75.507f, 1.61399f, TEMPSUMMON_DEAD_DESPAWN, 0);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //VolatileInfection_Timer
+ if (VolatileInfection_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_VOLATILEINFECTION);
+ VolatileInfection_Timer = 32000;
+ }else VolatileInfection_Timer -= diff;
+
+ //Darkplague_Timer
+ if (Darkplague_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_DARKPLAGUE);
+ Darkplague_Timer = 8000;
+ }else Darkplague_Timer -= diff;
+
+ //CorrosiveAcid_Timer
+ if (CorrosiveAcid_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CORROSIVEACID);
+ CorrosiveAcid_Timer = 25000;
+ }else CorrosiveAcid_Timer -= diff;
+
+ //NoxiousCatalyst_Timer
+ if (NoxiousCatalyst_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_NOXIOUSCATALYST);
+ NoxiousCatalyst_Timer = 38000;
+ }else NoxiousCatalyst_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_lorekeeperpolkelt(Creature* pCreature)
+{
+ return new boss_lorekeeperpolkeltAI(pCreature);
+}
+
+void AddSC_boss_lorekeeperpolkelt()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_lorekeeper_polkelt";
+ newscript->GetAI = &GetAI_boss_lorekeeperpolkelt;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp b/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp
new file mode 100644
index 0000000..349b03e
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp
@@ -0,0 +1,121 @@
+/* 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_Ras_Frostwhisper
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_FROSTBOLT 21369
+#define SPELL_ICEARMOR 18100 //This is actually a buff he gives himself
+#define SPELL_FREEZE 18763
+#define SPELL_FEAR 26070
+#define SPELL_CHILLNOVA 18099
+#define SPELL_FROSTVOLLEY 8398
+
+struct MANGOS_DLL_DECL boss_rasfrostAI : public ScriptedAI
+{
+ boss_rasfrostAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 IceArmor_Timer;
+ uint32 Frostbolt_Timer;
+ uint32 Freeze_Timer;
+ uint32 Fear_Timer;
+ uint32 ChillNova_Timer;
+ uint32 FrostVolley_Timer;
+
+ void Reset()
+ {
+ IceArmor_Timer = 2000;
+ Frostbolt_Timer = 8000;
+ ChillNova_Timer = 12000;
+ Freeze_Timer = 18000;
+ FrostVolley_Timer = 24000;
+ Fear_Timer = 45000;
+
+ m_creature->CastSpell(m_creature,SPELL_ICEARMOR,true);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //IceArmor_Timer
+ if (IceArmor_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ICEARMOR);
+ IceArmor_Timer = 180000;
+ }else IceArmor_Timer -= diff;
+
+ //Frostbolt_Timer
+ if (Frostbolt_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_FROSTBOLT);
+
+ Frostbolt_Timer = 8000;
+ }else Frostbolt_Timer -= diff;
+
+ //Freeze_Timer
+ if (Freeze_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FREEZE);
+ Freeze_Timer = 24000;
+ }else Freeze_Timer -= diff;
+
+ //Fear_Timer
+ if (Fear_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FEAR);
+ Fear_Timer = 30000;
+ }else Fear_Timer -= diff;
+
+ //ChillNova_Timer
+ if (ChillNova_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CHILLNOVA);
+ ChillNova_Timer = 14000;
+ }else ChillNova_Timer -= diff;
+
+ //FrostVolley_Timer
+ if (FrostVolley_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROSTVOLLEY);
+ FrostVolley_Timer = 15000;
+ }else FrostVolley_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_rasfrost(Creature* pCreature)
+{
+ return new boss_rasfrostAI(pCreature);
+}
+
+void AddSC_boss_rasfrost()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_boss_ras_frostwhisper";
+ newscript->GetAI = &GetAI_boss_rasfrost;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp b/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp
new file mode 100644
index 0000000..7d9dafb
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp
@@ -0,0 +1,111 @@
+/* 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_the_ravenian
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+#include "scholomance.h"
+
+#define SPELL_TRAMPLE 15550
+#define SPELL_CLEAVE 20691
+#define SPELL_SUNDERINCLEAVE 25174
+#define SPELL_KNOCKAWAY 10101
+
+struct MANGOS_DLL_DECL boss_theravenianAI : public ScriptedAI
+{
+ boss_theravenianAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Trample_Timer;
+ uint32 Cleave_Timer;
+ uint32 SunderingCleave_Timer;
+ uint32 KnockAway_Timer;
+ bool HasYelled;
+
+ void Reset()
+ {
+ Trample_Timer = 24000;
+ Cleave_Timer = 15000;
+ SunderingCleave_Timer = 40000;
+ KnockAway_Timer = 32000;
+ HasYelled = false;
+ }
+
+ void JustDied(Unit *killer)
+ {
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)m_creature->GetInstanceData())
+ {
+ pInstance->SetData(TYPE_RAVENIAN, DONE);
+
+ if (pInstance->GetData(TYPE_GANDLING) == SPECIAL)
+ m_creature->SummonCreature(1853, 180.73f, -9.43856f, 75.507f, 1.61399f, TEMPSUMMON_DEAD_DESPAWN, 0);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Trample_Timer
+ if (Trample_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_TRAMPLE);
+ Trample_Timer = 10000;
+ }else Trample_Timer -= diff;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = 7000;
+ }else Cleave_Timer -= diff;
+
+ //SunderingCleave_Timer
+ if (SunderingCleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SUNDERINCLEAVE);
+ SunderingCleave_Timer = 20000;
+ }else SunderingCleave_Timer -= diff;
+
+ //KnockAway_Timer
+ if (KnockAway_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KNOCKAWAY);
+ KnockAway_Timer = 12000;
+ }else KnockAway_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_theravenian(Creature* pCreature)
+{
+ return new boss_theravenianAI(pCreature);
+}
+
+void AddSC_boss_theravenian()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_the_ravenian";
+ newscript->GetAI = &GetAI_boss_theravenian;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp b/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp
new file mode 100644
index 0000000..add111f
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp
@@ -0,0 +1,103 @@
+/* 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_Vectus
+SD%Complete: 60
+SDComment: event not implemented
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ //EMOTE_GENERIC_FRENZY_KILL = -1000001,
+
+ SPELL_FLAMESTRIKE = 18399,
+ SPELL_BLAST_WAVE = 16046
+ //SPELL_FRENZY = 28371 //spell is used by Gluth, confirm this is for this boss too
+ //SPELL_FIRE_SHIELD = 0 //should supposedly have some aura, but proper spell not found
+};
+
+struct MANGOS_DLL_DECL boss_vectusAI : public ScriptedAI
+{
+ boss_vectusAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiFlameStrike_Timer;
+ uint32 m_uiBlastWave_Timer;
+ uint32 m_uiFrenzy_Timer;
+
+ void Reset()
+ {
+ m_uiFlameStrike_Timer = 2000;
+ m_uiBlastWave_Timer = 14000;
+ m_uiFrenzy_Timer = 0;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //m_uiFlameStrike_Timer
+ if (m_uiFlameStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FLAMESTRIKE);
+ m_uiFlameStrike_Timer = 30000;
+ }
+ else
+ m_uiFlameStrike_Timer -= uiDiff;
+
+ //BlastWave_Timer
+ if (m_uiBlastWave_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_BLAST_WAVE);
+ m_uiBlastWave_Timer = 12000;
+ }
+ else
+ m_uiBlastWave_Timer -= uiDiff;
+
+ //Frenzy_Timer
+ /*if (m_creature->GetHealthPercent() < 25.0f)
+ {
+ if (m_uiFrenzy_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FRENZY);
+ DoScriptText(EMOTE_GENERIC_FRENZY_KILL, m_creature);
+ m_uiFrenzy_Timer = 24000;
+ }
+ else
+ m_uiFrenzy_Timer -= uiDiff;
+ }*/
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_vectus(Creature* pCreature)
+{
+ return new boss_vectusAI(pCreature);
+}
+
+void AddSC_boss_vectus()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_vectus";
+ newscript->GetAI = &GetAI_boss_vectus;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp b/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp
new file mode 100644
index 0000000..fb6c3b1
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp
@@ -0,0 +1,130 @@
+/* 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_Scholomance
+SD%Complete: 100
+SDComment:
+SDCategory: Scholomance
+EndScriptData */
+
+#include "precompiled.h"
+#include "scholomance.h"
+
+struct MANGOS_DLL_DECL instance_scholomance : public ScriptedInstance
+{
+ instance_scholomance(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ uint64 m_uiGateKirtonosGUID;
+ uint64 m_uiGateGandlingGUID;
+ uint64 m_uiGateMiliciaGUID;
+ uint64 m_uiGateTheolenGUID;
+ uint64 m_uiGatePolkeltGUID;
+ uint64 m_uiGateRavenianGUID;
+ uint64 m_uiGateBarovGUID;
+ uint64 m_uiGateIlluciaGUID;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiGateKirtonosGUID = 0;
+ m_uiGateGandlingGUID = 0;
+ m_uiGateMiliciaGUID = 0;
+ m_uiGateTheolenGUID = 0;
+ m_uiGatePolkeltGUID = 0;
+ m_uiGateRavenianGUID = 0;
+ m_uiGateBarovGUID = 0;
+ m_uiGateIlluciaGUID = 0;
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case GO_GATE_KIRTONOS: m_uiGateKirtonosGUID = pGo->GetGUID(); break;
+ case GO_GATE_GANDLING: m_uiGateGandlingGUID = pGo->GetGUID(); break;
+ case GO_GATE_MALICIA: m_uiGateMiliciaGUID = pGo->GetGUID(); break;
+ case GO_GATE_THEOLEN: m_uiGateTheolenGUID = pGo->GetGUID(); break;
+ case GO_GATE_POLKELT: m_uiGatePolkeltGUID = pGo->GetGUID(); break;
+ case GO_GATE_RAVENIAN: m_uiGateRavenianGUID = pGo->GetGUID(); break;
+ case GO_GATE_BAROV: m_uiGateBarovGUID = pGo->GetGUID(); break;
+ case GO_GATE_ILLUCIA: m_uiGateIlluciaGUID = pGo->GetGUID(); break;
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_GANDLING:
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_KIRTONOS:
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_ALEXEIBAROV:
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_THEOLEN:
+ m_auiEncounter[3] = uiData;
+ break;
+ case TYPE_RAVENIAN:
+ m_auiEncounter[4] = uiData;
+ break;
+ case TYPE_POLKELT:
+ m_auiEncounter[5] = uiData;
+ break;
+ case TYPE_MALICIA:
+ m_auiEncounter[6] = uiData;
+ break;
+ case TYPE_ILLUCIABAROV:
+ m_auiEncounter[7] = uiData;
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ if (uiType == TYPE_GANDLING)
+ {
+ if (m_auiEncounter[2] == DONE && m_auiEncounter[3] == DONE && m_auiEncounter[4] == DONE &&
+ m_auiEncounter[5] == DONE && m_auiEncounter[6] == DONE && m_auiEncounter[7] == DONE)
+ {
+ m_auiEncounter[0] = SPECIAL;
+ return SPECIAL;
+ }
+ }
+
+ return 0;
+ }
+};
+
+InstanceData* GetInstanceData_instance_scholomance(Map* pMap)
+{
+ return new instance_scholomance(pMap);
+}
+
+void AddSC_instance_scholomance()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_scholomance";
+ newscript->GetInstanceData = &GetInstanceData_instance_scholomance;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/scholomance/scholomance.h b/scripts/eastern_kingdoms/scholomance/scholomance.h
new file mode 100644
index 0000000..b91227d
--- /dev/null
+++ b/scripts/eastern_kingdoms/scholomance/scholomance.h
@@ -0,0 +1,31 @@
+/* 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 */
+
+#ifndef DEF_SCHOLOMANCE_H
+#define DEF_SCHOLOMANCE_H
+
+enum
+{
+ MAX_ENCOUNTER = 8,
+
+ GO_GATE_KIRTONOS = 175570,
+ GO_GATE_GANDLING = 177374,
+ GO_GATE_MALICIA = 177375,
+ GO_GATE_THEOLEN = 177377,
+ GO_GATE_POLKELT = 177376,
+ GO_GATE_RAVENIAN = 177372,
+ GO_GATE_BAROV = 177373,
+ GO_GATE_ILLUCIA = 177371,
+
+ TYPE_GANDLING = 1,
+ TYPE_THEOLEN = 2,
+ TYPE_MALICIA = 3,
+ TYPE_ILLUCIABAROV = 4,
+ TYPE_ALEXEIBAROV = 5,
+ TYPE_POLKELT = 6,
+ TYPE_RAVENIAN = 7,
+ TYPE_KIRTONOS = 8
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/searing_gorge.cpp b/scripts/eastern_kingdoms/searing_gorge.cpp
new file mode 100644
index 0000000..c026146
--- /dev/null
+++ b/scripts/eastern_kingdoms/searing_gorge.cpp
@@ -0,0 +1,159 @@
+/* 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: Searing_Gorge
+SD%Complete: 80
+SDComment: Quest support: 3377, 3441 (More accurate info on Kalaran needed). Lothos Riftwaker teleport to Molten Core.
+SDCategory: Searing Gorge
+EndScriptData */
+
+/* ContentData
+npc_kalaran_windblade
+npc_lothos_riftwaker
+npc_zamael_lunthistle
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_kalaran_windblade
+######*/
+
+bool GossipHello_npc_kalaran_windblade(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(3441) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Tell me what drives this vengance?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_kalaran_windblade(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Continue please", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(1954, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Let me confer with my colleagues", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(1955, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(3441);
+ break;
+ }
+ return true;
+}
+
+/*######
+## npc_lothos_riftwaker
+######*/
+
+bool GossipHello_npc_lothos_riftwaker(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestRewardStatus(7487) || pPlayer->GetQuestRewardStatus(7848))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Teleport me to the Molten Core", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_lothos_riftwaker(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->TeleportTo(409, 1096.0f, -467.0f, -104.6f, 3.64f);
+ }
+
+ return true;
+}
+
+/*######
+## npc_zamael_lunthistle
+######*/
+
+bool GossipHello_npc_zamael_lunthistle(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(3377) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Tell me your story", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(1920, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_zamael_lunthistle(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Please continue...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(1921, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Goodbye", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(1922, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(3377);
+ break;
+ }
+ return true;
+}
+
+/*######
+##
+######*/
+
+void AddSC_searing_gorge()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_kalaran_windblade";
+ newscript->pGossipHello = &GossipHello_npc_kalaran_windblade;
+ newscript->pGossipSelect = &GossipSelect_npc_kalaran_windblade;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_lothos_riftwaker";
+ newscript->pGossipHello = &GossipHello_npc_lothos_riftwaker;
+ newscript->pGossipSelect = &GossipSelect_npc_lothos_riftwaker;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_zamael_lunthistle";
+ newscript->pGossipHello = &GossipHello_npc_zamael_lunthistle;
+ newscript->pGossipSelect = &GossipSelect_npc_zamael_lunthistle;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp b/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp
new file mode 100644
index 0000000..a612d34
--- /dev/null
+++ b/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp
@@ -0,0 +1,260 @@
+/* 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_Shadowfang_Keep
+SD%Complete: 90
+SDComment:
+SDCategory: Shadowfang Keep
+EndScriptData */
+
+#include "precompiled.h"
+#include "shadowfang_keep.h"
+
+enum
+{
+ MAX_ENCOUNTER = 6,
+
+ SAY_BOSS_DIE_AD = -1033007,
+ SAY_BOSS_DIE_AS = -1033008,
+
+ NPC_ASH = 3850,
+ NPC_ADA = 3849,
+// NPC_ARUGAL = 10000, //"Arugal" says intro text, not used
+ NPC_ARCHMAGE_ARUGAL = 4275, //"Archmage Arugal" does Fenrus event
+ NPC_FENRUS = 4274, //used to summon Arugal in Fenrus event
+ NPC_VINCENT = 4444, //Vincent should be "dead" is Arugal is done the intro already
+
+ GO_COURTYARD_DOOR = 18895, //door to open when talking to NPC's
+ GO_SORCERER_DOOR = 18972, //door to open when Fenrus the Devourer
+ GO_ARUGAL_DOOR = 18971, //door to open when Wolf Master Nandos
+ GO_ARUGAL_FOCUS = 18973 //this generates the lightning visual in the Fenrus event
+};
+
+struct MANGOS_DLL_DECL instance_shadowfang_keep : public ScriptedInstance
+{
+ instance_shadowfang_keep(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint64 m_uiAshGUID;
+ uint64 m_uiAdaGUID;
+
+ uint64 m_uiDoorCourtyardGUID;
+ uint64 m_uiDoorSorcererGUID;
+ uint64 m_uiDoorArugalGUID;
+
+ uint64 m_uiFenrusGUID;
+ uint64 m_uiVincentGUID;
+
+ uint64 m_uiArugalFocusGUID;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiAshGUID = 0;
+ m_uiAdaGUID = 0;
+
+ m_uiDoorCourtyardGUID = 0;
+ m_uiDoorSorcererGUID = 0;
+ m_uiDoorArugalGUID = 0;
+
+ m_uiFenrusGUID = 0;
+ m_uiVincentGUID = 0;
+
+ m_uiArugalFocusGUID = 0;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case NPC_ASH: m_uiAshGUID = pCreature->GetGUID(); break;
+ case NPC_ADA: m_uiAdaGUID = pCreature->GetGUID(); break;
+ case NPC_FENRUS: m_uiFenrusGUID = pCreature->GetGUID(); break;
+ case NPC_VINCENT:
+ m_uiVincentGUID = pCreature->GetGUID();
+ //if Arugal has done the intro, make Vincent dead!
+ if (m_auiEncounter[4] == DONE)
+ pCreature->SetStandState(UNIT_STAND_STATE_DEAD);
+ break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case GO_COURTYARD_DOOR:
+ m_uiDoorCourtyardGUID = pGo->GetGUID();
+ if (m_auiEncounter[0] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ //for this we ignore voidwalkers, because if the server restarts
+ //they won't be there, but Fenrus is dead so the door can't be opened!
+ case GO_SORCERER_DOOR:
+ m_uiDoorSorcererGUID = pGo->GetGUID();
+ if (m_auiEncounter[2] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_ARUGAL_DOOR:
+ m_uiDoorArugalGUID = pGo->GetGUID();
+ if (m_auiEncounter[3] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_ARUGAL_FOCUS:
+ m_uiArugalFocusGUID = pGo->GetGUID();
+ break;
+ }
+ }
+
+ void DoSpeech()
+ {
+ Creature* pAda = instance->GetCreature(m_uiAdaGUID);
+ Creature* pAsh = instance->GetCreature(m_uiAshGUID);
+
+ if (pAda && pAda->isAlive() && pAsh && pAsh->isAlive())
+ {
+ DoScriptText(SAY_BOSS_DIE_AD,pAda);
+ DoScriptText(SAY_BOSS_DIE_AS,pAsh);
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_FREE_NPC:
+ if (uiData == DONE)
+ DoUseDoorOrButton(m_uiDoorCourtyardGUID);
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_RETHILGORE:
+ if (uiData == DONE)
+ DoSpeech();
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_FENRUS:
+ if (uiData == DONE)
+ if (Creature* pFenrus = instance->GetCreature(m_uiFenrusGUID))
+ pFenrus->SummonCreature(NPC_ARCHMAGE_ARUGAL,-136.89f,2169.17f,136.58f,2.794f,TEMPSUMMON_TIMED_DESPAWN,30000);
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_NANDOS:
+ if (uiData == DONE)
+ DoUseDoorOrButton(m_uiDoorArugalGUID);
+ m_auiEncounter[3] = uiData;
+ break;
+ case TYPE_INTRO:
+ m_auiEncounter[4] = uiData;
+ break;
+ case TYPE_VOIDWALKER:
+ if (uiData == DONE)
+ {
+ m_auiEncounter[5]++;
+ if (m_auiEncounter[5] > 3)
+ DoUseDoorOrButton(m_uiDoorSorcererGUID);
+ }
+ break;
+ }
+
+ if (uiData == DONE)
+ {
+ 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];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_FREE_NPC:
+ return m_auiEncounter[0];
+ case TYPE_RETHILGORE:
+ return m_auiEncounter[1];
+ case TYPE_FENRUS:
+ return m_auiEncounter[2];
+ case TYPE_NANDOS:
+ return m_auiEncounter[3];
+ case TYPE_INTRO:
+ return m_auiEncounter[4];
+ }
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case DATA_LIGHTNING:
+ return m_uiArugalFocusGUID;
+ }
+ return 0;
+ }
+
+ const char* Save()
+ {
+ return strInstData.c_str();
+ }
+
+ void Load(const char* chrIn)
+ {
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
+ >> m_auiEncounter[4] >> m_auiEncounter[5];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstanceData_instance_shadowfang_keep(Map* pMap)
+{
+ return new instance_shadowfang_keep(pMap);
+}
+
+void AddSC_instance_shadowfang_keep()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_shadowfang_keep";
+ newscript->GetInstanceData = &GetInstanceData_instance_shadowfang_keep;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp b/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp
new file mode 100644
index 0000000..24ec02d
--- /dev/null
+++ b/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp
@@ -0,0 +1,935 @@
+/* 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: Shadowfang_Keep
+SD%Complete: 75
+SDComment: npc_shadowfang_prisoner using escortAI for movement to door.
+SDCategory: Shadowfang Keep
+EndScriptData */
+
+/* ContentData
+npc_shadowfang_prisoner
+mob_arugal_voidwalker
+npc_arugal
+boss_arugal
+npc_deathstalker_vincent
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+#include "shadowfang_keep.h"
+
+/*######
+## npc_shadowfang_prisoner
+######*/
+
+enum
+{
+ SAY_FREE_AS = -1033000,
+ SAY_OPEN_DOOR_AS = -1033001,
+ SAY_POST_DOOR_AS = -1033002,
+ EMOTE_VANISH_AS = -1033014,
+ SAY_FREE_AD = -1033003,
+ SAY_OPEN_DOOR_AD = -1033004,
+ SAY_POST1_DOOR_AD = -1033005,
+ SAY_POST2_DOOR_AD = -1033006,
+ EMOTE_UNLOCK_DOOR_AD = -1033015,
+
+ SPELL_UNLOCK = 6421,
+ SPELL_FIRE = 6422,
+ NPC_ASH = 3850,
+ NPC_ADA = 3849
+};
+
+#define GOSSIP_ITEM_DOOR "Please unlock the courtyard door."
+
+struct MANGOS_DLL_DECL npc_shadowfang_prisonerAI : public npc_escortAI
+{
+ npc_shadowfang_prisonerAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_uiNpcEntry = pCreature->GetEntry();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ uint32 m_uiNpcEntry;
+
+ void WaypointReached(uint32 uiPoint)
+ {
+ switch(uiPoint)
+ {
+ case 0:
+ if (m_uiNpcEntry == NPC_ASH)
+ DoScriptText(SAY_FREE_AS, m_creature);
+ else
+ DoScriptText(SAY_FREE_AD, m_creature);
+ break;
+ case 10:
+ if (m_uiNpcEntry == NPC_ASH)
+ DoScriptText(SAY_OPEN_DOOR_AS, m_creature);
+ else
+ DoScriptText(SAY_OPEN_DOOR_AD, m_creature);
+ break;
+ case 11:
+ if (m_uiNpcEntry == NPC_ASH)
+ DoCastSpellIfCan(m_creature, SPELL_UNLOCK);
+ else
+ DoScriptText(EMOTE_UNLOCK_DOOR_AD, m_creature);
+ break;
+ case 12:
+ if (m_uiNpcEntry != NPC_ASH)
+ m_creature->HandleEmote(EMOTE_ONESHOT_USESTANDING);
+ break;
+ case 13:
+ if (m_uiNpcEntry == NPC_ASH)
+ DoScriptText(SAY_POST_DOOR_AS, m_creature);
+ else
+ DoScriptText(SAY_POST1_DOOR_AD, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_FREE_NPC, DONE);
+ break;
+ case 14:
+ if (m_uiNpcEntry == NPC_ASH)
+ DoCastSpellIfCan(m_creature, SPELL_FIRE);
+ else
+ {
+ DoScriptText(SAY_POST2_DOOR_AD, m_creature);
+ SetRun();
+ }
+ break;
+ case 15:
+ if (m_uiNpcEntry == NPC_ASH)
+ DoScriptText(EMOTE_VANISH_AS, m_creature);
+ break;
+ }
+ }
+
+ void Reset() {}
+
+ //let's prevent Adamant from charging into Ashcrombe's cell
+ //and beating the crap out of him and vice versa XD
+ void AttackStart(Unit* pWho)
+ {
+ if (pWho)
+ {
+ if (pWho->GetEntry() == NPC_ASH || pWho->GetEntry() == NPC_ADA)
+ return;
+ else
+ ScriptedAI::AttackStart(pWho);
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_shadowfang_prisoner(Creature* pCreature)
+{
+ return new npc_shadowfang_prisonerAI(pCreature);
+}
+
+bool GossipHello_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature)
+{
+ ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+
+ if (pInstance && pInstance->GetData(TYPE_FREE_NPC) != DONE && pInstance->GetData(TYPE_RETHILGORE) == DONE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DOOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_shadowfang_prisoner(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (npc_shadowfang_prisonerAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start();
+ }
+ return true;
+}
+
+/*######
+## mob_arugal_voidwalker
+######*/
+
+struct Waypoint
+{
+ float fX, fY, fZ;
+};
+
+//Cordinates for voidwalker spawns
+static const Waypoint VWWaypoints[]=
+{
+ //fX fY fZ
+ {-146.06f, 2172.84f, 127.953f}, //this is the initial location, in the middle of the room
+ {-159.547f, 2178.11f, 128.944f}, //when they come back up, they hit this point then walk back down
+ {-171.113f, 2182.69f, 129.255f},
+ {-177.613f, 2175.59f, 128.161f},
+ {-185.396f, 2178.35f, 126.413f},
+ {-184.004f, 2188.31f, 124.122f},
+ {-172.781f, 2188.71f, 121.611f},
+ {-173.245f, 2176.93f, 119.085f},
+ {-183.145f, 2176.04f, 116.995f},
+ {-185.551f, 2185.77f, 114.784f},
+ {-177.502f, 2190.75f, 112.681f},
+ {-171.218f, 2182.61f, 110.314f},
+ {-173.857f, 2175.1f, 109.255f}
+};
+
+enum
+{
+ LAST_WAYPOINT = 12,
+
+ NPC_VOIDWALKER = 4627,
+
+ SPELL_DARK_OFFERING = 7154
+};
+
+struct MANGOS_DLL_DECL mob_arugal_voidwalkerAI : public ScriptedAI
+{
+ mob_arugal_voidwalkerAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bIsLeader = false;
+ m_uiLeaderGUID = 0;
+ m_uiCurrentPoint = 0;
+ m_bReverse = false;
+ }
+
+ uint32 m_uiResetTimer, m_uiDarkOffering;
+ uint8 m_uiCurrentPoint, m_uiPosition; //0 - leader, 1 - behind-right, 2 - behind, 3 - behind-left
+ uint64 m_uiLeaderGUID;
+ ScriptedInstance* m_pInstance;
+ bool m_bIsLeader, m_bReverse, m_bWPDone;
+
+ void Reset()
+ {
+ m_creature->AddSplineFlag(SPLINEFLAG_WALKMODE);
+ m_uiDarkOffering = urand(4400,12500);
+ m_bWPDone = true;
+
+ Creature* pLeader = m_creature->GetMap()->GetCreature(m_uiLeaderGUID);
+ if (pLeader && pLeader->isAlive())
+ {
+ m_creature->GetMotionMaster()->MoveFollow(pLeader, 1.0f, M_PI/2*m_uiPosition);
+ }
+ else
+ {
+ std::list lVoidwalkerList;
+ Creature* pNewLeader = NULL;
+ uint8 uiHighestPosition = 0;
+ GetCreatureListWithEntryInGrid(lVoidwalkerList, m_creature, NPC_VOIDWALKER, 50.0f);
+ for(std::list::iterator itr = lVoidwalkerList.begin(); itr != lVoidwalkerList.end(); ++itr)
+ {
+ if ((*itr)->isAlive())
+ {
+ if (mob_arugal_voidwalkerAI* pVoidwalkerAI = dynamic_cast((*itr)->AI()))
+ {
+ uint8 uiPosition = pVoidwalkerAI->GetPosition();
+ if (uiPosition > uiHighestPosition)
+ {
+ pNewLeader = (*itr);
+ uiHighestPosition = uiPosition;
+ }
+ }
+ }
+ }
+
+ if (pNewLeader)
+ {
+ m_uiLeaderGUID = pNewLeader->GetGUID();
+ if (pNewLeader == m_creature)
+ {
+ m_bIsLeader = true;
+ m_bWPDone = true;
+ }
+ else
+ m_creature->GetMotionMaster()->MoveFollow(pNewLeader, 1.0f, M_PI/2*m_uiPosition);
+ }
+ else
+ {
+ pNewLeader = m_creature;
+ m_bIsLeader = true;
+ m_bWPDone = true;
+ }
+ }
+ }
+
+ //this is the ACID script converted into C++
+ //unfortunately, we can't have both AIs at the same time :(
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_bIsLeader && m_bWPDone)
+ {
+ m_creature->GetMotionMaster()->MovePoint(m_uiCurrentPoint, VWWaypoints[m_uiCurrentPoint].fX,
+ VWWaypoints[m_uiCurrentPoint].fY, VWWaypoints[m_uiCurrentPoint].fZ);
+ m_bWPDone = false;
+ }
+
+ if (!m_creature->isInCombat())
+ return;
+
+ if (m_uiDarkOffering < uiDiff)
+ {
+ m_uiDarkOffering = urand(4400,12500);
+
+ if (Unit* pUnit = DoSelectLowestHpFriendly(10.0f, 290))
+ DoCastSpellIfCan(pUnit, SPELL_DARK_OFFERING);
+ }
+ else
+ m_uiDarkOffering -= uiDiff;
+
+ //Check if we have a current target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+
+ void MovementInform(uint32 uiMoveType, uint32 uiPointId)
+ {
+ if (uiMoveType != POINT_MOTION_TYPE || !m_bIsLeader)
+ return;
+
+ switch(uiPointId)
+ {
+ case 1:
+ if (m_bReverse)
+ m_bReverse = false;
+ break;
+ case LAST_WAYPOINT:
+ if (!m_bReverse)
+ m_bReverse = true;
+ break;
+ }
+
+ if (m_bReverse)
+ --m_uiCurrentPoint;
+ else
+ ++m_uiCurrentPoint;
+
+ m_bWPDone = true;
+
+ SendWaypoint();
+ }
+
+ void JustDied(Unit* /*pKiller*/)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_VOIDWALKER,DONE);
+ }
+
+ void SetPosition(uint8 uiPosition, Creature* pLeader)
+ {
+ m_uiPosition = uiPosition;
+
+ if (!uiPosition)
+ m_bIsLeader = true;
+ else
+ pLeader ? m_uiLeaderGUID = pLeader->GetGUID() : m_uiLeaderGUID = 0;
+
+ Reset();
+ }
+
+ uint8 GetPosition()
+ {
+ return m_uiPosition;
+ }
+
+ void SendWaypoint()
+ {
+ std::list lVoidwalkerList;
+ GetCreatureListWithEntryInGrid(lVoidwalkerList, m_creature, NPC_VOIDWALKER, 50.0f);
+ for(std::list::iterator itr = lVoidwalkerList.begin(); itr != lVoidwalkerList.end(); ++itr)
+ {
+ if ((*itr)->isAlive())
+ if (mob_arugal_voidwalkerAI* pVoidwalkerAI = dynamic_cast((*itr)->AI()))
+ pVoidwalkerAI->ReceiveWaypoint(m_uiCurrentPoint, m_bReverse);
+ }
+ }
+
+ void ReceiveWaypoint(uint32 uiNewPoint, bool bReverse)
+ {
+ m_uiCurrentPoint = uiNewPoint;
+ m_bReverse = bReverse;
+ }
+
+ void EnterEvadeMode()
+ {
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(true);
+ m_creature->LoadCreatureAddon();
+
+ m_creature->SetLootRecipient(NULL);
+
+ Reset();
+ }
+};
+
+CreatureAI* GetAI_mob_arugal_voidwalker(Creature* pCreature)
+{
+ return new mob_arugal_voidwalkerAI(pCreature);
+}
+
+/*######
+## boss_arugal
+######*/
+
+enum
+{
+ SPELL_VOID_BOLT = 7588,
+ SPELL_SHADOW_PORT_UPPER_LEDGE = 7587,
+ SPELL_SHADOW_PORT_SPAWN_LEDGE = 7586,
+ SPELL_SHADOW_PORT_STAIRS = 7136,
+ SPELL_ARUGALS_CURSE = 7621,
+ SPELL_THUNDERSHOCK = 7803,
+
+ YELL_AGGRO = -1033017,
+ YELL_KILLED_PLAYER = -1033018,
+ YELL_COMBAT = -1033019,
+ YELL_FENRUS = -1033013
+};
+
+enum ArugalPosition
+{
+ POSITION_SPAWN_LEDGE = 1,
+ POSITION_UPPER_LEDGE,
+ POSITION_STAIRS
+};
+
+struct SpawnPoint
+{
+ float fX, fY, fZ, fO;
+};
+
+//Cordinates for voidwalker spawns
+static const SpawnPoint VWSpawns[]=
+{
+ //fX fY fZ fO
+ {-155.352f, 2172.780f, 128.448f, 4.679f},
+ {-147.059f, 2163.193f, 128.696f, 0.128f},
+ {-148.869f, 2180.859f, 128.448f, 1.814f},
+ {-140.203f, 2175.263f, 128.448f, 0.373f},
+};
+
+//roughly the height of Fenrus' room,
+//used to tell how he should behave
+const float HEIGHT_FENRUS_ROOM = 140.0f;
+
+struct MANGOS_DLL_DECL boss_arugalAI : public ScriptedAI
+{
+ boss_arugalAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+
+ if (pCreature->GetPositionZ() < HEIGHT_FENRUS_ROOM)
+ {
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ m_bEventMode = true;
+ }
+ else
+ m_bEventMode = false;
+
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ ArugalPosition m_posPosition;
+ uint32 m_uiTeleportTimer, m_uiCurseTimer, m_uiVoidboltTimer, m_uiThundershockTimer, m_uiYellTimer, m_uiSpeechTimer;
+ uint8 m_uiSpeechStep;
+ bool m_bAttacking, m_bEventMode;
+
+ void Reset()
+ {
+ m_uiTeleportTimer = urand(22000, 26000);
+ m_uiCurseTimer = urand(20000, 30000);
+ m_uiVoidboltTimer = m_uiThundershockTimer = m_uiSpeechTimer = 0;
+ m_uiYellTimer = urand(32000, 46000);
+ m_bAttacking = true;
+ m_posPosition = POSITION_SPAWN_LEDGE;
+ m_uiSpeechStep = 1;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(YELL_AGGRO, m_creature);
+ DoCastSpellIfCan(pWho, SPELL_VOID_BOLT);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (pVictim->GetTypeId() == TYPEID_PLAYER)
+ DoScriptText(YELL_KILLED_PLAYER, m_creature);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_bEventMode)
+ {
+ if (!m_uiSpeechStep)
+ return;
+
+ if (m_uiSpeechTimer < uiDiff)
+ {
+ switch(m_uiSpeechStep)
+ {
+ case 1:
+ DoScriptText(YELL_FENRUS, m_creature);
+ m_creature->SetVisibility(VISIBILITY_ON);
+ m_uiSpeechTimer = 2000;
+ break;
+ case 2:
+ DoCastSpellIfCan(m_creature, SPELL_FIRE);
+ m_uiSpeechTimer = 5000;
+ break;
+ case 3:
+ if (m_pInstance)
+ if (GameObject* pLightning = m_creature->GetMap()->GetGameObject(m_pInstance->GetData64(DATA_LIGHTNING)))
+ pLightning->Use(m_creature);
+
+ m_uiSpeechTimer = 5000;
+ break;
+ case 4:
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ m_uiSpeechTimer = 500;
+ break;
+ case 5:
+ Creature *pVoidwalker, *pLeader;
+ pVoidwalker = pLeader = NULL;
+
+ for(uint8 i = 0; i < 4; i++)
+ {
+ pVoidwalker = m_creature->SummonCreature(NPC_VOIDWALKER,VWSpawns[i].fX,
+ VWSpawns[i].fY, VWSpawns[i].fZ, VWSpawns[i].fO, TEMPSUMMON_DEAD_DESPAWN, 1);
+
+ if (!pVoidwalker)
+ continue;
+
+ if (!i)
+ pLeader = pVoidwalker;
+
+ if (mob_arugal_voidwalkerAI* pVoidwalkerAI = dynamic_cast(pVoidwalker->AI()))
+ pVoidwalkerAI->SetPosition(i,pLeader);
+
+ pVoidwalker = NULL;
+ }
+ m_uiSpeechStep = 0;
+ return;
+ default:
+ m_uiSpeechStep = 0;
+ return;
+ }
+ ++m_uiSpeechStep;
+ }
+ else
+ m_uiSpeechTimer -= uiDiff;
+
+ return;
+ }
+
+ //Check if we have a current target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (GetManaPercent() < 6.0f && !m_bAttacking)
+ {
+ if (m_posPosition != POSITION_UPPER_LEDGE)
+ StartAttacking();
+ else if (m_uiTeleportTimer > 2000)
+ m_uiTeleportTimer = 2000;
+
+ m_bAttacking = true;
+ }
+ else if (GetManaPercent() > 12.0f && m_bAttacking)
+ {
+ StopAttacking();
+ m_bAttacking = false;
+ }
+
+ if (m_uiYellTimer < uiDiff)
+ {
+ DoScriptText(YELL_COMBAT, m_creature);
+ m_uiYellTimer = urand(34000, 68000);
+ }
+ else
+ m_uiYellTimer -= uiDiff;
+
+ if (m_uiCurseTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
+ DoCastSpellIfCan(pTarget, SPELL_ARUGALS_CURSE);
+
+ m_uiCurseTimer = urand(20000, 35000);
+ }
+ else
+ m_uiCurseTimer -= uiDiff;
+
+ if (m_uiThundershockTimer < uiDiff)
+ {
+ if (GetVictimDistance() < 5.0f)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_THUNDERSHOCK);
+ m_uiThundershockTimer = urand(30200, 38500);
+ }
+ }
+ else
+ m_uiThundershockTimer -= uiDiff;
+
+ if (m_uiVoidboltTimer < uiDiff)
+ {
+ if (!m_bAttacking)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_VOID_BOLT);
+ m_uiVoidboltTimer = urand(2900, 4800);
+ }
+ }
+ else
+ m_uiVoidboltTimer -= uiDiff;
+
+ if (m_uiTeleportTimer < uiDiff)
+ {
+ ArugalPosition posNewPosition;
+
+ if (m_posPosition == POSITION_SPAWN_LEDGE)
+ posNewPosition = (ArugalPosition)urand(2, 3);
+ else
+ {
+ posNewPosition = (ArugalPosition)urand(1, 2);
+
+ if (m_posPosition == posNewPosition)
+ posNewPosition = POSITION_STAIRS;
+ }
+
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ switch(posNewPosition)
+ {
+ case POSITION_SPAWN_LEDGE:
+ DoCastSpellIfCan(m_creature, SPELL_SHADOW_PORT_SPAWN_LEDGE, true);
+ break;
+ case POSITION_UPPER_LEDGE:
+ DoCastSpellIfCan(m_creature, SPELL_SHADOW_PORT_UPPER_LEDGE, true);
+ break;
+ case POSITION_STAIRS:
+ DoCastSpellIfCan(m_creature, SPELL_SHADOW_PORT_STAIRS, true);
+ break;
+ }
+
+ if (GetManaPercent() < 6.0f)
+ {
+ if (posNewPosition == POSITION_UPPER_LEDGE)
+ {
+ StopAttacking();
+ m_uiTeleportTimer = urand(2000, 2200);
+ }
+ else
+ {
+ StartAttacking();
+ m_uiTeleportTimer = urand(48000, 55000);
+ }
+ }
+ else
+ m_uiTeleportTimer = urand(48000, 55000);
+
+ m_posPosition = posNewPosition;
+ }
+ else
+ m_uiTeleportTimer -= uiDiff;
+
+ if (m_bAttacking)
+ DoMeleeAttackIfReady();
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (!m_bEventMode)
+ ScriptedAI::AttackStart(pWho);
+ }
+
+ //make the code nice and pleasing to the eye
+ inline float GetManaPercent()
+ {
+ return (((float)m_creature->GetPower(POWER_MANA) / (float)m_creature->GetMaxPower(POWER_MANA)) * 100);
+ }
+
+ inline float GetVictimDistance()
+ {
+ return (m_creature->getVictim() ? m_creature->GetDistance2d(m_creature->getVictim()) : 999.9f);
+ }
+
+ void StopAttacking()
+ {
+ if (Unit* victim = m_creature->getVictim())
+ m_creature->SendMeleeAttackStop(victim);
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
+ {
+ m_creature->GetMotionMaster()->Clear(false);
+ m_creature->GetMotionMaster()->MoveIdle();
+ m_creature->StopMoving();
+ }
+ }
+
+ void StartAttacking()
+ {
+ if (Unit* victim = m_creature->getVictim())
+ m_creature->SendMeleeAttackStart(victim);
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == IDLE_MOTION_TYPE)
+ {
+ m_creature->GetMotionMaster()->Clear(false);
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), 0.0f, 0.0f);
+ }
+ }
+};
+
+CreatureAI* GetAI_boss_arugal(Creature* pCreature)
+{
+ return new boss_arugalAI(pCreature);
+}
+
+/*######
+## npc_arugal
+######*/
+
+enum
+{
+ SAY_INTRO_1 = -1033009,
+ SAY_INTRO_2 = -1033010,
+ SAY_INTRO_3 = -1033011,
+ SAY_INTRO_4 = -1033012,
+
+ SPELL_SPAWN = 7741,
+
+ NPC_VINCENT = 4444
+};
+
+struct MANGOS_DLL_DECL npc_arugalAI : public ScriptedAI
+{
+ npc_arugalAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ uint32 m_uiSpeechTimer;
+ uint8 m_uiSpeechStep;
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ m_uiSpeechTimer = 0;
+ m_uiSpeechStep = 0;
+
+ m_creature->SetVisibility(VISIBILITY_OFF);
+
+ if (m_pInstance && m_pInstance->GetData(TYPE_INTRO) == NOT_STARTED)
+ m_uiSpeechStep = 1;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_uiSpeechStep)
+ return;
+
+ if (m_uiSpeechTimer < uiDiff)
+ {
+ switch(m_uiSpeechStep)
+ {
+ case 1:
+ m_creature->SetVisibility(VISIBILITY_ON);
+ m_uiSpeechTimer = 500;
+ break;
+ case 2:
+ DoCastSpellIfCan(m_creature, SPELL_SPAWN);
+ m_uiSpeechTimer = 2000;
+ break;
+ case 3:
+ //make him die
+ if (Creature* pVincent = GetClosestCreatureWithEntry(m_creature,NPC_VINCENT,20.0f))
+ pVincent->SetStandState(UNIT_STAND_STATE_DEAD);
+
+ m_uiSpeechTimer = 10000;
+ break;
+ case 4:
+ DoScriptText(SAY_INTRO_1, m_creature);
+ //m_creature->HandleEmote(EMOTE_ONESHOT_TALK);
+ m_uiSpeechTimer = 1750;
+ break;
+ case 5:
+ m_creature->HandleEmote(EMOTE_ONESHOT_POINT);
+ m_uiSpeechTimer = 1750;
+ break;
+ case 6:
+ DoScriptText(SAY_INTRO_2, m_creature);
+ m_uiSpeechTimer = 1750;
+ break;
+ case 7:
+ m_creature->HandleEmote(EMOTE_ONESHOT_EXCLAMATION);
+ m_uiSpeechTimer = 1750;
+ break;
+ case 8:
+ //m_creature->HandleEmote(EMOTE_ONESHOT_TALK);
+ DoScriptText(SAY_INTRO_3, m_creature);
+ m_uiSpeechTimer = 1750;
+ break;
+ case 9:
+ m_creature->HandleEmote(EMOTE_ONESHOT_LAUGH);
+ m_uiSpeechTimer = 1750;
+ break;
+ case 10:
+ DoScriptText(SAY_INTRO_4, m_creature);
+ m_uiSpeechTimer = 2000;
+ break;
+ case 11:
+ DoCastSpellIfCan(m_creature, SPELL_SPAWN);
+ m_uiSpeechTimer = 500;
+ break;
+ case 12:
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_INTRO,DONE);
+
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ m_uiSpeechStep = 0;
+ return;
+ default:
+ m_uiSpeechStep = 0;
+ return;
+ }
+ ++m_uiSpeechStep;
+ }
+ else
+ m_uiSpeechTimer -= uiDiff;
+ }
+
+ void AttackStart(Unit* /*who*/) { }
+};
+
+CreatureAI* GetAI_npc_arugal(Creature* pCreature)
+{
+ return new npc_arugalAI(pCreature);
+}
+
+/*######
+## npc_deathstalker_vincent
+######*/
+
+enum
+{
+ SAY_VINCENT_DIE = -1033016,
+
+ FACTION_FRIENDLY = 35
+};
+
+struct MANGOS_DLL_DECL npc_deathstalker_vincentAI : public ScriptedAI
+{
+ npc_deathstalker_vincentAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ if (m_pInstance && m_pInstance->GetData(TYPE_INTRO) == DONE && !m_creature->GetByteValue(UNIT_FIELD_BYTES_1, 0))
+ m_creature->SetStandState(UNIT_STAND_STATE_DEAD);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32& uiDamage)
+ {
+ if (pDoneBy)
+ {
+ m_creature->SetInCombatWith(pDoneBy);
+ pDoneBy->SetInCombatWith(m_creature);
+ }
+
+ if (m_creature->getStandState())
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ if (uiDamage >= m_creature->GetHealth())
+ {
+ m_creature->GetHealth() > 1 ? uiDamage = m_creature->GetHealth() - 1 : uiDamage = 0;
+ m_creature->setFaction(FACTION_FRIENDLY);
+ EnterEvadeMode();
+ DoScriptText(SAY_VINCENT_DIE, m_creature);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_creature->isInCombat() && m_creature->getFaction() == FACTION_FRIENDLY)
+ EnterEvadeMode();
+
+ ScriptedAI::UpdateAI(uiDiff);
+ }
+
+ void EnterEvadeMode()
+ {
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(true);
+ m_creature->LoadCreatureAddon();
+
+ m_creature->SetLootRecipient(NULL);
+
+ Reset();
+ }
+};
+
+CreatureAI* GetAI_npc_deathstalker_vincent(Creature* pCreature)
+{
+ return new npc_deathstalker_vincentAI(pCreature);
+}
+
+void AddSC_shadowfang_keep()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_shadowfang_prisoner";
+ newscript->pGossipHello = &GossipHello_npc_shadowfang_prisoner;
+ newscript->pGossipSelect = &GossipSelect_npc_shadowfang_prisoner;
+ newscript->GetAI = &GetAI_npc_shadowfang_prisoner;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_arugal_voidwalker";
+ newscript->GetAI = &GetAI_mob_arugal_voidwalker;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_arugal";
+ newscript->GetAI = &GetAI_npc_arugal;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_arugal";
+ newscript->GetAI = &GetAI_boss_arugal;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_deathstalker_vincent";
+ newscript->GetAI = &GetAI_npc_deathstalker_vincent;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h b/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h
new file mode 100644
index 0000000..3cfe4e8
--- /dev/null
+++ b/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h
@@ -0,0 +1,19 @@
+/* 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 */
+
+#ifndef DEF_SHADOWFANG_H
+#define DEF_SHADOWFANG_H
+
+enum
+{
+ TYPE_FREE_NPC = 1,
+ TYPE_RETHILGORE = 2,
+ TYPE_FENRUS = 3,
+ TYPE_NANDOS = 4,
+ TYPE_INTRO = 5,
+ TYPE_VOIDWALKER = 6,
+ DATA_LIGHTNING = 7
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/silvermoon_city.cpp b/scripts/eastern_kingdoms/silvermoon_city.cpp
new file mode 100644
index 0000000..d62c924
--- /dev/null
+++ b/scripts/eastern_kingdoms/silvermoon_city.cpp
@@ -0,0 +1,96 @@
+/* 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: Silvermoon_City
+SD%Complete: 100
+SDComment: Quest support: 9685
+SDCategory: Silvermoon City
+EndScriptData */
+
+/* ContentData
+npc_blood_knight_stillblade
+EndContentData */
+
+#include "precompiled.h"
+
+/*#######
+# npc_blood_knight_stillblade
+#######*/
+
+#define SAY_HEAL -1000193
+
+#define QUEST_REDEEMING_THE_DEAD 9685
+#define SPELL_SHIMMERING_VESSEL 31225
+#define SPELL_REVIVE_SELF 32343
+
+struct MANGOS_DLL_DECL npc_blood_knight_stillbladeAI : public ScriptedAI
+{
+ npc_blood_knight_stillbladeAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 lifeTimer;
+ bool spellHit;
+
+ void Reset()
+ {
+ lifeTimer = 120000;
+ m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_DEAD);
+ m_creature->SetStandState(UNIT_STAND_STATE_DEAD);
+ spellHit = false;
+ }
+
+ void MoveInLineOfSight(Unit *who) { }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (m_creature->IsStandState())
+ {
+ if (lifeTimer < diff)
+ m_creature->AI()->EnterEvadeMode();
+ else
+ lifeTimer -= diff;
+ }
+ }
+
+ void SpellHit(Unit *Hitter, const SpellEntry *Spellkind)
+ {
+ if ((Spellkind->Id == SPELL_SHIMMERING_VESSEL) && !spellHit &&
+ (Hitter->GetTypeId() == TYPEID_PLAYER) && (((Player*)Hitter)->IsActiveQuest(QUEST_REDEEMING_THE_DEAD)))
+ {
+ ((Player*)Hitter)->AreaExploredOrEventHappens(QUEST_REDEEMING_THE_DEAD);
+ DoCastSpellIfCan(m_creature,SPELL_REVIVE_SELF);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
+ //m_creature->RemoveAllAuras();
+ DoScriptText(SAY_HEAL, m_creature, Hitter);
+ spellHit = true;
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_blood_knight_stillblade(Creature* pCreature)
+{
+ return new npc_blood_knight_stillbladeAI(pCreature);
+}
+
+void AddSC_silvermoon_city()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "npc_blood_knight_stillblade";
+ newscript->GetAI = &GetAI_npc_blood_knight_stillblade;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/silverpine_forest.cpp b/scripts/eastern_kingdoms/silverpine_forest.cpp
new file mode 100644
index 0000000..0932281
--- /dev/null
+++ b/scripts/eastern_kingdoms/silverpine_forest.cpp
@@ -0,0 +1,415 @@
+/* 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: Silverpine_Forest
+SD%Complete: 100
+SDComment: Quest support: 435, 452, 1886
+SDCategory: Silverpine Forest
+EndScriptData */
+
+/* ContentData
+npc_astor_hadren
+npc_deathstalker_erland
+npc_deathstalker_faerleia
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_astor_hadren
+######*/
+
+struct MANGOS_DLL_DECL npc_astor_hadrenAI : public ScriptedAI
+{
+ npc_astor_hadrenAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ m_creature->setFaction(68);
+ }
+
+ void JustDied(Unit *who)
+ {
+ m_creature->setFaction(68);
+ }
+};
+
+CreatureAI* GetAI_npc_astor_hadren(Creature *_creature)
+{
+ return new npc_astor_hadrenAI(_creature);
+}
+
+bool GossipHello_npc_astor_hadren(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(1886) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "You're Astor Hadren, right?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+
+ pPlayer->SEND_GOSSIP_MENU(623, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_astor_hadren(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF + 1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "You've got something I need, Astor. And I'll be taking it now.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(624, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 2:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->setFaction(21);
+ pCreature->AI()->AttackStart(pPlayer);
+ break;
+ }
+ return true;
+}
+
+/*#####
+## npc_deathstalker_erland
+#####*/
+
+enum
+{
+ SAY_START_1 = -1000306,
+ SAY_START_2 = -1000307,
+ SAY_AGGRO_1 = -1000308,
+ SAY_AGGRO_2 = -1000309,
+ SAY_AGGRO_3 = -1000310,
+ SAY_PROGRESS = -1000311,
+ SAY_END = -1000312,
+ SAY_RANE = -1000313,
+ SAY_RANE_REPLY = -1000314,
+ SAY_CHECK_NEXT = -1000315,
+ SAY_QUINN = -1000316,
+ SAY_QUINN_REPLY = -1000317,
+ SAY_BYE = -1000318,
+
+ QUEST_ERLAND = 435,
+ NPC_RANE = 1950,
+ NPC_QUINN = 1951
+};
+
+struct MANGOS_DLL_DECL npc_deathstalker_erlandAI : public npc_escortAI
+{
+ npc_deathstalker_erlandAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ uiRaneGUID = 0;
+ uiQuinnGUID = 0;
+ Reset();
+ }
+
+ uint64 uiRaneGUID;
+ uint64 uiQuinnGUID;
+
+ void MoveInLineOfSight(Unit* pUnit)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ if (!uiRaneGUID && pUnit->GetEntry() == NPC_RANE)
+ {
+ if (m_creature->IsWithinDistInMap(pUnit, 30.0f))
+ uiRaneGUID = pUnit->GetGUID();
+ }
+ if (!uiQuinnGUID && pUnit->GetEntry() == NPC_QUINN)
+ {
+ if (m_creature->IsWithinDistInMap(pUnit, 30.0f))
+ uiQuinnGUID = pUnit->GetGUID();
+ }
+ }
+
+ npc_escortAI::MoveInLineOfSight(pUnit);
+ }
+
+ void WaypointReached(uint32 i)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch(i)
+ {
+ case 0:
+ DoScriptText(SAY_START_2, m_creature, pPlayer);
+ break;
+ case 13:
+ DoScriptText(SAY_END, m_creature, pPlayer);
+ pPlayer->GroupEventHappens(QUEST_ERLAND, m_creature);
+ break;
+ case 14:
+ if (Creature* pRane = m_creature->GetMap()->GetCreature(uiRaneGUID))
+ DoScriptText(SAY_RANE, pRane, m_creature);
+ break;
+ case 15:
+ DoScriptText(SAY_RANE_REPLY, m_creature);
+ break;
+ case 16:
+ DoScriptText(SAY_CHECK_NEXT, m_creature);
+ break;
+ case 24:
+ DoScriptText(SAY_QUINN, m_creature);
+ break;
+ case 25:
+ if (Creature* pQuinn = m_creature->GetMap()->GetCreature(uiQuinnGUID))
+ DoScriptText(SAY_QUINN_REPLY, pQuinn, m_creature);
+ break;
+ case 26:
+ DoScriptText(SAY_BYE, m_creature);
+ break;
+ }
+ }
+
+ void Reset()
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ uiRaneGUID = 0;
+ uiQuinnGUID = 0;
+ }
+ }
+
+ void Aggro(Unit* who)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_AGGRO_1, m_creature, who); break;
+ case 1: DoScriptText(SAY_AGGRO_2, m_creature, who); break;
+ case 2: DoScriptText(SAY_AGGRO_3, m_creature, who); break;
+ }
+ }
+};
+
+bool QuestAccept_npc_deathstalker_erland(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_ERLAND)
+ {
+ DoScriptText(SAY_START_1, pCreature);
+
+ if (npc_deathstalker_erlandAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_deathstalker_erland(Creature* pCreature)
+{
+ return new npc_deathstalker_erlandAI(pCreature);
+}
+
+/*#####
+## npc_deathstalker_faerleia
+#####*/
+
+enum
+{
+ QUEST_PYREWOOD_AMBUSH = 452,
+
+ // cast it after every wave
+ SPELL_DRINK_POTION = 3359,
+
+ SAY_START = -1000553,
+ SAY_COMPLETED = -1000554,
+
+ // 1st wave
+ NPC_COUNCILMAN_SMITHERS = 2060,
+ // 2nd wave
+ NPC_COUNCILMAN_THATHER = 2061,
+ NPC_COUNCILMAN_HENDRICKS = 2062,
+ // 3rd wave
+ NPC_COUNCILMAN_WILHELM = 2063,
+ NPC_COUNCILMAN_HARTIN = 2064,
+ NPC_COUNCILMAN_HIGARTH = 2066,
+ // final wave
+ NPC_COUNCILMAN_COOPER = 2065,
+ NPC_COUNCILMAN_BRUNSWICK = 2067,
+ NPC_LORD_MAYOR_MORRISON = 2068
+};
+
+struct SpawnPoint
+{
+ float fX;
+ float fY;
+ float fZ;
+ float fO;
+};
+
+SpawnPoint SpawnPoints[] =
+{
+ {-397.45f, 1509.56f, 18.87f, 4.73f},
+ {-398.35f, 1510.75f, 18.87f, 4.76f},
+ {-396.41f, 1511.06f, 18.87f, 4.74f}
+};
+
+static float m_afMoveCoords[] = {-410.69f, 1498.04f, 19.77f};
+
+struct MANGOS_DLL_DECL npc_deathstalker_faerleiaAI : public ScriptedAI
+{
+ npc_deathstalker_faerleiaAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ }
+
+ uint64 m_uiPlayerGUID;
+ uint32 m_uiWaveTimer;
+ uint32 m_uiSummonCount;
+ uint8 m_uiWaveCount;
+ bool m_bEventStarted;
+
+ void StartEvent(uint64 uiPlayerGUID)
+ {
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+
+ m_uiPlayerGUID = uiPlayerGUID;
+ m_bEventStarted = true;
+ m_uiWaveTimer = 10000;
+ m_uiSummonCount = 0;
+ m_uiWaveCount = 0;
+ }
+
+ void FinishEvent()
+ {
+ m_uiPlayerGUID = 0;
+ m_bEventStarted = false;
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID))
+ pPlayer->SendQuestFailed(QUEST_PYREWOOD_AMBUSH);
+
+ FinishEvent();
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ ++m_uiSummonCount;
+
+ // put them on correct waypoints later on
+ float fX, fY, fZ;
+ pSummoned->GetRandomPoint(m_afMoveCoords[0], m_afMoveCoords[1], m_afMoveCoords[2], 10.0f, fX, fY, fZ);
+ pSummoned->GetMotionMaster()->MovePoint(0, fX, fY, fZ);
+ }
+
+ void SummonedCreatureJustDied(Creature* pKilled)
+ {
+ --m_uiSummonCount;
+
+ if (!m_uiSummonCount)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_DRINK_POTION);
+
+ // final wave
+ if (m_uiWaveCount == 4)
+ {
+ DoScriptText(SAY_COMPLETED, m_creature);
+
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID))
+ pPlayer->GroupEventHappens(QUEST_PYREWOOD_AMBUSH, m_creature);
+
+ FinishEvent();
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_bEventStarted && !m_uiSummonCount)
+ {
+ if (m_uiWaveTimer < uiDiff)
+ {
+ switch(m_uiWaveCount)
+ {
+ case 0:
+ m_creature->SummonCreature(NPC_COUNCILMAN_SMITHERS, SpawnPoints[1].fX, SpawnPoints[1].fY, SpawnPoints[1].fZ, SpawnPoints[1].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ m_uiWaveTimer = 10000;
+ break;
+ case 1:
+ m_creature->SummonCreature(NPC_COUNCILMAN_THATHER, SpawnPoints[2].fX, SpawnPoints[2].fY, SpawnPoints[2].fZ, SpawnPoints[2].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ m_creature->SummonCreature(NPC_COUNCILMAN_HENDRICKS, SpawnPoints[1].fX, SpawnPoints[1].fY, SpawnPoints[1].fZ, SpawnPoints[1].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ m_uiWaveTimer = 10000;
+ break;
+ case 2:
+ m_creature->SummonCreature(NPC_COUNCILMAN_WILHELM, SpawnPoints[1].fX, SpawnPoints[1].fY, SpawnPoints[1].fZ, SpawnPoints[1].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ m_creature->SummonCreature(NPC_COUNCILMAN_HARTIN, SpawnPoints[0].fX, SpawnPoints[0].fY, SpawnPoints[0].fZ, SpawnPoints[0].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ m_creature->SummonCreature(NPC_COUNCILMAN_HIGARTH, SpawnPoints[2].fX, SpawnPoints[2].fY, SpawnPoints[2].fZ, SpawnPoints[2].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ m_uiWaveTimer = 8000;
+ break;
+ case 3:
+ m_creature->SummonCreature(NPC_COUNCILMAN_COOPER, SpawnPoints[1].fX, SpawnPoints[1].fY, SpawnPoints[1].fZ, SpawnPoints[1].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ m_creature->SummonCreature(NPC_COUNCILMAN_BRUNSWICK, SpawnPoints[2].fX, SpawnPoints[2].fY, SpawnPoints[2].fZ, SpawnPoints[2].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ m_creature->SummonCreature(NPC_LORD_MAYOR_MORRISON, SpawnPoints[0].fX, SpawnPoints[0].fY, SpawnPoints[0].fZ, SpawnPoints[0].fO, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 20000);
+ break;
+ }
+
+ ++m_uiWaveCount;
+ }
+ else
+ m_uiWaveTimer -= uiDiff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool QuestAccept_npc_deathstalker_faerleia(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_PYREWOOD_AMBUSH)
+ {
+ DoScriptText(SAY_START, pCreature, pPlayer);
+
+ if (npc_deathstalker_faerleiaAI* pFaerleiaAI = dynamic_cast(pCreature->AI()))
+ pFaerleiaAI->StartEvent(pPlayer->GetGUID());
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_deathstalker_faerleia(Creature* pCreature)
+{
+ return new npc_deathstalker_faerleiaAI(pCreature);
+}
+
+void AddSC_silverpine_forest()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_astor_hadren";
+ newscript->pGossipHello = &GossipHello_npc_astor_hadren;
+ newscript->pGossipSelect = &GossipSelect_npc_astor_hadren;
+ newscript->GetAI = &GetAI_npc_astor_hadren;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_deathstalker_erland";
+ newscript->GetAI = &GetAI_npc_deathstalker_erland;
+ newscript->pQuestAccept = &QuestAccept_npc_deathstalker_erland;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_deathstalker_faerleia";
+ newscript->GetAI = &GetAI_npc_deathstalker_faerleia;
+ newscript->pQuestAccept = &QuestAccept_npc_deathstalker_faerleia;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stormwind_city.cpp b/scripts/eastern_kingdoms/stormwind_city.cpp
new file mode 100644
index 0000000..282ba18
--- /dev/null
+++ b/scripts/eastern_kingdoms/stormwind_city.cpp
@@ -0,0 +1,268 @@
+/* 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: Stormwind_City
+SD%Complete: 100
+SDComment: Quest support: 1640, 1447, 4185, 11223 (DB support required for spell 42711)
+SDCategory: Stormwind City
+EndScriptData */
+
+/* ContentData
+npc_archmage_malin
+npc_bartleby
+npc_dashel_stonefist
+npc_lady_katrana_prestor
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_archmage_malin
+######*/
+
+#define GOSSIP_ITEM_MALIN "Can you send me to Theramore? I have an urgent message for Lady Jaina from Highlord Bolvar."
+
+bool GossipHello_npc_archmage_malin(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(11223) == QUEST_STATUS_COMPLETE && !pPlayer->GetQuestRewardStatus(11223))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MALIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_archmage_malin(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer, 42711, true);
+ }
+
+ return true;
+}
+
+/*######
+## npc_bartleby
+######*/
+
+enum
+{
+ FACTION_ENEMY = 168,
+ QUEST_BEAT = 1640
+};
+
+struct MANGOS_DLL_DECL npc_bartlebyAI : public ScriptedAI
+{
+ npc_bartlebyAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiNormalFaction = pCreature->getFaction();
+ Reset();
+ }
+
+ uint32 m_uiNormalFaction;
+
+ void Reset()
+ {
+ if (m_creature->getFaction() != m_uiNormalFaction)
+ m_creature->setFaction(m_uiNormalFaction);
+ }
+
+ void AttackedBy(Unit* pAttacker)
+ {
+ if (m_creature->getVictim())
+ return;
+
+ if (m_creature->IsFriendlyTo(pAttacker))
+ return;
+
+ AttackStart(pAttacker);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (uiDamage > m_creature->GetHealth() || ((m_creature->GetHealth() - uiDamage)*100 / m_creature->GetMaxHealth() < 15))
+ {
+ uiDamage = 0;
+
+ if (pDoneBy->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)pDoneBy)->AreaExploredOrEventHappens(QUEST_BEAT);
+
+ EnterEvadeMode();
+ }
+ }
+};
+
+bool QuestAccept_npc_bartleby(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_BEAT)
+ {
+ pCreature->setFaction(FACTION_ENEMY);
+ pCreature->AI()->AttackStart(pPlayer);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_bartleby(Creature* pCreature)
+{
+ return new npc_bartlebyAI(pCreature);
+}
+
+/*######
+## npc_dashel_stonefist
+######*/
+
+enum
+{
+ QUEST_MISSING_DIPLO_PT8 = 1447,
+ FACTION_HOSTILE = 168
+};
+
+struct MANGOS_DLL_DECL npc_dashel_stonefistAI : public ScriptedAI
+{
+ npc_dashel_stonefistAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiNormalFaction = pCreature->getFaction();
+ Reset();
+ }
+
+ uint32 m_uiNormalFaction;
+
+ void Reset()
+ {
+ if (m_creature->getFaction() != m_uiNormalFaction)
+ m_creature->setFaction(m_uiNormalFaction);
+ }
+
+ void AttackedBy(Unit* pAttacker)
+ {
+ if (m_creature->getVictim())
+ return;
+
+ if (m_creature->IsFriendlyTo(pAttacker))
+ return;
+
+ AttackStart(pAttacker);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (uiDamage > m_creature->GetHealth() || ((m_creature->GetHealth() - uiDamage)*100 / m_creature->GetMaxHealth() < 15))
+ {
+ uiDamage = 0;
+
+ if (pDoneBy->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)pDoneBy)->AreaExploredOrEventHappens(QUEST_MISSING_DIPLO_PT8);
+
+ EnterEvadeMode();
+ }
+ }
+};
+
+bool QuestAccept_npc_dashel_stonefist(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT8)
+ {
+ pCreature->setFaction(FACTION_HOSTILE);
+ pCreature->AI()->AttackStart(pPlayer);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_dashel_stonefist(Creature* pCreature)
+{
+ return new npc_dashel_stonefistAI(pCreature);
+}
+
+/*######
+## npc_lady_katrana_prestor
+######*/
+
+#define GOSSIP_ITEM_KAT_1 "Pardon the intrusion, Lady Prestor, but Highlord Bolvar suggested that I seek your advice."
+#define GOSSIP_ITEM_KAT_2 "My apologies, Lady Prestor."
+#define GOSSIP_ITEM_KAT_3 "Begging your pardon, Lady Prestor. That was not my intent."
+#define GOSSIP_ITEM_KAT_4 "Thank you for your time, Lady Prestor."
+
+bool GossipHello_npc_lady_katrana_prestor(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(4185) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(2693, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_lady_katrana_prestor(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(2694, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(2695, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_KAT_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->SEND_GOSSIP_MENU(2696, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(4185);
+ break;
+ }
+ return true;
+}
+
+void AddSC_stormwind_city()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_archmage_malin";
+ newscript->pGossipHello = &GossipHello_npc_archmage_malin;
+ newscript->pGossipSelect = &GossipSelect_npc_archmage_malin;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_bartleby";
+ newscript->GetAI = &GetAI_npc_bartleby;
+ newscript->pQuestAccept = &QuestAccept_npc_bartleby;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_dashel_stonefist";
+ newscript->GetAI = &GetAI_npc_dashel_stonefist;
+ newscript->pQuestAccept = &QuestAccept_npc_dashel_stonefist;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_lady_katrana_prestor";
+ newscript->pGossipHello = &GossipHello_npc_lady_katrana_prestor;
+ newscript->pGossipSelect = &GossipSelect_npc_lady_katrana_prestor;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stranglethorn_vale.cpp b/scripts/eastern_kingdoms/stranglethorn_vale.cpp
new file mode 100644
index 0000000..0623f82
--- /dev/null
+++ b/scripts/eastern_kingdoms/stranglethorn_vale.cpp
@@ -0,0 +1,107 @@
+/* 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: Stranglethorn_Vale
+SD%Complete: 100
+SDComment: Quest support: 592
+SDCategory: Stranglethorn Vale
+EndScriptData */
+
+/* ContentData
+mob_yenniku
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## mob_yenniku
+######*/
+
+struct MANGOS_DLL_DECL mob_yennikuAI : public ScriptedAI
+{
+ mob_yennikuAI(Creature *c) : ScriptedAI(c)
+ {
+ bReset = false;
+ Reset();
+ }
+
+ uint32 Reset_Timer;
+ bool bReset;
+
+ void Reset()
+ {
+ Reset_Timer = 0;
+ m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ //Yenniku's Release
+ if (!bReset && ((Player*)caster)->GetQuestStatus(592) == QUEST_STATUS_INCOMPLETE && spell->Id == 3607)
+ {
+ m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN);
+ m_creature->CombatStop(); //stop combat
+ m_creature->DeleteThreatList(); //unsure of this
+ m_creature->setFaction(83); //horde generic
+
+ bReset = true;
+ Reset_Timer = 60000;
+ }
+ }
+ return;
+ }
+
+ void Aggro(Unit *who) {}
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (bReset)
+ if (Reset_Timer < diff)
+ {
+ EnterEvadeMode();
+ bReset = false;
+ m_creature->setFaction(28); //troll, bloodscalp
+ }
+ else Reset_Timer -= diff;
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() )
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_mob_yenniku(Creature *_Creature)
+{
+ return new mob_yennikuAI (_Creature);
+}
+
+/*######
+##
+######*/
+
+void AddSC_stranglethorn_vale()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "mob_yenniku";
+ newscript->GetAI = &GetAI_mob_yenniku;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp b/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp
new file mode 100644
index 0000000..357a423
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp
@@ -0,0 +1,185 @@
+/* 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_Baron_Rivendare
+SD%Complete: 70
+SDComment: aura applied/defined in database
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+#define SAY_0 "Intruders! More pawns of the Argent Dawn, no doubt. I already count one of their number among my prisoners. Withdraw from my domain before she is executed!"
+#define SAY_1 "You're still here? Your foolishness is amusing! The Argent Dawn wench needn't suffer in vain. Leave at once and she shall be spared!"
+#define SAY_2 "I shall take great pleasure in taking this poor wretch's life! It's not too late, she needn't suffer in vain. Turn back and her death shall be merciful!"
+#define SAY_3 "May this prisoner's death serve as a warning. None shall defy the Scourge and live!"
+#define SAY_4 "So you see fit to toy with the Lich King's creations? Ramstein, be sure to give the intruders a proper greeting."
+#define SAY_5 "Time to take matters into my own hands. Come. Enter my domain and challenge the might of the Scourge!"
+
+#define ADD_1X 4017.403809f
+#define ADD_1Y -3339.703369f
+#define ADD_1Z 115.057655f
+#define ADD_1O 5.487860f
+
+#define ADD_2X 4013.189209f
+#define ADD_2Y -3351.808350f
+#define ADD_2Z 115.052254f
+#define ADD_2O 0.134280f
+
+#define ADD_3X 4017.738037f
+#define ADD_3Y -3363.478016f
+#define ADD_3Z 115.057274f
+#define ADD_3O 0.723313f
+
+#define ADD_4X 4048.877197f
+#define ADD_4Y -3363.223633f
+#define ADD_4Z 115.054253f
+#define ADD_4O 3.627735f
+
+#define ADD_5X 4051.777588f
+#define ADD_5Y -3350.893311f
+#define ADD_5Z 115.055351f
+#define ADD_5O 3.066176f
+
+#define ADD_6X 4048.375977f
+#define ADD_6Y -3339.966309f
+#define ADD_6Z 115.055222f
+#define ADD_6O 2.457497f
+
+#define SPELL_SHADOWBOLT 17393
+#define SPELL_CLEAVE 15284
+#define SPELL_MORTALSTRIKE 15708
+
+#define SPELL_UNHOLY_AURA 17467
+#define SPELL_RAISEDEAD 17473 //triggers death pact (17471)
+
+#define SPELL_RAISE_DEAD1 17475
+#define SPELL_RAISE_DEAD2 17476
+#define SPELL_RAISE_DEAD3 17477
+#define SPELL_RAISE_DEAD4 17478
+#define SPELL_RAISE_DEAD5 17479
+#define SPELL_RAISE_DEAD6 17480
+
+struct MANGOS_DLL_DECL boss_baron_rivendareAI : public ScriptedAI
+{
+ boss_baron_rivendareAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 ShadowBolt_Timer;
+ uint32 Cleave_Timer;
+ uint32 MortalStrike_Timer;
+ //uint32 RaiseDead_Timer;
+ uint32 SummonSkeletons_Timer;
+ Creature *Summoned;
+
+ void Reset()
+ {
+ ShadowBolt_Timer = 5000;
+ Cleave_Timer = 8000;
+ MortalStrike_Timer = 12000;
+ //RaiseDead_Timer = 30000;
+ SummonSkeletons_Timer = 34000;
+ }
+
+ void Aggro(Unit *who)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BARON,IN_PROGRESS);
+ }
+
+ void JustSummoned(Creature* summoned)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ summoned->AI()->AttackStart(target);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BARON,DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowBolt
+ if (ShadowBolt_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWBOLT);
+ ShadowBolt_Timer = 10000;
+ }else ShadowBolt_Timer -= diff;
+
+ //Cleave
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = urand(7000, 17000);
+ }else Cleave_Timer -= diff;
+
+ //MortalStrike
+ if (MortalStrike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MORTALSTRIKE);
+ MortalStrike_Timer = urand(10000, 25000);
+ }else MortalStrike_Timer -= diff;
+
+ //RaiseDead
+ //if (RaiseDead_Timer < diff)
+ //{
+ // DoCastSpellIfCan(m_creature,SPELL_RAISEDEAD);
+ // RaiseDead_Timer = 45000;
+ //}else RaiseDead_Timer -= diff;
+
+ //SummonSkeletons
+ if (SummonSkeletons_Timer < diff)
+ {
+ m_creature->SummonCreature(11197,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,29000);
+ m_creature->SummonCreature(11197,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,29000);
+ m_creature->SummonCreature(11197,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,29000);
+ m_creature->SummonCreature(11197,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,29000);
+ m_creature->SummonCreature(11197,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,29000);
+ m_creature->SummonCreature(11197,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,29000);
+
+ SummonSkeletons_Timer = 40000;
+ }else SummonSkeletons_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_baron_rivendare(Creature* pCreature)
+{
+ return new boss_baron_rivendareAI(pCreature);
+}
+
+void AddSC_boss_baron_rivendare()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_baron_rivendare";
+ newscript->GetAI = &GetAI_boss_baron_rivendare;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp b/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp
new file mode 100644
index 0000000..c356636
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp
@@ -0,0 +1,118 @@
+/* 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_Baroness_Anastari
+SD%Complete: 90
+SDComment: MC disabled
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+#define SPELL_BANSHEEWAIL 16565
+#define SPELL_BANSHEECURSE 16867
+#define SPELL_SILENCE 18327
+//#define SPELL_POSSESS 17244
+
+struct MANGOS_DLL_DECL boss_baroness_anastariAI : public ScriptedAI
+{
+ boss_baroness_anastariAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 BansheeWail_Timer;
+ uint32 BansheeCurse_Timer;
+ uint32 Silence_Timer;
+ //uint32 Possess_Timer;
+
+ void Reset()
+ {
+ BansheeWail_Timer = 1000;
+ BansheeCurse_Timer = 11000;
+ Silence_Timer = 13000;
+ //Possess_Timer = 35000;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BARONESS, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //BansheeWail
+ if (BansheeWail_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BANSHEEWAIL);
+ BansheeWail_Timer = 4000;
+ }else BansheeWail_Timer -= diff;
+
+ //BansheeCurse
+ if (BansheeCurse_Timer < diff)
+ {
+ if (!urand(0, 3))
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BANSHEECURSE);
+
+ BansheeCurse_Timer = 18000;
+ }else BansheeCurse_Timer -= diff;
+
+ //Silence
+ if (Silence_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SILENCE);
+ Silence_Timer = 13000;
+ }else Silence_Timer -= diff;
+
+ //Possess
+ /* if (Possess_Timer < diff)
+ {
+ //Cast
+ if (rand()%100 < 65)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target)DoCastSpellIfCan(target,SPELL_POSSESS);
+ }
+ Possess_Timer = 50000;
+ }else Possess_Timer -= diff;
+ */
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_baroness_anastari(Creature* pCreature)
+{
+ return new boss_baroness_anastariAI(pCreature);
+}
+
+void AddSC_boss_baroness_anastari()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_baroness_anastari";
+ newscript->GetAI = &GetAI_boss_baroness_anastari;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp b/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp
new file mode 100644
index 0000000..dce3542
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp
@@ -0,0 +1,215 @@
+/* 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_cannon_master_willey
+SD%Complete: 100
+SDComment:
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+
+//front, left
+#define ADD_1X 3553.851807f
+#define ADD_1Y -2945.885986f
+#define ADD_1Z 125.001015f
+#define ADD_1O 0.592007f
+//front, right
+#define ADD_2X 3559.206299f
+#define ADD_2Y -2952.929932f
+#define ADD_2Z 125.001015f
+#define ADD_2O 0.592007f
+//mid, left
+#define ADD_3X 3552.417480f
+#define ADD_3Y -2948.667236f
+#define ADD_3Z 125.001015f
+#define ADD_3O 0.592007f
+//mid, right
+#define ADD_4X 3555.651855f
+#define ADD_4Y -2953.519043f
+#define ADD_4Z 125.001015f
+#define ADD_4O 0.592007f
+//back, left
+#define ADD_5X 3547.927246f
+#define ADD_5Y -2950.977295f
+#define ADD_5Z 125.001015f
+#define ADD_5O 0.592007f
+//back, mid
+#define ADD_6X 3553.094697f
+#define ADD_6Y -2952.123291f
+#define ADD_6Z 125.001015f
+#define ADD_6O 0.592007f
+//back, right
+#define ADD_7X 3552.727539f
+#define ADD_7Y -2957.776123f
+#define ADD_7Z 125.001015f
+#define ADD_7O 0.592007f
+//behind, left
+#define ADD_8X 3547.156250f
+#define ADD_8Y -2953.162354f
+#define ADD_8Z 125.001015f
+#define ADD_8O 0.592007f
+//behind, right
+#define ADD_9X 3550.202148f
+#define ADD_9Y -2957.437744f
+#define ADD_9Z 125.001015f
+#define ADD_9O 0.592007f
+
+#define SPELL_KNOCKAWAY 10101
+#define SPELL_PUMMEL 15615
+#define SPELL_SHOOT 20463
+//#define SPELL_SUMMONCRIMSONRIFLEMAN 17279
+
+struct MANGOS_DLL_DECL boss_cannon_master_willeyAI : public ScriptedAI
+{
+ boss_cannon_master_willeyAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 KnockAway_Timer;
+ uint32 Pummel_Timer;
+ uint32 Shoot_Timer;
+ uint32 SummonRifleman_Timer;
+
+ void Reset()
+ {
+ Shoot_Timer = 1000;
+ Pummel_Timer = 7000;
+ KnockAway_Timer = 11000;
+ SummonRifleman_Timer = 15000;
+ }
+
+ void JustDied(Unit* Victim)
+ {
+ m_creature->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Pummel
+ if (Pummel_Timer < diff)
+ {
+ //Cast
+ if (rand()%100 < 90) //90% chance to cast
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_PUMMEL);
+ }
+ //12 seconds until we should cast this again
+ Pummel_Timer = 12000;
+ }else Pummel_Timer -= diff;
+
+ //KnockAway
+ if (KnockAway_Timer < diff)
+ {
+ //Cast
+ if (rand()%100 < 80) //80% chance to cast
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KNOCKAWAY);
+ }
+ //14 seconds until we should cast this again
+ KnockAway_Timer = 14000;
+ }else KnockAway_Timer -= diff;
+
+ //Shoot
+ if (Shoot_Timer < diff)
+ {
+ //Cast
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHOOT);
+ //1 seconds until we should cast this again
+ Shoot_Timer = 1000;
+ }else Shoot_Timer -= diff;
+
+ //SummonRifleman
+ if (SummonRifleman_Timer < diff)
+ {
+ //Cast
+ switch(urand(0, 8))
+ {
+ case 0:
+ m_creature->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ case 1:
+ m_creature->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ case 2:
+ m_creature->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ case 3:
+ m_creature->SummonCreature(11054,ADD_4X,ADD_4Y,ADD_4Z,ADD_4O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ case 4:
+ m_creature->SummonCreature(11054,ADD_5X,ADD_5Y,ADD_5Z,ADD_5O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ case 5:
+ m_creature->SummonCreature(11054,ADD_6X,ADD_6Y,ADD_6Z,ADD_6O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ case 6:
+ m_creature->SummonCreature(11054,ADD_7X,ADD_7Y,ADD_7Z,ADD_7O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ case 7:
+ m_creature->SummonCreature(11054,ADD_8X,ADD_8Y,ADD_8Z,ADD_8O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_2X,ADD_2Y,ADD_2Z,ADD_2O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ case 8:
+ m_creature->SummonCreature(11054,ADD_9X,ADD_9Y,ADD_9Z,ADD_9O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_1X,ADD_1Y,ADD_1Z,ADD_1O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ m_creature->SummonCreature(11054,ADD_3X,ADD_3Y,ADD_3Z,ADD_3O,TEMPSUMMON_TIMED_DESPAWN,240000);
+ break;
+ }
+ //30 seconds until we should cast this again
+ SummonRifleman_Timer = 30000;
+ }else SummonRifleman_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_cannon_master_willey(Creature* pCreature)
+{
+ return new boss_cannon_master_willeyAI(pCreature);
+}
+
+void AddSC_boss_cannon_master_willey()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_cannon_master_willey";
+ newscript->GetAI = &GetAI_boss_cannon_master_willey;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp b/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp
new file mode 100644
index 0000000..b586c21
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp
@@ -0,0 +1,213 @@
+/* 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_Dathrohan_Balnazzar
+SD%Complete: 95
+SDComment: Possibly need to fix/improve summons after death
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ //Dathrohan spells
+ SPELL_CRUSADERSHAMMER = 17286, //AOE stun
+ SPELL_CRUSADERSTRIKE = 17281,
+ SPELL_HOLYSTRIKE = 17284, //weapon dmg +3
+
+ //Transform
+ SPELL_BALNAZZARTRANSFORM = 17288, //restore full HP/mana, trigger spell Balnazzar Transform Stun
+
+ //Balnazzar spells
+ SPELL_SHADOWSHOCK = 17399,
+ SPELL_MINDBLAST = 17287,
+ SPELL_PSYCHICSCREAM = 13704,
+ SPELL_SLEEP = 12098,
+ SPELL_MINDCONTROL = 15690,
+
+ NPC_DATHROHAN = 10812,
+ NPC_BALNAZZAR = 10813,
+ NPC_ZOMBIE = 10698 //probably incorrect
+};
+
+struct SummonDef
+{
+ float m_fX, m_fY, m_fZ, m_fOrient;
+};
+
+SummonDef m_aSummonPoint[]=
+{
+ {3444.156f, -3090.626f, 135.002f, 2.240f}, //G1 front, left
+ {3449.123f, -3087.009f, 135.002f, 2.240f}, //G1 front, right
+ {3446.246f, -3093.466f, 135.002f, 2.240f}, //G1 back left
+ {3451.160f, -3089.904f, 135.002f, 2.240f}, //G1 back, right
+
+ {3457.995f, -3080.916f, 135.002f, 3.784f}, //G2 front, left
+ {3454.302f, -3076.330f, 135.002f, 3.784f}, //G2 front, right
+ {3460.975f, -3078.901f, 135.002f, 3.784f}, //G2 back left
+ {3457.338f, -3073.979f, 135.002f, 3.784f} //G2 back, right
+};
+
+struct MANGOS_DLL_DECL boss_dathrohan_balnazzarAI : public ScriptedAI
+{
+ boss_dathrohan_balnazzarAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiCrusadersHammer_Timer;
+ uint32 m_uiCrusaderStrike_Timer;
+ uint32 m_uiMindBlast_Timer;
+ uint32 m_uiHolyStrike_Timer;
+ uint32 m_uiShadowShock_Timer;
+ uint32 m_uiPsychicScream_Timer;
+ uint32 m_uiDeepSleep_Timer;
+ uint32 m_uiMindControl_Timer;
+ bool m_bTransformed;
+
+ void Reset()
+ {
+ m_uiCrusadersHammer_Timer = 8000;
+ m_uiCrusaderStrike_Timer = 12000;
+ m_uiMindBlast_Timer = 6000;
+ m_uiHolyStrike_Timer = 18000;
+ m_uiShadowShock_Timer = 4000;
+ m_uiPsychicScream_Timer = 16000;
+ m_uiDeepSleep_Timer = 20000;
+ m_uiMindControl_Timer = 10000;
+ m_bTransformed = false;
+
+ if (m_creature->GetEntry() == NPC_BALNAZZAR)
+ m_creature->UpdateEntry(NPC_DATHROHAN);
+
+ }
+
+ void JustDied(Unit* Victim)
+ {
+ static uint32 uiCount = sizeof(m_aSummonPoint)/sizeof(SummonDef);
+
+ for (uint8 i=0; iSummonCreature(NPC_ZOMBIE,
+ m_aSummonPoint[i].m_fX, m_aSummonPoint[i].m_fY, m_aSummonPoint[i].m_fZ, m_aSummonPoint[i].m_fOrient,
+ TEMPSUMMON_TIMED_DESPAWN, HOUR*IN_MILLISECONDS);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //START NOT TRANSFORMED
+ if (!m_bTransformed)
+ {
+ //MindBlast
+ if (m_uiMindBlast_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MINDBLAST);
+ m_uiMindBlast_Timer = urand(15000, 20000);
+ }else m_uiMindBlast_Timer -= uiDiff;
+
+ //CrusadersHammer
+ if (m_uiCrusadersHammer_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CRUSADERSHAMMER);
+ m_uiCrusadersHammer_Timer = 12000;
+ }else m_uiCrusadersHammer_Timer -= uiDiff;
+
+ //CrusaderStrike
+ if (m_uiCrusaderStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CRUSADERSTRIKE);
+ m_uiCrusaderStrike_Timer = 15000;
+ }else m_uiCrusaderStrike_Timer -= uiDiff;
+
+ //HolyStrike
+ if (m_uiHolyStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_HOLYSTRIKE);
+ m_uiHolyStrike_Timer = 15000;
+ }else m_uiHolyStrike_Timer -= uiDiff;
+
+ //BalnazzarTransform
+ if (m_creature->GetHealthPercent() < 40.0f)
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ //restore hp, mana and stun
+ DoCastSpellIfCan(m_creature,SPELL_BALNAZZARTRANSFORM);
+ m_creature->UpdateEntry(NPC_BALNAZZAR);
+ m_bTransformed = true;
+ }
+ }
+ else
+ {
+ //MindBlast
+ if (m_uiMindBlast_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MINDBLAST);
+ m_uiMindBlast_Timer = urand(15000, 20000);
+ }else m_uiMindBlast_Timer -= uiDiff;
+
+ //ShadowShock
+ if (m_uiShadowShock_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWSHOCK);
+ m_uiShadowShock_Timer = 11000;
+ }else m_uiShadowShock_Timer -= uiDiff;
+
+ //PsychicScream
+ if (m_uiPsychicScream_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget,SPELL_PSYCHICSCREAM);
+
+ m_uiPsychicScream_Timer = 20000;
+ }else m_uiPsychicScream_Timer -= uiDiff;
+
+ //DeepSleep
+ if (m_uiDeepSleep_Timer < uiDiff)
+ {
+ if (Unit *pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget,SPELL_SLEEP);
+
+ m_uiDeepSleep_Timer = 15000;
+ }else m_uiDeepSleep_Timer -= uiDiff;
+
+ //MindControl
+ if (m_uiMindControl_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MINDCONTROL);
+ m_uiMindControl_Timer = 15000;
+ }else m_uiMindControl_Timer -= uiDiff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_dathrohan_balnazzar(Creature* pCreature)
+{
+ return new boss_dathrohan_balnazzarAI(pCreature);
+}
+
+void AddSC_boss_dathrohan_balnazzar()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_dathrohan_balnazzar";
+ newscript->GetAI = &GetAI_boss_dathrohan_balnazzar;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp b/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp
new file mode 100644
index 0000000..c72171d
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp
@@ -0,0 +1,128 @@
+/* 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_Magistrate_Barthilas
+SD%Complete: 70
+SDComment:
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+#define SPELL_DRAININGBLOW 16793
+#define SPELL_CROWDPUMMEL 10887
+#define SPELL_MIGHTYBLOW 14099
+#define SPELL_FURIOUS_ANGER 16791
+
+#define MODEL_NORMAL 10433
+#define MODEL_HUMAN 3637
+
+struct MANGOS_DLL_DECL boss_magistrate_barthilasAI : public ScriptedAI
+{
+ boss_magistrate_barthilasAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 DrainingBlow_Timer;
+ uint32 CrowdPummel_Timer;
+ uint32 MightyBlow_Timer;
+ uint32 FuriousAnger_Timer;
+ uint32 AngerCount;
+
+ void Reset()
+ {
+ DrainingBlow_Timer = 20000;
+ CrowdPummel_Timer = 15000;
+ MightyBlow_Timer = 10000;
+ FuriousAnger_Timer = 5000;
+ AngerCount = 0;
+
+ if (m_creature->isAlive())
+ m_creature->SetDisplayId(MODEL_NORMAL);
+ else
+ m_creature->SetDisplayId(MODEL_HUMAN);
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ //nothing to see here yet
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ m_creature->SetDisplayId(MODEL_HUMAN);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (FuriousAnger_Timer < diff)
+ {
+ FuriousAnger_Timer = 4000;
+ if (AngerCount > 25)
+ return;
+
+ ++AngerCount;
+ m_creature->CastSpell(m_creature,SPELL_FURIOUS_ANGER,false);
+ }else FuriousAnger_Timer -= diff;
+
+ //DrainingBlow
+ if (DrainingBlow_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_DRAININGBLOW);
+ DrainingBlow_Timer = 15000;
+ }else DrainingBlow_Timer -= diff;
+
+ //CrowdPummel
+ if (CrowdPummel_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CROWDPUMMEL);
+ CrowdPummel_Timer = 15000;
+ }else CrowdPummel_Timer -= diff;
+
+ //MightyBlow
+ if (MightyBlow_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MIGHTYBLOW);
+ MightyBlow_Timer = 20000;
+ }else MightyBlow_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_magistrate_barthilas(Creature* pCreature)
+{
+ return new boss_magistrate_barthilasAI(pCreature);
+}
+
+void AddSC_boss_magistrate_barthilas()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_magistrate_barthilas";
+ newscript->GetAI = &GetAI_boss_magistrate_barthilas;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp b/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp
new file mode 100644
index 0000000..c831a3f
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp
@@ -0,0 +1,108 @@
+/* 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_Maleki_the_Pallid
+SD%Complete: 70
+SDComment:
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+#define SPELL_FROSTBOLT 17503
+#define SPELL_DRAIN_LIFE 17238
+#define SPELL_DRAIN_MANA 17243
+#define SPELL_ICETOMB 16869
+
+struct MANGOS_DLL_DECL boss_maleki_the_pallidAI : public ScriptedAI
+{
+ boss_maleki_the_pallidAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 FrostNova_Timer;
+ uint32 Frostbolt_Timer;
+ uint32 IceTomb_Timer;
+ uint32 DrainLife_Timer;
+
+ void Reset()
+ {
+ FrostNova_Timer = 11000;
+ Frostbolt_Timer = 1000;
+ IceTomb_Timer = 16000;
+ DrainLife_Timer = 31000;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_PALLID, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Frostbolt
+ if (Frostbolt_Timer < diff)
+ {
+ if (rand()%100 < 90)
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROSTBOLT);
+
+ Frostbolt_Timer = 3500;
+ }else Frostbolt_Timer -= diff;
+
+ //IceTomb
+ if (IceTomb_Timer < diff)
+ {
+ if (rand()%100 < 65)
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ICETOMB);
+
+ IceTomb_Timer = 28000;
+ }else IceTomb_Timer -= diff;
+
+ //DrainLife
+ if (DrainLife_Timer < diff)
+ {
+ if (rand()%100 < 55)
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_DRAIN_LIFE);
+
+ DrainLife_Timer = 31000;
+ }else DrainLife_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_maleki_the_pallid(Creature* pCreature)
+{
+ return new boss_maleki_the_pallidAI(pCreature);
+}
+
+void AddSC_boss_maleki_the_pallid()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_maleki_the_pallid";
+ newscript->GetAI = &GetAI_boss_maleki_the_pallid;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp b/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp
new file mode 100644
index 0000000..85fde3f
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.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: Boss_Nerubenkan
+SD%Complete: 70
+SDComment:
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+#define SPELL_ENCASINGWEBS 4962
+#define SPELL_PIERCEARMOR 6016
+#define SPELL_CRYPT_SCARABS 31602
+#define SPELL_RAISEUNDEADSCARAB 17235
+
+struct MANGOS_DLL_DECL boss_nerubenkanAI : public ScriptedAI
+{
+ boss_nerubenkanAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 EncasingWebs_Timer;
+ uint32 PierceArmor_Timer;
+ uint32 CryptScarabs_Timer;
+ uint32 RaiseUndeadScarab_Timer;
+
+ int Rand;
+ int RandX;
+ int RandY;
+ Creature* Summoned;
+
+ void Reset()
+ {
+ CryptScarabs_Timer = 3000;
+ EncasingWebs_Timer = 7000;
+ PierceArmor_Timer = 19000;
+ RaiseUndeadScarab_Timer = 3000;
+ }
+
+ void RaiseUndeadScarab(Unit* victim)
+ {
+ Rand = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: RandX = 0 - Rand; break;
+ case 1: RandX = 0 + Rand; break;
+ }
+ Rand = 0;
+ Rand = rand()%10;
+ switch(urand(0, 1))
+ {
+ case 0: RandY = 0 - Rand; break;
+ case 1: RandY = 0 + Rand; break;
+ }
+ Rand = 0;
+ Summoned = DoSpawnCreature(10876, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 180000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(victim);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_NERUB, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //EncasingWebs
+ if (EncasingWebs_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ENCASINGWEBS);
+ EncasingWebs_Timer = 30000;
+ }else EncasingWebs_Timer -= diff;
+
+ //PierceArmor
+ if (PierceArmor_Timer < diff)
+ {
+ if (rand()%100 < 75)
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_PIERCEARMOR);
+
+ PierceArmor_Timer = 35000;
+ }else PierceArmor_Timer -= diff;
+
+ //CryptScarabs
+ if (CryptScarabs_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CRYPT_SCARABS);
+ CryptScarabs_Timer = 16000;
+ }else CryptScarabs_Timer -= diff;
+
+ //RaiseUndeadScarab
+ if (RaiseUndeadScarab_Timer < diff)
+ {
+ RaiseUndeadScarab(m_creature->getVictim());
+ RaiseUndeadScarab_Timer = 18000;
+ }else RaiseUndeadScarab_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_nerubenkan(Creature* pCreature)
+{
+ return new boss_nerubenkanAI(pCreature);
+}
+
+void AddSC_boss_nerubenkan()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_nerubenkan";
+ newscript->GetAI = &GetAI_boss_nerubenkan;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp b/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp
new file mode 100644
index 0000000..b07a589
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp
@@ -0,0 +1,154 @@
+/* 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_Silver_Hand_Bosses
+SD%Complete: 40
+SDComment: Basic script to have support for Horde paladin epic mount (quest 9737). All 5 members of Order of the Silver Hand running this script (least for now)
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+/*#####
+# Additional:
+# Although this is a working solution, the correct would be in addition to check if Aurius is dead.
+# Once player extinguish the eternal flame (cast spell 31497->start event 11206) Aurius should become hostile.
+# Once Aurius is defeated, he should be the one summoning the ghosts.
+#####*/
+
+#define SH_GREGOR 17910
+#define SH_CATHELA 17911
+#define SH_NEMAS 17912
+#define SH_AELMAR 17913
+#define SH_VICAR 17914
+#define SH_QUEST_CREDIT 17915
+
+#define SPELL_HOLY_LIGHT 25263
+#define SPELL_DIVINE_SHIELD 13874
+
+struct MANGOS_DLL_DECL boss_silver_hand_bossesAI : public ScriptedAI
+{
+ boss_silver_hand_bossesAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 HolyLight_Timer;
+ uint32 DivineShield_Timer;
+
+ void Reset()
+ {
+ HolyLight_Timer = 20000;
+ DivineShield_Timer = 20000;
+
+ if (m_pInstance)
+ {
+ switch(m_creature->GetEntry())
+ {
+ case SH_AELMAR:
+ m_pInstance->SetData(TYPE_SH_AELMAR, 0);
+ break;
+ case SH_CATHELA:
+ m_pInstance->SetData(TYPE_SH_CATHELA, 0);
+ break;
+ case SH_GREGOR:
+ m_pInstance->SetData(TYPE_SH_GREGOR, 0);
+ break;
+ case SH_NEMAS:
+ m_pInstance->SetData(TYPE_SH_NEMAS, 0);
+ break;
+ case SH_VICAR:
+ m_pInstance->SetData(TYPE_SH_VICAR, 0);
+ break;
+ }
+ }
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (m_pInstance)
+ {
+ switch(m_creature->GetEntry())
+ {
+ case SH_AELMAR:
+ m_pInstance->SetData(TYPE_SH_AELMAR, 2);
+ break;
+ case SH_CATHELA:
+ m_pInstance->SetData(TYPE_SH_CATHELA, 2);
+ break;
+ case SH_GREGOR:
+ m_pInstance->SetData(TYPE_SH_GREGOR, 2);
+ break;
+ case SH_NEMAS:
+ m_pInstance->SetData(TYPE_SH_NEMAS, 2);
+ break;
+ case SH_VICAR:
+ m_pInstance->SetData(TYPE_SH_VICAR, 2);
+ break;
+ }
+ if (m_pInstance->GetData(TYPE_SH_QUEST) && Killer->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)Killer)->KilledMonsterCredit(SH_QUEST_CREDIT,m_creature->GetGUID());
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (HolyLight_Timer < diff)
+ {
+ if (m_creature->GetHealthPercent() < 20.0f)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HOLY_LIGHT);
+ HolyLight_Timer = 20000;
+ }
+ }else HolyLight_Timer -= diff;
+
+ if (DivineShield_Timer < diff)
+ {
+ if (m_creature->GetHealthPercent() < 5.0f)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_DIVINE_SHIELD);
+ DivineShield_Timer = 40000;
+ }
+ }else DivineShield_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+
+};
+CreatureAI* GetAI_boss_silver_hand_bossesAI(Creature* pCreature)
+{
+ return new boss_silver_hand_bossesAI(pCreature);
+}
+
+
+void AddSC_boss_order_of_silver_hand()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_silver_hand_bosses";
+ newscript->GetAI = &GetAI_boss_silver_hand_bossesAI;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp b/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp
new file mode 100644
index 0000000..66e14fb
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp
@@ -0,0 +1,139 @@
+/* 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_postmaster_malown
+SD%Complete: 50
+SDComment:
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+
+//Spell ID to summon this guy is 24627 "Summon Postmaster Malown"
+//He should be spawned along with three other elites once the third postbox has been opened
+
+#define SAY_MALOWNED "You just got MALOWNED!"
+
+#define SPELL_WAILINGDEAD 7713
+#define SPELL_BACKHAND 6253
+#define SPELL_CURSEOFWEAKNESS 8552
+#define SPELL_CURSEOFTONGUES 12889
+#define SPELL_CALLOFTHEGRAVE 17831
+
+struct MANGOS_DLL_DECL boss_postmaster_malownAI : public ScriptedAI
+{
+ boss_postmaster_malownAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 WailingDead_Timer;
+ uint32 Backhand_Timer;
+ uint32 CurseOfWeakness_Timer;
+ uint32 CurseOfTongues_Timer;
+ uint32 CallOfTheGrave_Timer;
+ bool HasYelled;
+
+ void Reset()
+ {
+ WailingDead_Timer = 19000; //lasts 6 sec
+ Backhand_Timer = 8000; //2 sec stun
+ CurseOfWeakness_Timer = 20000; //lasts 2 mins
+ CurseOfTongues_Timer = 22000;
+ CallOfTheGrave_Timer = 25000;
+ HasYelled = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //WailingDead
+ if (WailingDead_Timer < diff)
+ {
+ //Cast
+ if (rand()%100 < 65) //65% chance to cast
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_WAILINGDEAD);
+ }
+ //19 seconds until we should cast this again
+ WailingDead_Timer = 19000;
+ }else WailingDead_Timer -= diff;
+
+ //Backhand
+ if (Backhand_Timer < diff)
+ {
+ //Cast
+ if (rand()%100 < 45) //45% chance to cast
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BACKHAND);
+ }
+ //8 seconds until we should cast this again
+ Backhand_Timer = 8000;
+ }else Backhand_Timer -= diff;
+
+ //CurseOfWeakness
+ if (CurseOfWeakness_Timer < diff)
+ {
+ //Cast
+ if (rand()%100 < 3) //3% chance to cast
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CURSEOFWEAKNESS);
+ }
+ //20 seconds until we should cast this again
+ CurseOfWeakness_Timer = 20000;
+ }else CurseOfWeakness_Timer -= diff;
+
+ //CurseOfTongues
+ if (CurseOfTongues_Timer < diff)
+ {
+ //Cast
+ if (rand()%100 < 3) //3% chance to cast
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CURSEOFTONGUES);
+ }
+ //22 seconds until we should cast this again
+ CurseOfTongues_Timer = 22000;
+ }else CurseOfTongues_Timer -= diff;
+
+ //CallOfTheGrave
+ if (CallOfTheGrave_Timer < diff)
+ {
+ //Cast
+ if (rand()%100 < 5) //5% chance to cast
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CALLOFTHEGRAVE);
+ }
+ //25 seconds until we should cast this again
+ CallOfTheGrave_Timer = 25000;
+ }else CallOfTheGrave_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_postmaster_malown(Creature* pCreature)
+{
+ return new boss_postmaster_malownAI(pCreature);
+}
+
+void AddSC_boss_postmaster_malown()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_postmaster_malown";
+ newscript->GetAI = &GetAI_boss_postmaster_malown;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp b/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp
new file mode 100644
index 0000000..1be611f
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp
@@ -0,0 +1,94 @@
+/* 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_Ramstein_the_Gorger
+SD%Complete: 70
+SDComment:
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+#define SPELL_TRAMPLE 5568
+#define SPELL_KNOCKOUT 17307
+
+#define C_MINDLESS_UNDEAD 11030
+
+struct MANGOS_DLL_DECL boss_ramstein_the_gorgerAI : public ScriptedAI
+{
+ boss_ramstein_the_gorgerAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 Trample_Timer;
+ uint32 Knockout_Timer;
+
+ void Reset()
+ {
+ Trample_Timer = 3000;
+ Knockout_Timer = 12000;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ for(uint8 i = 0; i < 30; ++i)
+ m_creature->SummonCreature(C_MINDLESS_UNDEAD, 3969.35f, -3391.87f, 119.11f, 5.91f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,1800000);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_RAMSTEIN,DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Trample
+ if (Trample_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_TRAMPLE);
+ Trample_Timer = 7000;
+ }else Trample_Timer -= diff;
+
+ //Knockout
+ if (Knockout_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KNOCKOUT);
+ Knockout_Timer = 10000;
+ }else Knockout_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_ramstein_the_gorger(Creature* pCreature)
+{
+ return new boss_ramstein_the_gorgerAI(pCreature);
+}
+
+void AddSC_boss_ramstein_the_gorger()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_ramstein_the_gorger";
+ newscript->GetAI = &GetAI_boss_ramstein_the_gorger;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp b/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp
new file mode 100644
index 0000000..030cb9e
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp
@@ -0,0 +1,70 @@
+/* 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_timmy_the_cruel
+SD%Complete: 100
+SDComment:
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_SPAWN "TIMMY!"
+
+#define SPELL_RAVENOUSCLAW 17470
+
+struct MANGOS_DLL_DECL boss_timmy_the_cruelAI : public ScriptedAI
+{
+ boss_timmy_the_cruelAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 RavenousClaw_Timer;
+
+ void Reset()
+ {
+ RavenousClaw_Timer = 10000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //RavenousClaw
+ if (RavenousClaw_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_RAVENOUSCLAW);
+ RavenousClaw_Timer = 15000;
+ }else RavenousClaw_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_timmy_the_cruel(Creature* pCreature)
+{
+ return new boss_timmy_the_cruelAI(pCreature);
+}
+
+void AddSC_boss_timmy_the_cruel()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_timmy_the_cruel";
+ newscript->GetAI = &GetAI_boss_timmy_the_cruel;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp b/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp
new file mode 100644
index 0000000..4c58758
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp
@@ -0,0 +1,513 @@
+/* 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_Stratholme
+SD%Complete: 50
+SDComment: In progress. Undead side 80% implemented, wipe support for doors at slaughterhouse needed, event needs better implementation
+SDCategory: Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+instance_stratholme::instance_stratholme(Map* pMap) : ScriptedInstance(pMap),
+ m_uiBaronRunTimer(0),
+ m_uiSlaugtherSquareTimer(0),
+
+ m_uiServiceEntranceGUID(0),
+ m_uiGauntletGate1GUID(0),
+ m_uiPortGauntletGUID(0),
+ m_uiPortSlaugtherGUID(0),
+ m_uiPortElderGUID(0),
+ m_auiRamsteinDoorGUID(0),
+ m_auiRivendareDoorGUID(0),
+
+ m_uiBaronGUID(0),
+ m_uiYsidaTriggerGUID(0),
+
+ m_uiAcolyteAnnouncerGUID(0)
+{
+ Initialize();
+}
+
+
+void instance_stratholme::Initialize()
+{
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+ memset(&m_bIsSilverHandDead, false, sizeof(m_bIsSilverHandDead));
+ memset(&m_auiZigguratGUID, 0, sizeof(m_auiZigguratGUID));
+ memset(&m_auiCrystalSortedGUID, 0, sizeof(m_auiCrystalSortedGUID));
+
+ m_lCrystals.clear();
+ m_sAbomnationGUID.clear();
+ m_lAcolytes.clear();
+}
+
+bool instance_stratholme::StartSlaugtherSquare()
+{
+ if (m_auiEncounter[1] == SPECIAL && m_auiEncounter[2] == SPECIAL && m_auiEncounter[3] == SPECIAL)
+ {
+ if (Creature* pBaron = instance->GetCreature(m_uiBaronGUID))
+ DoScriptText(SAY_ANNOUNCE_RIVENDARE, pBaron);
+
+ DoUseDoorOrButton(m_uiPortGauntletGUID);
+ DoUseDoorOrButton(m_uiPortSlaugtherGUID);
+ return true;
+ }
+
+ debug_log("SD2: Instance Stratholme: Cannot open slaugther square yet.");
+ return false;
+}
+
+void instance_stratholme::OnCreatureCreate(Creature* pCreature)
+{
+ switch(pCreature->GetEntry())
+ {
+ case NPC_BARON: m_uiBaronGUID = pCreature->GetGUID(); break;
+ case NPC_YSIDA_TRIGGER: m_uiYsidaTriggerGUID = pCreature->GetGUID(); break;
+ case NPC_CRYSTAL: m_lCrystals.push_back(pCreature); break;
+ case NPC_ABOM_BILE:
+ case NPC_ABOM_VENOM: m_sAbomnationGUID.insert(pCreature->GetGUID()); break;
+ case NPC_THUZADIN_ACOLYTE: m_lAcolytes.push_back(pCreature); break;
+ }
+}
+
+void instance_stratholme::OnObjectCreate(GameObject* pGo)
+{
+ switch(pGo->GetEntry())
+ {
+ case GO_SERVICE_ENTRANCE:
+ m_uiServiceEntranceGUID = pGo->GetGUID();
+ break;
+ case GO_GAUNTLET_GATE1:
+ // TODO
+ //weird, but unless flag is set, client will not respond as expected. DB bug?
+ pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_LOCKED);
+ m_uiGauntletGate1GUID = pGo->GetGUID();
+ break;
+ case GO_ZIGGURAT_DOOR_1:
+ m_auiZigguratGUID[0] = pGo->GetGUID();
+ if (m_auiEncounter[1] == DONE || m_auiEncounter[1] == SPECIAL)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_ZIGGURAT_DOOR_2:
+ m_auiZigguratGUID[1] = pGo->GetGUID();
+ if (m_auiEncounter[2] == DONE || m_auiEncounter[2] == SPECIAL)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_ZIGGURAT_DOOR_3:
+ m_auiZigguratGUID[2] = pGo->GetGUID();
+ if (m_auiEncounter[3] == DONE || m_auiEncounter[3] == SPECIAL)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_ZIGGURAT_DOOR_4:
+ m_auiRamsteinDoorGUID = pGo->GetGUID();
+ if (m_auiEncounter[4] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_ZIGGURAT_DOOR_5:
+ m_auiRivendareDoorGUID = pGo->GetGUID();
+ if (m_auiEncounter[4] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_PORT_GAUNTLET:
+ m_uiPortGauntletGUID = pGo->GetGUID();
+ if (m_auiEncounter[1] == SPECIAL && m_auiEncounter[2] == SPECIAL && m_auiEncounter[3] == SPECIAL)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_PORT_SLAUGTHER:
+ m_uiPortSlaugtherGUID = pGo->GetGUID();
+ if (m_auiEncounter[1] == SPECIAL && m_auiEncounter[2] == SPECIAL && m_auiEncounter[3] == SPECIAL)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_PORT_ELDERS:
+ m_uiPortElderGUID = pGo->GetGUID();
+ break;
+ }
+}
+
+void instance_stratholme::SetData(uint32 uiType, uint32 uiData)
+{
+ switch(uiType)
+ {
+ case TYPE_BARON_RUN:
+ switch(uiData)
+ {
+ case IN_PROGRESS:
+ if (m_auiEncounter[0] == IN_PROGRESS || m_auiEncounter[0] == FAIL)
+ break;
+ m_uiBaronRunTimer = 45*MINUTE*IN_MILLISECONDS;
+ debug_log("SD2: Instance Stratholme: Baron run in progress.");
+ break;
+ case FAIL:
+ //may add code to remove aura from players, but in theory the time should be up already and removed.
+ break;
+ case DONE:
+ if (Creature* pYsidaT = instance->GetCreature(m_uiYsidaTriggerGUID))
+ pYsidaT->SummonCreature(NPC_YSIDA, pYsidaT->GetPositionX(), pYsidaT->GetPositionY(), pYsidaT->GetPositionZ(), pYsidaT->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN, 1800000);
+
+ m_uiBaronRunTimer = 0;
+ break;
+ }
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_BARONESS:
+ m_auiEncounter[1] = uiData;
+ if (uiData == DONE)
+ {
+ DoSortZiggurats();
+ DoUseDoorOrButton(m_auiZigguratGUID[0]);
+ }
+ if (uiData == SPECIAL)
+ StartSlaugtherSquare();
+ break;
+ case TYPE_NERUB:
+ m_auiEncounter[2] = uiData;
+ if (uiData == DONE)
+ {
+ DoSortZiggurats();
+ DoUseDoorOrButton(m_auiZigguratGUID[1]);
+ }
+ if (uiData == SPECIAL)
+ StartSlaugtherSquare();
+ break;
+ case TYPE_PALLID:
+ m_auiEncounter[3] = uiData;
+ if (uiData == DONE)
+ {
+ DoSortZiggurats();
+ DoUseDoorOrButton(m_auiZigguratGUID[2]);
+ }
+ if (uiData == SPECIAL)
+ StartSlaugtherSquare();
+ break;
+ case TYPE_RAMSTEIN:
+ if (uiData == IN_PROGRESS)
+ {
+ if (m_auiEncounter[4] != IN_PROGRESS)
+ DoUseDoorOrButton(m_uiPortGauntletGUID);
+
+ uint32 uiCount = m_sAbomnationGUID.size();
+ for(std::set::iterator i = m_sAbomnationGUID.begin(); i != m_sAbomnationGUID.end(); ++i)
+ {
+ if (Creature* pAbom = instance->GetCreature(*i))
+ {
+ if (!pAbom->isAlive())
+ --uiCount;
+ }
+ }
+
+ if (!uiCount)
+ {
+ //a bit itchy, it should close the door after 10 secs, but it doesn't. skipping it for now.
+ // TODO - not working correctly!
+ //DoUseDoorOrButton(m_auiRamsteinDoorGUID, 10);
+
+ if (Creature* pBaron = instance->GetCreature(m_uiBaronGUID))
+ pBaron->SummonCreature(NPC_RAMSTEIN, 4032.84f, -3390.24f, 119.73f, 4.71f, TEMPSUMMON_DEAD_DESPAWN, 0);
+
+ debug_log("SD2: Instance Stratholme: Ramstein spawned.");
+ }
+ else
+ debug_log("SD2: Instance Stratholme: %u Abomnation left to kill.", uiCount);
+ }
+ if (uiData == DONE)
+ {
+ m_uiSlaugtherSquareTimer = 5*MINUTE*IN_MILLISECONDS;
+ debug_log("SD2: Instance Stratholme: Slaugther event will continue in 5 minutes.");
+ }
+ m_auiEncounter[4] = uiData;
+ break;
+ case TYPE_BARON:
+ if (uiData == IN_PROGRESS)
+ {
+ if (GetData(TYPE_BARON_RUN) == IN_PROGRESS)
+ {
+ Map::PlayerList const& players = instance->GetPlayers();
+
+ if (!players.isEmpty())
+ {
+ for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ if (Player* pPlayer = itr->getSource())
+ {
+ if (pPlayer->HasAura(SPELL_BARON_ULTIMATUM))
+ pPlayer->RemoveAurasDueToSpell(SPELL_BARON_ULTIMATUM);
+
+ if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->AreaExploredOrEventHappens(QUEST_DEAD_MAN_PLEA);
+ }
+ }
+ }
+
+ SetData(TYPE_BARON_RUN,DONE);
+ }
+ }
+ if (uiData == DONE)
+ // Open a few doors again // TODO: needs research, how to handle wipes in this area!
+ DoUseDoorOrButton(m_uiPortGauntletGUID);
+
+ m_auiEncounter[5] = uiData;
+ break;
+
+ case TYPE_SH_AELMAR:
+ m_bIsSilverHandDead[0] = (uiData) ? true : false;
+ break;
+ case TYPE_SH_CATHELA:
+ m_bIsSilverHandDead[1] = (uiData) ? true : false;
+ break;
+ case TYPE_SH_GREGOR:
+ m_bIsSilverHandDead[2] = (uiData) ? true : false;
+ break;
+ case TYPE_SH_NEMAS:
+ m_bIsSilverHandDead[3] = (uiData) ? true : false;
+ break;
+ case TYPE_SH_VICAR:
+ m_bIsSilverHandDead[4] = (uiData) ? true : false;
+ break;
+ }
+
+ if (uiData == DONE)
+ {
+ 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];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+}
+
+void instance_stratholme::Load(const char* chrIn)
+{
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
+ >> m_auiEncounter[4] >> m_auiEncounter[5];
+
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ // Special Treatment for the Ziggurat-Bosses, as otherwise the event couldn't reload
+ if (m_auiEncounter[1] == DONE)
+ m_auiEncounter[1] = SPECIAL;
+ if (m_auiEncounter[2] == DONE)
+ m_auiEncounter[2] = SPECIAL;
+ if (m_auiEncounter[3] == DONE)
+ m_auiEncounter[3] = SPECIAL;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+}
+
+uint32 instance_stratholme::GetData(uint32 uiType)
+{
+ switch(uiType)
+ {
+ case TYPE_SH_QUEST:
+ if (m_bIsSilverHandDead[0] && m_bIsSilverHandDead[1] && m_bIsSilverHandDead[2] && m_bIsSilverHandDead[3] && m_bIsSilverHandDead[4])
+ return 1;
+ return 0;
+ case TYPE_BARON_RUN:
+ return m_auiEncounter[0];
+ case TYPE_BARONESS:
+ return m_auiEncounter[1];
+ case TYPE_NERUB:
+ return m_auiEncounter[2];
+ case TYPE_PALLID:
+ return m_auiEncounter[3];
+ case TYPE_RAMSTEIN:
+ return m_auiEncounter[4];
+ case TYPE_BARON:
+ return m_auiEncounter[5];
+ default:
+ return 0;
+ }
+}
+
+uint64 instance_stratholme::GetData64(uint32 uiData)
+{
+ switch(uiData)
+ {
+ case NPC_BARON:
+ return m_uiBaronGUID;
+ case NPC_YSIDA_TRIGGER:
+ return m_uiYsidaTriggerGUID;
+ default:
+ return 0;
+ }
+}
+
+static bool sortByHight(Creature* pFirst, Creature* pSecond)
+{
+ return pFirst && pSecond && pFirst->GetPositionZ() > pSecond->GetPositionZ();
+}
+
+void instance_stratholme::DoSortZiggurats()
+{
+ if (m_lAcolytes.empty())
+ return;
+
+ if (!m_uiAcolyteAnnouncerGUID)
+ {
+ // Sort the acolytes by hight, and the one with the biggest hight is the announcer (a bit outside the map)
+ m_lAcolytes.sort(sortByHight);
+ m_uiAcolyteAnnouncerGUID = (*m_lAcolytes.begin())->GetGUID();
+ m_lAcolytes.erase(m_lAcolytes.begin());
+ }
+
+ // Sort Acolytes
+ for (std::list::iterator itr = m_lAcolytes.begin(); itr != m_lAcolytes.end(); )
+ {
+ bool bAlreadyIterated = false;
+ for (uint8 i = 0; i < MAX_ZIGGURATS; ++i)
+ {
+ if (GameObject* pZigguratDoor = instance->GetGameObject(m_auiZigguratGUID[i]))
+ {
+ if ((*itr)->isAlive() && (*itr)->IsWithinDistInMap(pZigguratDoor, 50.0f, false))
+ {
+ m_alZigguratAcolyteGUID[i].push_back((*itr)->GetGUID());
+ itr = m_lAcolytes.erase(itr);
+ bAlreadyIterated = true;
+ break;
+ }
+ }
+ }
+
+ if (itr != m_lAcolytes.end() && !bAlreadyIterated)
+ ++itr;
+ }
+
+ // Sort Crystal
+ for (std::list::iterator itr = m_lCrystals.begin(); itr != m_lCrystals.end(); )
+ {
+ bool bAlreadyIterated = false;
+ for (uint8 i = 0; i < MAX_ZIGGURATS; ++i)
+ {
+ if (GameObject* pZigguratDoor = instance->GetGameObject(m_auiZigguratGUID[i]))
+ {
+ if ((*itr)->IsWithinDistInMap(pZigguratDoor, 50.0f, false))
+ {
+ m_auiCrystalSortedGUID[i] = ((*itr)->GetGUID());
+ itr = m_lCrystals.erase(itr);
+ bAlreadyIterated = true;
+ break;
+ }
+ }
+ }
+
+ if (itr != m_lCrystals.end() && !bAlreadyIterated)
+ ++itr;
+ }
+}
+
+void instance_stratholme::OnCreatureDeath(Creature* pCreature)
+{
+ if (pCreature->GetEntry() == NPC_THUZADIN_ACOLYTE)
+ {
+ for (uint8 i = 0; i < MAX_ZIGGURATS; ++i)
+ {
+ if (m_alZigguratAcolyteGUID[i].empty())
+ continue; // nothing to do anymore for this ziggurat
+
+ m_alZigguratAcolyteGUID[i].remove(pCreature->GetGUID());
+ if (m_alZigguratAcolyteGUID[i].empty())
+ {
+ // A random zone yell after one is cleared
+ int32 aAnnounceSay[MAX_ZIGGURATS] = {SAY_ANNOUNCE_ZIGGURAT_1, SAY_ANNOUNCE_ZIGGURAT_2, SAY_ANNOUNCE_ZIGGURAT_3};
+ if (Creature* pAnnouncer = instance->GetCreature(m_uiAcolyteAnnouncerGUID))
+ DoScriptText(aAnnounceSay[i], pAnnouncer);
+
+ // Kill Crystal
+ if (Creature* pCrystal = instance->GetCreature(m_auiCrystalSortedGUID[i]))
+ pCrystal->DealDamage(pCrystal, pCrystal->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+
+ switch (i)
+ {
+ case 0: SetData(TYPE_BARONESS, SPECIAL); break;
+ case 1: SetData(TYPE_NERUB, SPECIAL); break;
+ case 2: SetData(TYPE_PALLID, SPECIAL); break;
+ }
+ }
+ }
+ }
+}
+
+void instance_stratholme::Update(uint32 uiDiff)
+{
+ if (m_uiBaronRunTimer)
+ {
+ if (m_uiBaronRunTimer <= uiDiff)
+ {
+ if (GetData(TYPE_BARON_RUN) != DONE)
+ SetData(TYPE_BARON_RUN, FAIL);
+
+ m_uiBaronRunTimer = 0;
+ debug_log("SD2: Instance Stratholme: Baron run event reached end. Event has state %u.",GetData(TYPE_BARON_RUN));
+ }
+ else
+ m_uiBaronRunTimer -= uiDiff;
+ }
+
+ if (m_uiSlaugtherSquareTimer)
+ {
+ if (m_uiSlaugtherSquareTimer <= uiDiff)
+ {
+ if (Creature* pBaron = instance->GetCreature(m_uiBaronGUID))
+ {
+ for(uint8 i = 0; i < 4; ++i)
+ pBaron->SummonCreature(NPC_BLACK_GUARD, 4032.84f, -3390.24f, 119.73f, 4.71f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000);
+
+ DoUseDoorOrButton(m_auiRamsteinDoorGUID);
+ DoUseDoorOrButton(m_auiRivendareDoorGUID);
+
+ debug_log("SD2: Instance Stratholme: Black guard sentries spawned. Opening gates to baron.");
+ }
+ m_uiSlaugtherSquareTimer = 0;
+ }
+ else
+ m_uiSlaugtherSquareTimer -= uiDiff;
+ }
+}
+
+InstanceData* GetInstanceData_instance_stratholme(Map* pMap)
+{
+ return new instance_stratholme(pMap);
+}
+
+void AddSC_instance_stratholme()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "instance_stratholme";
+ pNewScript->GetInstanceData = &GetInstanceData_instance_stratholme;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/stratholme.cpp b/scripts/eastern_kingdoms/stratholme/stratholme.cpp
new file mode 100644
index 0000000..9fbe9a8
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/stratholme.cpp
@@ -0,0 +1,291 @@
+/* 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: Stratholme
+SD%Complete: 100
+SDComment: Misc mobs for instance. GO-script to apply aura and start event for quest 8945
+SDCategory: Stratholme
+EndScriptData */
+
+/* ContentData
+go_gauntlet_gate
+mob_freed_soul
+mob_restless_soul
+mobs_spectral_ghostly_citizen
+EndContentData */
+
+#include "precompiled.h"
+#include "stratholme.h"
+
+/*######
+## go_gauntlet_gate (this is the _first_ of the gauntlet gates, two exist)
+######*/
+
+bool GOHello_go_gauntlet_gate(Player* pPlayer, GameObject* pGo)
+{
+ ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData();
+
+ if (!pInstance)
+ return false;
+
+ if (pInstance->GetData(TYPE_BARON_RUN) != NOT_STARTED)
+ return false;
+
+ if (Group *pGroup = pPlayer->GetGroup())
+ {
+ for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
+ {
+ Player* pGroupie = itr->getSource();
+ if (!pGroupie)
+ continue;
+
+ if (pGroupie->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE &&
+ !pGroupie->HasAura(SPELL_BARON_ULTIMATUM, EFFECT_INDEX_0) &&
+ pGroupie->GetMap() == pGo->GetMap())
+ pGroupie->CastSpell(pGroupie,SPELL_BARON_ULTIMATUM,true);
+ }
+ }
+ else
+ {
+ if (pPlayer->GetQuestStatus(QUEST_DEAD_MAN_PLEA) == QUEST_STATUS_INCOMPLETE &&
+ !pPlayer->HasAura(SPELL_BARON_ULTIMATUM, EFFECT_INDEX_0) &&
+ pPlayer->GetMap() == pGo->GetMap())
+ pPlayer->CastSpell(pPlayer, SPELL_BARON_ULTIMATUM, true);
+ }
+
+ pInstance->SetData(TYPE_BARON_RUN,IN_PROGRESS);
+ return false;
+}
+
+/*######
+## mob_freed_soul
+######*/
+
+//Possibly more of these quotes around.
+#define SAY_ZAPPED0 -1329000
+#define SAY_ZAPPED1 -1329001
+#define SAY_ZAPPED2 -1329002
+#define SAY_ZAPPED3 -1329003
+
+struct MANGOS_DLL_DECL mob_freed_soulAI : public ScriptedAI
+{
+ mob_freed_soulAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ switch(urand(0, 3))
+ {
+ case 0: DoScriptText(SAY_ZAPPED0, m_creature); break;
+ case 1: DoScriptText(SAY_ZAPPED1, m_creature); break;
+ case 2: DoScriptText(SAY_ZAPPED2, m_creature); break;
+ case 3: DoScriptText(SAY_ZAPPED3, m_creature); break;
+ }
+ }
+};
+
+CreatureAI* GetAI_mob_freed_soul(Creature* pCreature)
+{
+ return new mob_freed_soulAI(pCreature);
+}
+
+/*######
+## mob_restless_soul
+######*/
+
+#define SPELL_EGAN_BLASTER 17368
+#define SPELL_SOUL_FREED 17370
+#define QUEST_RESTLESS_SOUL 5282
+#define ENTRY_RESTLESS 11122
+#define ENTRY_FREED 11136
+
+struct MANGOS_DLL_DECL mob_restless_soulAI : public ScriptedAI
+{
+ mob_restless_soulAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint64 Tagger;
+ uint32 Die_Timer;
+ bool Tagged;
+
+ void Reset()
+ {
+ Tagger = 0;
+ Die_Timer = 5000;
+ Tagged = false;
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ if (caster->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (!Tagged && spell->Id == SPELL_EGAN_BLASTER && ((Player*)caster)->GetQuestStatus(QUEST_RESTLESS_SOUL) == QUEST_STATUS_INCOMPLETE)
+ {
+ Tagged = true;
+ Tagger = caster->GetGUID();
+ }
+ }
+ }
+
+ void JustSummoned(Creature *summoned)
+ {
+ summoned->CastSpell(summoned,SPELL_SOUL_FREED,false);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (Tagged)
+ m_creature->SummonCreature(ENTRY_FREED, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 300000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (Tagged)
+ {
+ if (Die_Timer < diff)
+ {
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(Tagger))
+ pPlayer->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ else
+ Die_Timer -= diff;
+ }
+ }
+};
+
+CreatureAI* GetAI_mob_restless_soul(Creature* pCreature)
+{
+ return new mob_restless_soulAI(pCreature);
+}
+
+/*######
+## mobs_spectral_ghostly_citizen
+######*/
+
+enum
+{
+ SPELL_HAUNTING_PHANTOM = 16336,
+ SPELL_SLAP = 6754
+};
+
+struct MANGOS_DLL_DECL mobs_spectral_ghostly_citizenAI : public ScriptedAI
+{
+ mobs_spectral_ghostly_citizenAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Die_Timer;
+ bool Tagged;
+
+ void Reset()
+ {
+ Die_Timer = 5000;
+ Tagged = false;
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ if (!Tagged && spell->Id == SPELL_EGAN_BLASTER)
+ Tagged = true;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (Tagged)
+ {
+ for(uint32 i = 1; i <= 4; ++i)
+ {
+ float x,y,z;
+ m_creature->GetRandomPoint(m_creature->GetPositionX(),m_creature->GetPositionY(),m_creature->GetPositionZ(),20.0f,x,y,z);
+
+ //100%, 50%, 33%, 25% chance to spawn
+ uint32 j = urand(1,i);
+ if (j==1)
+ m_creature->SummonCreature(ENTRY_RESTLESS,x,y,z,0,TEMPSUMMON_CORPSE_DESPAWN,600000);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (Tagged)
+ {
+ if (Die_Timer < diff)
+ {
+ m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ else
+ Die_Timer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+
+ void ReceiveEmote(Player* pPlayer, uint32 emote)
+ {
+ switch(emote)
+ {
+ case TEXTEMOTE_DANCE:
+ EnterEvadeMode();
+ break;
+ case TEXTEMOTE_RUDE:
+ if (m_creature->IsWithinDistInMap(pPlayer, ATTACK_DISTANCE))
+ m_creature->CastSpell(pPlayer,SPELL_SLAP,false);
+ else
+ m_creature->HandleEmote(EMOTE_ONESHOT_RUDE);
+ break;
+ case TEXTEMOTE_WAVE:
+ m_creature->HandleEmote(EMOTE_ONESHOT_WAVE);
+ break;
+ case TEXTEMOTE_BOW:
+ m_creature->HandleEmote(EMOTE_ONESHOT_BOW);
+ break;
+ case TEXTEMOTE_KISS:
+ m_creature->HandleEmote(EMOTE_ONESHOT_FLEX);
+ break;
+ }
+ }
+};
+
+CreatureAI* GetAI_mobs_spectral_ghostly_citizen(Creature* pCreature)
+{
+ return new mobs_spectral_ghostly_citizenAI(pCreature);
+}
+
+void AddSC_stratholme()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "go_gauntlet_gate";
+ pNewScript->pGOHello = &GOHello_go_gauntlet_gate;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "mob_freed_soul";
+ pNewScript->GetAI = &GetAI_mob_freed_soul;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "mob_restless_soul";
+ pNewScript->GetAI = &GetAI_mob_restless_soul;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "mobs_spectral_ghostly_citizen";
+ pNewScript->GetAI = &GetAI_mobs_spectral_ghostly_citizen;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/stratholme/stratholme.h b/scripts/eastern_kingdoms/stratholme/stratholme.h
new file mode 100644
index 0000000..76f81d7
--- /dev/null
+++ b/scripts/eastern_kingdoms/stratholme/stratholme.h
@@ -0,0 +1,114 @@
+/* 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 */
+
+#ifndef DEF_STRATHOLME_H
+#define DEF_STRATHOLME_H
+
+enum
+{
+ MAX_ENCOUNTER = 6,
+ MAX_SILVERHAND = 5,
+ MAX_ZIGGURATS = 3,
+
+ TYPE_BARON_RUN = 1,
+ TYPE_BARONESS = 2,
+ TYPE_NERUB = 3,
+ TYPE_PALLID = 4,
+ TYPE_RAMSTEIN = 5,
+ TYPE_BARON = 6,
+
+ //DATA_BARON = 10, // Wasn't used, verify that it really was never used!
+ //DATA_YSIDA_TRIGGER = 11,
+
+ TYPE_SH_QUEST = 20,
+ TYPE_SH_CATHELA = 21,
+ TYPE_SH_GREGOR = 22,
+ TYPE_SH_NEMAS = 23,
+ TYPE_SH_VICAR = 24,
+ TYPE_SH_AELMAR = 25,
+
+ NPC_CRYSTAL = 10415, //three ziggurat crystals
+ NPC_BARON = 10440,
+ NPC_YSIDA_TRIGGER = 16100,
+ NPC_THUZADIN_ACOLYTE = 10399, //acolytes in ziggurats
+ NPC_RAMSTEIN = 10439,
+ NPC_ABOM_BILE = 10416,
+ NPC_ABOM_VENOM = 10417,
+ NPC_BLACK_GUARD = 10394,
+ NPC_YSIDA = 16031,
+
+ GO_SERVICE_ENTRANCE = 175368,
+ GO_GAUNTLET_GATE1 = 175357,
+ GO_ZIGGURAT_DOOR_1 = 175380, //baroness
+ GO_ZIGGURAT_DOOR_2 = 175379, //nerub'enkan
+ GO_ZIGGURAT_DOOR_3 = 175381, //maleki
+ GO_ZIGGURAT_DOOR_4 = 175405, //rammstein
+ GO_ZIGGURAT_DOOR_5 = 175796, //baron
+ GO_PORT_GAUNTLET = 175374, //port from gauntlet to slaugther
+ GO_PORT_SLAUGTHER = 175373, //port at slaugther
+ GO_PORT_ELDERS = 175377, //port at elders square
+
+ QUEST_DEAD_MAN_PLEA = 8945,
+ SPELL_BARON_ULTIMATUM = 27861,
+
+ SAY_ANNOUNCE_ZIGGURAT_1 = -1329004,
+ SAY_ANNOUNCE_ZIGGURAT_2 = -1329005,
+ SAY_ANNOUNCE_ZIGGURAT_3 = -1329006,
+ SAY_ANNOUNCE_RIVENDARE = -1329007
+};
+
+struct MANGOS_DLL_DECL instance_stratholme : public ScriptedInstance
+{
+ public:
+ instance_stratholme(Map* pMap);
+ ~instance_stratholme() {}
+
+ void Initialize();
+
+ void OnCreatureCreate(Creature* pCreature);
+ void OnObjectCreate(GameObject* pGo);
+
+ void SetData(uint32 uiType, uint32 uiData);
+ uint32 GetData(uint32 uiType);
+ uint64 GetData64(uint32 uiData);
+
+ const char* Save() { return strInstData.c_str(); }
+ void Load(const char* chrIn);
+
+ void OnCreatureDeath(Creature* pCreature);
+
+ void Update(uint32 uiDiff);
+
+ bool StartSlaugtherSquare();
+ void DoSortZiggurats();
+
+ protected:
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ bool m_bIsSilverHandDead[MAX_SILVERHAND];
+ std::string strInstData;
+
+ uint32 m_uiBaronRunTimer;
+ uint32 m_uiSlaugtherSquareTimer;
+
+ uint64 m_uiServiceEntranceGUID;
+ uint64 m_uiGauntletGate1GUID;
+ uint64 m_auiZigguratGUID[MAX_ZIGGURATS];
+ uint64 m_auiRamsteinDoorGUID;
+ uint64 m_auiRivendareDoorGUID;
+ uint64 m_uiPortGauntletGUID;
+ uint64 m_uiPortSlaugtherGUID;
+ uint64 m_uiPortElderGUID;
+
+ uint64 m_uiBaronGUID;
+ uint64 m_uiYsidaTriggerGUID;
+ uint64 m_uiAcolyteAnnouncerGUID;
+ uint64 m_auiCrystalSortedGUID[MAX_ZIGGURATS];
+
+ std::list m_lCrystals;
+ std::set m_sAbomnationGUID;
+ std::list m_lAcolytes; // done with pointers, to keep sorting easier
+ std::list m_alZigguratAcolyteGUID[MAX_ZIGGURATS];
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp b/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp
new file mode 100644
index 0000000..acd76c2
--- /dev/null
+++ b/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp
@@ -0,0 +1,158 @@
+/* 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_sunken_temple
+SD%Complete: 30
+SDComment:
+SDCategory: Sunken Temple
+EndScriptData */
+
+#include "precompiled.h"
+#include "sunken_temple.h"
+
+instance_sunken_temple::instance_sunken_temple(Map* pMap) : ScriptedInstance(pMap),
+ m_uiJammalainBarrierGUID(0),
+ m_uiProtectorsRemaining(0)
+{
+ Initialize();
+}
+
+void instance_sunken_temple::Initialize()
+{
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+}
+
+void instance_sunken_temple::OnObjectCreate(GameObject* pGo)
+{
+ switch(pGo->GetEntry())
+ {
+ case GO_JAMMALAIN_BARRIER:
+ m_uiJammalainBarrierGUID = pGo->GetGUID();
+ if (m_auiEncounter[1] == DONE)
+ DoUseDoorOrButton(m_uiJammalainBarrierGUID);
+ break;
+ }
+
+}
+
+void instance_sunken_temple::OnCreatureCreate(Creature* pCreature)
+{
+ switch(pCreature->GetEntry())
+ {
+ case NPC_ZOLO:
+ case NPC_GASHER:
+ case NPC_LORO:
+ case NPC_HUKKU:
+ case NPC_ZULLOR:
+ case NPC_MIJAN:
+ ++m_uiProtectorsRemaining;
+ break;
+ }
+}
+
+void instance_sunken_temple::SetData(uint32 uiType, uint32 uiData)
+{
+ switch(uiType)
+ {
+ case TYPE_ATALARION:
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_PROTECTORS:
+ if (uiData == DONE)
+ {
+ //Jammalain should yell here about barrier being destroyed
+ --m_uiProtectorsRemaining;
+ if (!m_uiProtectorsRemaining)
+ {
+ m_auiEncounter[1] = uiData;
+ DoUseDoorOrButton(m_uiJammalainBarrierGUID);
+ }
+ }
+ break;
+ case TYPE_JAMMALAIN:
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_MALFURION:
+ 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;
+ }
+}
+
+void instance_sunken_temple::Load(const char* chrIn)
+{
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+}
+
+uint32 instance_sunken_temple::GetData(uint32 uiType)
+{
+ switch(uiType)
+ {
+ case TYPE_ATALARION:
+ return m_auiEncounter[0];
+ case TYPE_PROTECTORS:
+ return m_auiEncounter[1];
+ case TYPE_JAMMALAIN:
+ return m_auiEncounter[2];
+ case TYPE_MALFURION:
+ return m_auiEncounter[3];
+ }
+ return 0;
+}
+
+InstanceData* GetInstanceData_instance_sunken_temple(Map* pMap)
+{
+ return new instance_sunken_temple(pMap);
+}
+
+void AddSC_instance_sunken_temple()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "instance_sunken_temple";
+ newscript->GetInstanceData = &GetInstanceData_instance_sunken_temple;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp b/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp
new file mode 100644
index 0000000..ff185a5
--- /dev/null
+++ b/scripts/eastern_kingdoms/sunken_temple/sunken_temple.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: Sunken_Temple
+SD%Complete: 100
+SDComment: Quest support: 8733
+SDCategory: Sunken Temple
+EndScriptData */
+
+/* ContentData
+at_shade_of_eranikus
+npc_malfurion_stormrage
+EndContentData */
+
+#include "precompiled.h"
+#include "sunken_temple.h"
+
+enum
+{
+ QUEST_THE_CHARGE_OF_DRAGONFLIGHTS = 8555,
+ QUEST_ERANIKUS_TYRANT_OF_DREAMS = 8733
+};
+
+bool AreaTrigger_at_shade_of_eranikus(Player* pPlayer, AreaTriggerEntry const* pAt)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pPlayer->GetInstanceData())
+ {
+ //Only do stuff, if the player has finished the PreQuest
+ if (pPlayer->GetQuestRewardStatus(QUEST_THE_CHARGE_OF_DRAGONFLIGHTS) &&
+ !pPlayer->GetQuestRewardStatus(QUEST_ERANIKUS_TYRANT_OF_DREAMS) &&
+ pPlayer->GetQuestStatus(QUEST_ERANIKUS_TYRANT_OF_DREAMS) != QUEST_STATUS_COMPLETE)
+ {
+ if (pInstance->GetData(TYPE_MALFURION) != DONE)
+ {
+ pPlayer->SummonCreature(NPC_MALFURION, -639.378723f, -4.238533f, -90.835098f, 2.724664f, TEMPSUMMON_DEAD_DESPAWN, 0);
+ pInstance->SetData(TYPE_MALFURION, DONE);
+ }
+ }
+ }
+ return false;
+}
+
+/*######
+## npc_malfurion_stormrage
+######*/
+enum
+{
+ EMOTE_MALFURION1 = -1109000,
+ SAY_MALFURION1 = -1109001,
+ SAY_MALFURION2 = -1109002,
+ SAY_MALFURION3 = -1109003,
+ SAY_MALFURION4 = -1109004,
+
+ MAX_MALFURION_TEMPLE_SPEECHES = 6
+};
+
+struct MANGOS_DLL_DECL npc_malfurionAI : public ScriptedAI
+{
+ npc_malfurionAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiSpeech = 0;
+ m_uiSayTimer = 0;
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ }
+
+ uint32 m_uiSayTimer;
+ uint32 m_uiSpeech;
+
+ void Reset() {}
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // we are in Sunken Temple
+ if (m_creature->GetMap()->IsDungeon())
+ {
+ if (m_uiSpeech < MAX_MALFURION_TEMPLE_SPEECHES)
+ {
+ if (m_uiSayTimer <= uiDiff)
+ {
+ switch (m_uiSpeech)
+ {
+ case 0:
+ DoScriptText(EMOTE_MALFURION1, m_creature);
+ m_uiSayTimer = 1500;
+ break;
+ case 1:
+ m_creature->HandleEmote(EMOTE_ONESHOT_BOW);
+ m_uiSayTimer = 2000;
+ break;
+ case 2:
+ DoScriptText(SAY_MALFURION1, m_creature);
+ m_uiSayTimer = 1000;
+ break;
+ case 3:
+ DoScriptText(SAY_MALFURION2, m_creature);
+ m_uiSayTimer = 1000;
+ break;
+ case 4:
+ DoScriptText(SAY_MALFURION3, m_creature);
+ m_uiSayTimer = 2000;
+ break;
+ case 5:
+ DoScriptText(SAY_MALFURION4, m_creature);
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ break;
+ }
+
+ ++m_uiSpeech;
+ }
+ else
+ m_uiSayTimer -= uiDiff;
+ }
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_malfurion(Creature* pCreature)
+{
+ return new npc_malfurionAI(pCreature);
+}
+
+void AddSC_sunken_temple()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "at_shade_of_eranikus";
+ newscript->pAreaTrigger = &AreaTrigger_at_shade_of_eranikus;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_malfurion_stormrage";
+ newscript->GetAI = &GetAI_npc_malfurion;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h b/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h
new file mode 100644
index 0000000..c2d2481
--- /dev/null
+++ b/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h
@@ -0,0 +1,74 @@
+/* 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 */
+
+#ifndef DEF_SUNKEN_TEMPLE_H
+#define DEF_SUNKEN_TEMPLE_H
+
+enum
+{
+ MAX_ENCOUNTER = 4,
+
+ TYPE_ATALARION = 1,
+ TYPE_PROTECTORS = 2,
+ TYPE_JAMMALAIN = 3,
+ TYPE_MALFURION = 4,
+
+ NPC_ATALARION = 8580,
+ NPC_DREAMSCYTH = 5721,
+ NPC_WEAVER = 5720,
+ NPC_AVATAR_OF_HAKKAR = 8443,
+ NPC_SHADE_OF_ERANIKUS = 5709,
+
+ // Jammalain min-bosses
+ NPC_ZOLO = 5712,
+ NPC_GASHER = 5713,
+ NPC_LORO = 5714,
+ NPC_HUKKU = 5715,
+ NPC_ZULLOR = 5716,
+ NPC_MIJAN = 5717,
+
+ NPC_MALFURION = 15362,
+
+ GO_ALTAR_OF_HAKKAR = 148836,
+
+ GO_ATALAI_STATUE_1 = 148830,
+ GO_ATALAI_STATUE_2 = 148831,
+ GO_ATALAI_STATUE_3 = 148832,
+ GO_ATALAI_STATUE_4 = 148833,
+ GO_ATALAI_STATUE_5 = 148834,
+ GO_ATALAI_STATUE_6 = 148835,
+
+ GO_ETERNAL_FLAME_1 = 148418,
+ GO_ETERNAL_FLAME_2 = 148419,
+ GO_ETERNAL_FLAME_3 = 148420,
+ GO_ETERNAL_FLAME_4 = 148421,
+
+ GO_JAMMALAIN_BARRIER = 149431
+};
+
+class MANGOS_DLL_DECL instance_sunken_temple : public ScriptedInstance
+{
+ public:
+ instance_sunken_temple(Map* pMap);
+ ~instance_sunken_temple() {}
+
+ void Initialize();
+
+ void OnObjectCreate(GameObject* pGo);
+ void OnCreatureCreate(Creature* pCreature);
+
+ void SetData(uint32 uiType, uint32 uiData);
+ uint32 GetData(uint32 uiType);
+
+ const char* Save() { return strInstData.c_str(); }
+ void Load(const char* chrIn);
+
+ protected:
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint64 m_uiJammalainBarrierGUID;
+ uint8 m_uiProtectorsRemaining;
+};
+#endif
diff --git a/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp b/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp
new file mode 100644
index 0000000..9965cbd
--- /dev/null
+++ b/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp
@@ -0,0 +1,221 @@
+/* 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_Brutallus
+SD%Complete: 50
+SDComment: Intro not made. Script for Madrigosa to be added here.
+SDCategory: Sunwell Plateau
+EndScriptData */
+
+#include "precompiled.h"
+#include "sunwell_plateau.h"
+
+enum Brutallus
+{
+ YELL_INTRO = -1580017,
+ YELL_INTRO_BREAK_ICE = -1580018,
+ YELL_INTRO_CHARGE = -1580019,
+ YELL_INTRO_KILL_MADRIGOSA = -1580020,
+ YELL_INTRO_TAUNT = -1580021,
+
+ YELL_MADR_ICE_BARRIER = -1580031,
+ YELL_MADR_INTRO = -1580032,
+ YELL_MADR_ICE_BLOCK = -1580033,
+ YELL_MADR_TRAP = -1580034,
+ YELL_MADR_DEATH = -1580035,
+
+ YELL_AGGRO = -1580022,
+ YELL_KILL1 = -1580023,
+ YELL_KILL2 = -1580024,
+ YELL_KILL3 = -1580025,
+ YELL_LOVE1 = -1580026,
+ YELL_LOVE2 = -1580027,
+ YELL_LOVE3 = -1580028,
+ YELL_BERSERK = -1580029,
+ YELL_DEATH = -1580030,
+
+ SPELL_METEOR_SLASH = 45150,
+ SPELL_BURN = 45141,
+ SPELL_BURN_AURA_EFFECT = 46394,
+ SPELL_STOMP = 45185,
+ SPELL_BERSERK = 26662
+};
+
+struct MANGOS_DLL_DECL boss_brutallusAI : public ScriptedAI
+{
+ boss_brutallusAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiSlashTimer;
+ uint32 m_uiBurnTimer;
+ uint32 m_uiStompTimer;
+ uint32 m_uiBerserkTimer;
+ uint32 m_uiLoveTimer;
+
+ void Reset()
+ {
+ m_uiSlashTimer = 11000;
+ m_uiStompTimer = 30000;
+ m_uiBurnTimer = 60000;
+ m_uiBerserkTimer = 360000;
+ m_uiLoveTimer = urand(10000, 17000);
+
+ //TODO: correct me when pre-event implemented
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BRUTALLUS, NOT_STARTED);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(YELL_AGGRO, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BRUTALLUS, IN_PROGRESS);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(YELL_KILL1, m_creature); break;
+ case 1: DoScriptText(YELL_KILL2, m_creature); break;
+ case 2: DoScriptText(YELL_KILL3, m_creature); break;
+ }
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(YELL_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_BRUTALLUS, DONE);
+ }
+
+ void SpellHitTarget(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (pSpell->Id == SPELL_BURN)
+ pCaster->CastSpell(pCaster, SPELL_BURN_AURA_EFFECT, true, NULL, NULL, m_creature->GetGUID());
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiLoveTimer < uiDiff)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(YELL_LOVE1, m_creature); break;
+ case 1: DoScriptText(YELL_LOVE2, m_creature); break;
+ case 2: DoScriptText(YELL_LOVE3, m_creature); break;
+ }
+ m_uiLoveTimer = urand(15000, 23000);
+ }
+ else
+ m_uiLoveTimer -= uiDiff;
+
+ if (m_uiSlashTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_METEOR_SLASH);
+ m_uiSlashTimer = 11000;
+ }
+ else
+ m_uiSlashTimer -= uiDiff;
+
+ if (m_uiStompTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->getVictim())
+ {
+ DoCastSpellIfCan(pTarget,SPELL_STOMP);
+
+ if (pTarget->HasAura(SPELL_BURN_AURA_EFFECT, EFFECT_INDEX_0))
+ pTarget->RemoveAurasDueToSpell(SPELL_BURN_AURA_EFFECT);
+ }
+
+ m_uiStompTimer = 30000;
+ }
+ else
+ m_uiStompTimer -= uiDiff;
+
+ if (m_uiBurnTimer < uiDiff)
+ {
+ //returns any unit
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ //so we get owner, in case unit was pet/totem/etc
+ if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself())
+ DoCastSpellIfCan(pPlayer, SPELL_BURN);
+ }
+
+ m_uiBurnTimer = 60000;
+ }
+ else
+ m_uiBurnTimer -= uiDiff;
+
+ if (m_uiBerserkTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature,SPELL_BERSERK) == CAST_OK)
+ {
+ DoScriptText(YELL_BERSERK, m_creature);
+ m_uiBerserkTimer = 20000;
+ }
+ }
+ else
+ m_uiBerserkTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_brutallus(Creature* pCreature)
+{
+ return new boss_brutallusAI(pCreature);
+}
+
+bool AreaTrigger_at_madrigosa(Player* pPlayer, AreaTriggerEntry const* pAt)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pPlayer->GetInstanceData())
+ {
+ //this simply set encounter state, and trigger ice barrier become active
+ //bosses can start pre-event based on this new state
+ if (pInstance->GetData(TYPE_BRUTALLUS) == NOT_STARTED)
+ pInstance->SetData(TYPE_BRUTALLUS, SPECIAL);
+ }
+
+ return false;
+}
+
+void AddSC_boss_brutallus()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_brutallus";
+ newscript->GetAI = &GetAI_boss_brutallus;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "at_madrigosa";
+ newscript->pAreaTrigger = &AreaTrigger_at_madrigosa;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp b/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp
new file mode 100644
index 0000000..a27705e
--- /dev/null
+++ b/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp
@@ -0,0 +1,622 @@
+/* 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_Kalecgos
+SD%Complete: 40
+SDComment: Script must be considered not complete.
+SDCategory: Sunwell Plateau
+EndScriptData */
+
+#include "precompiled.h"
+#include "sunwell_plateau.h"
+
+enum KalecgosEncounter
+{
+ //kalecgos dragon form
+ SAY_EVIL_AGGRO = -1580000,
+ SAY_EVIL_SPELL1 = -1580001,
+ SAY_EVIL_SPELL2 = -1580002,
+ SAY_EVIL_SLAY1 = -1580003,
+ SAY_EVIL_SLAY2 = -1580004,
+ SAY_EVIL_ENRAGE = -1580005,
+
+ //kalecgos humanoid form
+ SAY_GOOD_AGGRO = -1580006,
+ SAY_GOOD_NEAR_DEATH = -1580007,
+ SAY_GOOD_NEAR_DEATH2 = -1580008,
+ SAY_GOOD_PLRWIN = -1580009,
+
+ SAY_SATH_AGGRO = -1580010,
+ SAY_SATH_DEATH = -1580011,
+ SAY_SATH_SPELL1 = -1580012,
+ SAY_SATH_SPELL2 = -1580013,
+ SAY_SATH_SLAY1 = -1580014,
+ SAY_SATH_SLAY2 = -1580015,
+ SAY_SATH_ENRAGE = -1580016,
+
+ //Kalecgos
+ SPELL_SPECTRAL_BLAST_DUMMY = 44869,
+ SPELL_SPECTRAL_BLAST = 44866,
+
+ SPELL_ARCANE_BUFFET = 45018,
+ SPELL_FROST_BREATH = 44799,
+ SPELL_HEROIC_STRIKE = 45026,
+ SPELL_REVITALIZE = 45027,
+ SPELL_TAIL_LASH = 45122,
+ SPELL_TRANSFORM_KALEC = 45027,
+ SPELL_CRAZED_RAGE = 44806, // this should be 44807 instead
+
+ //Sathrovarr
+ SPELL_SPECTRAL_INVIS = 44801,
+ SPELL_CORRUPTING_STRIKE = 45029,
+ SPELL_CURSE_OF_BOUNDLESS_AGONY = 45032,
+ SPELL_SHADOW_BOLT_VOLLEY = 45031,
+
+ //Misc
+ SPELL_BANISH = 44836
+};
+
+uint32 WildMagic[]= { 44978, 45001, 45002, 45004, 45006, 45010 };
+
+const float KALECGOS_ARENA[3] = { 1704.34f, 928.17f, 53.08f };
+
+//#define NOTIFY_SPECTRALLY_EXHAUSTED "Your body is too exhausted to travel to the Spectral Realm."
+
+struct MANGOS_DLL_DECL boss_kalecgosAI : public ScriptedAI
+{
+ boss_kalecgosAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+
+ /*if (pCreature->getFaction() != 14)
+ {
+ error_db_log("SD2: creature entry %u has faction %u but spellId %u requires different.", pCreature->GetEntry(), pCreature->getFaction(), SPELL_SPECTRAL_REALM_FORCE_FACTION);
+ pCreature->setFaction(14);
+ }*/
+
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiArcaneBuffetTimer;
+ uint32 m_uiFrostBreathTimer;
+ uint32 m_uiWildMagicTimer;
+ uint32 m_uiSpectralBlastTimer;
+ uint32 m_uiExitTimer;
+
+ bool m_bUncorrupted;
+ bool m_bBanished;
+ bool m_bChecked;
+ bool m_bEnraged;
+ bool m_bHasSpectralTarget;
+
+ void Reset()
+ {
+ m_uiArcaneBuffetTimer = 8000;
+ m_uiFrostBreathTimer = 24000;
+ m_uiWildMagicTimer = 18000;
+ m_uiSpectralBlastTimer = 30000;
+
+ m_uiExitTimer = 0;
+
+ m_bUncorrupted = false;
+ m_bBanished = false;
+ m_bChecked = false;
+ m_bEnraged = false;
+ m_bHasSpectralTarget = false;
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ {
+ // Reset Sathrovarr too
+ if (Creature* pSath = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_SATHROVARR)))
+ {
+ if (pSath->isAlive() && pSath->getVictim())
+ pSath->AI()->EnterEvadeMode();
+ }
+
+ m_pInstance->SetData(TYPE_KALECGOS, NOT_STARTED);
+ }
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_EVIL_AGGRO, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_KALECGOS, IN_PROGRESS);
+ }
+
+ void DamageTaken(Unit* done_by, uint32 &damage)
+ {
+ if (damage >= m_creature->GetHealth() && done_by != m_creature)
+ {
+ if (!m_bUncorrupted)
+ {
+ damage = 0;
+ m_bBanished = true;
+ DoCastSpellIfCan(m_creature, SPELL_BANISH, true);
+ m_creature->GetMotionMaster()->MoveIdle();
+ }
+ else
+ {
+ damage = 0;
+ BeginOutro();
+ }
+ }
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_EVIL_SLAY1 : SAY_EVIL_SLAY2, m_creature);
+ }
+
+ void SendToInnerVeil(Unit* pTarget)
+ {
+ if (m_pInstance)
+ {
+ //just a hack for not implemented spell effect 144
+ ((Player*)pTarget)->TeleportTo(pTarget->GetMapId(), pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ()-125.0f, pTarget->GetOrientation());
+
+ pTarget->CastSpell(pTarget, SPELL_SPECTRAL_REALM_FORCE_FACTION, true);
+ pTarget->CastSpell(pTarget, SPELL_SPECTRAL_REALM, true);
+
+ m_pInstance->SetData64(DATA_PLAYER_SPECTRAL_REALM, pTarget->GetGUID());
+ }
+ }
+
+ void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell)
+ {
+ if (pSpell->Id == SPELL_SPECTRAL_BLAST_DUMMY && !m_bHasSpectralTarget)
+ {
+ if (pTarget->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (pTarget->HasAura(SPELL_SPECTRAL_EXHAUSTION, EFFECT_INDEX_0) || pTarget->HasAura(SPELL_SPECTRAL_REALM))
+ return;
+
+ if (pTarget == m_creature->getVictim())
+ return;
+
+ m_bHasSpectralTarget = true;
+ pTarget->CastSpell(pTarget, SPELL_SPECTRAL_BLAST, true);
+
+ SendToInnerVeil(pTarget);
+ }
+ }
+
+ void BeginOutro()
+ {
+ debug_log("SD2: KALEC: Beginning Outro");
+
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pSathrovarr = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_SATHROVARR)))
+ {
+ if (pSathrovarr->isAlive())
+ {
+ pSathrovarr->NearTeleportTo(KALECGOS_ARENA[0], KALECGOS_ARENA[1], KALECGOS_ARENA[2], 0.0f);
+ pSathrovarr->DealDamage(pSathrovarr, pSathrovarr->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ }
+
+ if (Creature* pKalec = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_KALECGOS_HUMAN)))
+ {
+ pKalec->DeleteThreatList();
+ pKalec->SetVisibility(VISIBILITY_OFF);
+ }
+
+ m_creature->GetMotionMaster()->MoveIdle();
+ m_creature->setFaction(35);
+ DoScriptText(SAY_GOOD_PLRWIN, m_creature);
+ m_uiExitTimer = 1000;
+ }
+
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if (type != POINT_MOTION_TYPE)
+ return;
+
+ if (id)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_KALECGOS, DONE);
+
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->getVictim() || !m_creature->SelectHostileTarget() || m_bBanished)
+ return;
+
+ if (!m_bEnraged && m_creature->GetHealthPercent() < 10.0f)
+ {
+ if (Creature* pSathrovarr = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_SATHROVARR)))
+ {
+ if (pSathrovarr->isAlive())
+ pSathrovarr->CastSpell(pSathrovarr, SPELL_CRAZED_RAGE, true);
+ }
+
+ m_creature->CastSpell(m_creature, SPELL_CRAZED_RAGE, true);
+ m_bEnraged = true;
+ }
+
+ if (!m_bChecked && m_creature->GetHealthPercent() < 1.0f)
+ {
+ m_bChecked = true;
+
+ if (!m_bUncorrupted)
+ {
+ m_bBanished = true;
+ DoCastSpellIfCan(m_creature, SPELL_BANISH, true);
+ m_creature->GetMotionMaster()->MoveIdle();
+ }
+ else
+ BeginOutro();
+ }
+
+ if (m_uiExitTimer)
+ {
+ if (m_uiExitTimer <= diff)
+ {
+ debug_log("SD2: KALEC: Exiting the arena");
+
+ float x, y, z;
+ m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 30, x, y, z);
+
+ z = 70.0f;
+
+ m_creature->GetMotionMaster()->MovePoint(1, x, y, z);
+ m_uiExitTimer = 0;
+ }else m_uiExitTimer -= diff;
+ }
+
+ if (m_uiArcaneBuffetTimer < diff)
+ {
+ if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_ARCANE_BUFFET) == CAST_OK)
+ {
+ if (!urand(0, 2))
+ DoScriptText(SAY_EVIL_SPELL1, m_creature);
+
+ m_uiArcaneBuffetTimer = 20000;
+ }
+ }
+ else
+ m_uiArcaneBuffetTimer -= diff;
+
+ if (m_uiFrostBreathTimer < diff)
+ {
+ if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FROST_BREATH) == CAST_OK)
+ {
+ if (!urand(0, 1))
+ DoScriptText(SAY_EVIL_SPELL2, m_creature);
+
+ m_uiFrostBreathTimer = 25000;
+ }
+ }
+ else
+ m_uiFrostBreathTimer -= diff;
+
+ if (m_uiWildMagicTimer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(target, WildMagic[rand()%6]);
+
+ m_uiWildMagicTimer = 19000;
+ }
+ else
+ m_uiWildMagicTimer -= diff;
+
+ if (m_uiSpectralBlastTimer < diff)
+ {
+ m_bHasSpectralTarget = false;
+ m_creature->CastSpell(m_creature, SPELL_SPECTRAL_BLAST_DUMMY, false);
+ m_uiSpectralBlastTimer = 30000;
+ }
+ else
+ m_uiSpectralBlastTimer -= diff;
+
+ if (!m_bBanished)
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_sathrovarrAI : public ScriptedAI
+{
+ boss_sathrovarrAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 CorruptingStrikeTimer;
+ uint32 CurseOfBoundlessAgonyTimer;
+ uint32 ShadowBoltVolleyTimer;
+ bool m_bBanished;
+ bool m_bEnraged;
+
+ void Reset()
+ {
+ // FIXME: Timers
+ CorruptingStrikeTimer = 5000;
+ CurseOfBoundlessAgonyTimer = 15000;
+ ShadowBoltVolleyTimer = 10000;
+
+ m_bBanished = false;
+ m_bEnraged = false;
+
+ m_creature->CastSpell(m_creature, SPELL_SPECTRAL_INVIS, true);
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_SATH_AGGRO, m_creature);
+
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pKalec = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_KALECGOS_HUMAN)))
+ {
+ m_creature->AddThreat(pKalec, 10000000.0f);
+ pKalec->AddThreat(m_creature, 10000000.0f);
+ }
+ }
+
+ void DamageTaken(Unit* done_by, uint32 &damage)
+ {
+ if (damage > m_creature->GetHealth())
+ {
+ damage = 0;
+ DoCastSpellIfCan(m_creature, SPELL_BANISH, CAST_TRIGGERED);
+ m_bBanished = true;
+
+ DoScriptText(SAY_SATH_DEATH, m_creature);
+
+ if (!m_pInstance)
+ return;
+
+ m_pInstance->SetData(DATA_SET_SPECTRAL_CHECK, 5000);
+
+ if (Creature* pKalecgos = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_KALECGOS_DRAGON)))
+ {
+ if (boss_kalecgosAI* pKalecgosAI = dynamic_cast(pKalecgos->AI()))
+ {
+ pKalecgosAI->m_bChecked = false;
+ pKalecgosAI->m_bUncorrupted = true;
+ }
+ }
+ }
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SATH_SLAY1 : SAY_SATH_SLAY2, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->getVictim() || !m_creature->SelectHostileTarget() || m_bBanished)
+ return;
+
+ if (!m_bEnraged && m_creature->GetHealthPercent() < 10.0f)
+ {
+ if (Creature* pKalecgos = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_KALECGOS_DRAGON)))
+ {
+ if (pKalecgos->isAlive())
+ pKalecgos->CastSpell(pKalecgos, SPELL_CRAZED_RAGE, true);
+ }
+
+ m_creature->CastSpell(m_creature, SPELL_CRAZED_RAGE, true);
+ m_bEnraged = true;
+ }
+
+ if (CorruptingStrikeTimer < diff)
+ {
+ if (!urand(0, 1))
+ DoScriptText(SAY_SATH_SPELL2, m_creature);
+
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CORRUPTING_STRIKE);
+ CorruptingStrikeTimer = 13000;
+ }else CorruptingStrikeTimer -= diff;
+
+ if (CurseOfBoundlessAgonyTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_CURSE_OF_BOUNDLESS_AGONY);
+
+ CurseOfBoundlessAgonyTimer = 35000;
+ }else CurseOfBoundlessAgonyTimer -= diff;
+
+ if (ShadowBoltVolleyTimer < diff)
+ {
+ if (!urand(0, 1))
+ DoScriptText(SAY_SATH_SPELL1, m_creature);
+
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOW_BOLT_VOLLEY);
+ ShadowBoltVolleyTimer = 15000;
+ }else ShadowBoltVolleyTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_kalecgos_humanoidAI : public ScriptedAI
+{
+ boss_kalecgos_humanoidAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 RevitalizeTimer;
+ uint32 HeroicStrikeTimer;
+
+ bool HasYelled10Percent;
+ bool HasYelled20Percent;
+
+ void Reset()
+ {
+ //TODO: Times!
+ RevitalizeTimer = 30000;
+ HeroicStrikeTimer = 8000;
+
+ HasYelled10Percent = false;
+ HasYelled20Percent = false;
+
+ m_creature->CastSpell(m_creature, SPELL_SPECTRAL_INVIS, true);
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_GOOD_AGGRO, m_creature);
+ }
+
+ void JustDied(Unit* killer)
+ {
+ // Whatever happens when Kalec (Half-elf) dies
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->getVictim() || !m_creature->SelectHostileTarget())
+ return;
+
+ if (RevitalizeTimer < diff)
+ {
+ if (m_pInstance)
+ {
+ /*Player* pPlayer = m_creature->GetMap()->GetPlayer(m_pInstance->GetData64(DATA_RANDOM_SPECTRAL_PLAYER));
+ if (pPlayer)
+ DoCastSpellIfCan(pPlayer, SPELL_REVITALIZE);*/
+ RevitalizeTimer = 30000;
+ }
+ }else RevitalizeTimer -= diff;
+
+ if (HeroicStrikeTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HEROIC_STRIKE);
+ HeroicStrikeTimer = 30000;
+ }else HeroicStrikeTimer -= diff;
+
+ if (m_creature->GetHealthPercent() < 20.0f && !HasYelled20Percent)
+ {
+ DoScriptText(SAY_GOOD_NEAR_DEATH, m_creature);
+ HasYelled20Percent = true;
+ }
+
+ if (m_creature->GetHealthPercent() < 10.0f && !HasYelled10Percent)
+ {
+ DoScriptText(SAY_GOOD_NEAR_DEATH2, m_creature);
+ HasYelled10Percent = true;
+ }
+ }
+};
+
+bool GOHello_go_spectral_rift(Player* pPlayer, GameObject* pGo)
+{
+ if (pGo->GetGoType() != GAMEOBJECT_TYPE_GOOBER)
+ return true;
+
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pPlayer->GetInstanceData())
+ {
+ if (pPlayer->HasAura(SPELL_SPECTRAL_EXHAUSTION, EFFECT_INDEX_0))
+ return true;
+
+ // Make them able to see Sathrovarr (he's invisible for some reason). Also, when this buff wears off, they get teleported back to Normal Realm (this is handled by Instance Script)
+ pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_TO_SPECTRAL_REALM, true);
+ pPlayer->CastSpell(pPlayer, SPELL_SPECTRAL_REALM_FORCE_FACTION, true);
+ pPlayer->CastSpell(pPlayer, SPELL_SPECTRAL_REALM, true);
+
+ // Add player to pSath's threat list
+ /*if (Creature* pSath = pInstance->instance->GetCreature(pInstance->GetData64(DATA_KALECGOS_DRAGON)))
+ {
+ if (pSath->isAlive())
+ {
+ debug_log("SD2: Adding %s in pSath' threatlist", pPlayer->GetName());
+ pSath->AddThreat(pPlayer);
+ }
+ }
+
+ // Remove player from Sathrovarr's threat list
+ if (Creature* pKalecgos = pInstance->instance->GetCreature(pInstance->GetData64(DATA_SATHROVARR)))
+ {
+ if (pKalecgos->isAlive())
+ {
+ if (HostileReference* pRef = pKalecgos->getThreatManager().getOnlineContainer().getReferenceByTarget(pPlayer))
+ {
+ pRef->removeReference();
+ debug_log("SD2: Deleting %s from pKalecgos's threatlist", pPlayer->GetName());
+ }
+ }
+ }*/
+
+ pInstance->SetData64(DATA_PLAYER_SPECTRAL_REALM, pPlayer->GetGUID());
+ }
+
+ return true;
+}
+
+CreatureAI* GetAI_boss_kalecgos(Creature* pCreature)
+{
+ return new boss_kalecgosAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_sathrovarr(Creature* pCreature)
+{
+ return new boss_sathrovarrAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_kalecgos_humanoid(Creature* pCreature)
+{
+ return new boss_kalecgos_humanoidAI(pCreature);
+}
+
+void AddSC_boss_kalecgos()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_kalecgos;
+ newscript->Name = "boss_kalecgos";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_sathrovarr;
+ newscript->Name = "boss_sathrovarr";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->GetAI = &GetAI_boss_kalecgos_humanoid;
+ newscript->Name = "boss_kalecgos_humanoid";
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->pGOHello = &GOHello_go_spectral_rift;
+ newscript->Name = "go_spectral_rift";
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp b/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp
new file mode 100644
index 0000000..8f5ddbc
--- /dev/null
+++ b/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp
@@ -0,0 +1,377 @@
+/* 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 */
+
+/* ScriptData
+SDName: Instance_Sunwell_Plateau
+SD%Complete: 70%
+SDComment:
+SDCategory: Sunwell_Plateau
+EndScriptData */
+
+#include "precompiled.h"
+#include "sunwell_plateau.h"
+
+/* Sunwell Plateau:
+0 - Kalecgos and Sathrovarr
+1 - Brutallus
+2 - Felmyst
+3 - Eredar Twins (Alythess and Sacrolash)
+4 - M'uru
+5 - Kil'Jaeden
+*/
+
+struct MANGOS_DLL_DECL instance_sunwell_plateau : public ScriptedInstance
+{
+ instance_sunwell_plateau(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ // Creatures
+ uint64 m_uiKalecgos_DragonGUID;
+ uint64 m_uiKalecgos_HumanGUID;
+ uint64 m_uiSathrovarrGUID;
+ uint64 m_uiBrutallusGUID;
+ uint64 m_uiFelmystGUID;
+ uint64 m_uiAlythessGUID;
+ uint64 m_uiSacrolashGUID;
+ uint64 m_uiMuruGUID;
+ uint64 m_uiKilJaedenGUID;
+ uint64 m_uiKilJaedenControllerGUID;
+ uint64 m_uiAnveenaGUID;
+ uint64 m_uiKalecgosGUID;
+
+ // GameObjects
+ uint64 m_uiForceFieldGUID; // Kalecgos Encounter
+ uint64 m_uiBossCollision1GUID;
+ uint64 m_uiBossCollision2GUID;
+ uint64 m_uiIceBarrierGUID; // Brutallus Encounter
+ uint64 m_uiDoorFireBarrierGUID;
+ uint64 m_uiDoorTheFirstGateGUID; // Felmyst Encounter
+ uint64 m_uiDoorTheSecondGateGUID; // Alythess Encounter
+ uint64 m_uiDoorRaid_Gate_07GUID; // Sacrolash Encounter
+ uint64 m_uiDoorRaid_Gate_08GUID; // Muru Encounter
+ uint64 m_uiDoorTheThirdGateGUID; // Entropius Encounter
+
+ // Misc
+ uint32 m_uiSpectralRealmTimer;
+ std::list SpectralRealmList;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ // Creatures
+ m_uiKalecgos_DragonGUID = 0;
+ m_uiKalecgos_HumanGUID = 0;
+ m_uiSathrovarrGUID = 0;
+ m_uiBrutallusGUID = 0;
+ m_uiFelmystGUID = 0;
+ m_uiAlythessGUID = 0;
+ m_uiSacrolashGUID = 0;
+ m_uiMuruGUID = 0;
+ m_uiKilJaedenGUID = 0;
+ m_uiKilJaedenControllerGUID = 0;
+ m_uiAnveenaGUID = 0;
+ m_uiKalecgosGUID = 0;
+
+ // GameObjects
+ m_uiForceFieldGUID = 0;
+ m_uiBossCollision1GUID = 0;
+ m_uiBossCollision2GUID = 0;
+ m_uiIceBarrierGUID = 0;
+ m_uiDoorFireBarrierGUID = 0;
+ m_uiDoorTheFirstGateGUID = 0;
+ m_uiDoorTheSecondGateGUID = 0;
+ m_uiDoorRaid_Gate_07GUID = 0;
+ m_uiDoorRaid_Gate_08GUID = 0;
+ m_uiDoorTheThirdGateGUID = 0;
+
+ // Misc
+ m_uiSpectralRealmTimer = 5000;
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ return true;
+
+ return false;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case 24850: m_uiKalecgos_DragonGUID = pCreature->GetGUID(); break;
+ case 24891: m_uiKalecgos_HumanGUID = pCreature->GetGUID(); break;
+ case 24892: m_uiSathrovarrGUID = pCreature->GetGUID(); break;
+ case 24882: m_uiBrutallusGUID = pCreature->GetGUID(); break;
+ case 25038: m_uiFelmystGUID = pCreature->GetGUID(); break;
+ case 25166: m_uiAlythessGUID = pCreature->GetGUID(); break;
+ case 25165: m_uiSacrolashGUID = pCreature->GetGUID(); break;
+ case 25741: m_uiMuruGUID = pCreature->GetGUID(); break;
+ case 25315: m_uiKilJaedenGUID = pCreature->GetGUID(); break;
+ case 25608: m_uiKilJaedenControllerGUID = pCreature->GetGUID(); break;
+ case 26046: m_uiAnveenaGUID = pCreature->GetGUID(); break;
+ case 25319: m_uiKalecgosGUID = pCreature->GetGUID(); break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case 188421:
+ m_uiForceFieldGUID = pGo->GetGUID();
+ break;
+ case 188523:
+ m_uiBossCollision1GUID = pGo->GetGUID();
+ break;
+ case 188524:
+ m_uiBossCollision2GUID = pGo->GetGUID();
+ break;
+ case 188119:
+ m_uiIceBarrierGUID = pGo->GetGUID();
+ break;
+ case 188075:
+ m_uiDoorFireBarrierGUID = pGo->GetGUID();
+ if (m_auiEncounter[0] == DONE && m_auiEncounter[1] == DONE && m_auiEncounter[2] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case 187766:
+ m_uiDoorTheFirstGateGUID = pGo->GetGUID();
+ break;
+ case 187764:
+ m_uiDoorTheSecondGateGUID = pGo->GetGUID();
+ if (m_auiEncounter[3] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case 187990:
+ m_uiDoorRaid_Gate_07GUID = pGo->GetGUID();
+ if (m_auiEncounter[3] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case 188118:
+ m_uiDoorRaid_Gate_08GUID = pGo->GetGUID();
+ if (m_auiEncounter[4] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case 187765:
+ m_uiDoorTheThirdGateGUID = pGo->GetGUID();
+ if (m_auiEncounter[4] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_KALECGOS: return m_auiEncounter[0];
+ case TYPE_BRUTALLUS: return m_auiEncounter[1];
+ case TYPE_FELMYST: return m_auiEncounter[2];
+ case TYPE_EREDAR_TWINS: return m_auiEncounter[3];
+ case TYPE_MURU: return m_auiEncounter[4];
+ case TYPE_KILJAEDEN: return m_auiEncounter[5];
+ }
+
+ return 0;
+ }
+
+ uint64 GetData64(uint32 id)
+ {
+ switch(id)
+ {
+ case DATA_KALECGOS_DRAGON: return m_uiKalecgos_DragonGUID;
+ case DATA_KALECGOS_HUMAN: return m_uiKalecgos_HumanGUID;
+ case DATA_SATHROVARR: return m_uiSathrovarrGUID;
+ case DATA_BRUTALLUS: return m_uiBrutallusGUID;
+ case DATA_FELMYST: return m_uiFelmystGUID;
+ case DATA_ALYTHESS: return m_uiAlythessGUID;
+ case DATA_SACROLASH: return m_uiSacrolashGUID;
+ case DATA_MURU: return m_uiMuruGUID;
+ case DATA_KILJAEDEN: return m_uiKilJaedenGUID;
+ case DATA_KILJAEDEN_CONTROLLER: return m_uiKilJaedenControllerGUID;
+ case DATA_ANVEENA: return m_uiAnveenaGUID;
+ case DATA_KALECGOS: return m_uiKalecgosGUID;
+ case DATA_GO_FORCEFIELD: return m_uiForceFieldGUID;
+ }
+ return 0;
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_KALECGOS:
+ if (uiData == IN_PROGRESS)
+ SpectralRealmList.clear();
+
+ DoUseDoorOrButton(m_uiForceFieldGUID);
+ DoUseDoorOrButton(m_uiBossCollision1GUID);
+ DoUseDoorOrButton(m_uiBossCollision2GUID);
+
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_BRUTALLUS:
+ if (uiData == SPECIAL)
+ DoUseDoorOrButton(m_uiIceBarrierGUID,MINUTE);
+
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_FELMYST:
+ m_auiEncounter[2] = uiData;
+ if (uiData == DONE)
+ DoUseDoorOrButton(m_uiDoorFireBarrierGUID);
+ break;
+ case TYPE_EREDAR_TWINS:
+ m_auiEncounter[3] = uiData;
+ if (uiData == DONE)
+ {
+ DoUseDoorOrButton(m_uiDoorTheSecondGateGUID);
+ DoUseDoorOrButton(m_uiDoorRaid_Gate_07GUID);
+ }
+ break;
+ case TYPE_MURU:
+ m_auiEncounter[4] = uiData;
+ if (uiData == DONE)
+ DoUseDoorOrButton(m_uiDoorRaid_Gate_08GUID);
+ break;
+ case TYPE_KILJAEDEN: m_auiEncounter[5] = uiData; break;
+ case DATA_SET_SPECTRAL_CHECK: m_uiSpectralRealmTimer = 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] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ const char* Save()
+ {
+ return strInstData.c_str();
+ }
+
+ void SetData64(uint32 uiData, uint64 uiGuid)
+ {
+ if (uiData == DATA_PLAYER_SPECTRAL_REALM)
+ SpectralRealmList.push_back(uiGuid);
+ }
+
+ void EjectPlayer(Player* pPlayer)
+ {
+ debug_log("SD2: Ejecting Player %s from Spectral Realm", pPlayer->GetName());
+
+ // Put player back in Kalecgos(Dragon)'s threat list
+ /*if (Creature* pKalecgos = instance->GetCreature(m_uiKalecgos_DragonGUID))
+ {
+ if (pKalecgos->isAlive())
+ {
+ debug_log("SD2: Adding %s in Kalecgos' threatlist", pPlayer->GetName());
+ pKalecgos->AddThreat(pPlayer);
+ }
+ }
+
+ // Remove player from Sathrovarr's threat list
+ if (Creature* pSath = instance->GetCreature(m_uiSathrovarrGUID))
+ {
+ if (pSath->isAlive())
+ {
+ if (HostileReference* pRef = pSath->getThreatManager().getOnlineContainer().getReferenceByTarget(pPlayer))
+ {
+ pRef->removeReference();
+ debug_log("SD2: Deleting %s from Sathrovarr's threatlist", pPlayer->GetName());
+ }
+ }
+ }*/
+
+ pPlayer->CastSpell(pPlayer, SPELL_TELEPORT_NORMAL_REALM, true);
+ pPlayer->CastSpell(pPlayer, SPELL_SPECTRAL_EXHAUSTION, true);
+ }
+
+ void EjectPlayers()
+ {
+ if (SpectralRealmList.empty())
+ return;
+
+ Map::PlayerList const& players = instance->GetPlayers();
+
+ for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ Player* plr = itr->getSource();
+
+ if (plr && !plr->HasAura(SPELL_SPECTRAL_REALM))
+ {
+ SpectralRealmList.remove(plr->GetGUID());
+ EjectPlayer(plr);
+ }
+ }
+
+ //SpectralRealmList.clear();
+ }
+
+ void Update(uint32 uiDiff)
+ {
+ // Only check for Spectral Realm if Kalecgos Encounter is running
+ if (m_auiEncounter[0] == IN_PROGRESS)
+ {
+ if (m_uiSpectralRealmTimer <= uiDiff)
+ {
+ EjectPlayers();
+ m_uiSpectralRealmTimer = 1000;
+ }
+ else
+ m_uiSpectralRealmTimer -= uiDiff;
+ }
+ }
+
+ void Load(const char* in)
+ {
+ if (!in)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(in);
+
+ std::istringstream loadStream(in);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >>
+ m_auiEncounter[3] >> m_auiEncounter[4] >> m_auiEncounter[5];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstanceData_instance_sunwell_plateau(Map* pMap)
+{
+ return new instance_sunwell_plateau(pMap);
+}
+
+void AddSC_instance_sunwell_plateau()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_sunwell_plateau";
+ newscript->GetInstanceData = &GetInstanceData_instance_sunwell_plateau;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h b/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h
new file mode 100644
index 0000000..e27c078
--- /dev/null
+++ b/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h
@@ -0,0 +1,49 @@
+/* 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 */
+
+#ifndef DEF_SUNWELLPLATEAU_H
+#define DEF_SUNWELLPLATEAU_H
+
+enum InstanceSWP
+{
+ MAX_ENCOUNTER = 6,
+
+ TYPE_KALECGOS = 0,
+ TYPE_BRUTALLUS = 1,
+ TYPE_FELMYST = 2,
+ TYPE_EREDAR_TWINS = 3,
+ TYPE_MURU = 4,
+ TYPE_KILJAEDEN = 5,
+
+ DATA_KALECGOS_DRAGON = 6,
+ DATA_KALECGOS_HUMAN = 7,
+ DATA_SATHROVARR = 8,
+ DATA_BRUTALLUS = 9,
+ DATA_FELMYST = 10,
+ DATA_ALYTHESS = 11,
+ DATA_SACROLASH = 12,
+ DATA_MURU = 13,
+ DATA_KILJAEDEN = 14,
+ DATA_KILJAEDEN_CONTROLLER = 15,
+ DATA_ANVEENA = 16,
+ DATA_KALECGOS = 17,
+
+ DATA_GO_FORCEFIELD = 18,
+ DATA_GO_FIRE_BARRIER = 19,
+ DATA_GO_FIRST_GATE = 20,
+ DATA_GO_SECOND_GATE = 21,
+ DATA_GO_RAID_GATE_07 = 22,
+ DATA_GO_RAID_GATE_08 = 23,
+ DATA_GO_THIRD_GATE = 24,
+
+ DATA_PLAYER_SPECTRAL_REALM = 25,
+ DATA_SET_SPECTRAL_CHECK = 26,
+
+ SPELL_SPECTRAL_REALM = 46021,
+ SPELL_TELEPORT_NORMAL_REALM = 46020,
+ SPELL_TELEPORT_TO_SPECTRAL_REALM = 46019,
+ SPELL_SPECTRAL_EXHAUSTION = 44867,
+ SPELL_SPECTRAL_REALM_FORCE_FACTION = 44852
+};
+#endif
diff --git a/scripts/eastern_kingdoms/swamp_of_sorrows.cpp b/scripts/eastern_kingdoms/swamp_of_sorrows.cpp
new file mode 100644
index 0000000..ee8e1f9
--- /dev/null
+++ b/scripts/eastern_kingdoms/swamp_of_sorrows.cpp
@@ -0,0 +1,165 @@
+/* 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: Swamp_of_Sorrows
+SD%Complete: 100
+SDComment: Quest support: 1393
+SDCategory: Swap of Sorrows
+EndScriptData */
+
+/* ContentData
+npc_galen_goodward
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_galen_goodward
+######*/
+
+enum Galen
+{
+ QUEST_GALENS_ESCAPE = 1393,
+
+ GO_GALENS_CAGE = 37118,
+
+ SAY_PERIODIC = -1000582,
+ SAY_QUEST_ACCEPTED = -1000583,
+ SAY_ATTACKED_1 = -1000584,
+ SAY_ATTACKED_2 = -1000585,
+ SAY_QUEST_COMPLETE = -1000586,
+ EMOTE_WHISPER = -1000587,
+ EMOTE_DISAPPEAR = -1000588
+};
+
+struct MANGOS_DLL_DECL npc_galen_goodwardAI : public npc_escortAI
+{
+ npc_galen_goodwardAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_uiGalensCageGUID = 0;
+ Reset();
+ }
+
+ uint64 m_uiGalensCageGUID;
+ uint32 m_uiPeriodicSay;
+
+ void Reset()
+ {
+ m_uiPeriodicSay = 6000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ DoScriptText(urand(0, 1) ? SAY_ATTACKED_1 : SAY_ATTACKED_2, m_creature, pWho);
+ }
+
+ void WaypointStart(uint32 uiPointId)
+ {
+ switch (uiPointId)
+ {
+ case 0:
+ {
+ GameObject* pCage = NULL;
+ if (m_uiGalensCageGUID)
+ pCage = m_creature->GetMap()->GetGameObject(m_uiGalensCageGUID);
+ else
+ pCage = GetClosestGameObjectWithEntry(m_creature, GO_GALENS_CAGE, INTERACTION_DISTANCE);
+ if (pCage)
+ {
+ pCage->UseDoorOrButton();
+ m_uiGalensCageGUID = pCage->GetGUID();
+ }
+ break;
+ }
+ case 21:
+ DoScriptText(EMOTE_DISAPPEAR, m_creature);
+ break;
+ }
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch (uiPointId)
+ {
+ case 0:
+ if (GameObject* pCage = m_creature->GetMap()->GetGameObject(m_uiGalensCageGUID))
+ pCage->ResetDoorOrButton();
+ break;
+ case 20:
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ m_creature->SetFacingToObject(pPlayer);
+ DoScriptText(SAY_QUEST_COMPLETE, m_creature, pPlayer);
+ DoScriptText(EMOTE_WHISPER, m_creature, pPlayer);
+ pPlayer->GroupEventHappens(QUEST_GALENS_ESCAPE, m_creature);
+ }
+ SetRun(true);
+ break;
+ }
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+
+ if (m_uiPeriodicSay < uiDiff)
+ {
+ if (HasEscortState(STATE_ESCORT_NONE))
+ DoScriptText(SAY_PERIODIC, m_creature);
+ m_uiPeriodicSay = 6000;
+ }
+ else
+ m_uiPeriodicSay -= uiDiff;
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool QuestAccept_npc_galen_goodward(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_GALENS_ESCAPE)
+ {
+
+ if (npc_galen_goodwardAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ {
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ pCreature->setFaction(FACTION_ESCORT_N_NEUTRAL_ACTIVE);
+ DoScriptText(SAY_QUEST_ACCEPTED, pCreature);
+ }
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_galen_goodward(Creature* pCreature)
+{
+ return new npc_galen_goodwardAI(pCreature);
+}
+
+void AddSC_swamp_of_sorrows()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_galen_goodward";
+ newscript->GetAI = &GetAI_npc_galen_goodward;
+ newscript->pQuestAccept = &QuestAccept_npc_galen_goodward;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/tirisfal_glades.cpp b/scripts/eastern_kingdoms/tirisfal_glades.cpp
new file mode 100644
index 0000000..2ccad8e
--- /dev/null
+++ b/scripts/eastern_kingdoms/tirisfal_glades.cpp
@@ -0,0 +1,208 @@
+/* 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: Tirisfal_Glades
+SD%Complete: 100
+SDComment: Quest support: 590, 1819
+SDCategory: Tirisfal Glades
+EndScriptData */
+
+/* ContentData
+go_mausoleum_door
+go_mausoleum_trigger
+npc_calvin_montague
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## go_mausoleum_door
+## go_mausoleum_trigger
+######*/
+
+enum
+{
+ QUEST_ULAG = 1819,
+ NPC_ULAG = 6390,
+ GO_TRIGGER = 104593,
+ GO_DOOR = 176594
+};
+
+bool GOHello_go_mausoleum_door(Player* pPlayer, GameObject* pGo)
+{
+ if (pPlayer->GetQuestStatus(QUEST_ULAG) != QUEST_STATUS_INCOMPLETE)
+ return false;
+
+ if (GameObject* pTrigger = GetClosestGameObjectWithEntry(pPlayer, GO_TRIGGER, 30.0f))
+ {
+ pTrigger->SetGoState(GO_STATE_READY);
+ pPlayer->SummonCreature(NPC_ULAG, 2390.26f, 336.47f, 40.01f, 2.26f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000);
+ return false;
+ }
+
+ return false;
+}
+
+bool GOHello_go_mausoleum_trigger(Player* pPlayer, GameObject* pGo)
+{
+ if (pPlayer->GetQuestStatus(QUEST_ULAG) != QUEST_STATUS_INCOMPLETE)
+ return false;
+
+ if (GameObject* pDoor = GetClosestGameObjectWithEntry(pPlayer, GO_DOOR, 30.0f))
+ {
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ pDoor->RemoveFlag(GAMEOBJECT_FLAGS,GO_FLAG_INTERACT_COND);
+ return true;
+ }
+
+ return false;
+}
+
+/*######
+## npc_calvin_montague
+######*/
+
+enum
+{
+ SAY_COMPLETE = -1000356,
+ SPELL_DRINK = 2639, // possibly not correct spell (but iconId is correct)
+ QUEST_590 = 590,
+ FACTION_HOSTILE = 168
+};
+
+struct MANGOS_DLL_DECL npc_calvin_montagueAI : public ScriptedAI
+{
+ npc_calvin_montagueAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiNormFaction = pCreature->getFaction();
+ Reset();
+ }
+
+ uint32 m_uiNormFaction;
+ uint32 m_uiPhase;
+ uint32 m_uiPhaseTimer;
+ uint64 m_uiPlayerGUID;
+
+ void Reset()
+ {
+ m_uiPhase = 0;
+ m_uiPhaseTimer = 5000;
+ m_uiPlayerGUID = 0;
+
+ if (m_creature->getFaction() != m_uiNormFaction)
+ m_creature->setFaction(m_uiNormFaction);
+ }
+
+ void AttackedBy(Unit* pAttacker)
+ {
+ if (m_creature->getVictim() || m_creature->IsFriendlyTo(pAttacker))
+ return;
+
+ AttackStart(pAttacker);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (uiDamage > m_creature->GetHealth() || ((m_creature->GetHealth() - uiDamage)*100 / m_creature->GetMaxHealth() < 15))
+ {
+ uiDamage = 0;
+
+ m_creature->setFaction(m_uiNormFaction);
+ m_creature->CombatStop(true);
+
+ m_uiPhase = 1;
+
+ if (pDoneBy->GetTypeId() == TYPEID_PLAYER)
+ m_uiPlayerGUID = pDoneBy->GetGUID();
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_uiPhase)
+ {
+ if (m_uiPhaseTimer < uiDiff)
+ m_uiPhaseTimer = 7500;
+ else
+ {
+ m_uiPhaseTimer -= uiDiff;
+ return;
+ }
+
+ switch(m_uiPhase)
+ {
+ case 1:
+ DoScriptText(SAY_COMPLETE, m_creature);
+ ++m_uiPhase;
+ break;
+ case 2:
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID))
+ pPlayer->AreaExploredOrEventHappens(QUEST_590);
+
+ m_creature->CastSpell(m_creature,SPELL_DRINK,true);
+ ++m_uiPhase;
+ break;
+ case 3:
+ EnterEvadeMode();
+ break;
+ }
+
+ return;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_calvin_montague(Creature* pCreature)
+{
+ return new npc_calvin_montagueAI(pCreature);
+}
+
+bool QuestAccept_npc_calvin_montague(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_590)
+ {
+ pCreature->setFaction(FACTION_HOSTILE);
+ pCreature->AI()->AttackStart(pPlayer);
+ }
+ return true;
+}
+
+void AddSC_tirisfal_glades()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "go_mausoleum_door";
+ newscript->pGOHello = &GOHello_go_mausoleum_door;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "go_mausoleum_trigger";
+ newscript->pGOHello = &GOHello_go_mausoleum_trigger;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_calvin_montague";
+ newscript->GetAI = &GetAI_npc_calvin_montague;
+ newscript->pQuestAccept = &QuestAccept_npc_calvin_montague;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp b/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp
new file mode 100644
index 0000000..913b6dc
--- /dev/null
+++ b/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp
@@ -0,0 +1,244 @@
+/* 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_Archaedas
+SD%Complete: 60
+SDComment: Need correct way to deal with awaken vault and guardian spells, waiting for additions in mangos for them (target combination 22/7)
+SDCategory: Uldaman
+EndScriptData */
+
+#include "precompiled.h"
+#include "uldaman.h"
+
+enum
+{
+ SPELL_GROUND_TREMOR = 6524,
+
+ SPELL_AWAKEN_EARTHEN_GUARDIAN = 10252,
+ SPELL_AWAKEN_VAULT_WARDER = 10258,
+ SPELL_AWAKEN_EARTHEN_DWARF = 10259,
+
+ SPELL_ARCHAEDAS_AWAKEN_VISUAL = 10347,
+
+ SAY_AGGRO = -1070001,
+ SAY_AWAKE_GUARDIANS = -1070002,
+ SAY_AWAKE_WARDERS = -1070003,
+ SAY_UNIT_SLAIN = -1070004
+};
+
+struct MANGOS_DLL_DECL boss_archaedasAI : public ScriptedAI
+{
+ boss_archaedasAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (instance_uldaman*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ instance_uldaman* m_pInstance;
+
+ uint32 m_uiAwakeningTimer;
+ uint32 m_uiAwakeDwarfTimer;
+ uint8 m_uiSubevent;
+ bool m_bDwarvesAwaken;
+ bool m_bGuardiansAwaken;
+ bool m_bWardersAwaken;
+
+ void Reset()
+ {
+ m_uiAwakeningTimer = 1000;
+ m_uiSubevent = 0;
+ m_uiAwakeDwarfTimer = 10000;
+ m_bGuardiansAwaken = false;
+ m_bWardersAwaken = false;
+ m_bDwarvesAwaken = false;
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARCHAEDAS, IN_PROGRESS);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(SAY_UNIT_SLAIN, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ // open door to vault (handled by instance script)
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARCHAEDAS, DONE);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARCHAEDAS, FAIL);
+ }
+
+ void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell)
+ {
+ if (pTarget->GetTypeId() != TYPEID_PLAYER)
+ {
+ if (pTarget->HasAura(SPELL_STONED, EFFECT_INDEX_0))
+ {
+ pTarget->RemoveAurasDueToSpell(SPELL_STONED);
+
+ if (Unit* pUnit = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ pTarget->SetInCombatWith(pUnit);
+ pTarget->AddThreat(pUnit);
+ }
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // so many things are based in this script on instance data
+ // so if we don't have access to it better do nothing
+ if (!m_pInstance)
+ return;
+
+ // OOC Intro part triggered by Altar activation
+ if (m_pInstance->GetData(TYPE_ARCHAEDAS) == SPECIAL)
+ {
+ if (m_uiAwakeningTimer <= uiDiff)
+ {
+ switch(m_uiSubevent)
+ {
+ case 0:
+ DoCastSpellIfCan(m_creature, SPELL_ARCHAEDAS_AWAKEN_VISUAL);
+ break;
+ case 1:
+ DoScriptText(SAY_AGGRO,m_creature,NULL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ break;
+ case 2:
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_pInstance->GetData64(DATA_EVENT_STARTER)))
+ AttackStart(pPlayer);
+ else
+ EnterEvadeMode();
+ break;
+ default:
+ break;
+ }
+
+ ++m_uiSubevent;
+ m_uiAwakeningTimer = 5000;
+ }
+ else
+ m_uiAwakeningTimer -= uiDiff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Awake random Dwarf
+ if (!m_bDwarvesAwaken && m_creature->GetHealthPercent() >= 33.0f)
+ {
+ if (m_uiAwakeDwarfTimer <= uiDiff)
+ {
+ if (Creature* pEarthen = m_pInstance->GetClosestDwarfNotInCombat(m_creature, PHASE_ARCHA_1))
+ {
+ if (DoCastSpellIfCan(pEarthen, SPELL_AWAKEN_EARTHEN_DWARF) == CAST_OK)
+ m_uiAwakeDwarfTimer = urand(9000, 12000);
+ }
+ else
+ m_bDwarvesAwaken = true;
+ }
+ else
+ m_uiAwakeDwarfTimer -= uiDiff;
+ }
+
+ //Awake Earthen Guardians
+ if (!m_bGuardiansAwaken && m_creature->GetHealthPercent() <= 66.0f)
+ {
+ if (Creature* pGuard = m_pInstance->GetClosestDwarfNotInCombat(m_creature, PHASE_ARCHA_2))
+ {
+ if (DoCastSpellIfCan(pGuard, SPELL_AWAKEN_EARTHEN_GUARDIAN) == CAST_OK)
+ {
+ DoScriptText(SAY_AWAKE_GUARDIANS, m_creature);
+ m_bGuardiansAwaken = true;
+ }
+ }
+ }
+
+ // Awake Warders
+ if (!m_bWardersAwaken && m_creature->GetHealthPercent() <= 33.0f)
+ {
+ if (Creature* pWarder = m_pInstance->GetClosestDwarfNotInCombat(m_creature, PHASE_ARCHA_3))
+ {
+ if (DoCastSpellIfCan(pWarder, SPELL_AWAKEN_VAULT_WARDER) == CAST_OK)
+ {
+ DoScriptText(SAY_AWAKE_WARDERS, m_creature);
+ m_bWardersAwaken = true;
+ }
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL npc_archaeras_addAI : public ScriptedAI
+{
+ npc_archaeras_addAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ Reset();
+ }
+
+ void Reset()
+ {
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_archaedas(Creature* pCreature)
+{
+ return new boss_archaedasAI(pCreature);
+}
+
+CreatureAI* GetAI_npc_archaeras_add(Creature* pCreature)
+{
+ return new npc_archaeras_addAI(pCreature);
+}
+
+void AddSC_boss_archaedas()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "boss_archaedas";
+ pNewScript->GetAI = &GetAI_boss_archaedas;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "mob_archaeras_add";
+ pNewScript->GetAI = &GetAI_npc_archaeras_add;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp b/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp
new file mode 100644
index 0000000..f0a8f72
--- /dev/null
+++ b/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp
@@ -0,0 +1,105 @@
+/* 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_Ironaya
+SD%Complete: 100
+SDComment:
+SDCategory: Uldaman
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_AGGRO -1070000
+
+#define SPELL_ARCINGSMASH 8374
+#define SPELL_KNOCKAWAY 10101
+#define SPELL_WSTOMP 11876
+
+struct MANGOS_DLL_DECL boss_ironayaAI : public ScriptedAI
+{
+ boss_ironayaAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Arcing_Timer;
+ bool hasCastedWstomp;
+ bool hasCastedKnockaway;
+
+ void Reset()
+ {
+ Arcing_Timer = 3000;
+ hasCastedKnockaway = false;
+ hasCastedWstomp = false;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //If we are <50% hp do knockaway ONCE
+ if (!hasCastedKnockaway && m_creature->GetHealthPercent() < 50.0f)
+ {
+ m_creature->CastSpell(m_creature->getVictim(),SPELL_KNOCKAWAY, true);
+
+ // current aggro target is knocked away pick new target
+ Unit* Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0);
+
+ if (!Target || Target == m_creature->getVictim())
+ Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 1);
+
+ if (Target)
+ m_creature->TauntApply(Target);
+
+ //Shouldn't cast this agian
+ hasCastedKnockaway = true;
+ }
+
+ //Arcing_Timer
+ if (Arcing_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_ARCINGSMASH);
+ Arcing_Timer = 13000;
+ }else Arcing_Timer -= diff;
+
+ if (!hasCastedWstomp && m_creature->GetHealthPercent() < 25.0f)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_WSTOMP);
+ hasCastedWstomp = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_ironaya(Creature* pCreature)
+{
+ return new boss_ironayaAI(pCreature);
+}
+
+void AddSC_boss_ironaya()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_ironaya";
+ newscript->GetAI = &GetAI_boss_ironaya;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp b/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp
new file mode 100644
index 0000000..ad12a39
--- /dev/null
+++ b/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp
@@ -0,0 +1,353 @@
+/* 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_Uldaman
+SD%Complete: 60
+SDComment:
+SDCategory: Uldaman
+EndScriptData
+*/
+
+#include "precompiled.h"
+#include "uldaman.h"
+
+instance_uldaman::instance_uldaman(Map* pMap) : ScriptedInstance(pMap),
+ m_uiTempleDoorUpperGUID(0),
+ m_uiTempleDoorLowerGUID(0),
+ m_uiAncientVaultGUID(0),
+ m_uiPlayerGUID(0),
+ m_uiStoneKeepersFallen(0),
+ m_uiKeeperCooldown(5000)
+{
+ Initialize();
+}
+
+void instance_uldaman::Initialize()
+{
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+ m_lWardens.clear();
+ m_mKeeperMap.clear();
+}
+
+void instance_uldaman::OnObjectCreate(GameObject* pGo)
+{
+ switch(pGo->GetEntry())
+ {
+ case GO_TEMPLE_DOOR_UPPER:
+ if (m_auiEncounter[0] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ m_uiTempleDoorUpperGUID = pGo->GetGUID();
+ break;
+ case GO_TEMPLE_DOOR_LOWER:
+ if (m_auiEncounter[0] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ m_uiTempleDoorLowerGUID = pGo->GetGUID();
+ break;
+ case GO_ANCIENT_VAULT:
+ if (m_auiEncounter[1] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ m_uiAncientVaultGUID = pGo->GetGUID();
+ break;
+ default:
+ break;
+ }
+}
+
+void instance_uldaman::OnCreatureCreate(Creature* pCreature)
+{
+ switch(pCreature->GetEntry())
+ {
+ case NPC_HALLSHAPER:
+ case NPC_CUSTODIAN:
+ case NPC_GUARDIAN:
+ case NPC_VAULT_WARDER:
+ m_lWardens.push_back(pCreature->GetGUID());
+ pCreature->CastSpell(pCreature, SPELL_STONED, true);
+ pCreature->SetNoCallAssistance(true); // no assistance
+ break;
+ case NPC_STONE_KEEPER:
+ m_mKeeperMap[pCreature->GetGUID()] = pCreature->isAlive();
+ pCreature->CastSpell(pCreature, SPELL_STONED, true);
+ pCreature->SetNoCallAssistance(true); // no assistance
+ break;
+ default:
+ break;
+ }
+}
+
+void instance_uldaman::SetData(uint32 uiType, uint32 uiData)
+{
+ switch(uiType)
+ {
+ case TYPE_ALTAR_EVENT:
+ if (uiData == DONE)
+ {
+ DoUseDoorOrButton(m_uiTempleDoorUpperGUID);
+ DoUseDoorOrButton(m_uiTempleDoorLowerGUID);
+
+ m_auiEncounter[0] = uiData;
+ }
+ break;
+
+ case TYPE_ARCHAEDAS:
+ if (uiData == FAIL)
+ {
+ for (std::list::iterator itr = m_lWardens.begin(); itr != m_lWardens.end(); ++itr)
+ {
+ if (Creature* pWarden = instance->GetCreature(*itr))
+ {
+ pWarden->SetDeathState(JUST_DIED);
+ pWarden->Respawn();
+ pWarden->SetNoCallAssistance(true);
+ }
+ }
+ }
+ else if (uiData == DONE)
+ {
+ for (std::list::iterator itr = m_lWardens.begin(); itr != m_lWardens.end(); ++itr)
+ {
+ Creature* pWarden = instance->GetCreature(*itr);
+ if (pWarden && pWarden->isAlive())
+ pWarden->ForcedDespawn();
+ }
+ DoUseDoorOrButton(m_uiAncientVaultGUID);
+ }
+ m_auiEncounter[1] = uiData;
+ break;
+ }
+
+ if (uiData == DONE)
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+
+ saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1];
+
+ strInstData = saveStream.str();
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+}
+
+void instance_uldaman::Load(const char* chrIn)
+{
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+}
+
+void instance_uldaman::SetData64(uint32 uiData, uint64 uiGuid)
+{
+ switch(uiData)
+ {
+ case DATA_EVENT_STARTER:
+ m_uiPlayerGUID = uiGuid;
+ break;
+ }
+}
+
+uint32 instance_uldaman::GetData(uint32 uiType)
+{
+ switch(uiType)
+ {
+ case TYPE_ARCHAEDAS:
+ return m_auiEncounter[1];
+ }
+ return 0;
+}
+
+uint64 instance_uldaman::GetData64(uint32 uiData)
+{
+ switch(uiData)
+ {
+ case DATA_EVENT_STARTER:
+ return m_uiPlayerGUID;
+ }
+ return 0;
+}
+
+void instance_uldaman::StartEvent(uint32 uiEventId, Player* pPlayer)
+{
+ m_uiPlayerGUID = pPlayer->GetGUID();
+
+ if (uiEventId == EVENT_ID_ALTAR_KEEPER)
+ {
+ if (m_auiEncounter[0] == NOT_STARTED)
+ m_auiEncounter[0] = IN_PROGRESS;
+ }
+ else if (m_auiEncounter[1] == NOT_STARTED || m_auiEncounter[1] == FAIL)
+ m_auiEncounter[1] = SPECIAL;
+}
+
+void instance_uldaman::DoResetKeeperEvent()
+{
+ m_auiEncounter[0] = NOT_STARTED;
+ m_uiStoneKeepersFallen = 0;
+
+ for (std::map::iterator itr = m_mKeeperMap.begin(); itr != m_mKeeperMap.end(); ++itr)
+ {
+ if (Creature* pKeeper = instance->GetCreature(itr->first))
+ {
+ pKeeper->SetDeathState(JUST_DIED);
+ pKeeper->Respawn();
+ pKeeper->CastSpell(pKeeper, SPELL_STONED, true);
+ pKeeper->SetNoCallAssistance(true);
+ itr->second = true;
+ }
+ }
+}
+
+Creature* instance_uldaman::GetClosestDwarfNotInCombat(Creature* pSearcher, uint32 uiPhase)
+{
+ std::list lTemp;
+
+ for (std::list::iterator itr = m_lWardens.begin(); itr != m_lWardens.end(); ++itr)
+ {
+ Creature* pTemp = instance->GetCreature(*itr);
+
+ if (pTemp && pTemp->isAlive() && !pTemp->getVictim())
+ {
+ switch(uiPhase)
+ {
+ case PHASE_ARCHA_1:
+ if (pTemp->GetEntry() != NPC_CUSTODIAN && pTemp->GetEntry() != NPC_HALLSHAPER)
+ continue;
+ break;
+ case PHASE_ARCHA_2:
+ if (pTemp->GetEntry() != NPC_GUARDIAN)
+ continue;
+ break;
+ case PHASE_ARCHA_3:
+ if (pTemp->GetEntry() != NPC_VAULT_WARDER)
+ continue;
+ break;
+ }
+
+ lTemp.push_back(pTemp);
+ }
+ }
+
+ if (lTemp.empty())
+ return NULL;
+
+ lTemp.sort(ObjectDistanceOrder(pSearcher));
+ return lTemp.front();
+}
+
+void instance_uldaman::Update(uint32 uiDiff)
+{
+ if (m_auiEncounter[0] == IN_PROGRESS)
+ {
+ if (m_uiKeeperCooldown >= uiDiff)
+ m_uiKeeperCooldown -= uiDiff;
+ else
+ {
+ m_uiKeeperCooldown = 5000;
+
+ if (!m_mKeeperMap.empty())
+ {
+ for(std::map::iterator itr = m_mKeeperMap.begin(); itr != m_mKeeperMap.end(); ++itr)
+ {
+ // died earlier
+ if (!itr->second)
+ continue;
+
+ if (Creature* pKeeper = instance->GetCreature(itr->first))
+ {
+ if (pKeeper->isAlive() && !pKeeper->getVictim())
+ {
+ if (Player* pPlayer = pKeeper->GetMap()->GetPlayer(m_uiPlayerGUID))
+ {
+ // we should use group instead, event starter can be dead while group is still fighting
+ if (pPlayer->isAlive() && !pPlayer->isInCombat())
+ {
+ pKeeper->RemoveAurasDueToSpell(SPELL_STONED);
+ pKeeper->SetInCombatWith(pPlayer);
+ pKeeper->AddThreat(pPlayer);
+ }
+ else
+ {
+ if (!pPlayer->isAlive())
+ DoResetKeeperEvent();
+ }
+ }
+
+ break;
+ }
+ else if (!pKeeper->isAlive())
+ {
+ itr->second = pKeeper->isAlive();
+ ++m_uiStoneKeepersFallen;
+ }
+ }
+ }
+
+ if (m_uiStoneKeepersFallen == m_mKeeperMap.size())
+ SetData(TYPE_ALTAR_EVENT, DONE);
+ }
+ }
+ }
+}
+
+InstanceData* GetInstanceData_instance_uldaman(Map* pMap)
+{
+ return new instance_uldaman(pMap);
+}
+
+bool ProcessEventId_event_spell_altar_boss_aggro(uint32 uiEventId, Object* pSource, Object* pTarget, bool bIsStart)
+{
+ if (bIsStart && pSource->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (instance_uldaman* pInstance = (instance_uldaman*)((Player*)pSource)->GetInstanceData())
+ {
+ pInstance->StartEvent(uiEventId, (Player*)pSource);
+ return true;
+ }
+ }
+ return false;
+}
+
+void AddSC_instance_uldaman()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "instance_uldaman";
+ pNewScript->GetInstanceData = &GetInstanceData_instance_uldaman;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "event_spell_altar_boss_aggro";
+ pNewScript->pProcessEventId = &ProcessEventId_event_spell_altar_boss_aggro;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/uldaman/uldaman.cpp b/scripts/eastern_kingdoms/uldaman/uldaman.cpp
new file mode 100644
index 0000000..1120b95
--- /dev/null
+++ b/scripts/eastern_kingdoms/uldaman/uldaman.cpp
@@ -0,0 +1,184 @@
+/* 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: Uldaman
+SD%Complete: 100
+SDComment: Quest support: 2278 + 1 trash mob.
+SDCategory: Uldaman
+EndScriptData */
+
+/* ContentData
+mob_jadespine_basilisk
+npc_lore_keeper_of_norgannon
+EndContentData */
+
+#include "precompiled.h"
+#include "uldaman.h"
+
+/*######
+## mob_jadespine_basilisk
+######*/
+
+#define SPELL_CSLUMBER 3636
+
+struct MANGOS_DLL_DECL mob_jadespine_basiliskAI : public ScriptedAI
+{
+ mob_jadespine_basiliskAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Cslumber_Timer;
+
+ void Reset()
+ {
+ Cslumber_Timer = 2000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Cslumber_Timer
+ if (Cslumber_Timer < diff)
+ {
+ //Cast
+ // DoCastSpellIfCan(m_creature->getVictim(),SPELL_CSLUMBER);
+ m_creature->CastSpell(m_creature->getVictim(),SPELL_CSLUMBER, true);
+
+ //Stop attacking target thast asleep and pick new target
+ Cslumber_Timer = 28000;
+
+ Unit* Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO, 0);
+
+ if (!Target || Target == m_creature->getVictim())
+ Target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+
+ if (Target)
+ m_creature->TauntApply(Target);
+
+ }else Cslumber_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_jadespine_basilisk(Creature* pCreature)
+{
+ return new mob_jadespine_basiliskAI(pCreature);
+}
+
+/*######
+## npc_lore_keeper_of_norgannon
+######*/
+
+bool GossipHello_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(2278) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Who are the Earthen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(1079, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_lore_keeper_of_norgannon(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What is a \"subterranean being matrix\"?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(1080, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What are the anomalies you speak of?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->SEND_GOSSIP_MENU(1081, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What is a resilient foundation of construction?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
+ pPlayer->SEND_GOSSIP_MENU(1082, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "So... the Earthen were made out of stone?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(1083, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Anything else I should know about the Earthen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
+ pPlayer->SEND_GOSSIP_MENU(1084, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+6:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I think I understand the Creators' design intent for the Earthen now. What are the Earthen's anomalies that you spoke of earlier?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7);
+ pPlayer->SEND_GOSSIP_MENU(1085, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+7:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What high-stress environments would cause the Earthen to destabilize?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+8);
+ pPlayer->SEND_GOSSIP_MENU(1086, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+8:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What happens when the Earthen destabilize?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9);
+ pPlayer->SEND_GOSSIP_MENU(1087, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+9:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Troggs?! Are the troggs you mention the same as the ones in the world today?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+10);
+ pPlayer->SEND_GOSSIP_MENU(1088, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+10:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "You mentioned two results when the Earthen destabilize. What is the second?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+11);
+ pPlayer->SEND_GOSSIP_MENU(1089, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+11:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Dwarves!!! Now you're telling me that dwarves originally came from the Earthen?!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+12);
+ pPlayer->SEND_GOSSIP_MENU(1090, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+12:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "These dwarves are the same ones today, yes? Do the dwarves maintain any other links to the Earthen?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+13);
+ pPlayer->SEND_GOSSIP_MENU(1091, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+13:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Who are the Creators?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+14);
+ pPlayer->SEND_GOSSIP_MENU(1092, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+14:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "This is a lot to think about.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+15);
+ pPlayer->SEND_GOSSIP_MENU(1093, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+15:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I will access the discs now.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+16);
+ pPlayer->SEND_GOSSIP_MENU(1094, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+16:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(2278);
+ break;
+ }
+ return true;
+}
+
+void AddSC_uldaman()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "mob_jadespine_basilisk";
+ pNewScript->GetAI = &GetAI_mob_jadespine_basilisk;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_lore_keeper_of_norgannon";
+ pNewScript->pGossipHello = &GossipHello_npc_lore_keeper_of_norgannon;
+ pNewScript->pGossipSelect = &GossipSelect_npc_lore_keeper_of_norgannon;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/uldaman/uldaman.h b/scripts/eastern_kingdoms/uldaman/uldaman.h
new file mode 100644
index 0000000..d07cfda
--- /dev/null
+++ b/scripts/eastern_kingdoms/uldaman/uldaman.h
@@ -0,0 +1,79 @@
+/* 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_ULDAMAN_H
+#define DEF_ULDAMAN_H
+
+enum
+{
+ MAX_ENCOUNTER = 2,
+
+ TYPE_ALTAR_EVENT = 1,
+ TYPE_ARCHAEDAS = 2,
+ DATA_EVENT_STARTER = 3,
+
+ GO_TEMPLE_DOOR_UPPER = 124367,
+ GO_TEMPLE_DOOR_LOWER = 141869,
+ GO_ANCIENT_VAULT = 124369,
+
+ NPC_CUSTODIAN = 7309,
+ NPC_HALLSHAPER = 7077,
+ NPC_GUARDIAN = 7076,
+ NPC_VAULT_WARDER = 10120,
+ NPC_STONE_KEEPER = 4857,
+
+ PHASE_ARCHA_1 = 1,
+ PHASE_ARCHA_2 = 2,
+ PHASE_ARCHA_3 = 3,
+
+ SPELL_STONED = 10255,
+
+ EVENT_ID_ALTAR_KEEPER = 2228, // spell 11568
+ EVENT_ID_ALTAR_ARCHAEDAS = 2268 // spell 10340
+};
+
+class MANGOS_DLL_DECL instance_uldaman : public ScriptedInstance
+{
+ public:
+ instance_uldaman(Map* pMap);
+ ~instance_uldaman() {}
+
+ void Initialize();
+
+ void OnObjectCreate(GameObject* pGo);
+ void OnCreatureCreate(Creature* pCreature);
+
+ void Update(uint32 uiDiff);
+
+ void SetData(uint32 uiType, uint32 uiData);
+ void SetData64(uint32 uiData, uint64 uiGuid);
+ uint32 GetData(uint32 uiType);
+ uint64 GetData64(uint32 uiData);
+
+ void StartEvent(uint32 uiEventId, Player* pPlayer);
+
+ void DoResetKeeperEvent();
+
+ Creature* GetClosestDwarfNotInCombat(Creature* pSearcher, uint32 uiPhase);
+
+ const char* Save() { return strInstData.c_str(); }
+ void Load(const char* chrIn);
+
+ protected:
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint64 m_uiTempleDoorUpperGUID;
+ uint64 m_uiTempleDoorLowerGUID;
+ uint64 m_uiAncientVaultGUID;
+ uint64 m_uiPlayerGUID;
+
+ uint32 m_uiKeeperCooldown;
+ uint32 m_uiStoneKeepersFallen;
+
+ std::list m_lWardens;
+ std::map m_mKeeperMap;
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/undercity.cpp b/scripts/eastern_kingdoms/undercity.cpp
new file mode 100644
index 0000000..916534b
--- /dev/null
+++ b/scripts/eastern_kingdoms/undercity.cpp
@@ -0,0 +1,258 @@
+/* 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: Undercity
+SD%Complete: 95
+SDComment: Quest support: 6628(Parqual Fintallas questions/'answers' might have more to it, need more info), 9180(post-event).
+SDCategory: Undercity
+EndScriptData */
+
+/* ContentData
+npc_lady_sylvanas_windrunner
+npc_highborne_lamenter
+npc_parqual_fintallas
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_lady_sylvanas_windrunner
+######*/
+
+#define SAY_LAMENT_END -1000196
+#define EMOTE_LAMENT_END -1000197
+
+#define SOUND_CREDIT 10896
+#define ENTRY_HIGHBORNE_LAMENTER 21628
+#define ENTRY_HIGHBORNE_BUNNY 21641
+
+#define SPELL_HIGHBORNE_AURA 37090
+#define SPELL_SYLVANAS_CAST 36568
+#define SPELL_RIBBON_OF_SOULS 34432 //the real one to use might be 37099
+
+float HighborneLoc[4][3]=
+{
+ {1285.41f, 312.47f, 0.51f},
+ {1286.96f, 310.40f, 1.00f},
+ {1289.66f, 309.66f, 1.52f},
+ {1292.51f, 310.50f, 1.99f},
+};
+#define HIGHBORNE_LOC_Y -61.00f
+#define HIGHBORNE_LOC_Y_NEW -55.50f
+
+struct MANGOS_DLL_DECL npc_lady_sylvanas_windrunnerAI : public ScriptedAI
+{
+ npc_lady_sylvanas_windrunnerAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ uint32 LamentEvent_Timer;
+ bool LamentEvent;
+ uint64 targetGUID;
+
+ float myX;
+ float myY;
+ float myZ;
+
+ void Reset()
+ {
+ myX = m_creature->GetPositionX();
+ myY = m_creature->GetPositionY();
+ myZ = m_creature->GetPositionZ();
+
+ LamentEvent_Timer = 5000;
+ LamentEvent = false;
+ targetGUID = 0;
+ }
+
+ void JustSummoned(Creature *summoned)
+ {
+ if (summoned->GetEntry() == ENTRY_HIGHBORNE_BUNNY)
+ {
+ if (Creature* pBunny = m_creature->GetMap()->GetCreature(targetGUID))
+ {
+ pBunny->NearTeleportTo(pBunny->GetPositionX(), pBunny->GetPositionY(), myZ+15.0f, 0.0f);
+ summoned->CastSpell(pBunny,SPELL_RIBBON_OF_SOULS,false);
+ }
+
+ targetGUID = summoned->GetGUID();
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (LamentEvent)
+ {
+ if (LamentEvent_Timer < diff)
+ {
+ float raX = myX;
+ float raY = myY;
+ float raZ = myZ;
+
+ m_creature->GetRandomPoint(myX,myY,myZ,20.0,raX,raY,raZ);
+ m_creature->SummonCreature(ENTRY_HIGHBORNE_BUNNY,raX,raY,myZ,0,TEMPSUMMON_TIMED_DESPAWN,3000);
+
+ LamentEvent_Timer = 2000;
+ if (!m_creature->HasAura(SPELL_SYLVANAS_CAST, EFFECT_INDEX_0))
+ {
+ DoScriptText(SAY_LAMENT_END, m_creature);
+ DoScriptText(EMOTE_LAMENT_END, m_creature);
+ LamentEvent = false;
+ }
+ }else LamentEvent_Timer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_npc_lady_sylvanas_windrunner(Creature* pCreature)
+{
+ return new npc_lady_sylvanas_windrunnerAI(pCreature);
+}
+
+bool ChooseReward_npc_lady_sylvanas_windrunner(Player* pPlayer, Creature* pCreature, const Quest* pQuest, uint32 slot)
+{
+ if (pQuest->GetQuestId() == 9180)
+ {
+ if (npc_lady_sylvanas_windrunnerAI* pSylvanAI = dynamic_cast(pCreature->AI()))
+ {
+ pSylvanAI->LamentEvent = true;
+ pSylvanAI->DoPlaySoundToSet(pCreature, SOUND_CREDIT);
+ }
+
+ pCreature->CastSpell(pCreature,SPELL_SYLVANAS_CAST,false);
+
+ for(uint8 i = 0; i < 4; ++i)
+ pCreature->SummonCreature(ENTRY_HIGHBORNE_LAMENTER, HighborneLoc[i][0], HighborneLoc[i][1], HIGHBORNE_LOC_Y, HighborneLoc[i][2], TEMPSUMMON_TIMED_DESPAWN, 160000);
+ }
+
+ return true;
+}
+
+/*######
+## npc_highborne_lamenter
+######*/
+
+struct MANGOS_DLL_DECL npc_highborne_lamenterAI : public ScriptedAI
+{
+ npc_highborne_lamenterAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ uint32 EventMove_Timer;
+ uint32 EventCast_Timer;
+ bool EventMove;
+ bool EventCast;
+
+ void Reset()
+ {
+ EventMove_Timer = 10000;
+ EventCast_Timer = 17500;
+ EventMove = true;
+ EventCast = true;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (EventMove)
+ {
+ if (EventMove_Timer < diff)
+ {
+ m_creature->AddSplineFlag(SPLINEFLAG_NO_SPLINE);
+ m_creature->SendMonsterMoveWithSpeed(m_creature->GetPositionX(),m_creature->GetPositionY(),HIGHBORNE_LOC_Y_NEW,5000);
+ m_creature->GetMap()->CreatureRelocation(m_creature,m_creature->GetPositionX(),m_creature->GetPositionY(),HIGHBORNE_LOC_Y_NEW,m_creature->GetOrientation());
+ EventMove = false;
+ }else EventMove_Timer -= diff;
+ }
+ if (EventCast)
+ {
+ if (EventCast_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_HIGHBORNE_AURA);
+ EventCast = false;
+ }else EventCast_Timer -= diff;
+ }
+ }
+};
+CreatureAI* GetAI_npc_highborne_lamenter(Creature* pCreature)
+{
+ return new npc_highborne_lamenterAI(pCreature);
+}
+
+/*######
+## npc_parqual_fintallas
+######*/
+
+#define SPELL_MARK_OF_SHAME 6767
+
+bool GossipHello_npc_parqual_fintallas(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(6628) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasAura(SPELL_MARK_OF_SHAME, EFFECT_INDEX_0))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Gul'dan", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Kel'Thuzad", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Ner'zhul", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(5822, pCreature->GetGUID());
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(5821, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_parqual_fintallas(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer,SPELL_MARK_OF_SHAME,false);
+ }
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+2)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(6628);
+ }
+ return true;
+}
+
+/*######
+## AddSC
+######*/
+
+void AddSC_undercity()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_lady_sylvanas_windrunner";
+ newscript->GetAI = &GetAI_npc_lady_sylvanas_windrunner;
+ newscript->pChooseReward = &ChooseReward_npc_lady_sylvanas_windrunner;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_highborne_lamenter";
+ newscript->GetAI = &GetAI_npc_highborne_lamenter;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_parqual_fintallas";
+ newscript->pGossipHello = &GossipHello_npc_parqual_fintallas;
+ newscript->pGossipSelect = &GossipSelect_npc_parqual_fintallas;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/western_plaguelands.cpp b/scripts/eastern_kingdoms/western_plaguelands.cpp
new file mode 100644
index 0000000..da19bb7
--- /dev/null
+++ b/scripts/eastern_kingdoms/western_plaguelands.cpp
@@ -0,0 +1,222 @@
+/* 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: Western_Plaguelands
+SD%Complete: 90
+SDComment: Quest support: 5216,5219,5222,5225,5229,5231,5233,5235. To obtain Vitreous Focuser (could use more spesifics about gossip items)
+SDCategory: Western Plaguelands
+EndScriptData */
+
+/* ContentData
+npcs_dithers_and_arbington
+npc_myranda_hag
+npc_the_scourge_cauldron
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npcs_dithers_and_arbington
+######*/
+
+bool GossipHello_npcs_dithers_and_arbington(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+ if (pCreature->isVendor())
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+
+ if (pPlayer->GetQuestRewardStatus(5237) || pPlayer->GetQuestRewardStatus(5238))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What does the Felstone Field Cauldron need?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What does the Dalson's Tears Cauldron need?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What does the Writhing Haunt Cauldron need?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What does the Gahrron's Withering Cauldron need?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
+ pPlayer->SEND_GOSSIP_MENU(3985, pCreature->GetGUID());
+ }else
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npcs_dithers_and_arbington(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_TRADE:
+ pPlayer->SEND_VENDORLIST(pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Thanks, i need a Vitreous Focuser", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(3980, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Thanks, i need a Vitreous Focuser", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(3981, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Thanks, i need a Vitreous Focuser", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(3982, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Thanks, i need a Vitreous Focuser", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(3983, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer, 17529, false);
+ break;
+ }
+ return true;
+}
+
+/*######
+## npc_myranda_the_hag
+######*/
+
+enum
+{
+ QUEST_SUBTERFUGE = 5862,
+ QUEST_IN_DREAMS = 5944,
+ SPELL_SCARLET_ILLUSION = 17961
+};
+
+#define GOSSIP_ITEM_ILLUSION "I am ready for the illusion, Myranda."
+
+bool GossipHello_npc_myranda_the_hag(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(QUEST_SUBTERFUGE) == QUEST_STATUS_COMPLETE &&
+ !pPlayer->GetQuestRewardStatus(QUEST_IN_DREAMS) && !pPlayer->HasAura(SPELL_SCARLET_ILLUSION))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ILLUSION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(4773, pCreature->GetGUID());
+ return true;
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_myranda_the_hag(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer, SPELL_SCARLET_ILLUSION, false);
+ }
+ return true;
+}
+
+/*######
+## npc_the_scourge_cauldron
+######*/
+
+struct MANGOS_DLL_DECL npc_the_scourge_cauldronAI : public ScriptedAI
+{
+ npc_the_scourge_cauldronAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset() {}
+
+ void DoDie()
+ {
+ //summoner dies here
+ m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ //override any database `spawntimesecs` to prevent duplicated summons
+ uint32 rTime = m_creature->GetRespawnDelay();
+ if (rTime<600)
+ m_creature->SetRespawnDelay(600);
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ if (!who || who->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ {
+ switch(m_creature->GetAreaId())
+ {
+ case 199: //felstone
+ if (((Player*)who)->GetQuestStatus(5216) == QUEST_STATUS_INCOMPLETE ||
+ ((Player*)who)->GetQuestStatus(5229) == QUEST_STATUS_INCOMPLETE)
+ {
+ m_creature->SummonCreature(11075, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000);
+ DoDie();
+ }
+ break;
+ case 200: //dalson
+ if (((Player*)who)->GetQuestStatus(5219) == QUEST_STATUS_INCOMPLETE ||
+ ((Player*)who)->GetQuestStatus(5231) == QUEST_STATUS_INCOMPLETE)
+ {
+ m_creature->SummonCreature(11077, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000);
+ DoDie();
+ }
+ break;
+ case 201: //gahrron
+ if (((Player*)who)->GetQuestStatus(5225) == QUEST_STATUS_INCOMPLETE ||
+ ((Player*)who)->GetQuestStatus(5235) == QUEST_STATUS_INCOMPLETE)
+ {
+ m_creature->SummonCreature(11078, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000);
+ DoDie();
+ }
+ break;
+ case 202: //writhing
+ if (((Player*)who)->GetQuestStatus(5222) == QUEST_STATUS_INCOMPLETE ||
+ ((Player*)who)->GetQuestStatus(5233) == QUEST_STATUS_INCOMPLETE)
+ {
+ m_creature->SummonCreature(11076, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,600000);
+ DoDie();
+ }
+ break;
+ }
+ }
+ }
+};
+CreatureAI* GetAI_npc_the_scourge_cauldron(Creature* pCreature)
+{
+ return new npc_the_scourge_cauldronAI(pCreature);
+}
+
+/*######
+##
+######*/
+
+void AddSC_western_plaguelands()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npcs_dithers_and_arbington";
+ newscript->pGossipHello = &GossipHello_npcs_dithers_and_arbington;
+ newscript->pGossipSelect = &GossipSelect_npcs_dithers_and_arbington;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_myranda_the_hag";
+ newscript->pGossipHello = &GossipHello_npc_myranda_the_hag;
+ newscript->pGossipSelect = &GossipSelect_npc_myranda_the_hag;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_the_scourge_cauldron";
+ newscript->GetAI = &GetAI_npc_the_scourge_cauldron;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/westfall.cpp b/scripts/eastern_kingdoms/westfall.cpp
new file mode 100644
index 0000000..0ecd8d0
--- /dev/null
+++ b/scripts/eastern_kingdoms/westfall.cpp
@@ -0,0 +1,266 @@
+/* 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: Westfall
+SD%Complete: 90
+SDComment: Quest support: 155, 1651
+SDCategory: Westfall
+EndScriptData */
+
+/* ContentData
+npc_daphne_stilwell
+npc_defias_traitor
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_daphne_stilwell
+######*/
+
+enum
+{
+ SAY_DS_START = -1000293,
+ SAY_DS_DOWN_1 = -1000294,
+ SAY_DS_DOWN_2 = -1000295,
+ SAY_DS_DOWN_3 = -1000296,
+ SAY_DS_PROLOGUE = -1000297,
+
+ SPELL_SHOOT = 6660,
+ QUEST_TOME_VALOR = 1651,
+ NPC_DEFIAS_RAIDER = 6180,
+ EQUIP_ID_RIFLE = 2511
+};
+
+struct MANGOS_DLL_DECL npc_daphne_stilwellAI : public npc_escortAI
+{
+ npc_daphne_stilwellAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_uiWPHolder = 0;
+ Reset();
+ }
+
+ uint32 m_uiWPHolder;
+ uint32 m_uiShootTimer;
+
+ void Reset()
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ switch(m_uiWPHolder)
+ {
+ case 7: DoScriptText(SAY_DS_DOWN_1, m_creature); break;
+ case 8: DoScriptText(SAY_DS_DOWN_2, m_creature); break;
+ case 9: DoScriptText(SAY_DS_DOWN_3, m_creature); break;
+ }
+ }
+ else
+ m_uiWPHolder = 0;
+
+ m_uiShootTimer = 0;
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ m_uiWPHolder = uiPointId;
+
+ switch(uiPointId)
+ {
+ case 4:
+ SetEquipmentSlots(false, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE, EQUIP_ID_RIFLE);
+ m_creature->SetSheath(SHEATH_STATE_RANGED);
+ m_creature->HandleEmote(EMOTE_STATE_USESTANDING_NOSHEATHE);
+ break;
+ case 7:
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836f, 1569.755f, 54.267f, 4.230f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697f, 1569.124f, 54.421f, 4.206f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237f, 1568.307f, 54.620f, 4.206f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ break;
+ case 8:
+ m_creature->SetSheath(SHEATH_STATE_RANGED);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836f, 1569.755f, 54.267f, 4.230f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697f, 1569.124f, 54.421f, 4.206f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237f, 1568.307f, 54.620f, 4.206f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11448.037f, 1570.213f, 54.961f, 4.283f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ break;
+ case 9:
+ m_creature->SetSheath(SHEATH_STATE_RANGED);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11450.836f, 1569.755f, 54.267f, 4.230f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11449.697f, 1569.124f, 54.421f, 4.206f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11448.237f, 1568.307f, 54.620f, 4.206f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11448.037f, 1570.213f, 54.961f, 4.283f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ m_creature->SummonCreature(NPC_DEFIAS_RAIDER, -11449.018f, 1570.738f, 54.828f, 4.220f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ break;
+ case 10:
+ SetRun(false);
+ break;
+ case 11:
+ DoScriptText(SAY_DS_PROLOGUE, m_creature);
+ break;
+ case 13:
+ SetEquipmentSlots(true);
+ m_creature->SetSheath(SHEATH_STATE_UNARMED);
+ m_creature->HandleEmote(EMOTE_STATE_USESTANDING_NOSHEATHE);
+ break;
+ case 17:
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_TOME_VALOR, m_creature);
+ break;
+ }
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (!pWho)
+ return;
+
+ if (m_creature->Attack(pWho, false))
+ {
+ m_creature->AddThreat(pWho);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ m_creature->GetMotionMaster()->MoveChase(pWho, 30.0f);
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->AI()->AttackStart(m_creature);
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiShootTimer < uiDiff)
+ {
+ m_uiShootTimer = 1000;
+
+ if (!m_creature->IsWithinDist(m_creature->getVictim(), ATTACK_DISTANCE))
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHOOT);
+
+ }
+ else
+ m_uiShootTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool QuestAccept_npc_daphne_stilwell(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_TOME_VALOR)
+ {
+ DoScriptText(SAY_DS_START, pCreature);
+
+ if (npc_daphne_stilwellAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(true, pPlayer->GetGUID(), pQuest);
+ }
+
+ return true;
+}
+
+CreatureAI* GetAI_npc_daphne_stilwell(Creature* pCreature)
+{
+ return new npc_daphne_stilwellAI(pCreature);
+}
+
+/*######
+## npc_defias_traitor
+######*/
+
+enum
+{
+ SAY_START = -1000101,
+ SAY_PROGRESS = -1000102,
+ SAY_END = -1000103,
+ SAY_AGGRO_1 = -1000104,
+ SAY_AGGRO_2 = -1000105,
+
+ QUEST_DEFIAS_BROTHERHOOD = 155
+};
+
+struct MANGOS_DLL_DECL npc_defias_traitorAI : public npc_escortAI
+{
+ npc_defias_traitorAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch (uiPointId)
+ {
+ case 35:
+ SetRun(false);
+ break;
+ case 36:
+ if (Player* pPlayer = GetPlayerForEscort())
+ DoScriptText(SAY_PROGRESS, m_creature, pPlayer);
+ break;
+ case 44:
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ DoScriptText(SAY_END, m_creature, pPlayer);
+ pPlayer->GroupEventHappens(QUEST_DEFIAS_BROTHERHOOD, m_creature);
+ }
+ break;
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(urand(0, 1) ? SAY_AGGRO_1 : SAY_AGGRO_2, m_creature);
+ }
+
+ void Reset() { }
+};
+
+bool QuestAccept_npc_defias_traitor(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_DEFIAS_BROTHERHOOD)
+ {
+ DoScriptText(SAY_START, pCreature, pPlayer);
+
+ if (npc_defias_traitorAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(true, pPlayer->GetGUID(), pQuest);
+ }
+
+ return true;
+}
+
+CreatureAI* GetAI_npc_defias_traitor(Creature* pCreature)
+{
+ return new npc_defias_traitorAI(pCreature);
+}
+
+void AddSC_westfall()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_daphne_stilwell";
+ pNewScript->GetAI = &GetAI_npc_daphne_stilwell;
+ pNewScript->pQuestAccept = &QuestAccept_npc_daphne_stilwell;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_defias_traitor";
+ pNewScript->GetAI = &GetAI_npc_defias_traitor;
+ pNewScript->pQuestAccept = &QuestAccept_npc_defias_traitor;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/wetlands.cpp b/scripts/eastern_kingdoms/wetlands.cpp
new file mode 100644
index 0000000..b01a99b
--- /dev/null
+++ b/scripts/eastern_kingdoms/wetlands.cpp
@@ -0,0 +1,167 @@
+/* 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: Wetlands
+SD%Complete: 80
+SDComment: Quest support: 1249
+SDCategory: Wetlands
+EndScriptData */
+
+/* ContentData
+npc_mikhail
+npc_tapoke_slim_jahn
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_tapoke_slim_jahn
+######*/
+
+enum
+{
+ QUEST_MISSING_DIPLO_PT11 = 1249,
+ FACTION_ENEMY = 168,
+ SPELL_STEALTH = 1785,
+ SPELL_CALL_FRIENDS = 16457, //summons 1x friend
+ NPC_SLIMS_FRIEND = 4971,
+ NPC_TAPOKE_SLIM_JAHN = 4962
+};
+
+struct MANGOS_DLL_DECL npc_tapoke_slim_jahnAI : public npc_escortAI
+{
+ npc_tapoke_slim_jahnAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ bool m_bFriendSummoned;
+
+ void Reset()
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ m_bFriendSummoned = false;
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 2:
+ if (m_creature->HasStealthAura())
+ m_creature->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+
+ SetRun();
+ m_creature->setFaction(FACTION_ENEMY);
+ break;
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && !m_bFriendSummoned && pPlayer)
+ {
+ for(uint8 i = 0; i < 3; ++i)
+ m_creature->CastSpell(m_creature, SPELL_CALL_FRIENDS, true);
+
+ m_bFriendSummoned = true;
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (Player* pPlayer = GetPlayerForEscort())
+ pSummoned->AI()->AttackStart(pPlayer);
+ }
+
+ void AttackedBy(Unit* pAttacker)
+ {
+ if (m_creature->getVictim())
+ return;
+
+ if (m_creature->IsFriendlyTo(pAttacker))
+ return;
+
+ AttackStart(pAttacker);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32& uiDamage)
+ {
+ if (m_creature->GetHealthPercent() < 20.0f)
+ {
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ pPlayer->GroupEventHappens(QUEST_MISSING_DIPLO_PT11, m_creature);
+
+ uiDamage = 0;
+
+ m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A);
+ m_creature->RemoveAllAuras();
+ m_creature->DeleteThreatList();
+ m_creature->CombatStop(true);
+
+ SetRun(false);
+ }
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_tapoke_slim_jahn(Creature* pCreature)
+{
+ return new npc_tapoke_slim_jahnAI(pCreature);
+}
+
+/*######
+## npc_mikhail
+######*/
+
+bool QuestAccept_npc_mikhail(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT11)
+ {
+ Creature* pSlim = GetClosestCreatureWithEntry(pCreature, NPC_TAPOKE_SLIM_JAHN, 25.0f);
+
+ if (!pSlim)
+ return false;
+
+ if (!pSlim->HasStealthAura())
+ pSlim->CastSpell(pSlim, SPELL_STEALTH, true);
+
+ if (npc_tapoke_slim_jahnAI* pEscortAI = dynamic_cast(pSlim->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return false;
+}
+
+/*######
+## AddSC
+######*/
+
+void AddSC_wetlands()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_tapoke_slim_jahn";
+ newscript->GetAI = &GetAI_npc_tapoke_slim_jahn;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_mikhail";
+ newscript->pQuestAccept = &QuestAccept_npc_mikhail;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp b/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp
new file mode 100644
index 0000000..c90776f
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp
@@ -0,0 +1,311 @@
+/* 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_Akilzon
+SD%Complete: 50
+SDComment: TODO: Correct timers, correct details, remove hack for eagles
+SDCategory: Zul'Aman
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulaman.h"
+
+enum
+{
+ SAY_EVENT1 = -1568024,
+ SAY_EVENT2 = -1568025,
+ SAY_AGGRO = -1568026,
+ SAY_SUMMON = -1568027,
+ SAY_SUMMON_ALT = -1568028,
+ SAY_ENRAGE = -1568029,
+ SAY_SLAY1 = -1568030,
+ SAY_SLAY2 = -1568031,
+ SAY_DEATH = -1568032,
+ EMOTE_STORM = -1568033,
+
+ SPELL_STATIC_DISRUPTION = 43622,
+ SPELL_STATIC_VISUAL = 45265,
+
+ SPELL_CALL_LIGHTNING = 43661,
+ SPELL_GUST_OF_WIND = 43621,
+
+ SPELL_ELECTRICAL_STORM = 43648,
+ SPELL_STORMCLOUD_VISUAL = 45213,
+
+ SPELL_BERSERK = 45078,
+
+ NPC_SOARING_EAGLE = 24858,
+ MAX_EAGLE_COUNT = 6,
+
+ //SE_LOC_X_MAX = 400,
+ //SE_LOC_X_MIN = 335,
+ //SE_LOC_Y_MAX = 1435,
+ //SE_LOC_Y_MIN = 1370
+};
+
+struct MANGOS_DLL_DECL boss_akilzonAI : public ScriptedAI
+{
+ boss_akilzonAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiStaticDisruptTimer;
+ uint32 m_uiCallLightTimer;
+ uint32 m_uiGustOfWindTimer;
+ uint32 m_uiStormTimer;
+ uint32 m_uiSummonEagleTimer;
+ uint32 m_uiBerserkTimer;
+ bool m_bIsBerserk;
+
+ void Reset()
+ {
+ m_uiStaticDisruptTimer = urand(7000, 14000);
+ m_uiCallLightTimer = urand(15000, 25000);
+ m_uiGustOfWindTimer = urand(20000, 30000);
+ m_uiStormTimer = 50000;
+ m_uiSummonEagleTimer = 65000;
+ m_uiBerserkTimer = MINUTE*8*IN_MILLISECONDS;
+ m_bIsBerserk = false;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ m_creature->SetInCombatWithZone();
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (!m_pInstance)
+ return;
+
+ m_pInstance->SetData(TYPE_AKILZON, DONE);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_SOARING_EAGLE)
+ pSummoned->SetInCombatWithZone();
+ }
+
+ void DoSummonEagles()
+ {
+ for(uint32 i = 0; i < MAX_EAGLE_COUNT; ++i)
+ {
+ float fX, fY, fZ;
+ m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+15.0f, 30.0f, fX, fY, fZ);
+
+ m_creature->SummonCreature(NPC_SOARING_EAGLE, fX, fY, fZ, m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 1000);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiCallLightTimer < uiDiff)
+ {
+ m_creature->CastSpell(m_creature->getVictim(), SPELL_CALL_LIGHTNING, false);
+ m_uiCallLightTimer = urand(15000, 25000);
+ }else m_uiCallLightTimer -= uiDiff;
+
+ if (m_uiStaticDisruptTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
+ m_creature->CastSpell(pTarget, SPELL_STATIC_DISRUPTION, false);
+
+ m_uiStaticDisruptTimer = urand(7000, 14000);
+ }else m_uiStaticDisruptTimer -= uiDiff;
+
+ if (m_uiStormTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoScriptText(EMOTE_STORM, m_creature);
+ m_creature->CastSpell(pTarget, SPELL_ELECTRICAL_STORM, false);
+ }
+
+ m_uiStormTimer = 60000;
+ }else m_uiStormTimer -= uiDiff;
+
+ if (m_uiGustOfWindTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
+ m_creature->CastSpell(pTarget, SPELL_GUST_OF_WIND, false);
+
+ m_uiGustOfWindTimer = urand(20000, 30000);
+ }else m_uiGustOfWindTimer -= uiDiff;
+
+ if (m_uiSummonEagleTimer < uiDiff)
+ {
+ DoScriptText(urand(0,1) ? SAY_SUMMON : SAY_SUMMON_ALT, m_creature);
+ DoSummonEagles();
+ m_uiSummonEagleTimer = 60000;
+ }else m_uiSummonEagleTimer -= uiDiff;
+
+ if (!m_bIsBerserk && m_uiBerserkTimer < uiDiff)
+ {
+ DoScriptText(SAY_ENRAGE, m_creature);
+ m_creature->CastSpell(m_creature, SPELL_BERSERK, true);
+ m_bIsBerserk = true;
+ }else m_uiBerserkTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_akilzon(Creature* pCreature)
+{
+ return new boss_akilzonAI(pCreature);
+}
+
+enum
+{
+ SPELL_EAGLE_SWOOP = 44732,
+ POINT_ID_RANDOM = 1
+};
+
+struct MANGOS_DLL_DECL mob_soaring_eagleAI : public ScriptedAI
+{
+ mob_soaring_eagleAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiEagleSwoopTimer;
+ uint32 m_uiReturnTimer;
+ bool m_bCanMoveToRandom;
+ bool m_bCanCast;
+
+ void Reset()
+ {
+ m_uiEagleSwoopTimer = urand(2000, 6000);
+ m_uiReturnTimer = 800;
+ m_bCanMoveToRandom = false;
+ m_bCanCast = true;
+
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (!pWho)
+ return;
+
+ if (m_creature->Attack(pWho, false))
+ {
+ m_creature->AddThreat(pWho);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+ }
+ }
+
+ void MovementInform(uint32 uiType, uint32 uiPointId)
+ {
+ if (uiType != POINT_MOTION_TYPE)
+ return;
+
+ m_bCanCast = true;
+ }
+
+ void DoMoveToRandom()
+ {
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pAzkil = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_AKILZON)))
+ {
+ float fX, fY, fZ;
+ pAzkil->GetRandomPoint(pAzkil->GetPositionX(), pAzkil->GetPositionY(), pAzkil->GetPositionZ()+15.0f, 30.0f, fX, fY, fZ);
+
+ if (m_creature->HasSplineFlag(SPLINEFLAG_WALKMODE))
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+
+ m_creature->GetMotionMaster()->MovePoint(POINT_ID_RANDOM, fX, fY, fZ);
+
+ m_bCanMoveToRandom = false;
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_bCanMoveToRandom)
+ {
+ if (m_uiReturnTimer < uiDiff)
+ {
+ DoMoveToRandom();
+ m_uiReturnTimer = 800;
+ }else m_uiReturnTimer -= uiDiff;
+ }
+
+ if (!m_bCanCast)
+ return;
+
+ if (m_uiEagleSwoopTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ DoCastSpellIfCan(pTarget,SPELL_EAGLE_SWOOP);
+
+ m_bCanMoveToRandom = true;
+ m_bCanCast = false;
+ }
+
+ m_uiEagleSwoopTimer = urand(4000, 6000);
+ }else m_uiEagleSwoopTimer -= uiDiff;
+ }
+};
+
+CreatureAI* GetAI_mob_soaring_eagle(Creature* pCreature)
+{
+ return new mob_soaring_eagleAI(pCreature);
+}
+
+void AddSC_boss_akilzon()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_akilzon";
+ newscript->GetAI = &GetAI_boss_akilzon;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_soaring_eagle";
+ newscript->GetAI = &GetAI_mob_soaring_eagle;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp b/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp
new file mode 100644
index 0000000..12f5159
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp
@@ -0,0 +1,400 @@
+/* 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_Halazzi
+SD%Complete: 70
+SDComment: Details and timers need check.
+SDCategory: Zul'Aman
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulaman.h"
+#include "ObjectMgr.h"
+
+enum
+{
+ SAY_AGGRO = -1568034,
+ SAY_SPLIT = -1568035,
+ SAY_MERGE = -1568036,
+ SAY_SABERLASH1 = -1568037,
+ SAY_SABERLASH2 = -1568038,
+ SAY_BERSERK = -1568039,
+ SAY_KILL1 = -1568040,
+ SAY_KILL2 = -1568041,
+ SAY_DEATH = -1568042,
+ SAY_EVENT1 = -1568043,
+ SAY_EVENT2 = -1568044,
+
+ SPELL_DUAL_WIELD = 42459,
+ SPELL_SABER_LASH = 43267,
+ SPELL_FRENZY = 43139,
+ SPELL_FLAMESHOCK = 43303,
+ SPELL_EARTHSHOCK = 43305,
+ SPELL_BERSERK = 45078,
+
+ //SPELL_TRANSFORM_TO_ORIGINAL = 43311,
+
+ //SPELL_TRANSFIGURE = 44054,
+
+ SPELL_TRANSFIGURE_TO_TROLL = 43142,
+ //SPELL_TRANSFIGURE_TO_TROLL_TRIGGERED = 43573,
+
+ SPELL_TRANSFORM_TO_LYNX_75 = 43145,
+ SPELL_TRANSFORM_TO_LYNX_50 = 43271,
+ SPELL_TRANSFORM_TO_LYNX_25 = 43272,
+
+ SPELL_SUMMON_LYNX = 43143,
+ SPELL_SUMMON_TOTEM = 43302,
+
+ NPC_TOTEM = 24224
+};
+
+enum HalazziPhase
+{
+ PHASE_SINGLE = 0,
+ PHASE_TOTEM = 1,
+ PHASE_FINAL = 2
+};
+
+struct MANGOS_DLL_DECL boss_halazziAI : public ScriptedAI
+{
+ boss_halazziAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiPhase;
+ uint32 m_uiPhaseCounter;
+ uint32 m_uiFrenzyTimer;
+ uint32 m_uiSaberLashTimer;
+ uint32 m_uiShockTimer;
+ uint32 m_uiTotemTimer;
+ uint32 m_uiCheckTimer;
+ uint32 m_uiBerserkTimer;
+ bool m_bIsBerserk;
+
+ void Reset()
+ {
+ m_uiPhase = PHASE_SINGLE; // reset phase
+ m_uiPhaseCounter = 3;
+
+ m_uiCheckTimer = IN_MILLISECONDS;
+ m_uiFrenzyTimer = 16*IN_MILLISECONDS;
+ m_uiSaberLashTimer = 20*IN_MILLISECONDS;
+ m_uiShockTimer = 10*IN_MILLISECONDS;
+ m_uiTotemTimer = 12*IN_MILLISECONDS;
+ m_uiBerserkTimer = 10*MINUTE*IN_MILLISECONDS;
+ m_bIsBerserk = false;
+
+ m_creature->SetMaxHealth(m_creature->GetCreatureInfo()->maxhealth);
+
+ if (m_pInstance)
+ {
+ if (Creature* pSpiritLynx = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_SPIRIT_LYNX)))
+ pSpiritLynx->ForcedDespawn();
+ }
+ }
+
+ void JustReachedHome()
+ {
+ m_pInstance->SetData(TYPE_HALAZZI, NOT_STARTED);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ m_creature->SetInCombatWithZone();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_HALAZZI, IN_PROGRESS);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (pVictim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ DoScriptText(urand(0, 1) ? SAY_KILL1 : SAY_KILL2, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_HALAZZI, DONE);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_SPIRIT_LYNX)
+ pSummoned->SetInCombatWithZone();
+ }
+
+ void DoUpdateStats(const CreatureInfo* pInfo)
+ {
+ m_creature->SetMaxHealth(pInfo->maxhealth);
+
+ if (m_uiPhase == PHASE_SINGLE)
+ {
+ m_creature->SetHealth(m_creature->GetMaxHealth()/4*m_uiPhaseCounter);
+ --m_uiPhaseCounter;
+ }
+ }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (pSpell->EffectApplyAuraName[0] != SPELL_AURA_TRANSFORM)
+ return;
+
+ // possibly hack and health should be set by Aura::HandleAuraTransform()
+ if (const CreatureInfo* pInfo = GetCreatureTemplateStore(pSpell->EffectMiscValue[0]))
+ DoUpdateStats(pInfo);
+
+ if (m_uiPhase == PHASE_TOTEM)
+ DoCastSpellIfCan(m_creature, SPELL_SUMMON_LYNX);
+ }
+
+ void PhaseChange()
+ {
+ if (m_uiPhase == PHASE_SINGLE)
+ {
+ if (m_creature->GetHealthPercent() <= float(25*m_uiPhaseCounter))
+ {
+ if (!m_uiPhaseCounter)
+ {
+ // final phase
+ m_uiPhase = PHASE_FINAL;
+ m_uiFrenzyTimer = 16*IN_MILLISECONDS;
+ m_uiSaberLashTimer = 20*IN_MILLISECONDS;
+ }
+ else
+ {
+ m_uiPhase = PHASE_TOTEM;
+ m_uiShockTimer = 10*IN_MILLISECONDS;
+ m_uiTotemTimer = 12*IN_MILLISECONDS;
+
+ DoScriptText(SAY_SPLIT, m_creature);
+ m_creature->CastSpell(m_creature, SPELL_TRANSFIGURE_TO_TROLL, false);
+ }
+ }
+ }
+ else
+ {
+ Creature* pSpiritLynx = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_SPIRIT_LYNX));
+
+ if (m_creature->GetHealthPercent() < 10.0f ||
+ (pSpiritLynx && pSpiritLynx->GetHealthPercent() < 10.0f))
+ {
+ m_uiPhase = PHASE_SINGLE;
+
+ DoScriptText(SAY_MERGE, m_creature);
+
+ uint32 uiSpellId;
+
+ switch(m_uiPhaseCounter)
+ {
+ case 3: uiSpellId = SPELL_TRANSFORM_TO_LYNX_75; break;
+ case 2: uiSpellId = SPELL_TRANSFORM_TO_LYNX_50; break;
+ case 1: uiSpellId = SPELL_TRANSFORM_TO_LYNX_25; break;
+ }
+
+ m_creature->CastSpell(m_creature, uiSpellId, false);
+
+ if (pSpiritLynx)
+ pSpiritLynx->ForcedDespawn();
+
+ m_uiFrenzyTimer = 16*IN_MILLISECONDS;
+ m_uiSaberLashTimer = 20*IN_MILLISECONDS;
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!m_bIsBerserk)
+ {
+ if (m_uiBerserkTimer < uiDiff)
+ {
+ DoScriptText(SAY_BERSERK, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_BERSERK, CAST_TRIGGERED);
+ m_bIsBerserk = true;
+ }
+ else
+ m_uiBerserkTimer -= uiDiff;
+ }
+
+ if (m_uiPhase != PHASE_FINAL)
+ {
+ if (m_uiCheckTimer < uiDiff)
+ {
+ if (m_pInstance)
+ PhaseChange();
+ else
+ m_uiPhase = PHASE_FINAL;
+
+ m_uiCheckTimer = IN_MILLISECONDS;
+ }
+ else
+ m_uiCheckTimer -= uiDiff;
+ }
+
+ if (m_uiPhase == PHASE_FINAL || m_uiPhase == PHASE_SINGLE)
+ {
+ if (m_uiFrenzyTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FRENZY);
+ m_uiFrenzyTimer = 16*IN_MILLISECONDS;
+ }
+ else
+ m_uiFrenzyTimer -= uiDiff;
+
+ if (m_uiSaberLashTimer < uiDiff)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SABERLASH1 : SAY_SABERLASH2, m_creature);
+
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SABER_LASH);
+ m_uiSaberLashTimer = 20*IN_MILLISECONDS;
+ }
+ else
+ m_uiSaberLashTimer -= uiDiff;
+ }
+
+ if (m_uiPhase == PHASE_FINAL || m_uiPhase == PHASE_TOTEM)
+ {
+ if (m_uiTotemTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_SUMMON_TOTEM);
+ m_uiTotemTimer = 20*IN_MILLISECONDS;
+ }
+ else
+ m_uiTotemTimer -= uiDiff;
+
+ if (m_uiShockTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ if (pTarget->IsNonMeleeSpellCasted(false))
+ DoCastSpellIfCan(pTarget, SPELL_EARTHSHOCK);
+ else
+ DoCastSpellIfCan(pTarget, SPELL_FLAMESHOCK);
+
+ m_uiShockTimer = urand(10000, 14000);
+ }
+ }
+ else
+ m_uiShockTimer -= uiDiff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_halazzi(Creature* pCreature)
+{
+ return new boss_halazziAI(pCreature);
+}
+
+enum
+{
+ SPELL_LYNX_FRENZY = 43290,
+ SPELL_SHRED_ARMOR = 43243
+};
+
+struct MANGOS_DLL_DECL boss_spirit_lynxAI : public ScriptedAI
+{
+ boss_spirit_lynxAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiFrenzyTimer;
+ uint32 m_uiShredArmorTimer;
+
+ void Reset()
+ {
+ m_uiFrenzyTimer = urand(10000, 20000); //first frenzy after 10-20 seconds
+ m_uiShredArmorTimer = 4000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pHalazzi = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_HALAZZI)))
+ pHalazzi->AI()->KilledUnit(pVictim);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiFrenzyTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_LYNX_FRENZY);
+ m_uiFrenzyTimer = urand(20000, 30000); //subsequent frenzys casted every 20-30 seconds
+ }
+ else
+ m_uiFrenzyTimer -= uiDiff;
+
+ if (m_uiShredArmorTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHRED_ARMOR);
+ m_uiShredArmorTimer = 4000;
+ }
+ else
+ m_uiShredArmorTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_spirit_lynx(Creature* pCreature)
+{
+ return new boss_spirit_lynxAI(pCreature);
+}
+
+void AddSC_boss_halazzi()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_halazzi";
+ newscript->GetAI = &GetAI_boss_halazzi;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_spirit_lynx";
+ newscript->GetAI = &GetAI_boss_spirit_lynx;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp b/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp
new file mode 100644
index 0000000..532769f
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp
@@ -0,0 +1,784 @@
+/* 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_Janalai
+SD%Complete: 75
+SDComment:
+SDCategory: Zul'Aman
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulaman.h"
+
+enum
+{
+ SAY_AGGRO = -1568000,
+ SAY_FIRE_BOMBS = -1568001,
+ SAY_SUMMON_HATCHER = -1568002,
+ SAY_ALL_EGGS = -1568003,
+ SAY_BERSERK = -1568004,
+ SAY_SLAY_1 = -1568005,
+ SAY_SLAY_2 = -1568006,
+ SAY_DEATH = -1568007,
+ SAY_EVENT_STRANGERS = -1568008,
+ SAY_EVENT_FRIENDS = -1568009,
+
+ //Jan'alai
+ SPELL_FLAME_BREATH = 43140,
+ SPELL_FIRE_WALL = 43113,
+ SPELL_ENRAGE = 44779,
+ SPELL_TELETOCENTER = 43098,
+ SPELL_SUMMONALL = 43097,
+ SPELL_BERSERK = 47008,
+ SPELL_SUMMON_HATCHER_1 = 43962,
+ SPELL_SUMMON_HATCHER_2 = 45340,
+
+ //Fire Bob Spells
+ SPELL_FIRE_BOMB_CHANNEL = 42621,
+ SPELL_FIRE_BOMB_THROW = 42628,
+ SPELL_FIRE_BOMB_DUMMY = 42629,
+ SPELL_FIRE_BOMB_DAMAGE = 42630,
+
+ //NPC's
+ NPC_FIRE_BOMB = 23920,
+ NPC_AMANI_HATCHER_1 = 23818,
+ NPC_AMANI_HATCHER_2 = 24504,
+ NPC_HATCHLING = 23598,
+
+ //Hatcher Spells
+ SPELL_HATCH_EGG = 43734, //spell 42471 also exist
+ SPELL_HATCH_ALL_EGGS = 43144,
+
+ //Eggs spells
+ SPELL_SUMMON_DRAGONHAWK = 42493,
+
+ //Hatchling Spells
+ SPELL_FLAMEBUFFED = 43299
+};
+
+//spells should summon Fire Bomb, used in Throw5Bombs()
+static uint32 m_auiSpellFireBombSummon[]=
+{
+ 42622, 42623, 42624, 42625, 42626
+};
+
+const int area_dx = 44;
+const int area_dy = 51;
+
+float JanalainPos[1][3] =
+{
+ {-33.93f, 1149.27f, 19.0f}
+};
+
+float FireWallCoords[4][4] =
+{
+ {-10.13f, 1149.27f, 19.0f, M_PI_F},
+ {-33.93f, 1123.90f, 19.0f, 0.5f*M_PI_F},
+ {-54.80f, 1150.08f, 19.0f, 0.0f},
+ {-33.93f, 1175.68f, 19.0f, 1.5f*M_PI_F}
+};
+
+struct WaypointDef
+{
+ float m_fX, m_fY, m_fZ;
+};
+
+WaypointDef m_aHatcherRight[]=
+{
+ {-86.203f, 1136.834f, 5.594f}, //this is summon point, not regular waypoint
+ {-74.783f, 1145.827f, 5.420f},
+ {-56.957f, 1146.713f, 18.725f},
+ {-45.428f, 1141.697f, 18.709f},
+ {-34.002f, 1124.427f, 18.711f},
+ {-34.085f, 1106.158f, 18.711f}
+};
+
+WaypointDef m_aHatcherLeft[]=
+{
+ {-85.420f, 1167.321f, 5.594f}, //this is summon point, not regular waypoint
+ {-73.569f, 1154.960f, 5.510f},
+ {-56.985f, 1153.373f, 18.608f},
+ {-45.515f, 1158.356f, 18.709f},
+ {-33.314f, 1174.816f, 18.709f},
+ {-33.097f, 1195.359f, 18.709f}
+};
+
+float hatcherway_l[5][3] =
+{
+ {-87.46f, 1170.09f, 6.0f},
+ {-74.41f, 1154.75f, 6.0f},
+ {-52.74f, 1153.32f, 19.0f},
+ {-33.37f, 1172.46f, 19.0f},
+ {-33.09f, 1203.87f, 19.0f}
+};
+
+float hatcherway_r[5][3] =
+{
+ {-86.57f, 1132.85f, 6.0f},
+ {-73.94f, 1146.00f, 6.0f},
+ {-52.29f, 1146.51f, 19.0f},
+ {-33.57f, 1125.72f, 19.0f},
+ {-34.29f, 1095.22f, 19.0f}
+};
+
+struct MANGOS_DLL_DECL boss_janalaiAI : public ScriptedAI
+{
+ boss_janalaiAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiHatcher1GUID = 0;
+ m_uiHatcher2GUID = 0;
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 fire_breath_timer;
+
+ std::list m_lBombsGUIDList;
+ std::list m_lEggsRemainingList;
+
+ uint32 m_uiBombTimer;
+ uint32 m_uiBombSequenzeTimer;
+ uint32 m_uiBombPhase;
+ uint32 m_uiBombCounter;
+
+ uint32 enrage_timer;
+ uint32 hatchertime;
+ uint32 eggs;
+ uint32 wipetimer;
+
+ bool m_bIsBombing;
+ bool m_bCanBlowUpBombs;
+ bool m_bIsEggRemaining;
+ bool enraged;
+ bool enragetime;
+
+ uint64 m_uiHatcher1GUID;
+ uint64 m_uiHatcher2GUID;
+
+ void Reset()
+ {
+ m_lBombsGUIDList.clear();
+ m_lEggsRemainingList.clear();
+
+ if (Creature* pHatcher = m_creature->GetMap()->GetCreature(m_uiHatcher1GUID))
+ {
+ pHatcher->AI()->EnterEvadeMode();
+ pHatcher->SetDeathState(JUST_DIED);
+ m_uiHatcher1GUID = 0;
+ }
+
+ if (Creature* pHatcher = m_creature->GetMap()->GetCreature(m_uiHatcher2GUID))
+ {
+ pHatcher->AI()->EnterEvadeMode();
+ pHatcher->SetDeathState(JUST_DIED);
+ m_uiHatcher2GUID = 0;
+ }
+
+ fire_breath_timer = 8000;
+
+ m_uiBombTimer = 30000;
+ m_bIsBombing = false;
+ m_uiBombSequenzeTimer = 1500;
+ m_uiBombPhase = 0;
+ m_uiBombCounter = 0;
+ m_bCanBlowUpBombs = false;
+ m_bIsEggRemaining = true;
+
+ enrage_timer = MINUTE*5*IN_MILLISECONDS;
+ hatchertime = 10000;
+ wipetimer = MINUTE*10*IN_MILLISECONDS;
+ enraged = false;
+ enragetime = false;
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_JANALAI, NOT_STARTED);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_JANALAI, DONE);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY_1 : SAY_SLAY_2, m_creature);
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_JANALAI, IN_PROGRESS);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ switch(pSummoned->GetEntry())
+ {
+ case NPC_AMANI_HATCHER_1:
+ m_uiHatcher1GUID = pSummoned->GetGUID();
+ break;
+ case NPC_AMANI_HATCHER_2:
+ m_uiHatcher2GUID = pSummoned->GetGUID();
+ break;
+ case NPC_FIRE_BOMB:
+ if (m_bIsBombing)
+ {
+ //store bombs in list to be used in BlowUpBombs()
+ m_lBombsGUIDList.push_back(pSummoned->GetGUID());
+
+ if (pSummoned->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
+ pSummoned->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ //visual spell, spell hit pSummoned after a short time
+ m_creature->CastSpell(pSummoned,SPELL_FIRE_BOMB_THROW,true);
+ }
+ else
+ {
+ pSummoned->CastSpell(pSummoned, SPELL_FIRE_WALL, true);
+ }
+ break;
+ }
+ }
+
+ void SpellHitTarget(Unit* pUnit, const SpellEntry* pSpell)
+ {
+ //when spell actually hit the fire bombs, make then cast spell(making them "visible")
+ if (pUnit->GetEntry() == NPC_FIRE_BOMB && pSpell->Id == SPELL_FIRE_BOMB_THROW)
+ pUnit->CastSpell(pUnit,SPELL_FIRE_BOMB_DUMMY,false);
+ }
+
+ void CreateFireWall() // Create Firewall
+ {
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[0][0],FireWallCoords[0][1],FireWallCoords[0][2],FireWallCoords[0][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[0][0],FireWallCoords[0][1]+5,FireWallCoords[0][2],FireWallCoords[0][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[0][0],FireWallCoords[0][1]-5,FireWallCoords[0][2],FireWallCoords[0][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[1][0]-2,FireWallCoords[1][1]-2,FireWallCoords[1][2],FireWallCoords[1][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[1][0]+2,FireWallCoords[1][1]+2,FireWallCoords[1][2],FireWallCoords[1][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[2][0],FireWallCoords[2][1],FireWallCoords[2][2],FireWallCoords[2][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[2][0],FireWallCoords[2][1]-5,FireWallCoords[2][2],FireWallCoords[2][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[2][0],FireWallCoords[2][1]+5,FireWallCoords[2][2],FireWallCoords[2][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[3][0]-2,FireWallCoords[3][1],FireWallCoords[3][2],FireWallCoords[3][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+
+ m_creature->SummonCreature(NPC_FIRE_BOMB,FireWallCoords[3][0]+2,FireWallCoords[3][1],FireWallCoords[3][2],FireWallCoords[3][3],TEMPSUMMON_TIMED_DESPAWN,11500);
+ }
+
+ void Throw5Bombs()
+ {
+ //all available spells (each spell has different radius for summon location)
+ uint8 uiMaxBombs = sizeof(m_auiSpellFireBombSummon)/sizeof(uint32);
+
+ //float fX, fY, fZ;
+ //float fRadius = 5.0f;
+
+ for(uint8 i = 0; i < uiMaxBombs; ++i)
+ {
+ m_creature->CastSpell(m_creature, m_auiSpellFireBombSummon[i], true);
+
+ //workaround part
+ //m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), fRadius+(fRadius*i), fX, fY, fZ);
+ //m_creature->SummonCreature(NPC_FIRE_BOMB, fX, fY, fZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN, MINUTE*IN_MILLISECONDS);
+ }
+
+ ++m_uiBombCounter;
+ }
+
+ //Teleport every player into the middle if more than 20 yards away (possibly what spell 43096 should do)
+ void TeleportPlayersOutOfRange()
+ {
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pTemp = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ if (pTemp && pTemp->GetTypeId() == TYPEID_PLAYER && !m_creature->IsWithinDist(pTemp, 20.0f))
+ m_creature->CastSpell(pTemp, SPELL_SUMMONALL, true);
+ }
+ }
+
+ void BlowUpBombs()
+ {
+ if (m_lBombsGUIDList.empty())
+ return;
+
+ for(std::list::iterator itr = m_lBombsGUIDList.begin(); itr != m_lBombsGUIDList.end(); ++itr)
+ {
+ if (Creature* pBomb = m_creature->GetMap()->GetCreature(*itr))
+ {
+ //do damage and then remove aura (making them "disappear")
+ pBomb->CastSpell(pBomb, SPELL_FIRE_BOMB_DAMAGE, false, NULL, NULL, m_creature->GetGUID());
+ pBomb->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_DUMMY);
+ }
+ }
+
+ m_lBombsGUIDList.clear();
+ }
+
+ void DoHatchRemainingEggs()
+ {
+ GetCreatureListWithEntryInGrid(m_lEggsRemainingList, m_creature, NPC_EGG, 125.0f);
+
+ if (!m_lEggsRemainingList.empty())
+ {
+ for(std::list::iterator itr = m_lEggsRemainingList.begin(); itr != m_lEggsRemainingList.end(); ++itr)
+ {
+ if ((*itr)->isAlive())
+ (*itr)->CastSpell((*itr), SPELL_SUMMON_DRAGONHAWK, true);
+ }
+
+ m_bIsEggRemaining = false;
+
+ if (!m_pInstance)
+ return;
+
+ if (uint32 uiEggsRemaining_Right = m_pInstance->GetData(DATA_J_EGGS_RIGHT))
+ {
+ for(uint32 i = 0; i < uiEggsRemaining_Right; ++i)
+ m_pInstance->SetData(DATA_J_EGGS_RIGHT, SPECIAL);
+ }
+
+ if (uint32 uiEggsRemaining_Left = m_pInstance->GetData(DATA_J_EGGS_LEFT))
+ {
+ for(uint32 i = 0; i < uiEggsRemaining_Left; ++i)
+ m_pInstance->SetData(DATA_J_EGGS_LEFT, SPECIAL);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //blow up bombs happen after bombing is over, so handle this here
+ if (m_bCanBlowUpBombs)
+ {
+ if (m_uiBombSequenzeTimer < diff)
+ {
+ BlowUpBombs();
+ m_bCanBlowUpBombs = false;
+ }else m_uiBombSequenzeTimer -= diff;
+ }
+
+ if (!m_bIsBombing) // every Spell if NOT Bombing
+ {
+ if (m_uiBombTimer < diff)
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoScriptText(SAY_FIRE_BOMBS, m_creature);
+
+ //first clear movement
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
+ m_creature->GetMotionMaster()->MovementExpired();
+
+ //then teleport self
+ DoCastSpellIfCan(m_creature, SPELL_TELETOCENTER, CAST_TRIGGERED);
+
+ //then players and create the firewall
+ TeleportPlayersOutOfRange();
+ CreateFireWall();
+
+ //prepare variables for bombing sequenze
+ m_lBombsGUIDList.clear();
+
+ m_uiBombPhase = 0;
+ m_uiBombSequenzeTimer = 500;
+ m_uiBombCounter = 0;
+
+ m_uiBombTimer = urand(20000, 40000);
+ m_bIsBombing = true;
+
+ //we don't want anything else to happen this Update()
+ return;
+ }else m_uiBombTimer -=diff;
+
+ //FIRE BREATH several videos says every 8Secounds
+ if (fire_breath_timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_FLAME_BREATH);
+ fire_breath_timer = 8000;
+ }else fire_breath_timer -=diff;
+
+ //enrage if under 25% hp before 5 min.
+ if (m_creature->GetHealthPercent() < 25.0f && !enraged)
+ {
+ enragetime = true;
+ enrage_timer = 600000;
+ }
+
+ //Enrage but only if not bombing
+ if (enragetime && !enraged)
+ {
+ DoScriptText(SAY_BERSERK, m_creature);
+
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(m_creature,SPELL_ENRAGE);
+ enraged = true;
+ }
+
+ //Hatch All
+ if (m_bIsEggRemaining && m_creature->GetHealthPercent() < 35.0f)
+ {
+ DoScriptText(SAY_ALL_EGGS, m_creature);
+
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoCastSpellIfCan(m_creature, SPELL_HATCH_ALL_EGGS);
+
+ DoHatchRemainingEggs();
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ else // every Spell if Bombing
+ {
+ if (m_uiBombSequenzeTimer < diff)
+ {
+ switch(m_uiBombPhase)
+ {
+ case 0:
+ m_creature->CastSpell(m_creature,SPELL_FIRE_BOMB_CHANNEL,true);
+ m_uiBombSequenzeTimer = 500;
+ ++m_uiBombPhase;
+ break;
+ case 1:
+ if (m_uiBombCounter < 8)
+ {
+ Throw5Bombs();
+ m_uiBombSequenzeTimer = 500;
+ }
+ else
+ {
+ m_uiBombSequenzeTimer = 1000;
+ ++m_uiBombPhase;
+ }
+ break;
+ case 2:
+ m_bCanBlowUpBombs = true;
+ m_uiBombSequenzeTimer = 2000;
+ m_creature->RemoveAurasDueToSpell(SPELL_FIRE_BOMB_CHANNEL);
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ m_bIsBombing = false;
+ break;
+ }
+
+ }else m_uiBombSequenzeTimer -= diff;
+ }
+
+ //Enrage after 5 minutes
+ if (enrage_timer < diff)
+ {
+ enragetime = true;
+ enrage_timer = 600000;
+ }else enrage_timer -=diff;
+
+ //Call Hatcher
+ if (m_bIsEggRemaining)
+ {
+ if (hatchertime < diff)
+ {
+ if (!m_pInstance || (m_pInstance->GetData(DATA_J_EGGS_LEFT) == 0 && m_pInstance->GetData(DATA_J_EGGS_RIGHT) == 0))
+ m_bIsEggRemaining = false;
+ else
+ {
+ DoScriptText(SAY_SUMMON_HATCHER, m_creature);
+
+ Creature* pHatcer1 = m_creature->GetMap()->GetCreature(m_uiHatcher1GUID);
+ Creature* pHatcer2 = m_creature->GetMap()->GetCreature(m_uiHatcher2GUID);
+
+ if (!pHatcer1 || (pHatcer1 && !pHatcer1->isAlive()))
+ {
+ if (Creature* pHatcher = m_creature->SummonCreature(NPC_AMANI_HATCHER_1, m_aHatcherRight[0].m_fX, m_aHatcherRight[0].m_fY, m_aHatcherRight[0].m_fZ, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ pHatcher->GetMotionMaster()->MovePoint(1, m_aHatcherRight[1].m_fX, m_aHatcherRight[1].m_fY, m_aHatcherRight[1].m_fZ);
+ }
+
+ if (!pHatcer2 || (pHatcer2 && !pHatcer2->isAlive()))
+ {
+ if (Creature* pHatcher = m_creature->SummonCreature(NPC_AMANI_HATCHER_2, m_aHatcherLeft[0].m_fX, m_aHatcherLeft[0].m_fY, m_aHatcherLeft[0].m_fZ, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ pHatcher->GetMotionMaster()->MovePoint(1, m_aHatcherLeft[1].m_fX, m_aHatcherLeft[1].m_fY, m_aHatcherLeft[1].m_fZ);
+ }
+
+ hatchertime = 90000;
+ }
+
+ }else hatchertime -=diff;
+ }
+
+ //WIPE after 10 minutes
+ if (wipetimer < diff)
+ {
+ if (DoCastSpellIfCan(m_creature,SPELL_ENRAGE) == CAST_OK)
+ {
+ DoScriptText(SAY_BERSERK, m_creature);
+ wipetimer = 30000;
+ }
+ }else wipetimer -=diff;
+
+ //check for reset ... exploit preventing ... pulled from his podest
+ EnterEvadeIfOutOfCombatArea(diff);
+ }
+};
+
+CreatureAI* GetAI_boss_janalaiAI(Creature* pCreature)
+{
+ return new boss_janalaiAI(pCreature);
+}
+
+struct MANGOS_DLL_DECL mob_jandalai_firebombAI : public ScriptedAI
+{
+ mob_jandalai_firebombAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset() {}
+
+ void AttackStart(Unit* who) {}
+
+ void MoveInLineOfSight(Unit* who) {}
+
+ void UpdateAI(const uint32 diff) {}
+};
+
+CreatureAI* GetAI_mob_jandalai_firebombAI(Creature* pCreature)
+{
+ return new mob_jandalai_firebombAI(pCreature);
+}
+
+struct MANGOS_DLL_DECL mob_amanishi_hatcherAI : public ScriptedAI
+{
+ mob_amanishi_hatcherAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiWaypoint;
+ uint32 m_uiHatchlingTimer;
+ uint32 m_uiHatchlingCount;
+ bool m_bCanMoveNext;
+ bool m_bWaypointEnd;
+
+ void Reset()
+ {
+ m_uiWaypoint = 0;
+ m_uiHatchlingTimer = 1000;
+ m_uiHatchlingCount = 1;
+ m_bCanMoveNext = false;
+ m_bWaypointEnd = false;
+
+ if (m_creature->HasSplineFlag(SPLINEFLAG_WALKMODE))
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ }
+
+ void MoveInLineOfSight(Unit* pWho) {}
+
+ void AttackStart(Unit* pWho)
+ {
+ if (!pWho)
+ return;
+
+ if (m_creature->Attack(pWho, false))
+ {
+ m_creature->AddThreat(pWho);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+ }
+ }
+
+ void MovementInform(uint32 uiType, uint32 uiPointId)
+ {
+ if (uiType != POINT_MOTION_TYPE || m_bWaypointEnd)
+ return;
+
+ uint32 uiCount = (m_creature->GetEntry() == NPC_AMANI_HATCHER_1) ?
+ (sizeof(m_aHatcherRight)/sizeof(WaypointDef)) : (sizeof(m_aHatcherLeft)/sizeof(WaypointDef));
+
+ m_uiWaypoint = uiPointId+1;
+
+ if (uiCount == m_uiWaypoint)
+ m_bWaypointEnd = true;
+
+ m_bCanMoveNext = true;
+ }
+
+ void DoHatchEggs(uint32 uiCount)
+ {
+ uint32 uiSaveRightOrLeft = m_creature->GetEntry() == NPC_AMANI_HATCHER_1 ? DATA_J_EGGS_RIGHT : DATA_J_EGGS_LEFT;
+
+ for(uint32 i = 0; i < uiCount; ++i)
+ {
+ if (Creature* pEgg = GetClosestCreatureWithEntry(m_creature, NPC_EGG, 40.0f))
+ pEgg->CastSpell(pEgg, SPELL_SUMMON_DRAGONHAWK, true);
+
+ m_pInstance->SetData(uiSaveRightOrLeft, SPECIAL);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_bCanMoveNext)
+ {
+ m_bCanMoveNext = false;
+
+ if (m_bWaypointEnd)
+ m_creature->GetMotionMaster()->Clear();
+ else
+ {
+ if (m_creature->GetEntry() == NPC_AMANI_HATCHER_1)
+ m_creature->GetMotionMaster()->MovePoint(m_uiWaypoint, m_aHatcherRight[m_uiWaypoint].m_fX, m_aHatcherRight[m_uiWaypoint].m_fY, m_aHatcherRight[m_uiWaypoint].m_fZ);
+ else
+ m_creature->GetMotionMaster()->MovePoint(m_uiWaypoint, m_aHatcherLeft[m_uiWaypoint].m_fX, m_aHatcherLeft[m_uiWaypoint].m_fY, m_aHatcherLeft[m_uiWaypoint].m_fZ);
+ }
+ }
+
+ if (m_bWaypointEnd)
+ {
+ if (m_uiHatchlingTimer < uiDiff)
+ {
+ m_uiHatchlingTimer = 10000;
+
+ if (!m_pInstance)
+ return;
+
+ uint32 uiEggsRemaining = m_creature->GetEntry() == NPC_AMANI_HATCHER_1 ? m_pInstance->GetData(DATA_J_EGGS_RIGHT) : m_pInstance->GetData(DATA_J_EGGS_LEFT);
+
+ if (!uiEggsRemaining)
+ {
+ //instead, should run to other side and start hatch if eggs remain
+ m_creature->ForcedDespawn();
+ return;
+ }
+ else if (m_uiHatchlingCount == uiEggsRemaining/2)
+ m_uiHatchlingCount = uiEggsRemaining;
+
+ DoCastSpellIfCan(m_creature,SPELL_HATCH_EGG);
+
+ DoHatchEggs(m_uiHatchlingCount);
+
+ ++m_uiHatchlingCount;
+
+ }else m_uiHatchlingTimer -= uiDiff;
+ }
+ }
+};
+
+CreatureAI* GetAI_mob_amanishi_hatcherAI(Creature* pCreature)
+{
+ return new mob_amanishi_hatcherAI(pCreature);
+}
+
+struct MANGOS_DLL_DECL mob_hatchlingAI : public ScriptedAI
+{
+ mob_hatchlingAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 buffer_timer;
+ bool start;
+
+ void Reset()
+ {
+ buffer_timer = 7000;
+ start = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!start)
+ {
+ if (m_creature->GetPositionY() > 1150)
+ m_creature->GetMotionMaster()->MovePoint(0, hatcherway_l[3][0]+rand()%4-2,hatcherway_l[3][1]+rand()%4-2,hatcherway_l[3][2]);
+ else
+ m_creature->GetMotionMaster()->MovePoint(0,hatcherway_r[3][0]+rand()%4-2,hatcherway_r[3][1]+rand()%4-2,hatcherway_r[3][2]);
+ start = true;
+ }
+
+ if (m_pInstance && m_pInstance->GetData(TYPE_JANALAI) == NOT_STARTED)
+ {
+ m_creature->ForcedDespawn();
+ return;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (buffer_timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_FLAMEBUFFED);
+
+ buffer_timer = 7000;
+ }else buffer_timer -=diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_hatchlingAI(Creature* pCreature)
+{
+ return new mob_hatchlingAI(pCreature);
+}
+
+void AddSC_boss_janalai()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_janalai";
+ newscript->GetAI = &GetAI_boss_janalaiAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_jandalai_firebomb";
+ newscript->GetAI = &GetAI_mob_jandalai_firebombAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_amanishi_hatcher";
+ newscript->GetAI = &GetAI_mob_amanishi_hatcherAI;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_hatchling";
+ newscript->GetAI = &GetAI_mob_hatchlingAI;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/boss_malacrass.cpp b/scripts/eastern_kingdoms/zulaman/boss_malacrass.cpp
new file mode 100644
index 0000000..34df95b
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/boss_malacrass.cpp
@@ -0,0 +1,867 @@
+/* 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_Malacrass
+SD%Complete: 10
+SDComment: Contain adds and adds selection
+SDCategory: Zul'Aman
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulaman.h"
+
+enum
+{
+ SAY_AGGRO = -1568045,
+ SAY_ENRAGE = -1568046,
+ SAY_KILL1 = -1568047,
+ SAY_KILL2 = -1568048,
+ SAY_SOUL_SIPHON = -1568049,
+ SAY_DRAIN_POWER = -1568050,
+ SAY_SPIRIT_BOLTS = -1568051,
+ SAY_ADD_DIED1 = -1568052,
+ SAY_ADD_DIED2 = -1568053,
+ SAY_ADD_DIED3 = -1568054,
+ SAY_DEATH = -1568055,
+
+ SPELL_SPIRIT_BOLTS = 43383,
+ SPELL_SIPHON_SOUL = 43501,
+ SPELL_DRAIN_POWER = 44131,
+
+ //for various powers he uses after using soul drain
+ //Death Knight
+ SPELL_DK_DEATH_AND_DECAY = 61603,
+ SPELL_DK_PLAGUE_STRIKE = 61606,
+ SPELL_DK_MARK_OF_BLOOD = 61600,
+
+ //Druid
+ SPELL_DR_THORNS = 43420,
+ SPELL_DR_LIFEBLOOM = 43421,
+ SPELL_DR_MOONFIRE = 43545,
+
+ //Hunter
+ SPELL_HU_EXPLOSIVE_TRAP = 43444,
+ SPELL_HU_FREEZING_TRAP = 43447,
+ SPELL_HU_SNAKE_TRAP = 43449,
+
+ //Mage
+ SPELL_MG_FIREBALL = 41383,
+ SPELL_MG_FROST_NOVA = 43426,
+ SPELL_MG_ICE_LANCE = 43427,
+ SPELL_MG_FROSTBOLT = 43428,
+
+ //Paladin
+ SPELL_PA_CONSECRATION = 43429,
+ SPELL_PA_AVENGING_WRATH = 43430,
+ SPELL_PA_HOLY_LIGHT = 43451,
+
+ //Priest
+ SPELL_PR_HEAL = 41372,
+ SPELL_PR_MIND_BLAST = 41374,
+ SPELL_PR_SW_DEATH = 41375,
+ SPELL_PR_PSYCHIC_SCREAM = 43432,
+ SPELL_PR_MIND_CONTROL = 43550,
+ SPELL_PR_PAIN_SUPP = 44416,
+
+ //Rogue
+ SPELL_RO_WOUND_POISON = 39665,
+ SPELL_RO_BLIND = 43433,
+ SPELL_RO_SLICE_DICE = 43457,
+
+ //Shaman
+ SPELL_SH_CHAIN_LIGHT = 43435,
+ SPELL_SH_FIRE_NOVA = 43436,
+ SPELL_SH_HEALING_WAVE = 43548,
+
+ //Warlock
+ SPELL_WL_CURSE_OF_DOOM = 43439,
+ SPELL_WL_RAIN_OF_FIRE = 43440,
+ SPELL_WL_UNSTABLE_AFFL = 35183,
+
+ //Warrior
+ SPELL_WR_MORTAL_STRIKE = 43441,
+ SPELL_WR_WHIRLWIND = 43442,
+ SPELL_WR_SPELL_REFLECT = 43443,
+
+ //misc
+ //WEAPON_ID = 33494, //weapon equip id, must be set by database.
+ MAX_ACTIVE_ADDS = 4
+};
+
+//Adds X positions
+static float m_afAddPosX[4] = {128.279f, 123.261f, 112.084f, 106.473f};
+
+const float ADD_POS_Y = 921.279f;
+const float ADD_POS_Z = 33.889f;
+const float ADD_ORIENT = 1.527f;
+
+struct SpawnGroup
+{
+ uint32 m_uiCreatureEntry;
+ uint32 m_uiCreatureEntryAlt;
+};
+
+SpawnGroup m_auiSpawnEntry[] =
+{
+ {24240, 24241}, //Alyson Antille / Thurg
+ {24242, 24243}, //Slither / Lord Raadan
+ {24244, 24245}, //Gazakroth / Fenstalker
+ {24246, 24247}, //Darkheart / Koragg
+};
+
+struct MANGOS_DLL_DECL boss_malacrassAI : public ScriptedAI
+{
+ boss_malacrassAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ memset(&m_auiAddGUIDs, 0, sizeof(m_auiAddGUIDs));
+ m_lAddsEntryList.clear();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ std::list m_lAddsEntryList;
+ uint64 m_auiAddGUIDs[MAX_ACTIVE_ADDS];
+
+ void Reset()
+ {
+ InitializeAdds();
+
+ if (!m_pInstance)
+ return;
+
+ m_pInstance->SetData(TYPE_MALACRASS, NOT_STARTED);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_MALACRASS, FAIL);
+
+ for(uint8 i = 0; i < MAX_ACTIVE_ADDS; ++i)
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiAddGUIDs[i]))
+ pAdd->AI()->EnterEvadeMode();
+ }
+ }
+
+ void InitializeAdds()
+ {
+ //not if m_creature are dead, so avoid
+ if (!m_creature->isAlive())
+ return;
+
+ uint8 j = 0;
+
+ //it's empty, so first time
+ if (m_lAddsEntryList.empty())
+ {
+ //fill list with entries from creature array
+ for(uint8 i = 0; i < MAX_ACTIVE_ADDS; ++i)
+ m_lAddsEntryList.push_back(rand()%2 ? m_auiSpawnEntry[i].m_uiCreatureEntry : m_auiSpawnEntry[i].m_uiCreatureEntryAlt);
+
+ //summon mobs from the list
+ for(std::list::iterator itr = m_lAddsEntryList.begin(); itr != m_lAddsEntryList.end(); ++itr)
+ {
+ if (Creature* pAdd = m_creature->SummonCreature((*itr), m_afAddPosX[j], ADD_POS_Y, ADD_POS_Z, ADD_ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ m_auiAddGUIDs[j] = pAdd->GetGUID();
+
+ ++j;
+ }
+ }
+ else
+ {
+ for(std::list::iterator itr = m_lAddsEntryList.begin(); itr != m_lAddsEntryList.end(); ++itr)
+ {
+ Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiAddGUIDs[j]);
+
+ //object already removed, not exist
+ if (!pAdd)
+ {
+ if (pAdd = m_creature->SummonCreature((*itr), m_afAddPosX[j], ADD_POS_Y, ADD_POS_Z, ADD_ORIENT, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ m_auiAddGUIDs[j] = pAdd->GetGUID();
+ }
+ ++j;
+ }
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+
+ DoScriptText(SAY_AGGRO, m_creature);
+ AddsAttack(pWho);
+
+ if (!m_pInstance)
+ return;
+
+ m_pInstance->SetData(TYPE_MALACRASS, IN_PROGRESS);
+ }
+
+ void AddsAttack(Unit* pWho)
+ {
+ for(uint8 i = 0; i < MAX_ACTIVE_ADDS; ++i)
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiAddGUIDs[i]))
+ {
+ if (!pAdd->getVictim())
+ pAdd->AI()->AttackStart(pWho);
+ }
+ }
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (pVictim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ DoScriptText(urand(0, 1) ? SAY_KILL1 : SAY_KILL2, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ CleanAdds();
+
+ if (!m_pInstance)
+ return;
+
+ m_pInstance->SetData(TYPE_MALACRASS, DONE);
+ }
+
+ void CleanAdds()
+ {
+ for(uint8 i = 0; i < MAX_ACTIVE_ADDS; ++i)
+ {
+ if (Creature* pAdd = m_creature->GetMap()->GetCreature(m_auiAddGUIDs[i]))
+ {
+ pAdd->AI()->EnterEvadeMode();
+ pAdd->SetDeathState(JUST_DIED);
+ }
+ }
+
+ memset(&m_auiAddGUIDs, 0, sizeof(m_auiAddGUIDs));
+ m_lAddsEntryList.clear();
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_malacrass(Creature* pCreature)
+{
+ return new boss_malacrassAI(pCreature);
+}
+
+//common AI for adds
+struct MANGOS_DLL_DECL boss_malacrass_addAI : public ScriptedAI
+{
+ boss_malacrass_addAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset() { }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void MoveInLineOfSight(Unit* pWho)
+ {
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pMalacrass = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_MALACRASS)))
+ pMalacrass->AI()->KilledUnit(pVictim);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pMalacrass = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_MALACRASS)))
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_ADD_DIED1, pMalacrass); break;
+ case 1: DoScriptText(SAY_ADD_DIED2, pMalacrass); break;
+ case 2: DoScriptText(SAY_ADD_DIED3, pMalacrass); break;
+ }
+ }
+ }
+
+ bool IsEnemyPlayerInRangeForSpell(uint32 uiSpellId)
+ {
+ SpellEntry const* pSpell = GetSpellStore()->LookupEntry(uiSpellId);
+
+ //if spell not valid
+ if (!pSpell)
+ return false;
+
+ //spell known, so lookup using rangeIndex
+ SpellRangeEntry const* pSpellRange = GetSpellRangeStore()->LookupEntry(pSpell->rangeIndex);
+
+ //not valid, so return
+ if (!pSpellRange)
+ return false;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator iter = tList.begin();iter != tList.end(); ++iter)
+ {
+ Unit* pTarget = m_creature->GetMap()->GetUnit((*iter)->getUnitGuid());
+
+ if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER)
+ {
+ //if target further away than maxrange or closer than minrange, statement is false
+ if (m_creature->IsInRange(pTarget, pSpellRange->minRange, pSpellRange->maxRange))
+ return true;
+ }
+ }
+
+ return false;
+ }
+};
+
+enum
+{
+ SPELL_BLOODLUST = 43578,
+ SPELL_CLEAVE = 15496
+};
+
+struct MANGOS_DLL_DECL mob_thurgAI : public boss_malacrass_addAI
+{
+ mob_thurgAI(Creature* pCreature) : boss_malacrass_addAI(pCreature) { Reset(); }
+
+ uint32 m_uiBloodlustTimer;
+ uint32 m_uiCleaveTimer;
+
+ void Reset()
+ {
+ m_uiBloodlustTimer = 15000;
+ m_uiCleaveTimer = 10000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiBloodlustTimer < uiDiff)
+ {
+ std::list lTempList = DoFindFriendlyMissingBuff(50.0f, SPELL_BLOODLUST);
+
+ if (!lTempList.empty())
+ {
+ Unit* pTarget = *(lTempList.begin());
+ DoCastSpellIfCan(pTarget, SPELL_BLOODLUST);
+ }
+
+ m_uiBloodlustTimer = 12000;
+ }
+ else
+ m_uiBloodlustTimer -= uiDiff;
+
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleaveTimer = 12000;
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_thurg(Creature* pCreature)
+{
+ return new mob_thurgAI(pCreature);
+}
+
+enum
+{
+ SPELL_ARCANE_TORRENT = 33390,
+ SPELL_FLASH_HEAL = 43575,
+ SPELL_DISPEL_MAGIC = 43577
+};
+
+const float RANGE_FRIENDLY_TARGET = 40.0;
+
+struct MANGOS_DLL_DECL mob_alyson_antilleAI : public boss_malacrass_addAI
+{
+ mob_alyson_antilleAI(Creature* pCreature) : boss_malacrass_addAI(pCreature) { Reset(); }
+
+ uint32 m_uiArcaneTorrentTimer;
+ uint32 m_uiFlashHealTimer;
+ uint32 m_uiDispelMagicTimer;
+
+ void Reset()
+ {
+ m_uiArcaneTorrentTimer = 0;
+ m_uiFlashHealTimer = 2500;
+ m_uiDispelMagicTimer = 10000;
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (!pWho)
+ return;
+
+ if (m_creature->Attack(pWho, false))
+ {
+ m_creature->AddThreat(pWho);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ m_creature->GetMotionMaster()->MoveChase(pWho, 20.0f);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiArcaneTorrentTimer < uiDiff)
+ {
+ if (IsEnemyPlayerInRangeForSpell(SPELL_ARCANE_TORRENT))
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ARCANE_TORRENT);
+ m_uiArcaneTorrentTimer = 60000;
+ }
+ else
+ m_uiArcaneTorrentTimer = 1000;
+ }
+ else
+ m_uiArcaneTorrentTimer -= uiDiff;
+
+ if (m_uiFlashHealTimer < uiDiff)
+ {
+ //this will fail if we previously was following target and pTarget is now different than before
+ if (Unit* pTarget = DoSelectLowestHpFriendly(RANGE_FRIENDLY_TARGET*2, 30000))
+ {
+ if (pTarget->IsWithinDistInMap(m_creature, RANGE_FRIENDLY_TARGET))
+ {
+ DoCastSpellIfCan(pTarget, SPELL_FLASH_HEAL);
+
+ //if not already chasing, start chase
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), 20.0f);
+ }
+ else
+ {
+ //if chasing, start follow target instead
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
+ {
+ m_creature->GetMotionMaster()->MovementExpired();
+ m_creature->GetMotionMaster()->MoveFollow(pTarget, 20.0f, 0.0f);
+ }
+ }
+ }
+
+ m_uiFlashHealTimer = 2500;
+ }
+ else
+ m_uiFlashHealTimer -= uiDiff;
+
+ if (m_uiDispelMagicTimer < uiDiff)
+ {
+ Unit* pTarget = NULL;
+ std::list lTempList = DoFindFriendlyCC(RANGE_FRIENDLY_TARGET);
+
+ if (!lTempList.empty())
+ pTarget = *(lTempList.begin());
+ else
+ pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+
+ if (pTarget)
+ DoCastSpellIfCan(pTarget, SPELL_DISPEL_MAGIC);
+
+ m_uiDispelMagicTimer = 12000;
+ }
+ else
+ m_uiDispelMagicTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_alyson_antille(Creature* pCreature)
+{
+ return new mob_alyson_antilleAI(pCreature);
+}
+
+enum
+{
+ SPELL_FIREBOLT = 43584
+};
+
+struct MANGOS_DLL_DECL mob_gazakrothAI : public boss_malacrass_addAI
+{
+ mob_gazakrothAI(Creature* pCreature) : boss_malacrass_addAI(pCreature){ Reset(); }
+
+ uint32 m_uiFireboltTimer;
+
+ void Reset()
+ {
+ m_uiFireboltTimer = 1000;
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (!pWho)
+ return;
+
+ if (m_creature->Attack(pWho, false))
+ {
+ m_creature->AddThreat(pWho);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ m_creature->GetMotionMaster()->MoveChase(pWho, 20.0f);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiFireboltTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FIREBOLT);
+ m_uiFireboltTimer = 1000;
+ }
+ else
+ m_uiFireboltTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_gazakroth(Creature* pCreature)
+{
+ return new mob_gazakrothAI(pCreature);
+}
+
+enum
+{
+ SPELL_FLAME_BREATH = 43582,
+ SPELL_THUNDERCLAP = 43583
+};
+
+struct MANGOS_DLL_DECL mob_lord_raadanAI : public boss_malacrass_addAI
+{
+ mob_lord_raadanAI(Creature* pCreature) : boss_malacrass_addAI(pCreature) { Reset(); }
+
+ uint32 m_uiFlameBreathTimer;
+ uint32 m_uiThunderclapTimer;
+
+ void Reset()
+ {
+ m_uiFlameBreathTimer = 8000;
+ m_uiThunderclapTimer = 13000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiThunderclapTimer < uiDiff)
+ {
+ if (IsEnemyPlayerInRangeForSpell(SPELL_THUNDERCLAP))
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_THUNDERCLAP);
+ m_uiThunderclapTimer = 12000;
+ }
+ else
+ m_uiThunderclapTimer = 1000;
+ }
+ else
+ m_uiThunderclapTimer -= uiDiff;
+
+ if (m_uiFlameBreathTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FLAME_BREATH);
+ m_uiFlameBreathTimer = 12000;
+ }
+ else
+ m_uiFlameBreathTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_lord_raadan(Creature* pCreature)
+{
+ return new mob_lord_raadanAI(pCreature);
+}
+
+enum
+{
+ SPELL_PSYCHIC_WAIL = 43590
+};
+
+struct MANGOS_DLL_DECL mob_darkheartAI : public boss_malacrass_addAI
+{
+ mob_darkheartAI(Creature* pCreature) : boss_malacrass_addAI(pCreature) { Reset(); }
+
+ uint32 m_uiPsychicWailTimer;
+
+ void Reset()
+ {
+ m_uiPsychicWailTimer = 8000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiPsychicWailTimer < uiDiff)
+ {
+ if (IsEnemyPlayerInRangeForSpell(SPELL_PSYCHIC_WAIL))
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_PSYCHIC_WAIL);
+ m_uiPsychicWailTimer = 12000;
+ }
+ else
+ m_uiPsychicWailTimer = 1000;
+ }
+ else
+ m_uiPsychicWailTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_darkheart(Creature* pCreature)
+{
+ return new mob_darkheartAI(pCreature);
+}
+
+enum
+{
+ SPELL_VENOM_SPIT = 43579
+};
+
+struct MANGOS_DLL_DECL mob_slitherAI : public boss_malacrass_addAI
+{
+ mob_slitherAI(Creature* pCreature) : boss_malacrass_addAI(pCreature) { Reset(); }
+
+ uint32 m_uiVenomSpitTimer;
+
+ void Reset()
+ {
+ m_uiVenomSpitTimer = 4000;
+ }
+
+ void AttackStart(Unit* pWho)
+ {
+ if (!pWho)
+ return;
+
+ if (m_creature->Attack(pWho, false))
+ {
+ m_creature->AddThreat(pWho);
+ m_creature->SetInCombatWith(pWho);
+ pWho->SetInCombatWith(m_creature);
+
+ m_creature->GetMotionMaster()->MoveChase(pWho, 20.0f);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiVenomSpitTimer < uiDiff)
+ {
+ if (Unit* pVictim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pVictim, SPELL_VENOM_SPIT);
+
+ m_uiVenomSpitTimer = 2500;
+ }
+ else
+ m_uiVenomSpitTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_slither(Creature* pCreature)
+{
+ return new mob_slitherAI(pCreature);
+}
+
+enum
+{
+ SPELL_VOLATILE_INFECTION = 43586
+};
+
+struct MANGOS_DLL_DECL mob_fenstalkerAI : public boss_malacrass_addAI
+{
+ mob_fenstalkerAI(Creature* pCreature) : boss_malacrass_addAI(pCreature) { Reset(); }
+
+ uint32 m_uiVolatileInfectionTimer;
+
+ void Reset()
+ {
+ m_uiVolatileInfectionTimer = 15000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiVolatileInfectionTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_VOLATILE_INFECTION);
+ m_uiVolatileInfectionTimer = 12000;
+ }
+ else
+ m_uiVolatileInfectionTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_fenstalker(Creature* pCreature)
+{
+ return new mob_fenstalkerAI(pCreature);
+}
+
+enum
+{
+ SPELL_COLD_STARE = 43593,
+ SPELL_MIGHTY_BLOW = 43592,
+};
+
+struct MANGOS_DLL_DECL mob_koraggAI : public boss_malacrass_addAI
+{
+ mob_koraggAI(Creature* pCreature) : boss_malacrass_addAI(pCreature) { Reset(); }
+
+ uint32 m_uiColdStareTimer;
+ uint32 m_uiMightyBlowTimer;
+
+ void Reset()
+ {
+ m_uiColdStareTimer = 15000;
+ m_uiMightyBlowTimer = 10000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiMightyBlowTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIGHTY_BLOW);
+ m_uiMightyBlowTimer = 12000;
+ }
+ else
+ m_uiMightyBlowTimer -= uiDiff;
+
+ if (m_uiColdStareTimer < uiDiff)
+ {
+ if (Unit* pVictim = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pVictim, SPELL_COLD_STARE);
+
+ m_uiColdStareTimer = 12000;
+ }
+ else
+ m_uiColdStareTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_koragg(Creature* pCreature)
+{
+ return new mob_koraggAI(pCreature);
+}
+
+void AddSC_boss_malacrass()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_malacrass";
+ newscript->GetAI = &GetAI_boss_malacrass;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_thurg";
+ newscript->GetAI = &GetAI_mob_thurg;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_gazakroth";
+ newscript->GetAI = &GetAI_mob_gazakroth;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_lord_raadan";
+ newscript->GetAI = &GetAI_mob_lord_raadan;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_darkheart";
+ newscript->GetAI = &GetAI_mob_darkheart;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_slither";
+ newscript->GetAI = &GetAI_mob_slither;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_fenstalker";
+ newscript->GetAI = &GetAI_mob_fenstalker;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_koragg";
+ newscript->GetAI = &GetAI_mob_koragg;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_alyson_antille";
+ newscript->GetAI = &GetAI_mob_alyson_antille;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp b/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp
new file mode 100644
index 0000000..a427834
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp
@@ -0,0 +1,257 @@
+/* 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_Nalorakk
+SD%Complete: 80
+SDComment: Todo: Trash Waves
+SDCategory: Zul'Aman
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulaman.h"
+
+enum
+{
+ SAY_WAVE1_AGGRO = -1568010,
+ SAY_WAVE2_STAIR1 = -1568011,
+ SAY_WAVE3_STAIR2 = -1568012,
+ SAY_WAVE4_PLATFORM = -1568013,
+
+ SAY_EVENT1_SACRIFICE = -1568014,
+ SAY_EVENT2_SACRIFICE = -1568015,
+
+ SAY_AGGRO = -1568016,
+ SAY_SURGE = -1568017,
+ SAY_TOBEAR = -1568018,
+ SAY_TOTROLL = -1568019,
+ SAY_BERSERK = -1568020,
+ SAY_SLAY1 = -1568021,
+ SAY_SLAY2 = -1568022,
+ SAY_DEATH = -1568023,
+
+ SPELL_BERSERK = 45078, //unsure, this increases damage, size and speed
+
+ //Defines for Troll form
+ SPELL_BRUTALSWIPE = 42384,
+ SPELL_MANGLE = 42389,
+ SPELL_SURGE = 42402,
+ SPELL_BEARFORM = 42377,
+
+ //Defines for Bear form
+ SPELL_LACERATINGSLASH = 42395,
+ SPELL_RENDFLESH = 42397,
+ SPELL_DEAFENINGROAR = 42398
+};
+
+struct MANGOS_DLL_DECL boss_nalorakkAI : public ScriptedAI
+{
+ boss_nalorakkAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 ChangeForm_Timer;
+ uint32 BrutalSwipe_Timer;
+ uint32 Mangle_Timer;
+ uint32 Surge_Timer;
+ uint32 LaceratingSlash_Timer;
+ uint32 RendFlesh_Timer;
+ uint32 DeafeningRoar_Timer;
+ uint32 ShapeShiftCheck_Timer;
+ uint32 Berserk_Timer;
+ bool inBearForm;
+ bool Berserking;
+ bool ChangedToBear;
+ bool ChangedToTroll;
+
+ void Reset()
+ {
+ ChangeForm_Timer = 45000;
+ BrutalSwipe_Timer = 12000;
+ Mangle_Timer = 15000;
+ Surge_Timer = 20000;
+ LaceratingSlash_Timer = 6000;
+ RendFlesh_Timer = 6000;
+ DeafeningRoar_Timer = 20000;
+ ShapeShiftCheck_Timer = 40000;
+ Berserk_Timer = 600000;
+ inBearForm = false;
+ Berserking = false;
+ ChangedToBear = false;
+ ChangedToTroll = true;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (!m_pInstance)
+ return;
+
+ m_pInstance->SetData(TYPE_NALORAKK, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Berserking
+ if ((Berserk_Timer < diff) && (!Berserking))
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_BERSERK) == CAST_OK)
+ {
+ DoScriptText(SAY_BERSERK, m_creature);
+ Berserking = true;
+ }
+ }else Berserk_Timer -= diff;
+
+ //Don't check if we're shapeshifted every UpdateAI
+ if (ShapeShiftCheck_Timer < diff)
+ {
+ //This will return true if we have bearform aura
+ inBearForm = m_creature->HasAura(SPELL_BEARFORM, EFFECT_INDEX_0);
+ ShapeShiftCheck_Timer = 1000;
+ }else ShapeShiftCheck_Timer -= diff;
+
+ //Spells for Troll Form (only to be casted if we NOT have bear phase aura)
+ if (!inBearForm)
+ {
+ //We just changed to troll form!
+ if (!ChangedToTroll)
+ {
+ DoScriptText(SAY_TOTROLL, m_creature);
+
+ ChangedToTroll = true;
+ ChangedToBear = false;
+ //Reset spell timers
+ LaceratingSlash_Timer = urand(6000, 25000);
+ RendFlesh_Timer = urand(6000, 25000);
+ DeafeningRoar_Timer = urand(15000, 25000);
+ ShapeShiftCheck_Timer = 40000;
+ }
+
+ //Brutal Swipe (some sources may say otherwise, but I've never seen this in Bear form)
+ if (BrutalSwipe_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_BRUTALSWIPE);
+ BrutalSwipe_Timer = urand(7000, 15000);
+ }else BrutalSwipe_Timer -= diff;
+
+ //Mangle
+ if (Mangle_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MANGLE);
+ Mangle_Timer = urand(3000, 15000);
+ }else Mangle_Timer -= diff;
+
+ //Surge
+ if (Surge_Timer < diff)
+ {
+ //select a random unit other than the main tank
+ Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1);
+
+ //if there aren't other units, cast on the tank
+ if (!target)
+ target = m_creature->getVictim();
+
+ if (DoCastSpellIfCan(target, SPELL_SURGE) == CAST_OK)
+ DoScriptText(SAY_SURGE, m_creature);
+
+ Surge_Timer = urand(15000, 32500);
+ }else Surge_Timer -= diff;
+
+ //Change to Bear Form if we're in Troll Form for 45sec
+ if (ChangeForm_Timer < diff)
+ {
+ m_creature->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
+ DoCastSpellIfCan(m_creature, SPELL_BEARFORM);
+ //And 30sec (bear form) + 45sec (troll form) before we should cast this again
+ ChangeForm_Timer = 75000;
+ }else ChangeForm_Timer -= diff;
+ }
+ //Spells for Bear Form (only to be casted if we have bear phase aura)
+ else
+ {
+ //We just changed to bear form!
+ if (!ChangedToBear)
+ {
+ DoScriptText(SAY_TOBEAR, m_creature);
+
+ ChangedToBear = true;
+ ChangedToTroll = false;
+ //Reset spell timers
+ Surge_Timer = urand(15000, 32000);
+ BrutalSwipe_Timer = urand(7000, 20000);
+ Mangle_Timer = urand(3000, 20000);
+ ShapeShiftCheck_Timer = 25000;
+ }
+
+ //Lacerating Slash
+ if (LaceratingSlash_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_LACERATINGSLASH);
+ LaceratingSlash_Timer = urand(6000, 20000);
+ }else LaceratingSlash_Timer -= diff;
+
+ //Rend Flesh
+ if (RendFlesh_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_RENDFLESH);
+ RendFlesh_Timer = urand(6000, 20000);
+ }else RendFlesh_Timer -= diff;
+
+ //Deafening Roar
+ if (DeafeningRoar_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_DEAFENINGROAR);
+ DeafeningRoar_Timer = urand(15000, 25000);
+ }else DeafeningRoar_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_nalorakk(Creature* pCreature)
+{
+ return new boss_nalorakkAI(pCreature);
+}
+
+void AddSC_boss_nalorakk()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_nalorakk";
+ newscript->GetAI = &GetAI_boss_nalorakk;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp b/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp
new file mode 100644
index 0000000..cd41d39
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp
@@ -0,0 +1,153 @@
+/* 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_Zuljin
+SD%Complete: 0
+SDComment:
+SDCategory: Zul'Aman
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulaman.h"
+
+enum
+{
+ SAY_INTRO = -1568056,
+ SAY_AGGRO = -1568057,
+ SAY_BEAR_TRANSFORM = -1568058,
+ SAY_EAGLE_TRANSFORM = -1568059,
+ SAY_LYNX_TRANSFORM = -1568060,
+ SAY_DRAGONHAWK_TRANSFORM = -1568061,
+ SAY_FIRE_BREATH = -1568062,
+ SAY_BERSERK = -1568053,
+ SAY_KILL1 = -1568064,
+ SAY_KILL2 = -1568065,
+ SAY_DEATH = -1568066,
+
+ // Troll Form
+ SPELL_WHIRLWIND = 17207,
+ SPELL_GRIEVOUS_THROW = 43093, //removes debuff after full healed
+
+ // Bear Form
+ SPELL_CREEPING_PARALYSIS = 43095, //should cast on the whole raid
+ SPELL_OVERPOWER = 43456, //use after melee attack dodged
+
+ // Eagle Form
+ SPELL_ENERGY_STORM = 43983, //enemy area aura, trigger 42577
+ SPELL_ZAP_INFORM = 42577,
+ SPELL_ZAP_DAMAGE = 43137, //1250 damage
+ SPELL_SUMMON_CYCLONE = 43112, //summon four feather vortex
+ CREATURE_FEATHER_VORTEX = 24136,
+ SPELL_CYCLONE_VISUAL = 43119, //trigger 43147 visual
+ SPELL_CYCLONE_PASSIVE = 43120, //trigger 43121 (4y aoe) every second
+
+ // Lynx Form
+ SPELL_CLAW_RAGE_HASTE = 42583,
+ SPELL_CLAW_RAGE_TRIGGER = 43149,
+ SPELL_CLAW_RAGE_DAMAGE = 43150,
+ SPELL_LYNX_RUSH_HASTE = 43152,
+ SPELL_LYNX_RUSH_DAMAGE = 43153,
+
+ // Dragonhawk Form
+ SPELL_FLAME_WHIRL = 43213, //trigger two spells
+ SPELL_FLAME_BREATH = 43215,
+ SPELL_SUMMON_PILLAR = 43216, //summon 24187
+ CREATURE_COLUMN_OF_FIRE = 24187,
+ SPELL_PILLAR_TRIGGER = 43218, //trigger 43217
+
+ // Cosmetic
+ SPELL_SPIRIT_AURA = 42466,
+ SPELL_SIPHON_SOUL = 43501,
+
+ // Transforms
+ SPELL_SHAPE_OF_THE_BEAR = 42594,
+ SPELL_SHAPE_OF_THE_EAGLE = 42606,
+ SPELL_SHAPE_OF_THE_LYNX = 42607,
+ SPELL_SHAPE_OF_THE_DRAGONHAWK = 42608,
+
+ SPELL_BERSERK = 45078,
+
+ WEAPON_ID = 33975,
+
+ PHASE_BEAR = 0,
+ PHASE_EAGLE = 1,
+ PHASE_LYNX = 2,
+ PHASE_DRAGONHAWK = 3,
+ PHASE_TROLL = 4
+};
+
+//coords for going for changing form
+const float CENTER_X = 120.148811f;
+const float CENTER_Y = 703.713684f;
+const float CENTER_Z = 45.111477f;
+
+struct MANGOS_DLL_DECL boss_zuljinAI : public ScriptedAI
+{
+ boss_zuljinAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_KILL1 : SAY_KILL2, m_creature);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (!m_pInstance)
+ return;
+
+ m_pInstance->SetData(TYPE_ZULJIN, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_zuljin(Creature* pCreature)
+{
+ return new boss_zuljinAI(pCreature);
+}
+
+void AddSC_boss_zuljin()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_zuljin";
+ newscript->GetAI = &GetAI_boss_zuljin;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp b/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp
new file mode 100644
index 0000000..a12b9e8
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp
@@ -0,0 +1,364 @@
+/* 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_Zulaman
+SD%Complete: 25
+SDComment:
+SDCategory: Zul'Aman
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulaman.h"
+
+struct MANGOS_DLL_DECL instance_zulaman : public ScriptedInstance
+{
+ instance_zulaman(Map* pMap) : ScriptedInstance(pMap) {Initialize();}
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ uint32 m_auiRandVendor[MAX_VENDOR];
+ std::string strInstData;
+
+ uint32 m_uiEventTimer;
+ uint32 m_uiEventMinuteStep;
+
+ uint32 m_uiGongCount;
+
+ uint64 m_uiAkilzonGUID;
+ uint64 m_uiNalorakkGUID;
+ uint64 m_uiJanalaiGUID;
+ uint64 m_uiHalazziGUID;
+ uint64 m_uiSpiritLynxGUID;
+ uint64 m_uiZuljinGUID;
+ uint64 m_uiMalacrassGUID;
+ uint64 m_uiHarrisonGUID;
+
+ uint64 m_uiStrangeGongGUID;
+ uint64 m_uiMassiveGateGUID;
+ uint64 m_uiMalacrassEntranceGUID;
+
+ std::list m_lEggsGUIDList;
+ uint32 m_uiEggsRemainingCount_Left;
+ uint32 m_uiEggsRemainingCount_Right;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+ memset(&m_auiRandVendor, 0, sizeof(m_auiRandVendor));
+
+ m_uiEventTimer = MINUTE*IN_MILLISECONDS;
+ m_uiEventMinuteStep = MINUTE/3;
+
+ m_uiGongCount = 0;
+
+ m_uiAkilzonGUID = 0;
+ m_uiNalorakkGUID = 0;
+ m_uiJanalaiGUID = 0;
+ m_uiHalazziGUID = 0;
+ m_uiSpiritLynxGUID = 0;
+ m_uiZuljinGUID = 0;
+ m_uiMalacrassGUID = 0;
+ m_uiHarrisonGUID = 0;
+
+ m_uiStrangeGongGUID = 0;
+ m_uiMassiveGateGUID = 0;
+ m_uiMalacrassEntranceGUID = 0;
+
+ m_lEggsGUIDList.clear();
+ m_uiEggsRemainingCount_Left = 20;
+ m_uiEggsRemainingCount_Right = 20;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case 23574: m_uiAkilzonGUID = pCreature->GetGUID(); break;
+ case 23576: m_uiNalorakkGUID = pCreature->GetGUID(); break;
+ case 23578: m_uiJanalaiGUID = pCreature->GetGUID(); break;
+ case 23577: m_uiHalazziGUID = pCreature->GetGUID(); break;
+ case 23863: m_uiZuljinGUID = pCreature->GetGUID(); break;
+ case 24239: m_uiMalacrassGUID = pCreature->GetGUID(); break;
+ case 24358: m_uiHarrisonGUID = pCreature->GetGUID(); break;
+ case NPC_SPIRIT_LYNX: m_uiSpiritLynxGUID = pCreature->GetGUID(); break;
+ case NPC_EGG:
+ if (m_auiEncounter[3] != DONE)
+ m_lEggsGUIDList.push_back(pCreature->GetGUID());
+ break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case 187359:
+ m_uiStrangeGongGUID = pGo->GetGUID();
+ break;
+ case 186728:
+ m_uiMassiveGateGUID = pGo->GetGUID();
+ if (m_auiEncounter[0] == IN_PROGRESS || m_auiEncounter[0] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case 186305:
+ m_uiMalacrassEntranceGUID = pGo->GetGUID();
+ break;
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ debug_log("SD2: Instance Zulaman: SetData received for type %u with data %u",uiType,uiData);
+
+ switch(uiType)
+ {
+ case TYPE_EVENT_RUN:
+ if (uiData == SPECIAL)
+ {
+ ++m_uiGongCount;
+ if (m_uiGongCount == 5)
+ m_auiEncounter[0] = uiData;
+ }
+ if (uiData == IN_PROGRESS)
+ {
+ DoUseDoorOrButton(m_uiMassiveGateGUID);
+ DoUpdateWorldState(WORLD_STATE_COUNTER,m_uiEventMinuteStep);
+ DoUpdateWorldState(WORLD_STATE_ID,1);
+ m_auiEncounter[0] = uiData;
+ }
+ break;
+ case TYPE_AKILZON:
+ if (uiData == DONE)
+ {
+ if (m_auiEncounter[0] == IN_PROGRESS)
+ {
+ m_uiEventMinuteStep += MINUTE/6; //add 10 minutes
+ DoUpdateWorldState(WORLD_STATE_COUNTER,m_uiEventMinuteStep);
+ }
+ }
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_NALORAKK:
+ if (uiData == DONE)
+ {
+ if (m_auiEncounter[0] == IN_PROGRESS)
+ {
+ m_uiEventMinuteStep += MINUTE/4; //add 15 minutes
+ DoUpdateWorldState(WORLD_STATE_COUNTER,m_uiEventMinuteStep);
+ }
+ }
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_JANALAI:
+ if (uiData == NOT_STARTED)
+ {
+ m_uiEggsRemainingCount_Left = 20;
+ m_uiEggsRemainingCount_Right = 20;
+
+ if (!m_lEggsGUIDList.empty())
+ {
+ for(std::list::iterator itr = m_lEggsGUIDList.begin(); itr != m_lEggsGUIDList.end(); ++itr)
+ {
+ if (Creature* pEgg = instance->GetCreature(*itr))
+ {
+ if (!pEgg->isAlive())
+ pEgg->Respawn();
+ }
+ }
+ }
+ }
+ if (uiData == DONE)
+ m_lEggsGUIDList.clear();
+
+ m_auiEncounter[3] = uiData;
+ break;
+ case TYPE_HALAZZI:
+ m_auiEncounter[4] = uiData;
+ break;
+ case TYPE_ZULJIN:
+ m_auiEncounter[5] = uiData;
+ break;
+ case TYPE_MALACRASS:
+ m_auiEncounter[6] = uiData;
+ break;
+
+ case DATA_J_EGGS_RIGHT:
+ --m_uiEggsRemainingCount_Right;
+ break;
+ case DATA_J_EGGS_LEFT:
+ --m_uiEggsRemainingCount_Left;
+ break;
+
+ case TYPE_RAND_VENDOR_1:
+ m_auiRandVendor[0] = uiData;
+ break;
+ case TYPE_RAND_VENDOR_2:
+ m_auiRandVendor[1] = uiData;
+ break;
+ default:
+ error_log("SD2: Instance Zulaman: ERROR SetData = %u for type %u does not exist/not implemented.",uiType,uiData);
+ break;
+ }
+
+ if (m_auiEncounter[1] == DONE && m_auiEncounter[2] == DONE && m_auiEncounter[3] == DONE &&
+ m_auiEncounter[4] == DONE && m_auiEncounter[5] != IN_PROGRESS)
+ DoUseDoorOrButton(m_uiMalacrassEntranceGUID);
+
+ if (uiData == DONE || (uiType == TYPE_EVENT_RUN && uiData == IN_PROGRESS))
+ {
+ 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];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ const char* Save()
+ {
+ return strInstData.c_str();
+ }
+
+ void Load(const char* chrIn)
+ {
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
+ >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6];
+
+ //not changing m_uiEncounter[0], TYPE_EVENT_RUN must not reset to NOT_STARTED
+ for(uint8 i = 1; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_EVENT_RUN:
+ return m_auiEncounter[0];
+ case TYPE_AKILZON:
+ return m_auiEncounter[1];
+ case TYPE_NALORAKK:
+ return m_auiEncounter[2];
+ case TYPE_JANALAI:
+ return m_auiEncounter[3];
+ case TYPE_HALAZZI:
+ return m_auiEncounter[4];
+ case TYPE_ZULJIN:
+ return m_auiEncounter[5];
+ case TYPE_MALACRASS:
+ return m_auiEncounter[6];
+
+ case DATA_J_EGGS_LEFT:
+ return m_uiEggsRemainingCount_Left;
+ case DATA_J_EGGS_RIGHT:
+ return m_uiEggsRemainingCount_Right;
+
+ case TYPE_RAND_VENDOR_1:
+ return m_auiRandVendor[0];
+ case TYPE_RAND_VENDOR_2:
+ return m_auiRandVendor[1];
+ }
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_AKILZON:
+ return m_uiAkilzonGUID;
+ case DATA_NALORAKK:
+ return m_uiNalorakkGUID;
+ case DATA_JANALAI:
+ return m_uiJanalaiGUID;
+ case DATA_HALAZZI:
+ return m_uiHalazziGUID;
+ case DATA_SPIRIT_LYNX:
+ return m_uiSpiritLynxGUID;
+ case DATA_ZULJIN:
+ return m_uiZuljinGUID;
+ case DATA_MALACRASS:
+ return m_uiMalacrassGUID;
+ case DATA_HARRISON:
+ return m_uiHarrisonGUID;
+ case DATA_GO_GONG:
+ return m_uiStrangeGongGUID;
+ case DATA_GO_ENTRANCE:
+ return m_uiMassiveGateGUID;
+ case DATA_GO_MALACRASS_GATE:
+ return m_uiMalacrassEntranceGUID;
+ }
+ return 0;
+ }
+
+ void Update(uint32 uiDiff)
+ {
+ if (GetData(TYPE_EVENT_RUN) == IN_PROGRESS)
+ {
+ if (m_uiEventTimer <= uiDiff)
+ {
+ if (m_uiEventMinuteStep == 0)
+ {
+ debug_log("SD2: Instance Zulaman: event time reach end, event failed.");
+ m_auiEncounter[0] = FAIL;
+ return;
+ }
+
+ --m_uiEventMinuteStep;
+ DoUpdateWorldState(WORLD_STATE_COUNTER, m_uiEventMinuteStep);
+ debug_log("SD2: Instance Zulaman: minute decrease to %u.",m_uiEventMinuteStep);
+
+ m_uiEventTimer = MINUTE*IN_MILLISECONDS;
+ }
+ else
+ m_uiEventTimer -= uiDiff;
+ }
+ }
+};
+
+InstanceData* GetInstanceData_instance_zulaman(Map* pMap)
+{
+ return new instance_zulaman(pMap);
+}
+
+void AddSC_instance_zulaman()
+{
+ Script* pNewScript;
+ pNewScript = new Script;
+ pNewScript->Name = "instance_zulaman";
+ pNewScript->GetInstanceData = &GetInstanceData_instance_zulaman;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/zulaman.cpp b/scripts/eastern_kingdoms/zulaman/zulaman.cpp
new file mode 100644
index 0000000..0ba94d6
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/zulaman.cpp
@@ -0,0 +1,262 @@
+/* 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: Zulaman
+SD%Complete: 90
+SDComment: Forest Frog will turn into different NPC's. Workaround to prevent new entry from running this script
+SDCategory: Zul'Aman
+EndScriptData */
+
+/* ContentData
+npc_forest_frog
+EndContentData */
+
+#include "precompiled.h"
+#include "zulaman.h"
+#include "escort_ai.h"
+
+/*######
+## npc_forest_frog
+######*/
+
+enum
+{
+ SPELL_REMOVE_AMANI_CURSE = 43732,
+ SPELL_PUSH_MOJO = 43923,
+ ENTRY_FOREST_FROG = 24396
+};
+
+struct MANGOS_DLL_DECL npc_forest_frogAI : public ScriptedAI
+{
+ npc_forest_frogAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset() { }
+
+ void DoSpawnRandom()
+ {
+ if (m_pInstance)
+ {
+ uint32 cEntry = 0;
+ switch(urand(0, 10))
+ {
+ case 0: cEntry = 24024; break; //Kraz
+ case 1: cEntry = 24397; break; //Mannuth
+ case 2: cEntry = 24403; break; //Deez
+ case 3: cEntry = 24404; break; //Galathryn
+ case 4: cEntry = 24405; break; //Adarrah
+ case 5: cEntry = 24406; break; //Fudgerick
+ case 6: cEntry = 24407; break; //Darwen
+ case 7: cEntry = 24445; break; //Mitzi
+ case 8: cEntry = 24448; break; //Christian
+ case 9: cEntry = 24453; break; //Brennan
+ case 10: cEntry = 24455; break; //Hollee
+ }
+
+ if (!m_pInstance->GetData(TYPE_RAND_VENDOR_1))
+ if (!urand(0, 9))
+ cEntry = 24408; //Gunter
+
+ if (!m_pInstance->GetData(TYPE_RAND_VENDOR_2))
+ if (!urand(0, 9))
+ cEntry = 24409; //Kyren
+
+ if (cEntry)
+ m_creature->UpdateEntry(cEntry);
+
+ if (cEntry == 24408)
+ m_pInstance->SetData(TYPE_RAND_VENDOR_1,DONE);
+
+ if (cEntry == 24409)
+ m_pInstance->SetData(TYPE_RAND_VENDOR_2,DONE);
+ }
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *spell)
+ {
+ if (spell->Id == SPELL_REMOVE_AMANI_CURSE && caster->GetTypeId() == TYPEID_PLAYER && m_creature->GetEntry() == ENTRY_FOREST_FROG)
+ {
+ //increase or decrease chance of mojo?
+ if (!urand(0, 49))
+ DoCastSpellIfCan(caster, SPELL_PUSH_MOJO, CAST_TRIGGERED);
+ else
+ DoSpawnRandom();
+ }
+ }
+};
+CreatureAI* GetAI_npc_forest_frog(Creature* pCreature)
+{
+ return new npc_forest_frogAI(pCreature);
+}
+
+/*######
+## npc_harrison_jones_za
+######*/
+
+enum
+{
+ SAY_START = -1568079,
+ SAY_AT_GONG = -1568080,
+ SAY_OPEN_ENTRANCE = -1568081,
+
+ SPELL_BANGING_THE_GONG = 45225
+};
+
+#define GOSSIP_ITEM_BEGIN "Thanks for the concern, but we intend to explore Zul'Aman."
+
+struct MANGOS_DLL_DECL npc_harrison_jones_zaAI : public npc_escortAI
+{
+ npc_harrison_jones_zaAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ if (!m_pInstance)
+ return;
+
+ switch(uiPointId)
+ {
+ case 1:
+ DoScriptText(SAY_AT_GONG, m_creature);
+
+ if (GameObject* pEntranceDoor = m_pInstance->instance->GetGameObject(m_pInstance->GetData64(DATA_GO_GONG)))
+ pEntranceDoor->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1);
+
+ //Start bang gong for 2min
+ m_creature->CastSpell(m_creature, SPELL_BANGING_THE_GONG, false);
+ SetEscortPaused(true);
+ break;
+ case 3:
+ DoScriptText(SAY_OPEN_ENTRANCE, m_creature);
+ break;
+ case 4:
+ m_pInstance->SetData(TYPE_EVENT_RUN,IN_PROGRESS);
+ //TODO: Spawn group of Amani'shi Savage and make them run to entrance
+ break;
+ }
+ }
+
+ void Reset() { }
+
+ void StartEvent()
+ {
+ DoScriptText(SAY_START, m_creature);
+ Start();
+ }
+
+ void SetHoldState(bool bOnHold)
+ {
+ SetEscortPaused(bOnHold);
+
+ //Stop banging gong if still
+ if (m_pInstance && m_pInstance->GetData(TYPE_EVENT_RUN) == SPECIAL && m_creature->HasAura(SPELL_BANGING_THE_GONG))
+ m_creature->RemoveAurasDueToSpell(SPELL_BANGING_THE_GONG);
+ }
+};
+
+bool GossipHello_npc_harrison_jones_za(Player* pPlayer, Creature* pCreature)
+{
+ ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pInstance && pInstance->GetData(TYPE_EVENT_RUN) == NOT_STARTED)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_harrison_jones_za(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ if (npc_harrison_jones_zaAI* pHarrisonAI = dynamic_cast(pCreature->AI()))
+ pHarrisonAI->StartEvent();
+
+ pPlayer->CLOSE_GOSSIP_MENU();
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_harrison_jones_za(Creature* pCreature)
+{
+ return new npc_harrison_jones_zaAI(pCreature);
+}
+
+/*######
+## go_strange_gong
+######*/
+
+//Unsure how this Gong must work. Here we always return false to allow Mangos always process further.
+bool GOHello_go_strange_gong(Player* pPlayer, GameObject* pGo)
+{
+ ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData();
+
+ if (!pInstance)
+ return false;
+
+ if (pInstance->GetData(TYPE_EVENT_RUN) == SPECIAL)
+ {
+ if (Creature* pCreature = pGo->GetMap()->GetCreature(pInstance->GetData64(DATA_HARRISON)))
+ {
+ if (npc_harrison_jones_zaAI* pHarrisonAI = dynamic_cast(pCreature->AI()))
+ pHarrisonAI->SetHoldState(false);
+ }
+ else
+ error_log("SD2: Instance Zulaman: go_strange_gong failed");
+
+ pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1);
+ return false;
+ }
+
+ pInstance->SetData(TYPE_EVENT_RUN, SPECIAL);
+ return false;
+}
+
+void AddSC_zulaman()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_forest_frog";
+ newscript->GetAI = &GetAI_npc_forest_frog;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_harrison_jones_za";
+ newscript->GetAI = &GetAI_npc_harrison_jones_za;
+ newscript->pGossipHello = &GossipHello_npc_harrison_jones_za;
+ newscript->pGossipSelect = &GossipSelect_npc_harrison_jones_za;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "go_strange_gong";
+ newscript->pGOHello = &GOHello_go_strange_gong;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulaman/zulaman.h b/scripts/eastern_kingdoms/zulaman/zulaman.h
new file mode 100644
index 0000000..a76e421
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulaman/zulaman.h
@@ -0,0 +1,60 @@
+/* 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 */
+
+#ifndef DEF_ZULAMAN_H
+#define DEF_ZULAMAN_H
+
+enum InstanceZA
+{
+ MAX_ENCOUNTER = 7,
+ MAX_VENDOR = 2,
+
+ SAY_INST_RELEASE = -1568067,
+ SAY_INST_BEGIN = -1568068,
+ SAY_INST_PROGRESS_1 = -1568069,
+ SAY_INST_PROGRESS_2 = -1568070,
+ SAY_INST_PROGRESS_3 = -1568071,
+ SAY_INST_WARN_1 = -1568072,
+ SAY_INST_WARN_2 = -1568073,
+ SAY_INST_WARN_3 = -1568074,
+ SAY_INST_WARN_4 = -1568075,
+ SAY_INST_SACRIF1 = -1568076,
+ SAY_INST_SACRIF2 = -1568077,
+ SAY_INST_COMPLETE = -1568078,
+
+ WORLD_STATE_ID = 3104,
+ WORLD_STATE_COUNTER = 3106,
+
+ TYPE_EVENT_RUN = 1,
+ TYPE_AKILZON = 2,
+ TYPE_NALORAKK = 3,
+ TYPE_JANALAI = 4,
+ TYPE_HALAZZI = 5,
+ TYPE_MALACRASS = 6,
+ TYPE_ZULJIN = 7,
+
+ TYPE_RAND_VENDOR_1 = 8,
+ TYPE_RAND_VENDOR_2 = 9,
+
+ DATA_AKILZON = 10,
+ DATA_NALORAKK = 11,
+ DATA_JANALAI = 12,
+ DATA_HALAZZI = 13,
+ DATA_MALACRASS = 14,
+ DATA_ZULJIN = 15,
+ DATA_HARRISON = 16,
+ DATA_SPIRIT_LYNX = 17,
+
+ DATA_J_EGGS_RIGHT = 19,
+ DATA_J_EGGS_LEFT = 20,
+
+ DATA_GO_GONG = 21,
+ DATA_GO_MALACRASS_GATE = 22,
+ DATA_GO_ENTRANCE = 23,
+
+ NPC_EGG = 23817,
+ NPC_SPIRIT_LYNX = 24143
+};
+
+#endif
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp b/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp
new file mode 100644
index 0000000..ffc7b65
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp
@@ -0,0 +1,289 @@
+/* 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_Arlokk
+SD%Complete: 95
+SDComment: Wrong cleave and red aura is missing.
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+bool GOHello_go_gong_of_bethekk(Player* pPlayer, GameObject* pGo)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData())
+ {
+ if (pInstance->GetData(TYPE_ARLOKK) == DONE || pInstance->GetData(TYPE_ARLOKK) == IN_PROGRESS)
+ return true;
+
+ pInstance->SetData(TYPE_ARLOKK, IN_PROGRESS);
+ }
+
+ return false;
+}
+
+enum
+{
+ SAY_AGGRO = -1309011,
+ SAY_FEAST_PANTHER = -1309012,
+ SAY_DEATH = -1309013,
+
+ SPELL_SHADOWWORDPAIN = 23952,
+ SPELL_GOUGE = 24698,
+ SPELL_MARK = 24210,
+ SPELL_CLEAVE = 26350, //Perhaps not right. Not a red aura...
+ SPELL_PANTHER_TRANSFORM = 24190,
+
+ MODEL_ID_NORMAL = 15218,
+ MODEL_ID_PANTHER = 15215,
+ MODEL_ID_BLANK = 11686,
+
+ NPC_ZULIAN_PROWLER = 15101
+};
+
+struct MANGOS_DLL_DECL boss_arlokkAI : public ScriptedAI
+{
+ boss_arlokkAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiShadowWordPain_Timer;
+ uint32 m_uiGouge_Timer;
+ uint32 m_uiMark_Timer;
+ uint32 m_uiCleave_Timer;
+ uint32 m_uiVanish_Timer;
+ uint32 m_uiVisible_Timer;
+
+ uint32 m_uiSummon_Timer;
+ uint32 m_uiSummonCount;
+
+ uint64 m_uiMarkedGUID;
+
+ bool m_bIsPhaseTwo;
+ bool m_bIsVanished;
+
+ void Reset()
+ {
+ m_uiShadowWordPain_Timer = 8000;
+ m_uiGouge_Timer = 14000;
+ m_uiMark_Timer = 35000;
+ m_uiCleave_Timer = 4000;
+ m_uiVanish_Timer = 60000;
+ m_uiVisible_Timer = 6000;
+
+ m_uiSummon_Timer = 5000;
+ m_uiSummonCount = 0;
+
+ m_bIsPhaseTwo = false;
+ m_bIsVanished = false;
+
+ m_uiMarkedGUID = 0;
+
+ m_creature->SetDisplayId(MODEL_ID_NORMAL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARLOKK, NOT_STARTED);
+
+ //we should be summoned, so despawn
+ m_creature->ForcedDespawn();
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ m_creature->SetDisplayId(MODEL_ID_NORMAL);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARLOKK, DONE);
+ }
+
+ void DoSummonPhanters()
+ {
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiMarkedGUID))
+ {
+ if (pPlayer->isAlive())
+ DoScriptText(SAY_FEAST_PANTHER, m_creature, pPlayer);
+ }
+
+ m_creature->SummonCreature(NPC_ZULIAN_PROWLER, -11532.7998f, -1649.6734f, 41.4800f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ m_creature->SummonCreature(NPC_ZULIAN_PROWLER, -11532.9970f, -1606.4840f, 41.2979f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiMarkedGUID))
+ {
+ if (pPlayer->isAlive())
+ pSummoned->AI()->AttackStart(pPlayer);
+ }
+
+ ++m_uiSummonCount;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!m_bIsPhaseTwo)
+ {
+ if (m_uiShadowWordPain_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWWORDPAIN);
+ m_uiShadowWordPain_Timer = 15000;
+ }
+ else
+ m_uiShadowWordPain_Timer -= uiDiff;
+
+ if (m_uiMark_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ if (Player* pMark = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself())
+ {
+ DoCastSpellIfCan(pMark, SPELL_MARK);
+ m_uiMarkedGUID = pMark->GetGUID();
+ }
+ else
+ {
+ if (m_uiMarkedGUID)
+ m_uiMarkedGUID = 0;
+
+ error_log("SD2: boss_arlokk could not accuire a new target to mark.");
+ }
+ }
+
+ m_uiMark_Timer = 15000;
+ }
+ else
+ m_uiMark_Timer -= uiDiff;
+ }
+ else
+ {
+ //Cleave_Timer
+ if (m_uiCleave_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleave_Timer = 16000;
+ }
+ else
+ m_uiCleave_Timer -= uiDiff;
+
+ //Gouge_Timer
+ if (m_uiGouge_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_GOUGE);
+
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-80);
+
+ m_uiGouge_Timer = urand(17000, 27000);
+ }
+ else
+ m_uiGouge_Timer -= uiDiff;
+ }
+
+ if (m_uiSummonCount <= 30)
+ {
+ if (m_uiSummon_Timer < uiDiff)
+ {
+ DoSummonPhanters();
+ m_uiSummon_Timer = 5000;
+ }
+ else
+ m_uiSummon_Timer -= uiDiff;
+ }
+
+ if (m_uiVanish_Timer < uiDiff)
+ {
+ //Invisble Model
+ m_creature->SetDisplayId(MODEL_ID_BLANK);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ m_creature->AttackStop();
+ DoResetThreat();
+
+ m_bIsVanished = true;
+
+ m_uiVanish_Timer = 45000;
+ m_uiVisible_Timer = 6000;
+ }
+ else
+ m_uiVanish_Timer -= uiDiff;
+
+ if (m_bIsVanished)
+ {
+ if (m_uiVisible_Timer < uiDiff)
+ {
+ //The Panther Model
+ m_creature->SetDisplayId(MODEL_ID_PANTHER);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
+ m_creature->UpdateDamagePhysical(BASE_ATTACK);
+
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ AttackStart(pTarget);
+
+ m_bIsPhaseTwo = true;
+ m_bIsVanished = false;
+ }
+ else
+ m_uiVisible_Timer -= uiDiff;
+ }
+ else
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_arlokk(Creature* pCreature)
+{
+ return new boss_arlokkAI(pCreature);
+}
+
+void AddSC_boss_arlokk()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "go_gong_of_bethekk";
+ newscript->pGOHello = &GOHello_go_gong_of_bethekk;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_arlokk";
+ newscript->GetAI = &GetAI_boss_arlokk;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp b/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp
new file mode 100644
index 0000000..b5732b9
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp
@@ -0,0 +1,88 @@
+/* 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_Gahz'ranka
+SD%Complete: 85
+SDComment: Massive Geyser with knockback not working. Spell buggy.
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_FROSTBREATH 16099
+#define SPELL_MASSIVEGEYSER 22421 //Not working. Cause its a summon...
+#define SPELL_SLAM 24326
+
+struct MANGOS_DLL_DECL boss_gahzrankaAI : public ScriptedAI
+{
+ boss_gahzrankaAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+ uint32 Frostbreath_Timer;
+ uint32 MassiveGeyser_Timer;
+ uint32 Slam_Timer;
+
+ void Reset()
+ {
+ Frostbreath_Timer = 8000;
+ MassiveGeyser_Timer = 25000;
+ Slam_Timer = 17000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Frostbreath_Timer
+ if (Frostbreath_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROSTBREATH);
+ Frostbreath_Timer = urand(7000, 11000);
+ }else Frostbreath_Timer -= diff;
+
+ //MassiveGeyser_Timer
+ if (MassiveGeyser_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MASSIVEGEYSER);
+ DoResetThreat();
+
+ MassiveGeyser_Timer = urand(22000, 32000);
+ }else MassiveGeyser_Timer -= diff;
+
+ //Slam_Timer
+ if (Slam_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SLAM);
+ Slam_Timer = urand(12000, 20000);
+ }else Slam_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_gahzranka(Creature* pCreature)
+{
+ return new boss_gahzrankaAI(pCreature);
+}
+
+void AddSC_boss_gahzranka()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_gahzranka";
+ newscript->GetAI = &GetAI_boss_gahzranka;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp b/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp
new file mode 100644
index 0000000..ad2bc1f
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp
@@ -0,0 +1,88 @@
+/* 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_Grilek
+SD%Complete: 100
+SDComment:
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+#define SPELL_AVARTAR 24646 //The Enrage Spell
+#define SPELL_GROUNDTREMOR 6524
+
+struct MANGOS_DLL_DECL boss_grilekAI : public ScriptedAI
+{
+ boss_grilekAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Avartar_Timer;
+ uint32 GroundTremor_Timer;
+
+ void Reset()
+ {
+ Avartar_Timer = urand(15000, 25000);
+ GroundTremor_Timer = urand(8000, 16000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Avartar_Timer
+ if (Avartar_Timer < diff)
+ {
+
+ DoCastSpellIfCan(m_creature, SPELL_AVARTAR);
+ Unit* target = NULL;
+
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1);
+
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50);
+ if (target)
+ AttackStart(target);
+
+ Avartar_Timer = urand(25000, 35000);
+ }else Avartar_Timer -= diff;
+
+ //GroundTremor_Timer
+ if (GroundTremor_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_GROUNDTREMOR);
+ GroundTremor_Timer = urand(12000, 16000);
+ }else GroundTremor_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_grilek(Creature* pCreature)
+{
+ return new boss_grilekAI(pCreature);
+}
+
+void AddSC_boss_grilek()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_grilek";
+ newscript->GetAI = &GetAI_boss_grilek;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp b/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp
new file mode 100644
index 0000000..b509fe3
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp
@@ -0,0 +1,251 @@
+/* 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_Hakkar
+SD%Complete: 95
+SDComment: Blood siphon spell buggy cause of Core Issue.
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+#define SAY_AGGRO -1309020
+#define SAY_FLEEING -1309021
+#define SAY_MINION_DESTROY -1309022 //where does it belong?
+#define SAY_PROTECT_ALTAR -1309023 //where does it belong?
+
+#define SPELL_BLOODSIPHON 24322
+#define SPELL_CORRUPTEDBLOOD 24328
+#define SPELL_CAUSEINSANITY 24327 //Not working disabled.
+#define SPELL_WILLOFHAKKAR 24178
+#define SPELL_ENRAGE 24318
+
+// The Aspects of all High Priests
+#define SPELL_ASPECT_OF_JEKLIK 24687
+#define SPELL_ASPECT_OF_VENOXIS 24688
+#define SPELL_ASPECT_OF_MARLI 24686
+#define SPELL_ASPECT_OF_THEKAL 24689
+#define SPELL_ASPECT_OF_ARLOKK 24690
+
+struct MANGOS_DLL_DECL boss_hakkarAI : public ScriptedAI
+{
+ boss_hakkarAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 BloodSiphon_Timer;
+ uint32 CorruptedBlood_Timer;
+ uint32 CauseInsanity_Timer;
+ uint32 WillOfHakkar_Timer;
+ uint32 Enrage_Timer;
+
+ uint32 CheckJeklik_Timer;
+ uint32 CheckVenoxis_Timer;
+ uint32 CheckMarli_Timer;
+ uint32 CheckThekal_Timer;
+ uint32 CheckArlokk_Timer;
+
+ uint32 AspectOfJeklik_Timer;
+ uint32 AspectOfVenoxis_Timer;
+ uint32 AspectOfMarli_Timer;
+ uint32 AspectOfThekal_Timer;
+ uint32 AspectOfArlokk_Timer;
+
+ bool Enraged;
+
+ void Reset()
+ {
+ BloodSiphon_Timer = 90000;
+ CorruptedBlood_Timer = 25000;
+ CauseInsanity_Timer = 17000;
+ WillOfHakkar_Timer = 17000;
+ Enrage_Timer = 600000;
+
+ CheckJeklik_Timer = 1000;
+ CheckVenoxis_Timer = 2000;
+ CheckMarli_Timer = 3000;
+ CheckThekal_Timer = 4000;
+ CheckArlokk_Timer = 5000;
+
+ AspectOfJeklik_Timer = 4000;
+ AspectOfVenoxis_Timer = 7000;
+ AspectOfMarli_Timer = 12000;
+ AspectOfThekal_Timer = 8000;
+ AspectOfArlokk_Timer = 18000;
+
+ Enraged = false;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //BloodSiphon_Timer
+ if (BloodSiphon_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BLOODSIPHON);
+ BloodSiphon_Timer = 90000;
+ }else BloodSiphon_Timer -= diff;
+
+ //CorruptedBlood_Timer
+ if (CorruptedBlood_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CORRUPTEDBLOOD);
+ CorruptedBlood_Timer = urand(30000, 45000);
+ }else CorruptedBlood_Timer -= diff;
+
+ //CauseInsanity_Timer
+ /*if (CauseInsanity_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_CAUSEINSANITY);
+
+ CauseInsanity_Timer = urand(35000, 43000);
+ }else CauseInsanity_Timer -= diff;*/
+
+ //WillOfHakkar_Timer
+ if (WillOfHakkar_Timer < diff)
+ {
+
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_WILLOFHAKKAR);
+
+ WillOfHakkar_Timer = urand(25000, 35000);
+ }else WillOfHakkar_Timer -= diff;
+
+ if (!Enraged && Enrage_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ Enraged = true;
+ }else Enrage_Timer -= diff;
+
+ //Checking if Jeklik is dead. If not we cast her Aspect
+ if (CheckJeklik_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_JEKLIK) != DONE)
+ {
+ if (AspectOfJeklik_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ASPECT_OF_JEKLIK);
+ AspectOfJeklik_Timer = urand(10000, 14000);
+ }else AspectOfJeklik_Timer -= diff;
+ }
+ }
+ CheckJeklik_Timer = 1000;
+ }else CheckJeklik_Timer -= diff;
+
+ //Checking if Venoxis is dead. If not we cast his Aspect
+ if (CheckVenoxis_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_VENOXIS) != DONE)
+ {
+ if (AspectOfVenoxis_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ASPECT_OF_VENOXIS);
+ AspectOfVenoxis_Timer = 8000;
+ }else AspectOfVenoxis_Timer -= diff;
+ }
+ }
+ CheckVenoxis_Timer = 1000;
+ }else CheckVenoxis_Timer -= diff;
+
+ //Checking if Marli is dead. If not we cast her Aspect
+ if (CheckMarli_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_MARLI) != DONE)
+ {
+ if (AspectOfMarli_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ASPECT_OF_MARLI);
+ AspectOfMarli_Timer = 10000;
+ }else AspectOfMarli_Timer -= diff;
+
+ }
+ }
+ CheckMarli_Timer = 1000;
+ }else CheckMarli_Timer -= diff;
+
+ //Checking if Thekal is dead. If not we cast his Aspect
+ if (CheckThekal_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_THEKAL) != DONE)
+ {
+ if (AspectOfThekal_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_ASPECT_OF_THEKAL);
+ AspectOfThekal_Timer = 15000;
+ }else AspectOfThekal_Timer -= diff;
+ }
+ }
+ CheckThekal_Timer = 1000;
+ }else CheckThekal_Timer -= diff;
+
+ //Checking if Arlokk is dead. If yes we cast her Aspect
+ if (CheckArlokk_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_ARLOKK) != DONE)
+ {
+ if (AspectOfArlokk_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_ASPECT_OF_ARLOKK);
+ DoResetThreat();
+
+ AspectOfArlokk_Timer = urand(10000, 15000);
+ }else AspectOfArlokk_Timer -= diff;
+ }
+ }
+ CheckArlokk_Timer = 1000;
+ }else CheckArlokk_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_hakkar(Creature* pCreature)
+{
+ return new boss_hakkarAI(pCreature);
+}
+
+void AddSC_boss_hakkar()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_hakkar";
+ newscript->GetAI = &GetAI_boss_hakkar;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp b/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp
new file mode 100644
index 0000000..8bba263
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp
@@ -0,0 +1,96 @@
+/* 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_Hazzarah
+SD%Complete: 100
+SDComment:
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+#define SPELL_MANABURN 26046
+#define SPELL_SLEEP 24664
+
+struct MANGOS_DLL_DECL boss_hazzarahAI : public ScriptedAI
+{
+ boss_hazzarahAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ManaBurn_Timer;
+ uint32 Sleep_Timer;
+ uint32 Illusions_Timer;
+
+ void Reset()
+ {
+ ManaBurn_Timer = urand(4000, 10000);
+ Sleep_Timer = urand(10000, 18000);
+ Illusions_Timer = urand(10000, 18000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ManaBurn_Timer
+ if (ManaBurn_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MANABURN);
+ ManaBurn_Timer = urand(8000, 16000);
+ }else ManaBurn_Timer -= diff;
+
+ //Sleep_Timer
+ if (Sleep_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SLEEP);
+ Sleep_Timer = urand(12000, 20000);
+ }else Sleep_Timer -= diff;
+
+ //Illusions_Timer
+ if (Illusions_Timer < diff)
+ {
+ //We will summon 3 illusions that will spawn on a random gamer and attack this gamer
+ //We will just use one model for the beginning
+ for(int i = 0; i < 3; ++i)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ if (Creature* pIllusion = m_creature->SummonCreature(15163, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000))
+ pIllusion->AI()->AttackStart(pTarget);
+ }
+ }
+
+ Illusions_Timer = urand(15000, 25000);
+ }else Illusions_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_hazzarah(Creature* pCreature)
+{
+ return new boss_hazzarahAI(pCreature);
+}
+
+void AddSC_boss_hazzarah()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_hazzarah";
+ newscript->GetAI = &GetAI_boss_hazzarah;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp b/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp
new file mode 100644
index 0000000..cf1b3cb
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp
@@ -0,0 +1,284 @@
+/* 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_Jeklik
+SD%Complete: 85
+SDComment: Problem in finding the right flying batriders for spawning and making them fly.
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+#define SAY_AGGRO -1309002
+#define SAY_RAIN_FIRE -1309003
+#define SAY_DEATH -1309004
+
+#define SPELL_CHARGE 22911
+#define SPELL_SONICBURST 23918
+#define SPELL_SCREECH 6605
+#define SPELL_SHADOW_WORD_PAIN 23952
+#define SPELL_MIND_FLAY 23953
+#define SPELL_CHAIN_MIND_FLAY 26044 //Right ID unknown. So disabled
+#define SPELL_GREATERHEAL 23954
+#define SPELL_BAT_FORM 23966
+
+// Batriders Spell
+#define SPELL_BOMB 40332 //Wrong ID but Magmadars bomb is not working...
+
+struct MANGOS_DLL_DECL boss_jeklikAI : public ScriptedAI
+{
+ boss_jeklikAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 Charge_Timer;
+ uint32 SonicBurst_Timer;
+ uint32 Screech_Timer;
+ uint32 SpawnBats_Timer;
+ uint32 ShadowWordPain_Timer;
+ uint32 MindFlay_Timer;
+ uint32 ChainMindFlay_Timer;
+ uint32 GreaterHeal_Timer;
+ uint32 SpawnFlyingBats_Timer;
+
+ bool PhaseTwo;
+
+ void Reset()
+ {
+ Charge_Timer = 20000;
+ SonicBurst_Timer = 8000;
+ Screech_Timer = 13000;
+ SpawnBats_Timer = 60000;
+ ShadowWordPain_Timer = 6000;
+ MindFlay_Timer = 11000;
+ ChainMindFlay_Timer = 26000;
+ GreaterHeal_Timer = 50000;
+ SpawnFlyingBats_Timer = 10000;
+
+ PhaseTwo = false;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_BAT_FORM);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_JEKLIK, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_creature->GetHealthPercent() > 50.0f)
+ {
+ if (Charge_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_CHARGE);
+
+ Charge_Timer = urand(15000, 30000);
+ }else Charge_Timer -= diff;
+
+ if (SonicBurst_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SONICBURST);
+ SonicBurst_Timer = urand(8000, 13000);
+ }else SonicBurst_Timer -= diff;
+
+ if (Screech_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SCREECH);
+ Screech_Timer = urand(18000, 26000);
+ }else Screech_Timer -= diff;
+
+ if (SpawnBats_Timer < diff)
+ {
+ Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+
+ Creature* Bat = NULL;
+ Bat = m_creature->SummonCreature(11368, -12291.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (target && Bat) Bat ->AI()->AttackStart(target);
+
+ Bat = m_creature->SummonCreature(11368, -12289.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (target && Bat) Bat ->AI()->AttackStart(target);
+
+ Bat = m_creature->SummonCreature(11368, -12293.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (target && Bat) Bat ->AI()->AttackStart(target);
+
+ Bat = m_creature->SummonCreature(11368, -12291.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (target && Bat) Bat ->AI()->AttackStart(target);
+
+ Bat = m_creature->SummonCreature(11368, -12289.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (target && Bat) Bat ->AI()->AttackStart(target);
+
+ Bat = m_creature->SummonCreature(11368, -12293.6220f, -1380.2640f, 144.8304f, 5.483f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (target && Bat) Bat ->AI()->AttackStart(target);
+
+ SpawnBats_Timer = 60000;
+ }else SpawnBats_Timer -= diff;
+ }
+ else
+ {
+ if (PhaseTwo)
+ {
+ if (PhaseTwo && ShadowWordPain_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ DoCastSpellIfCan(target, SPELL_SHADOW_WORD_PAIN);
+ ShadowWordPain_Timer = urand(12000, 18000);
+ }
+ }ShadowWordPain_Timer -=diff;
+
+ if (MindFlay_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIND_FLAY);
+ MindFlay_Timer = 16000;
+ }MindFlay_Timer -=diff;
+
+ if (ChainMindFlay_Timer < diff)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CHAIN_MIND_FLAY);
+ ChainMindFlay_Timer = urand(15000, 30000);
+ }ChainMindFlay_Timer -=diff;
+
+ if (GreaterHeal_Timer < diff)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(m_creature,SPELL_GREATERHEAL);
+ GreaterHeal_Timer = urand(25000, 35000);
+ }GreaterHeal_Timer -=diff;
+
+ if (SpawnFlyingBats_Timer < diff)
+ {
+ Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+
+ Creature* FlyingBat = m_creature->SummonCreature(14965, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ()+15, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (FlyingBat)
+ {
+ if (target)
+ FlyingBat->AI()->AttackStart(target);
+ }
+
+ SpawnFlyingBats_Timer = urand(10000, 15000);
+ } else SpawnFlyingBats_Timer -=diff;
+ }
+ else
+ {
+ m_creature->SetDisplayId(15219);
+ DoResetThreat();
+ PhaseTwo = true;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+//Flying Bat
+struct MANGOS_DLL_DECL mob_batriderAI : public ScriptedAI
+{
+ mob_batriderAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 Bomb_Timer;
+ uint32 Check_Timer;
+
+ void Reset()
+ {
+ Bomb_Timer = 2000;
+ Check_Timer = 1000;
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void UpdateAI (const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Bomb_Timer
+ if (Bomb_Timer < diff)
+ {
+ if (Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ DoCastSpellIfCan(target, SPELL_BOMB);
+ Bomb_Timer = 5000;
+ }
+ }else Bomb_Timer -= diff;
+
+ //Check_Timer
+ if (Check_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_JEKLIK) == DONE)
+ {
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->RemoveCorpse();
+ return;
+ }
+ }
+ Check_Timer = 1000;
+ }else Check_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_jeklik(Creature* pCreature)
+{
+ return new boss_jeklikAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_batrider(Creature* pCreature)
+{
+ return new mob_batriderAI(pCreature);
+}
+
+void AddSC_boss_jeklik()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_jeklik";
+ newscript->GetAI = &GetAI_boss_jeklik;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_batrider";
+ newscript->GetAI = &GetAI_mob_batrider;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp b/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp
new file mode 100644
index 0000000..08234ba
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp
@@ -0,0 +1,276 @@
+/* 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_Jin'do the Hexxer
+SD%Complete: 85
+SDComment: Mind Control not working because of core bug. Shades visible for all.
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+#define SAY_AGGRO -1309014
+
+#define SPELL_BRAINWASHTOTEM 24262
+#define SPELL_POWERFULLHEALINGWARD 24309 //We will not use this spell. We will summon a totem by script cause the spell totems will not cast.
+#define SPELL_HEX 24053
+#define SPELL_DELUSIONSOFJINDO 24306
+#define SPELL_SHADEOFJINDO 24308 //We will not use this spell. We will summon a shade by script.
+
+//Healing Ward Spell
+#define SPELL_HEAL 38588 //Totems are not working right. Right heal spell ID is 24311 but this spell is not casting...
+
+//Shade of Jindo Spell
+#define SPELL_SHADOWSHOCK 19460
+#define SPELL_INVISIBLE 24699
+
+struct MANGOS_DLL_DECL boss_jindoAI : public ScriptedAI
+{
+ boss_jindoAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 BrainWashTotem_Timer;
+ uint32 HealingWard_Timer;
+ uint32 Hex_Timer;
+ uint32 Delusions_Timer;
+ uint32 Teleport_Timer;
+
+ void Reset()
+ {
+ BrainWashTotem_Timer = 20000;
+ HealingWard_Timer = 16000;
+ Hex_Timer = 8000;
+ Delusions_Timer = 10000;
+ Teleport_Timer = 5000;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //BrainWashTotem_Timer
+ if (BrainWashTotem_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BRAINWASHTOTEM);
+ BrainWashTotem_Timer = urand(18000, 26000);
+ }else BrainWashTotem_Timer -= diff;
+
+ //HealingWard_Timer
+ if (HealingWard_Timer < diff)
+ {
+ //DoCastSpellIfCan(m_creature, SPELL_POWERFULLHEALINGWARD);
+ m_creature->SummonCreature(14987, m_creature->GetPositionX()+3, m_creature->GetPositionY()-2, m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,30000);
+ HealingWard_Timer = urand(14000, 20000);
+ }else HealingWard_Timer -= diff;
+
+ //Hex_Timer
+ if (Hex_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HEX);
+
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-80);
+
+ Hex_Timer = urand(12000, 20000);
+ }else Hex_Timer -= diff;
+
+ //Casting the delusion curse with a shade. So shade will attack the same target with the curse.
+ if (Delusions_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ DoCastSpellIfCan(target, SPELL_DELUSIONSOFJINDO);
+
+ Creature *Shade = m_creature->SummonCreature(14986, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Shade)
+ Shade->AI()->AttackStart(target);
+ }
+
+ Delusions_Timer = urand(4000, 12000);
+ }else Delusions_Timer -= diff;
+
+ //Teleporting a random gamer and spawning 9 skeletons that will attack this gamer
+ if (Teleport_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target && target->GetTypeId() == TYPEID_PLAYER)
+ {
+ DoTeleportPlayer(target, -11583.7783f, -1249.4278f, 77.5471f, 4.745f);
+
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(target,-100);
+
+ Creature *Skeletons;
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()-2, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()-4, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()+2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()-2, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()+4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX(), target->GetPositionY()-4, target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ Skeletons = m_creature->SummonCreature(14826, target->GetPositionX()+3, target->GetPositionY(), target->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Skeletons)
+ Skeletons->AI()->AttackStart(target);
+ }
+
+ Teleport_Timer = urand(15000, 23000);
+ }else Teleport_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+//Healing Ward
+struct MANGOS_DLL_DECL mob_healing_wardAI : public ScriptedAI
+{
+ mob_healing_wardAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 Heal_Timer;
+
+ void Reset()
+ {
+ Heal_Timer = 2000;
+ }
+
+ void UpdateAI (const uint32 diff)
+ {
+ //Heal_Timer
+ if (Heal_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (Unit *pJindo = m_pInstance->instance->GetCreature(m_pInstance->GetData64(DATA_JINDO)))
+ {
+ if (pJindo->isAlive())
+ DoCastSpellIfCan(pJindo, SPELL_HEAL);
+ }
+ }
+ Heal_Timer = 3000;
+ }else Heal_Timer -= diff;
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+//Shade of Jindo
+struct MANGOS_DLL_DECL mob_shade_of_jindoAI : public ScriptedAI
+{
+ mob_shade_of_jindoAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 ShadowShock_Timer;
+
+ void Reset()
+ {
+ ShadowShock_Timer = 1000;
+ m_creature->CastSpell(m_creature, SPELL_INVISIBLE,true);
+ }
+
+ void UpdateAI (const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ShadowShock_Timer
+ if (ShadowShock_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOWSHOCK);
+ ShadowShock_Timer = 2000;
+ }else ShadowShock_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_jindo(Creature* pCreature)
+{
+ return new boss_jindoAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_healing_ward(Creature* pCreature)
+{
+ return new mob_healing_wardAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_shade_of_jindo(Creature* pCreature)
+{
+ return new mob_shade_of_jindoAI(pCreature);
+}
+
+void AddSC_boss_jindo()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_jindo";
+ newscript->GetAI = &GetAI_boss_jindo;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_healing_ward";
+ newscript->GetAI = &GetAI_mob_healing_ward;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_shade_of_jindo";
+ newscript->GetAI = &GetAI_mob_shade_of_jindo;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp b/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp
new file mode 100644
index 0000000..9dc763a
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp
@@ -0,0 +1,445 @@
+/* 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_Mandokir
+SD%Complete: 80
+SDComment: test Threating Gaze. Script depends on ACID script for Vilebranch Speaker
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+enum
+{
+ NPC_OHGAN = 14988,
+ NPC_CHAINED_SPIRIT = 15117, //resing spirits
+
+ SAY_AGGRO = -1309015,
+ SAY_DING_KILL = -1309016,
+ SAY_GRATS_JINDO = -1309017,
+ SAY_WATCH = -1309018,
+ SAY_WATCH_WHISPER = -1309019,
+
+ EMOTE_RAGE = -1309024,
+
+ SPELL_CHARGE = 24315,
+ SPELL_CLEAVE = 20691,
+ SPELL_FEAR = 29321,
+ SPELL_WHIRLWIND = 24236,
+ SPELL_MORTAL_STRIKE = 24573,
+ SPELL_ENRAGE = 23537,
+ SPELL_WATCH = 24314,
+ SPELL_SUMMON_PLAYER = 25104,
+ SPELL_LEVEL_UP = 24312,
+
+ //Ohgans Spells
+ SPELL_SUNDERARMOR = 24317,
+
+ //Chained Spirit Spells
+ SPELL_REVIVE = 24341,
+
+ POINT_DOWNSTAIRS = 1
+};
+
+struct SpawnLocations
+{
+ float fX, fY, fZ, fAng;
+};
+
+static SpawnLocations aSpirits[]=
+{
+ {-12150.9f, -1956.24f, 133.407f, 2.57835f},
+ {-12157.1f, -1972.78f, 133.947f, 2.64903f},
+ {-12172.3f, -1982.63f, 134.061f, 1.48664f},
+ {-12194.0f, -1979.54f, 132.194f, 1.45916f},
+ {-12211.3f, -1978.49f, 133.580f, 1.35705f},
+ {-12228.4f, -1977.10f, 132.728f, 1.25495f},
+ {-12250.0f, -1964.78f, 135.066f, 0.92901f},
+ {-12264.0f, -1953.08f, 134.072f, 0.62663f},
+ {-12289.0f, -1924.00f, 132.620f, 5.37829f},
+ {-12267.3f, -1902.26f, 131.328f, 5.32724f},
+ {-12255.3f, -1893.53f, 134.026f, 5.06413f},
+ {-12229.9f, -1891.39f, 134.704f, 4.40047f},
+ {-12215.9f, -1889.09f, 137.273f, 4.70285f},
+ {-12200.5f, -1890.69f, 135.777f, 4.84422f},
+ {-12186.0f, -1890.12f, 134.261f, 4.36513f},
+ {-12246.3f, -1890.09f, 135.475f, 4.73427f},
+ {-12170.7f, -1894.85f, 133.852f, 3.51690f},
+ {-12279.0f, -1931.92f, 136.130f, 0.04151f},
+ {-12266.1f, -1940.72f, 132.606f, 0.70910f}
+};
+
+static SpawnLocations aMandokirDownstairsPos = {-12196.30f, -1948.37f, 130.31f, 3.77f};
+
+struct MANGOS_DLL_DECL boss_mandokirAI : public ScriptedAI
+{
+ boss_mandokirAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_uiOhganGUID = 0;
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiWatch_Timer;
+ uint32 m_uiCleave_Timer;
+ uint32 m_uiWhirlwind_Timer;
+ uint32 m_uiFear_Timer;
+ uint32 m_uiMortalStrike_Timer;
+ uint32 m_uiCheck_Timer;
+
+ uint8 m_uiKillCount;
+
+ bool m_bRaptorDead;
+ bool m_bMandokirDownstairs;
+
+ float m_fTargetThreat;
+ uint64 m_uiWatchTarget;
+ uint64 m_uiOhganGUID;
+
+ void Reset()
+ {
+ m_uiWatch_Timer = 33000;
+ m_uiCleave_Timer = 7000;
+ m_uiWhirlwind_Timer = 20000;
+ m_uiFear_Timer = 1000;
+ m_uiMortalStrike_Timer = 1000;
+ m_uiCheck_Timer = 1000;
+
+ m_uiKillCount = 0;
+
+ m_bRaptorDead = false;
+ m_bMandokirDownstairs = false;
+
+ m_fTargetThreat = 0.0f;
+ m_uiWatchTarget = 0;
+
+ if (Creature* pOhgan = m_creature->GetMap()->GetCreature(m_uiOhganGUID))
+ pOhgan->ForcedDespawn();
+ }
+
+ // should evade to bottom of the stairs when raid fail
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_OHGAN, FAIL);
+
+ std::list lSpirits; //despawn spirits
+ GetCreatureListWithEntryInGrid(lSpirits, m_creature, NPC_CHAINED_SPIRIT, DEFAULT_VISIBILITY_INSTANCE);
+
+ if (!lSpirits.empty())
+ {
+ for(std::list::iterator iter = lSpirits.begin(); iter != lSpirits.end(); ++iter)
+ {
+ if ((*iter) && (*iter)->isAlive())
+ (*iter)->ForcedDespawn();
+ }
+ }
+
+ m_bMandokirDownstairs = false;
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (pVictim->GetTypeId() == TYPEID_PLAYER)
+ {
+ ++m_uiKillCount;
+
+ if (m_uiKillCount == 3)
+ {
+ DoScriptText(SAY_DING_KILL, m_creature);
+
+ if (m_pInstance)
+ {
+ if (Creature* jTemp = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_JINDO)))
+ {
+ if (jTemp->isAlive())
+ DoScriptText(SAY_GRATS_JINDO, jTemp);
+ }
+ }
+
+ DoCastSpellIfCan(m_creature, SPELL_LEVEL_UP, CAST_TRIGGERED);
+ m_creature->SetLevel(m_creature->getLevel() + 1);
+ m_uiKillCount = 0;
+ }
+
+ if (m_creature->isInCombat())
+ {
+ if (Creature *pSpirit = GetClosestCreatureWithEntry(pVictim, NPC_CHAINED_SPIRIT, 50.0f))
+ pSpirit->CastSpell(pVictim, SPELL_REVIVE, false);
+ }
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ m_creature->SetInCombatWithZone();
+
+ uint32 uiCount = sizeof(aSpirits)/sizeof(SpawnLocations);
+
+ for(uint8 i = 0; i < uiCount; ++i)
+ m_creature->SummonCreature(NPC_CHAINED_SPIRIT, aSpirits[i].fX, aSpirits[i].fY, aSpirits[i].fZ, aSpirits[i].fAng, TEMPSUMMON_CORPSE_DESPAWN, 0);
+
+ //At combat start Mandokir is mounted so we must unmount it first
+ m_creature->Unmount();
+
+ //And summon his raptor
+ m_creature->SummonCreature(NPC_OHGAN, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 35000);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_OHGAN)
+ {
+ m_uiOhganGUID = pSummoned->GetGUID();
+
+ if (m_creature->getVictim())
+ pSummoned->AI()->AttackStart(m_creature->getVictim());
+ }
+ }
+
+ void SummonedCreatureDespawn(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_OHGAN)
+ m_uiOhganGUID = 0;
+ }
+
+ void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell)
+ {
+ if (pSpell->Id == SPELL_WATCH)
+ {
+ DoScriptText(SAY_WATCH, m_creature, pTarget);
+ DoScriptText(SAY_WATCH_WHISPER, m_creature, pTarget);
+
+ m_uiWatchTarget = pTarget->GetGUID();
+ m_fTargetThreat = m_creature->getThreatManager().getThreat(pTarget);
+ m_uiWatch_Timer = 6000;
+
+ //Could use this instead of hard coded timer for the above (but no script access),
+ //but would still a hack since we should better use the dummy, at aura removal
+ //SpellDurationEntry* const pDuration = sSpellDurationStore.LookupEntry(pSpell->DurationIndex);
+ }
+ }
+
+ void MovementInform(uint32 uiMoveType, uint32 uiPointId)
+ {
+ if (uiMoveType != POINT_MOTION_TYPE || !m_pInstance)
+ return;
+
+ if (uiPointId == POINT_DOWNSTAIRS)
+ {
+ // evaded at least once, and then attackable
+ if (m_pInstance->GetData(TYPE_OHGAN) == FAIL)
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ else
+ m_creature->SetInCombatWithZone();
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_bMandokirDownstairs && m_pInstance && (m_pInstance->GetData(TYPE_OHGAN) == SPECIAL || m_pInstance->GetData(TYPE_OHGAN) == FAIL))
+ {
+ m_bMandokirDownstairs = true;
+ m_creature->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ m_creature->GetMotionMaster()->MovePoint(POINT_DOWNSTAIRS, aMandokirDownstairsPos.fX, aMandokirDownstairsPos.fY, aMandokirDownstairsPos.fZ);
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiWatch_Timer < uiDiff)
+ {
+ //If someone is watched
+ if (m_uiWatchTarget)
+ {
+ Player* pWatchTarget = m_creature->GetMap()->GetPlayer(m_uiWatchTarget);
+
+ //If threat is higher that previously saved, mandokir will act
+ if (pWatchTarget && pWatchTarget->isAlive() && m_creature->getThreatManager().getThreat(pWatchTarget) > m_fTargetThreat)
+ {
+ if (!m_creature->IsWithinLOSInMap(pWatchTarget))
+ m_creature->CastSpell(pWatchTarget, SPELL_SUMMON_PLAYER, true);
+
+ DoCastSpellIfCan(pWatchTarget, SPELL_CHARGE);
+ }
+
+ m_uiWatchTarget = 0;
+ }
+ else
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ if (Player* pPlayer = pTarget->GetCharmerOrOwnerPlayerOrPlayerItself())
+ m_creature->CastSpell(pPlayer, SPELL_WATCH, false);
+ }
+ }
+
+ m_uiWatch_Timer = 20000;
+ }
+ else
+ m_uiWatch_Timer -= uiDiff;
+
+ if (!m_uiWatchTarget)
+ {
+ //Cleave
+ if (m_uiCleave_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
+ m_uiCleave_Timer = 7000;
+ }
+ else
+ m_uiCleave_Timer -= uiDiff;
+
+ //Whirlwind
+ if (m_uiWhirlwind_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_WHIRLWIND);
+ m_uiWhirlwind_Timer = 18000;
+ }
+ else
+ m_uiWhirlwind_Timer -= uiDiff;
+
+ //If more then 3 targets in melee range mandokir will cast fear
+ if (m_uiFear_Timer < uiDiff)
+ {
+ uint8 uiTargetInRangeCount = 0;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pTarget = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ if (pTarget && pTarget->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(pTarget, ATTACK_DISTANCE))
+ ++uiTargetInRangeCount;
+ }
+
+ if (uiTargetInRangeCount > 3)
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FEAR);
+
+ m_uiFear_Timer = 4000;
+ }
+ else
+ m_uiFear_Timer -= uiDiff;
+
+ //Mortal Strike if target below 50% hp
+ if (m_creature->getVictim()->GetHealthPercent() < 50.0f)
+ {
+ if (m_uiMortalStrike_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_STRIKE);
+ m_uiMortalStrike_Timer = 15000;
+ }
+ else
+ m_uiMortalStrike_Timer -= uiDiff;
+ }
+ }
+
+ //Checking if Ohgan is dead. If yes Mandokir will enrage.
+ if (!m_bRaptorDead && m_pInstance && m_pInstance->GetData(TYPE_OHGAN) == DONE)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ DoScriptText(EMOTE_RAGE, m_creature);
+ m_bRaptorDead = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+//Ohgan
+struct MANGOS_DLL_DECL mob_ohganAI : public ScriptedAI
+{
+ mob_ohganAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiSunderArmor_Timer;
+
+ void Reset()
+ {
+ m_uiSunderArmor_Timer = 5000;
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_OHGAN, DONE);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ if (pVictim->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (m_creature->isInCombat())
+ {
+ if (Creature* pSpirit = GetClosestCreatureWithEntry(pVictim, NPC_CHAINED_SPIRIT, 50.0f))
+ pSpirit->CastSpell(pVictim, SPELL_REVIVE, false);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // SunderArmor
+ if (m_uiSunderArmor_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUNDERARMOR);
+ m_uiSunderArmor_Timer = urand(10000, 15000);
+ }
+ else
+ m_uiSunderArmor_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_mandokir(Creature* pCreature)
+{
+ return new boss_mandokirAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_ohgan(Creature* pCreature)
+{
+ return new mob_ohganAI(pCreature);
+}
+
+void AddSC_boss_mandokir()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_mandokir";
+ newscript->GetAI = &GetAI_boss_mandokir;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_ohgan";
+ newscript->GetAI = &GetAI_mob_ohgan;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp b/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp
new file mode 100644
index 0000000..e8f1323
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp
@@ -0,0 +1,367 @@
+/* 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_Marli
+SD%Complete: 100
+SDComment: Vilebranch Speaker respawned when wipe?
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+enum
+{
+ GO_EGG = 179985,
+
+ // the spider
+ NPC_SPAWN_OF_MARLI = 15041,
+
+ SAY_AGGRO = -1309005,
+ SAY_TRANSFORM = -1309006,
+ SAY_TRANSFORMBACK = -1309024,
+ SAY_SPIDER_SPAWN = -1309007,
+ SAY_DEATH = -1309008,
+
+ SPELL_CHARGE = 22911,
+ SPELL_ENVELOPINGWEBS = 24110,
+ SPELL_POISONVOLLEY = 24099,
+ SPELL_SPIDER_FORM = 24084,
+ SPELL_DRAIN_LIFE = 24300,
+ SPELL_CORROSIVE_POISON = 24111,
+ SPELL_TRANSFORM_BACK = 24085,
+ SPELL_TRASH = 3391,
+ SPELL_HATCH = 24083, //visual
+
+ //The Spider Spells
+ SPELL_LEVELUP = 24312 //visual
+};
+
+struct MANGOS_DLL_DECL boss_marliAI : public ScriptedAI
+{
+ boss_marliAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_uiDefaultModel = m_creature->GetDisplayId();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiPoisonVolley_Timer;
+ uint32 m_uiSpawnSpider_Timer;
+ uint32 m_uiCharge_Timer;
+ uint32 m_uiAspect_Timer;
+ uint32 m_uiTransform_Timer;
+ uint32 m_uiTransformBack_Timer;
+ uint32 m_uiDrainLife_Timer;
+ uint32 m_uiCorrosivePoison_Timer;
+ uint32 m_uiWebs_Timer;
+ uint32 m_uiTrash_Timer;
+
+ bool m_bFirstSpidersAreSpawned;
+ bool m_bIsInPhaseTwo;
+ bool m_bHasWebbed;
+
+ uint32 m_uiDefaultModel;
+
+ void Reset()
+ {
+ m_uiPoisonVolley_Timer = 15000;
+ m_uiSpawnSpider_Timer = 20000;
+ m_uiAspect_Timer = 12000;
+ m_uiTransform_Timer = 60000;
+ m_uiTransformBack_Timer = 60000;
+ m_uiDrainLife_Timer = 30000;
+ m_uiCorrosivePoison_Timer = 1000;
+ m_uiWebs_Timer = 5000;
+ m_uiTrash_Timer = 5000;
+
+ m_bFirstSpidersAreSpawned = false;
+ m_bIsInPhaseTwo = false;
+ m_bHasWebbed = false;
+
+ std::list lSpiderEggs;
+ GetGameObjectListWithEntryInGrid(lSpiderEggs, m_creature, GO_EGG, DEFAULT_VISIBILITY_INSTANCE);
+ if (lSpiderEggs.empty())
+ debug_log("SD2: boss_marli, no Eggs with the entry %u were found", GO_EGG);
+ else
+ {
+ for(std::list::iterator iter = lSpiderEggs.begin(); iter != lSpiderEggs.end(); ++iter)
+ {
+ if ((*iter)->GetGoState() == GO_STATE_ACTIVE)
+ (*iter)->SetGoState(GO_STATE_READY);
+ }
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ if (!m_bFirstSpidersAreSpawned)
+ {
+ DoScriptText(SAY_SPIDER_SPAWN, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_HATCH);
+
+ for(uint8 i = 0; i < 4 ; ++i)
+ {
+ if (GameObject *pEgg = SelectNextEgg())
+ {
+ pEgg->SetGoState(GO_STATE_ACTIVE);
+ m_creature->SummonCreature(NPC_SPAWN_OF_MARLI, pEgg->GetPositionX(), pEgg->GetPositionY(), pEgg->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ }
+ }
+
+ m_bFirstSpidersAreSpawned = true;
+ }
+ }
+
+ GameObject* SelectNextEgg()
+ {
+ std::list lEggs;
+ GetGameObjectListWithEntryInGrid(lEggs, m_creature, GO_EGG, DEFAULT_VISIBILITY_INSTANCE);
+ if (lEggs.empty())
+ debug_log("SD2: boss_marli, no Eggs with the entry %i were found", GO_EGG);
+ else
+ {
+ lEggs.sort(ObjectDistanceOrder(m_creature));
+ for(std::list::iterator iter = lEggs.begin(); iter != lEggs.end(); ++iter)
+ {
+ if ((*iter)->GetGoState() == (GO_STATE_READY))
+ return (*iter);
+ }
+ }
+ return NULL;
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == NPC_SPAWN_OF_MARLI)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ pSummoned->AI()->AttackStart(pTarget);
+ }
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_MARLI, DONE);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!m_bIsInPhaseTwo)
+ {
+ if (m_uiPoisonVolley_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_POISONVOLLEY);
+ m_uiPoisonVolley_Timer = urand(10000, 20000);
+ }
+ else
+ m_uiPoisonVolley_Timer -= uiDiff;
+
+ if (m_uiDrainLife_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_DRAIN_LIFE);
+ m_uiDrainLife_Timer = urand(20000, 50000);
+ }
+ else
+ m_uiDrainLife_Timer -= uiDiff;
+
+ if (m_uiSpawnSpider_Timer < uiDiff)
+ {
+ if (GameObject *pEgg = SelectNextEgg())
+ {
+ pEgg->SetGoState(GO_STATE_ACTIVE);
+ m_creature->SummonCreature(NPC_SPAWN_OF_MARLI, pEgg->GetPositionX(), pEgg->GetPositionY(), pEgg->GetPositionZ(),0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ }
+ m_uiSpawnSpider_Timer = urand(20000, 30000);
+ }
+ else
+ m_uiSpawnSpider_Timer -= uiDiff;
+ }
+ else
+ {
+ if (!m_bHasWebbed && m_uiWebs_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ENVELOPINGWEBS);
+ m_uiWebs_Timer = urand(10000, 15000);
+ m_uiCharge_Timer = 1000;
+ m_bHasWebbed = true;
+ }
+ else
+ m_uiWebs_Timer -= uiDiff;
+
+ if (m_bHasWebbed && m_uiCharge_Timer < uiDiff)
+ {
+ //Shouldn't be random target but highestaggro not Webbed player
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ DoCastSpellIfCan(pTarget, SPELL_CHARGE);
+ DoResetThreat();
+ AttackStart(pTarget);
+ m_bHasWebbed = false;
+ /*
+ DoResetThreat();
+ Unit* pTarget = NULL;
+ uint8 i = 0 ;
+ while (i < 5) // max 3 tries to get a random target with power_mana
+ {
+ ++i; //not aggro leader
+ pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (pTarget && pTarget->getPowerType() == POWER_MANA)
+ i=5;
+ }
+ */
+ }
+ m_uiWebs_Timer = urand(10000, 20000);
+ }
+ else
+ m_uiCharge_Timer -= uiDiff;
+
+ if (m_uiCorrosivePoison_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_CORROSIVE_POISON);
+ m_uiCorrosivePoison_Timer = urand(25000, 35000);
+ }
+ else
+ m_uiCorrosivePoison_Timer -= uiDiff;
+ }
+
+ if (m_uiTransformBack_Timer < uiDiff)
+ {
+ if (!m_bIsInPhaseTwo)
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoScriptText(SAY_TRANSFORM, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_SPIDER_FORM);
+
+ const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 35)));
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 35)));
+ m_creature->UpdateDamagePhysical(BASE_ATTACK);
+
+ DoResetThreat();
+
+ m_bIsInPhaseTwo = true;
+ }
+ else
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoScriptText(SAY_TRANSFORMBACK, m_creature);
+ DoCastSpellIfCan(m_creature,SPELL_TRANSFORM_BACK);
+
+ m_creature->SetDisplayId(m_uiDefaultModel);
+
+ const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 1)));
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 1)));
+ m_creature->UpdateDamagePhysical(BASE_ATTACK);
+
+ m_bIsInPhaseTwo = false;
+ }
+
+ m_uiTransformBack_Timer = urand(55000, 70000);
+ }
+ else
+ m_uiTransformBack_Timer -= uiDiff;
+
+ if (m_uiTrash_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_TRASH);
+ m_uiTrash_Timer = urand(10000, 20000);
+ }
+ else
+ m_uiTrash_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+//Spawn of Marli
+struct MANGOS_DLL_DECL mob_spawn_of_marliAI : public ScriptedAI
+{
+ mob_spawn_of_marliAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ Reset();
+ m_pInstance = (ScriptedInstance*)m_creature->GetInstanceData();
+ }
+
+ ScriptedInstance* m_pInstance;
+ uint32 m_uiLevelUp_Timer;
+
+ void Reset()
+ {
+ m_uiLevelUp_Timer = 3000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiLevelUp_Timer < uiDiff)
+ {
+ if (m_pInstance && m_pInstance->GetData(TYPE_MARLI) != DONE)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_LEVELUP);
+ m_creature->SetLevel(m_creature->getLevel() + 1);
+ }
+ m_uiLevelUp_Timer = 3000;
+ }
+ else
+ m_uiLevelUp_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_marli(Creature* pCreature)
+{
+ return new boss_marliAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_spawn_of_marli(Creature* pCreature)
+{
+ return new mob_spawn_of_marliAI(pCreature);
+}
+
+void AddSC_boss_marli()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_marli";
+ newscript->GetAI = &GetAI_boss_marli;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_spawn_of_marli";
+ newscript->GetAI = &GetAI_mob_spawn_of_marli;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp b/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp
new file mode 100644
index 0000000..d33bcc6
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp
@@ -0,0 +1,145 @@
+/* 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_Renataki
+SD%Complete: 100
+SDComment:
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+#define SPELL_AMBUSH 24337
+#define SPELL_THOUSANDBLADES 24649
+
+#define EQUIP_ID_MAIN_HAND 0 //was item display id 31818, but this id does not exist
+
+struct MANGOS_DLL_DECL boss_renatakiAI : public ScriptedAI
+{
+ boss_renatakiAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Invisible_Timer;
+ uint32 Ambush_Timer;
+ uint32 Visible_Timer;
+ uint32 Aggro_Timer;
+ uint32 ThousandBlades_Timer;
+
+ bool Invisible;
+ bool Ambushed;
+
+ void Reset()
+ {
+ Invisible_Timer = urand(8000, 18000);
+ Ambush_Timer = 3000;
+ Visible_Timer = 4000;
+ Aggro_Timer = urand(15000, 25000);
+ ThousandBlades_Timer = urand(4000, 8000);
+
+ Invisible = false;
+ Ambushed = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Invisible_Timer
+ if (Invisible_Timer < diff)
+ {
+ m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
+
+ SetEquipmentSlots(false, EQUIP_UNEQUIP, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
+ m_creature->SetDisplayId(11686);
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ Invisible = true;
+
+ Invisible_Timer = urand(15000, 30000);
+ }else Invisible_Timer -= diff;
+
+ if (Invisible)
+ {
+ if (Ambush_Timer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ m_creature->NearTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f);
+ DoCastSpellIfCan(pTarget, SPELL_AMBUSH);
+ }
+
+ Ambushed = true;
+ Ambush_Timer = 3000;
+ }else Ambush_Timer -= diff;
+ }
+
+ if (Ambushed)
+ {
+ if (Visible_Timer < diff)
+ {
+ m_creature->InterruptSpell(CURRENT_GENERIC_SPELL);
+
+ m_creature->SetDisplayId(15268);
+ SetEquipmentSlots(false, EQUIP_ID_MAIN_HAND, EQUIP_NO_CHANGE, EQUIP_NO_CHANGE);
+
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ Invisible = false;
+
+ Visible_Timer = 4000;
+ }else Visible_Timer -= diff;
+ }
+
+ //Resetting some aggro so he attacks other gamers
+ if (!Invisible)
+ if (Aggro_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1);
+
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-50);
+
+ if (target)
+ AttackStart(target);
+
+ Aggro_Timer = urand(7000, 20000);
+ }else Aggro_Timer -= diff;
+
+ if (!Invisible)
+ if (ThousandBlades_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_THOUSANDBLADES);
+ ThousandBlades_Timer = urand(7000, 12000);
+ }else ThousandBlades_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_renataki(Creature* pCreature)
+{
+ return new boss_renatakiAI(pCreature);
+}
+
+void AddSC_boss_renataki()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_renataki";
+ newscript->GetAI = &GetAI_boss_renataki;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp b/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp
new file mode 100644
index 0000000..528ddcd
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp
@@ -0,0 +1,545 @@
+/* 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_Thekal
+SD%Complete: 95
+SDComment: Almost finished.
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+#define SAY_AGGRO -1309009
+#define SAY_DEATH -1309010
+
+#define SPELL_MORTALCLEAVE 22859
+#define SPELL_SILENCE 23207
+#define SPELL_FRENZY 23342
+#define SPELL_FORCEPUNCH 24189
+#define SPELL_CHARGE 24408
+#define SPELL_ENRAGE 23537
+#define SPELL_SUMMONTIGERS 24183
+#define SPELL_TIGER_FORM 24169
+#define SPELL_RESURRECT 24173 //We will not use this spell.
+
+//Zealot Lor'Khan Spells
+#define SPELL_SHIELD 25020
+#define SPELL_BLOODLUST 24185
+#define SPELL_GREATERHEAL 24208
+#define SPELL_DISARM 22691
+
+//Zealot Lor'Khan Spells
+#define SPELL_SWEEPINGSTRIKES 18765
+#define SPELL_SINISTERSTRIKE 15667
+#define SPELL_GOUGE 24698
+#define SPELL_KICK 15614
+#define SPELL_BLIND 21060
+
+struct MANGOS_DLL_DECL boss_thekalAI : public ScriptedAI
+{
+ boss_thekalAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 MortalCleave_Timer;
+ uint32 Silence_Timer;
+ uint32 Frenzy_Timer;
+ uint32 ForcePunch_Timer;
+ uint32 Charge_Timer;
+ uint32 Enrage_Timer;
+ uint32 SummonTigers_Timer;
+ uint32 Check_Timer;
+ uint32 Resurrect_Timer;
+
+ bool Enraged;
+ bool PhaseTwo;
+ bool WasDead;
+
+ void Reset()
+ {
+ MortalCleave_Timer = 4000;
+ Silence_Timer = 9000;
+ Frenzy_Timer = 30000;
+ ForcePunch_Timer = 4000;
+ Charge_Timer = 12000;
+ Enrage_Timer = 32000;
+ SummonTigers_Timer = 25000;
+ Check_Timer = 10000;
+ Resurrect_Timer = 10000;
+
+ Enraged = false;
+ PhaseTwo = false;
+ WasDead = false;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_THEKAL, DONE);
+ }
+
+ void JustReachedHome()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_THEKAL, NOT_STARTED);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Check_Timer for the death of LorKhan and Zath.
+ if (!WasDead && Check_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL)
+ {
+ //Resurrect LorKhan
+ if (Creature *pLorKhan = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_LORKHAN)))
+ {
+ pLorKhan->SetStandState(UNIT_STAND_STATE_STAND);
+ pLorKhan->setFaction(14);
+ pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0));
+
+ m_pInstance->SetData(TYPE_LORKHAN, DONE);
+ }
+ }
+
+ if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL)
+ {
+ //Resurrect Zath
+ if (Creature *pZath = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ZATH)))
+ {
+ pZath->SetStandState(UNIT_STAND_STATE_STAND);
+ pZath->setFaction(14);
+ pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pZath->SetHealth(int(pZath->GetMaxHealth()*1.0));
+
+ m_pInstance->SetData(TYPE_ZATH, DONE);
+ }
+ }
+ }
+ Check_Timer = 5000;
+ }else Check_Timer -= diff;
+
+ if (!PhaseTwo && MortalCleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MORTALCLEAVE);
+ MortalCleave_Timer = urand(15000, 20000);
+ }else MortalCleave_Timer -= diff;
+
+ if (!PhaseTwo && Silence_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SILENCE);
+ Silence_Timer = urand(20000, 25000);
+ }else Silence_Timer -= diff;
+
+ if (!PhaseTwo && !WasDead && m_creature->GetHealthPercent() < 5.0f)
+ {
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetStandState(UNIT_STAND_STATE_SLEEP);
+ m_creature->AttackStop();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_THEKAL, SPECIAL);
+
+ WasDead = true;
+ }
+
+ //Thekal will transform to Tiger if he died and was not resurrected after 10 seconds.
+ if (!PhaseTwo && WasDead)
+ {
+ if (Resurrect_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_TIGER_FORM);
+ m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, 2.00f);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetHealth(int(m_creature->GetMaxHealth()*1.0));
+ const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 40)));
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 40)));
+ m_creature->UpdateDamagePhysical(BASE_ATTACK);
+ DoResetThreat();
+ PhaseTwo = true;
+ }else Resurrect_Timer -= diff;
+ }
+
+ if (m_creature->GetHealthPercent() == 100.0f && WasDead)
+ {
+ WasDead = false;
+ }
+
+ if (PhaseTwo)
+ {
+ if (Charge_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ {
+ DoCastSpellIfCan(target,SPELL_CHARGE);
+ DoResetThreat();
+ AttackStart(target);
+ }
+ Charge_Timer = urand(15000, 22000);
+ }else Charge_Timer -= diff;
+
+ if (Frenzy_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_FRENZY);
+ Frenzy_Timer = 30000;
+ }else Frenzy_Timer -= diff;
+
+ if (ForcePunch_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SILENCE);
+ ForcePunch_Timer = urand(16000, 21000);
+ }else ForcePunch_Timer -= diff;
+
+ if (SummonTigers_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SUMMONTIGERS);
+ SummonTigers_Timer = urand(10000, 14000);
+ }else SummonTigers_Timer -= diff;
+
+ if (m_creature->GetHealthPercent() < 11.0f && !Enraged)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ Enraged = true;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+//Zealot Lor'Khan
+struct MANGOS_DLL_DECL mob_zealot_lorkhanAI : public ScriptedAI
+{
+ mob_zealot_lorkhanAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ uint32 Shield_Timer;
+ uint32 BloodLust_Timer;
+ uint32 GreaterHeal_Timer;
+ uint32 Disarm_Timer;
+ uint32 Check_Timer;
+
+ bool FakeDeath;
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ Shield_Timer = 1000;
+ BloodLust_Timer = 16000;
+ GreaterHeal_Timer = 32000;
+ Disarm_Timer = 6000;
+ Check_Timer = 10000;
+
+ FakeDeath = false;
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_LORKHAN, NOT_STARTED);
+
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void UpdateAI (const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Shield_Timer
+ if (Shield_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_SHIELD);
+ Shield_Timer = 61000;
+ }else Shield_Timer -= diff;
+
+ //BloodLust_Timer
+ if (BloodLust_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_BLOODLUST);
+ BloodLust_Timer = urand(20000, 28000);
+ }else BloodLust_Timer -= diff;
+
+ //Casting Greaterheal to Thekal or Zath if they are in meele range.
+ if (GreaterHeal_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ Creature* pThekal = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_THEKAL));
+ Creature* pZath = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ZATH));
+
+ switch(urand(0, 1))
+ {
+ case 0:
+ if (pThekal && m_creature->IsWithinDistInMap(pThekal, ATTACK_DISTANCE))
+ DoCastSpellIfCan(pThekal, SPELL_GREATERHEAL);
+ break;
+ case 1:
+ if (pZath && m_creature->IsWithinDistInMap(pZath, ATTACK_DISTANCE))
+ DoCastSpellIfCan(pZath, SPELL_GREATERHEAL);
+ break;
+ }
+ }
+
+ GreaterHeal_Timer = urand(15000, 20000);
+ }else GreaterHeal_Timer -= diff;
+
+ //Disarm_Timer
+ if (Disarm_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_DISARM);
+ Disarm_Timer = urand(15000, 25000);
+ }else Disarm_Timer -= diff;
+
+ //Check_Timer for the death of LorKhan and Zath.
+ if (!FakeDeath && Check_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL)
+ {
+ //Resurrect Thekal
+ if (Creature* pThekal = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_THEKAL)))
+ {
+ pThekal->SetStandState(UNIT_STAND_STATE_STAND);
+ pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pThekal->setFaction(14);
+ pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0));
+ }
+ }
+
+ if (m_pInstance->GetData(TYPE_ZATH) == SPECIAL)
+ {
+ //Resurrect Zath
+ if (Creature* pZath = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_ZATH)))
+ {
+ pZath->SetStandState(UNIT_STAND_STATE_STAND);
+ pZath->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pZath->setFaction(14);
+ pZath->SetHealth(int(pZath->GetMaxHealth()*1.0));
+ }
+ }
+ }
+
+ Check_Timer = 5000;
+ }else Check_Timer -= diff;
+
+ if (m_creature->GetHealthPercent() < 5.0f)
+ {
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetStandState(UNIT_STAND_STATE_SLEEP);
+ m_creature->setFaction(35);
+ m_creature->AttackStop();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_LORKHAN, SPECIAL);
+
+ FakeDeath = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+//Zealot Zath
+struct MANGOS_DLL_DECL mob_zealot_zathAI : public ScriptedAI
+{
+ mob_zealot_zathAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ uint32 SweepingStrikes_Timer;
+ uint32 SinisterStrike_Timer;
+ uint32 Gouge_Timer;
+ uint32 Kick_Timer;
+ uint32 Blind_Timer;
+ uint32 Check_Timer;
+
+ bool FakeDeath;
+
+ ScriptedInstance* m_pInstance;
+
+ void Reset()
+ {
+ SweepingStrikes_Timer = 13000;
+ SinisterStrike_Timer = 8000;
+ Gouge_Timer = 25000;
+ Kick_Timer = 18000;
+ Blind_Timer = 5000;
+ Check_Timer = 10000;
+
+ FakeDeath = false;
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ZATH, NOT_STARTED);
+
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ void UpdateAI (const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //SweepingStrikes_Timer
+ if (SweepingStrikes_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SWEEPINGSTRIKES);
+ SweepingStrikes_Timer = urand(22000, 26000);
+ }else SweepingStrikes_Timer -= diff;
+
+ //SinisterStrike_Timer
+ if (SinisterStrike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SINISTERSTRIKE);
+ SinisterStrike_Timer = urand(8000, 16000);
+ }else SinisterStrike_Timer -= diff;
+
+ //Gouge_Timer
+ if (Gouge_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_GOUGE);
+
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-100);
+
+ Gouge_Timer = urand(17000, 27000);
+ }else Gouge_Timer -= diff;
+
+ //Kick_Timer
+ if (Kick_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KICK);
+ Kick_Timer = urand(15000, 25000);
+ }else Kick_Timer -= diff;
+
+ //Blind_Timer
+ if (Blind_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_BLIND);
+ Blind_Timer = urand(10000, 20000);
+ }else Blind_Timer -= diff;
+
+ //Check_Timer for the death of LorKhan and Zath.
+ if (!FakeDeath && Check_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_LORKHAN) == SPECIAL)
+ {
+ //Resurrect LorKhan
+ if (Creature* pLorKhan = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_LORKHAN)))
+ {
+ pLorKhan->SetStandState(UNIT_STAND_STATE_STAND);
+ pLorKhan->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pLorKhan->setFaction(14);
+ pLorKhan->SetHealth(int(pLorKhan->GetMaxHealth()*1.0));
+ }
+ }
+
+ if (m_pInstance->GetData(TYPE_THEKAL) == SPECIAL)
+ {
+ //Resurrect Thekal
+ if (Creature* pThekal = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_THEKAL)))
+ {
+ pThekal->SetStandState(UNIT_STAND_STATE_STAND);
+ pThekal->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ pThekal->setFaction(14);
+ pThekal->SetHealth(int(pThekal->GetMaxHealth()*1.0));
+ }
+ }
+ }
+
+ Check_Timer = 5000;
+ }else Check_Timer -= diff;
+
+ if (m_creature->GetHealthPercent() <= 5.0f)
+ {
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetStandState(UNIT_STAND_STATE_SLEEP);
+ m_creature->setFaction(35);
+ m_creature->AttackStop();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ZATH, SPECIAL);
+
+ FakeDeath = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_thekal(Creature* pCreature)
+{
+ return new boss_thekalAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_zealot_lorkhan(Creature* pCreature)
+{
+ return new mob_zealot_lorkhanAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_zealot_zath(Creature* pCreature)
+{
+ return new mob_zealot_zathAI(pCreature);
+}
+
+void AddSC_boss_thekal()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_thekal";
+ newscript->GetAI = &GetAI_boss_thekal;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_zealot_lorkhan";
+ newscript->GetAI = &GetAI_mob_zealot_lorkhan;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_zealot_zath";
+ newscript->GetAI = &GetAI_mob_zealot_zath;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp b/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp
new file mode 100644
index 0000000..30cc000
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp
@@ -0,0 +1,265 @@
+/* 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_Venoxis
+SD%Complete: 100
+SDComment:
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+enum
+{
+ NPC_RAZZASHI_COBRA = 11373,
+
+ SAY_TRANSFORM = -1309000,
+ SAY_DEATH = -1309001,
+
+ SPELL_HOLY_FIRE = 23860,
+ SPELL_HOLY_WRATH = 23979,
+ SPELL_VENOMSPIT = 23862,
+ SPELL_HOLY_NOVA = 23858,
+ SPELL_POISON_CLOUD = 23861,
+ SPELL_SNAKE_FORM = 23849,
+ SPELL_RENEW = 23895,
+ SPELL_BERSERK = 23537,
+ SPELL_DISPELL = 23859,
+ SPELL_PARASITIC = 23865,
+ SPELL_TRASH = 3391
+};
+
+struct MANGOS_DLL_DECL boss_venoxisAI : public ScriptedAI
+{
+ boss_venoxisAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_fDefaultSize = m_creature->GetFloatValue(OBJECT_FIELD_SCALE_X);
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 m_uiHolyFire_Timer;
+ uint32 m_uiHolyWrath_Timer;
+ uint32 m_uiVenomSpit_Timer;
+ uint32 m_uiRenew_Timer;
+ uint32 m_uiPoisonCloud_Timer;
+ uint32 m_uiHolyNova_Timer;
+ uint32 m_uiDispell_Timer;
+ uint32 m_uiParasitic_Timer;
+ uint32 m_uiTrash_Timer;
+
+ uint8 m_uiTargetsInRangeCount;
+
+ bool m_bPhaseTwo;
+ bool m_bInBerserk;
+
+ float m_fDefaultSize;
+
+ void Reset()
+ {
+ m_uiHolyFire_Timer = 10000;
+ m_uiHolyWrath_Timer = 60500;
+ m_uiVenomSpit_Timer = 5500;
+ m_uiRenew_Timer = 30500;
+ m_uiPoisonCloud_Timer = 2000;
+ m_uiHolyNova_Timer = 5000;
+ m_uiDispell_Timer = 35000;
+ m_uiParasitic_Timer = 10000;
+ m_uiTrash_Timer = 5000;
+
+ m_uiTargetsInRangeCount = 0;
+
+ m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fDefaultSize);
+
+ m_bPhaseTwo = false;
+ m_bInBerserk = false;
+ }
+
+ void JustReachedHome()
+ {
+ std::list m_lCobras;
+ GetCreatureListWithEntryInGrid(m_lCobras, m_creature, NPC_RAZZASHI_COBRA, DEFAULT_VISIBILITY_INSTANCE);
+
+ if (m_lCobras.empty())
+ debug_log("SD2: boss_venoxis, no Cobras with the entry %u were found", NPC_RAZZASHI_COBRA);
+ else
+ {
+ for(std::list::iterator iter = m_lCobras.begin(); iter != m_lCobras.end(); ++iter)
+ {
+ if ((*iter) && !(*iter)->isAlive())
+ (*iter)->Respawn();
+ }
+ }
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_VENOXIS, DONE);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (!m_bPhaseTwo && (m_creature->GetHealth()+uiDamage)*100 / m_creature->GetMaxHealth() < 50)
+ {
+ DoScriptText(SAY_TRANSFORM, m_creature);
+
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(m_creature,SPELL_SNAKE_FORM);
+
+ m_creature->SetFloatValue(OBJECT_FIELD_SCALE_X, m_fDefaultSize*2);
+ const CreatureInfo *cinfo = m_creature->GetCreatureInfo();
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, (cinfo->mindmg +((cinfo->mindmg/100) * 25)));
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, (cinfo->maxdmg +((cinfo->maxdmg/100) * 25)));
+ m_creature->UpdateDamagePhysical(BASE_ATTACK);
+ DoResetThreat();
+ m_bPhaseTwo = true;
+ }
+
+ if (m_bPhaseTwo && !m_bInBerserk && (m_creature->GetHealth()+uiDamage)*100 / m_creature->GetMaxHealth() < 11)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(m_creature, SPELL_BERSERK);
+ m_bInBerserk = true;
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!m_bPhaseTwo)
+ {
+ if (m_uiDispell_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_DISPELL);
+ m_uiDispell_Timer = urand(15000, 30000);
+ }
+ else
+ m_uiDispell_Timer -= uiDiff;
+
+ if (m_uiRenew_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_RENEW);
+ m_uiRenew_Timer = urand(20000, 30000);
+ }
+ else
+ m_uiRenew_Timer -= uiDiff;
+
+ if (m_uiHolyWrath_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HOLY_WRATH);
+ m_uiHolyWrath_Timer = urand(15000, 25000);
+ }
+ else
+ m_uiHolyWrath_Timer -= uiDiff;
+
+ if (m_uiHolyNova_Timer < uiDiff)
+ {
+ m_uiTargetsInRangeCount = 0;
+ for(uint8 i = 0; i < 10; ++i)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_TOPAGGRO,i))
+ if (m_creature->IsWithinDistInMap(pTarget, ATTACK_DISTANCE))
+ ++m_uiTargetsInRangeCount;
+ }
+
+ if (m_uiTargetsInRangeCount > 1)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_HOLY_NOVA);
+ m_uiHolyNova_Timer = 1000;
+ }
+ else
+ {
+ m_uiHolyNova_Timer = 2000;
+ }
+ }
+ else
+ m_uiHolyNova_Timer -= uiDiff;
+
+ if (m_uiHolyFire_Timer < uiDiff && m_uiTargetsInRangeCount < 3)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget, SPELL_HOLY_FIRE);
+
+ m_uiHolyFire_Timer = 8000;
+ }
+ else
+ m_uiHolyFire_Timer -= uiDiff;
+ }
+ else
+ {
+ if (m_uiPoisonCloud_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_POISON_CLOUD);
+ m_uiPoisonCloud_Timer = 15000;
+ }
+ else
+ m_uiPoisonCloud_Timer -= uiDiff;
+
+ if (m_uiVenomSpit_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget, SPELL_VENOMSPIT);
+
+ m_uiVenomSpit_Timer = urand(15000, 20000);
+ }
+ else
+ m_uiVenomSpit_Timer -= uiDiff;
+
+ if (m_uiParasitic_Timer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(pTarget, SPELL_PARASITIC);
+
+ m_uiParasitic_Timer = 10000;
+ }
+ else
+ m_uiParasitic_Timer -= uiDiff;
+ }
+
+ if (m_uiTrash_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_TRASH);
+ m_uiTrash_Timer = urand(10000, 20000);
+ }
+ else
+ m_uiTrash_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_venoxis(Creature* pCreature)
+{
+ return new boss_venoxisAI(pCreature);
+}
+
+void AddSC_boss_venoxis()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_venoxis";
+ newscript->GetAI = &GetAI_boss_venoxis;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp b/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp
new file mode 100644
index 0000000..7cabb8e
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp
@@ -0,0 +1,80 @@
+/* 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_Wushoolay
+SD%Complete: 100
+SDComment:
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+#define SPELL_LIGHTNINGCLOUD 25033
+#define SPELL_LIGHTNINGWAVE 24819
+
+struct MANGOS_DLL_DECL boss_wushoolayAI : public ScriptedAI
+{
+ boss_wushoolayAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 LightningCloud_Timer;
+ uint32 LightningWave_Timer;
+
+ void Reset()
+ {
+ LightningCloud_Timer = urand(5000, 10000);
+ LightningWave_Timer = urand(8000, 16000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //LightningCloud_Timer
+ if (LightningCloud_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_LIGHTNINGCLOUD);
+ LightningCloud_Timer = urand(15000, 20000);
+ }else LightningCloud_Timer -= diff;
+
+ //LightningWave_Timer
+ if (LightningWave_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target) DoCastSpellIfCan(target,SPELL_LIGHTNINGWAVE);
+
+ LightningWave_Timer = urand(12000, 16000);
+ }else LightningWave_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_wushoolay(Creature* pCreature)
+{
+ return new boss_wushoolayAI(pCreature);
+}
+
+void AddSC_boss_wushoolay()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_wushoolay";
+ newscript->GetAI = &GetAI_boss_wushoolay;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp b/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp
new file mode 100644
index 0000000..8246820
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp
@@ -0,0 +1,244 @@
+/* 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_ZulGurub
+SD%Complete: 80
+SDComment: Missing reset function after killing a boss for Ohgan, Thekal.
+SDCategory: Zul'Gurub
+EndScriptData */
+
+#include "precompiled.h"
+#include "zulgurub.h"
+
+struct MANGOS_DLL_DECL instance_zulgurub : public ScriptedInstance
+{
+ instance_zulgurub(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ std::string strInstData;
+ // If all High Priest bosses were killed. Lorkhan, Zath and Ohgan are added too.
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ // Storing Lorkhan, Zath and Thekal because we need to cast on them later. Jindo is needed for heal function too.
+ uint64 m_uiLorKhanGUID;
+ uint64 m_uiZathGUID;
+ uint64 m_uiThekalGUID;
+ uint64 m_uiJindoGUID;
+ uint64 m_uiHakkarGUID;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiLorKhanGUID = 0;
+ m_uiZathGUID = 0;
+ m_uiThekalGUID = 0;
+ m_uiJindoGUID = 0;
+ m_uiHakkarGUID = 0;
+ }
+
+ // each time High Priest dies lower Hakkar's HP
+ void LowerHakkarHitPoints()
+ {
+ if (Creature* pHakkar = instance->GetCreature(m_uiHakkarGUID))
+ {
+ if (pHakkar->isAlive())
+ {
+ pHakkar->SetMaxHealth(pHakkar->GetMaxHealth() - 60000);
+ pHakkar->SetHealth(pHakkar->GetHealth() - 60000);
+ }
+ }
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ //not active in Zul'Gurub
+ return false;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case NPC_LORKHAN:
+ m_uiLorKhanGUID = pCreature->GetGUID();
+ break;
+ case NPC_ZATH:
+ m_uiZathGUID = pCreature->GetGUID();
+ break;
+ case NPC_THEKAL:
+ m_uiThekalGUID = pCreature->GetGUID();
+ break;
+ case NPC_JINDO:
+ m_uiJindoGUID = pCreature->GetGUID();
+ break;
+ case NPC_HAKKAR:
+ m_uiHakkarGUID = pCreature->GetGUID();
+ for(uint8 i = 0; i < 5; ++i)
+ {
+ if (m_auiEncounter[i] == DONE)
+ LowerHakkarHitPoints();
+ }
+ break;
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_ARLOKK:
+ m_auiEncounter[0] = uiData;
+ if (uiData == DONE)
+ LowerHakkarHitPoints();
+ break;
+ case TYPE_JEKLIK:
+ m_auiEncounter[1] = uiData;
+ if (uiData == DONE)
+ LowerHakkarHitPoints();
+ break;
+ case TYPE_VENOXIS:
+ m_auiEncounter[2] = uiData;
+ if (uiData == DONE)
+ LowerHakkarHitPoints();
+ break;
+ case TYPE_MARLI:
+ m_auiEncounter[3] = uiData;
+ if (uiData == DONE)
+ LowerHakkarHitPoints();
+ break;
+ case TYPE_THEKAL:
+ m_auiEncounter[4] = uiData;
+ if (uiData == DONE)
+ LowerHakkarHitPoints();
+ break;
+ case TYPE_LORKHAN:
+ m_auiEncounter[5] = uiData;
+ break;
+ case TYPE_ZATH:
+ m_auiEncounter[6] = uiData;
+ break;
+ case TYPE_OHGAN:
+ m_auiEncounter[7] = uiData;
+ break;
+ case TYPE_HAKKAR:
+ m_auiEncounter[8] = 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] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " "
+ << m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ const char* Save()
+ {
+ return strInstData.c_str();
+ }
+
+ void Load(const char* chrIn)
+ {
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
+ >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7]
+ >> m_auiEncounter[8];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_ARLOKK:
+ return m_auiEncounter[0];
+ case TYPE_JEKLIK:
+ return m_auiEncounter[1];
+ case TYPE_VENOXIS:
+ return m_auiEncounter[2];
+ case TYPE_MARLI:
+ return m_auiEncounter[3];
+ case TYPE_THEKAL:
+ return m_auiEncounter[4];
+ case TYPE_LORKHAN:
+ return m_auiEncounter[5];
+ case TYPE_ZATH:
+ return m_auiEncounter[6];
+ case TYPE_OHGAN:
+ return m_auiEncounter[7];
+ case TYPE_HAKKAR:
+ return m_auiEncounter[8];
+ }
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_LORKHAN:
+ return m_uiLorKhanGUID;
+ case DATA_ZATH:
+ return m_uiZathGUID;
+ case DATA_THEKAL:
+ return m_uiThekalGUID;
+ case DATA_JINDO:
+ return m_uiJindoGUID;
+ case DATA_HAKKAR:
+ return m_uiHakkarGUID;
+ }
+ return 0;
+ }
+};
+
+InstanceData* GetInstanceData_instance_zulgurub(Map* pMap)
+{
+ return new instance_zulgurub(pMap);
+}
+
+void AddSC_instance_zulgurub()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "instance_zulgurub";
+ newscript->GetInstanceData = &GetInstanceData_instance_zulgurub;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/eastern_kingdoms/zulgurub/zulgurub.h b/scripts/eastern_kingdoms/zulgurub/zulgurub.h
new file mode 100644
index 0000000..7aed3df
--- /dev/null
+++ b/scripts/eastern_kingdoms/zulgurub/zulgurub.h
@@ -0,0 +1,35 @@
+/* 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 */
+
+#ifndef DEF_ZULGURUB_H
+#define DEF_ZULGURUB_H
+
+enum
+{
+ MAX_ENCOUNTER = 9,
+
+ NPC_LORKHAN = 11347,
+ NPC_ZATH = 11348,
+ NPC_THEKAL = 14509,
+ NPC_JINDO = 11380,
+ NPC_HAKKAR = 14834,
+
+ TYPE_ARLOKK = 1,
+ TYPE_JEKLIK = 2,
+ TYPE_VENOXIS = 3,
+ TYPE_MARLI = 4,
+ TYPE_OHGAN = 5,
+ TYPE_THEKAL = 6,
+ TYPE_ZATH = 7,
+ TYPE_LORKHAN = 8,
+ TYPE_HAKKAR = 9,
+
+ DATA_JINDO = 10,
+ DATA_LORKHAN = 11,
+ DATA_THEKAL = 12,
+ DATA_ZATH = 13,
+ DATA_HAKKAR = 14
+};
+
+#endif
diff --git a/scripts/examples/example_creature.cpp b/scripts/examples/example_creature.cpp
new file mode 100644
index 0000000..dcea997
--- /dev/null
+++ b/scripts/examples/example_creature.cpp
@@ -0,0 +1,272 @@
+/* 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: Example_Creature
+SD%Complete: 100
+SDComment: Short custom scripting example
+SDCategory: Script Examples
+EndScriptData */
+
+#include "precompiled.h"
+
+// **** This script is designed as an example for others to build on ****
+// **** Please modify whatever you'd like to as this script is only for developement ****
+
+// **** Script Info ****
+// This script is written in a way that it can be used for both friendly and hostile monsters
+// Its primary purpose is to show just how much you can really do with scripts
+// I recommend trying it out on both an agressive NPC and on friendly npc
+
+// **** Quick Info ****
+// Functions with Handled Function marked above them are functions that are called automatically by the core
+// Functions that are marked Custom Function are functions I've created to simplify code
+
+enum
+{
+ //List of text id's. The text is stored in database, also in a localized version
+ //(if translation not exist for the textId, default english text will be used)
+ //Not required to define in this way, but simplify if changes are needed.
+ SAY_AGGRO = -1999900,
+ SAY_RANDOM_0 = -1999901,
+ SAY_RANDOM_1 = -1999902,
+ SAY_RANDOM_2 = -1999903,
+ SAY_RANDOM_3 = -1999904,
+ SAY_RANDOM_4 = -1999905,
+ SAY_BESERK = -1999906,
+ SAY_PHASE = -1999907,
+ SAY_DANCE = -1999908,
+ SAY_SALUTE = -1999909,
+
+ //List of spells. Not required to define them in this way, but will make it easier to maintain in case spellId change
+ SPELL_BUFF = 25661,
+ SPELL_ONE = 12555,
+ SPELL_ONE_ALT = 24099,
+ SPELL_TWO = 10017,
+ SPELL_THREE = 26027,
+ SPELL_ENRAGE = 23537,
+ SPELL_BESERK = 32309,
+
+ FACTION_WORGEN = 24
+};
+
+//List of gossip item texts. Items will appear in the gossip window.
+#define GOSSIP_ITEM "I'm looking for a fight"
+
+struct MANGOS_DLL_DECL example_creatureAI : public ScriptedAI
+{
+ //*** HANDLED FUNCTION ***
+ //This is the constructor, called only once when the creature is first created
+ example_creatureAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ //*** CUSTOM VARIABLES ****
+ //These variables are for use only by this individual script.
+ //Nothing else will ever call them but us.
+
+ uint32 m_uiSay_Timer; //Timer for random chat
+ uint32 m_uiRebuff_Timer; //Timer for rebuffing
+ uint32 m_uiSpell_1_Timer; //Timer for spell 1 when in combat
+ uint32 m_uiSpell_2_Timer; //Timer for spell 1 when in combat
+ uint32 m_uiSpell_3_Timer; //Timer for spell 1 when in combat
+ uint32 m_uiBeserk_Timer; //Timer until we go into Beserk (enraged) mode
+ uint32 m_uiPhase; //The current battle phase we are in
+ uint32 m_uiPhase_Timer; //Timer until phase transition
+
+ //*** HANDLED FUNCTION ***
+ //This is called whenever the core decides we need to evade
+ void Reset()
+ {
+ m_uiPhase = 1; //Start in phase 1
+ m_uiPhase_Timer = 60000; //60 seconds
+ m_uiSpell_1_Timer = 5000; //5 seconds
+ m_uiSpell_2_Timer = 37000; //37 seconds
+ m_uiSpell_3_Timer = 19000; //19 seconds
+ m_uiBeserk_Timer = 120000; //2 minutes
+ }
+
+ //*** HANDLED FUNCTION ***
+ //Attack Start is called whenever someone hits us.
+ void Aggro(Unit* pWho)
+ {
+ //Say some stuff
+ DoScriptText(SAY_AGGRO, m_creature, pWho);
+ }
+
+ //Our Recive emote function
+ void ReceiveEmote(Player* pPlayer, uint32 uiTextEmote)
+ {
+ m_creature->HandleEmote(uiTextEmote);
+
+ switch(uiTextEmote)
+ {
+ case TEXTEMOTE_DANCE:
+ DoScriptText(SAY_DANCE, m_creature);
+ break;
+ case TEXTEMOTE_SALUTE:
+ DoScriptText(SAY_SALUTE, m_creature);
+ break;
+ }
+ }
+
+ //*** HANDLED FUNCTION ***
+ //Update AI is called Every single map update (roughly once every 100ms if a player is within the grid)
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Out of combat timers
+ if (!m_creature->getVictim())
+ {
+ //Random Say timer
+ if (m_uiSay_Timer < uiDiff)
+ {
+ //Random switch between 5 outcomes
+ switch(urand(0, 4))
+ {
+ case 0: DoScriptText(SAY_RANDOM_0, m_creature); break;
+ case 1: DoScriptText(SAY_RANDOM_1, m_creature); break;
+ case 2: DoScriptText(SAY_RANDOM_2, m_creature); break;
+ case 3: DoScriptText(SAY_RANDOM_3, m_creature); break;
+ case 4: DoScriptText(SAY_RANDOM_4, m_creature); break;
+ }
+
+ m_uiSay_Timer = 45000; //Say something agian in 45 seconds
+ }
+ else
+ m_uiSay_Timer -= uiDiff;
+
+ //Rebuff timer
+ if (m_uiRebuff_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BUFF);
+ m_uiRebuff_Timer = 900000; //Rebuff agian in 15 minutes
+ }
+ else
+ m_uiRebuff_Timer -= uiDiff;
+ }
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Spell 1 timer
+ if (m_uiSpell_1_Timer < uiDiff)
+ {
+ //Cast spell one on our current target.
+ if (rand()%50 > 10)
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_ONE_ALT);
+ else if (m_creature->IsWithinDist(m_creature->getVictim(), 25.0f))
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_ONE);
+
+ m_uiSpell_1_Timer = 5000;
+ }
+ else
+ m_uiSpell_1_Timer -= uiDiff;
+
+ //Spell 2 timer
+ if (m_uiSpell_2_Timer < uiDiff)
+ {
+ //Cast spell one on our current target.
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_TWO);
+ m_uiSpell_2_Timer = 37000;
+ }
+ else
+ m_uiSpell_2_Timer -= uiDiff;
+
+ //Beserk timer
+ if (m_uiPhase > 1)
+ {
+ //Spell 3 timer
+ if (m_uiSpell_3_Timer < uiDiff)
+ {
+ //Cast spell one on our current target.
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_THREE);
+
+ m_uiSpell_3_Timer = 19000;
+ }
+ else
+ m_uiSpell_3_Timer -= uiDiff;
+
+ if (m_uiBeserk_Timer < uiDiff)
+ {
+ //Say our line then cast uber death spell
+ DoScriptText(SAY_BESERK, m_creature, m_creature->getVictim());
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_BESERK);
+
+ //Cast our beserk spell agian in 12 seconds if we didn't kill everyone
+ m_uiBeserk_Timer = 12000;
+ }
+ else
+ m_uiBeserk_Timer -= uiDiff;
+ }
+ else if (m_uiPhase == 1) //Phase timer
+ {
+ if (m_uiPhase_Timer < uiDiff)
+ {
+ //Go to next phase
+ ++m_uiPhase;
+ DoScriptText(SAY_PHASE, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ }
+ else
+ m_uiPhase_Timer -= uiDiff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+//This is the GetAI method used by all scripts that involve AI
+//It is called every time a new creature using this script is created
+CreatureAI* GetAI_example_creature(Creature* pCreature)
+{
+ return new example_creatureAI(pCreature);
+}
+
+//This function is called when the player clicks an option on the gossip menu
+bool GossipSelect_example_creature(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ //Set our faction to hostile twoards all
+ pCreature->setFaction(FACTION_WORGEN);
+ pCreature->AI()->AttackStart(pPlayer);
+ }
+
+ return true;
+}
+
+//This function is called when the player opens the gossip menu
+bool GossipHello_example_creature(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID());
+
+ return true;
+}
+
+//This is the actual function called only once durring InitScripts()
+//It must define all handled functions that are to be run in this script
+void AddSC_example_creature()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "example_creature";
+ newscript->GetAI = &GetAI_example_creature;
+ newscript->pGossipHello = &GossipHello_example_creature;
+ newscript->pGossipSelect = &GossipSelect_example_creature;
+ newscript->RegisterSelf(false);
+}
diff --git a/scripts/examples/example_escort.cpp b/scripts/examples/example_escort.cpp
new file mode 100644
index 0000000..566e5b0
--- /dev/null
+++ b/scripts/examples/example_escort.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: Example_Escort
+SD%Complete: 100
+SDComment: Script used for testing escortAI
+SDCategory: Script Examples
+EndScriptData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+enum
+{
+ NPC_FELBOAR = 21878,
+
+ SPELL_DEATH_COIL = 33130,
+ SPELL_ELIXIR_OF_FORTITUDE = 3593,
+ SPELL_BLUE_FIREWORK = 11540,
+
+ SAY_AGGRO1 = -1999910,
+ SAY_AGGRO2 = -1999911,
+ SAY_WP_1 = -1999912,
+ SAY_WP_2 = -1999913,
+ SAY_WP_3 = -1999914,
+ SAY_WP_4 = -1999915,
+ SAY_DEATH_1 = -1999916,
+ SAY_DEATH_2 = -1999917,
+ SAY_DEATH_3 = -1999918,
+ SAY_SPELL = -1999919,
+ SAY_RAND_1 = -1999920,
+ SAY_RAND_2 = -1999921
+};
+
+#define GOSSIP_ITEM_1 "Click to Test Escort(Attack, Run)"
+#define GOSSIP_ITEM_2 "Click to Test Escort(NoAttack, Walk)"
+#define GOSSIP_ITEM_3 "Click to Test Escort(NoAttack, Run)"
+
+struct MANGOS_DLL_DECL example_escortAI : public npc_escortAI
+{
+ // CreatureAI functions
+ example_escortAI(Creature* pCreature) : npc_escortAI(pCreature) {Reset();}
+
+ uint32 m_uiDeathCoilTimer;
+ uint32 m_uiChatTimer;
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->AI()->AttackStart(m_creature);
+ }
+
+ // Pure Virtual Functions (Have to be implemented)
+ void WaypointReached(uint32 uiWP)
+ {
+ switch (uiWP)
+ {
+ case 1:
+ DoScriptText(SAY_WP_1, m_creature);
+ break;
+ case 3:
+ DoScriptText(SAY_WP_2, m_creature);
+ m_creature->SummonCreature(NPC_FELBOAR, m_creature->GetPositionX()+5.0f, m_creature->GetPositionY()+7.0f, m_creature->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000);
+ break;
+ case 4:
+ if (Player* pTmpPlayer = GetPlayerForEscort())
+ {
+ //pTmpPlayer is the target of the text
+ DoScriptText(SAY_WP_3, m_creature, pTmpPlayer);
+ //pTmpPlayer is the source of the text
+ DoScriptText(SAY_WP_4, pTmpPlayer);
+ }
+ break;
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ if (Player* pTemp = GetPlayerForEscort())
+ DoScriptText(SAY_AGGRO1, m_creature, pTemp);
+ }
+ else
+ DoScriptText(SAY_AGGRO2, m_creature);
+ }
+
+ void Reset()
+ {
+ m_uiDeathCoilTimer = 4000;
+ m_uiChatTimer = 4000;
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ if (Player* pTemp = GetPlayerForEscort())
+ {
+ // not a likely case, code here for the sake of example
+ if (pKiller == m_creature)
+ {
+ //This is actually a whisper. You control the text type in database
+ DoScriptText(SAY_DEATH_1, m_creature, pTemp);
+ }
+ else
+ DoScriptText(SAY_DEATH_2, m_creature, pTemp);
+ }
+ }
+ else
+ DoScriptText(SAY_DEATH_3, m_creature);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ //Must update npc_escortAI
+ npc_escortAI::UpdateAI(uiDiff);
+
+ //Combat check
+ if (m_creature->getVictim())
+ {
+ if (m_uiDeathCoilTimer < uiDiff)
+ {
+ DoScriptText(SAY_SPELL, m_creature);
+ m_creature->CastSpell(m_creature->getVictim(), SPELL_DEATH_COIL, false);
+ m_uiDeathCoilTimer = 4000;
+ }
+ else
+ m_uiDeathCoilTimer -= uiDiff;
+ }
+ else
+ {
+ //Out of combat but being escorted
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ if (m_uiChatTimer < uiDiff)
+ {
+ if (m_creature->HasAura(SPELL_ELIXIR_OF_FORTITUDE, EFFECT_INDEX_0))
+ {
+ DoScriptText(SAY_RAND_1, m_creature);
+ m_creature->CastSpell(m_creature, SPELL_BLUE_FIREWORK, false);
+ }
+ else
+ {
+ DoScriptText(SAY_RAND_2, m_creature);
+ m_creature->CastSpell(m_creature, SPELL_ELIXIR_OF_FORTITUDE, false);
+ }
+
+ m_uiChatTimer = 12000;
+ }
+ else
+ m_uiChatTimer -= uiDiff;
+ }
+ }
+ }
+};
+
+CreatureAI* GetAI_example_escort(Creature* pCreature)
+{
+ return new example_escortAI(pCreature);
+}
+
+bool GossipHello_example_escort(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID());
+ pPlayer->PrepareGossipMenu(pCreature, 0);
+
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+
+ pPlayer->SendPreparedGossip(pCreature);
+
+ return true;
+}
+
+bool GossipSelect_example_escort(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ example_escortAI* pEscortAI = dynamic_cast(pCreature->AI());
+
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (pEscortAI)
+ pEscortAI->Start(true, pPlayer->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (pEscortAI)
+ pEscortAI->Start(false, pPlayer->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (pEscortAI)
+ pEscortAI->Start(true, pPlayer->GetGUID());
+ break;
+ default:
+ return false; // nothing defined -> mangos core handling
+ }
+
+ return true; // no default handling -> prevent mangos core handling
+}
+
+void AddSC_example_escort()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "example_escort";
+ newscript->GetAI = &GetAI_example_escort;
+ newscript->pGossipHello = &GossipHello_example_escort;
+ newscript->pGossipSelect = &GossipSelect_example_escort;
+ newscript->RegisterSelf(false);
+}
diff --git a/scripts/examples/example_gossip_codebox.cpp b/scripts/examples/example_gossip_codebox.cpp
new file mode 100644
index 0000000..ddf3056
--- /dev/null
+++ b/scripts/examples/example_gossip_codebox.cpp
@@ -0,0 +1,99 @@
+/* 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: Example_Gossip_Codebox
+SD%Complete: 100
+SDComment: Show a codebox in gossip option
+SDCategory: Script Examples
+EndScriptData */
+
+#include "precompiled.h"
+#include
+
+enum
+{
+ SPELL_POLYMORPH = 12826,
+ SPELL_MARK_OF_THE_WILD = 26990,
+
+ SAY_NOT_INTERESTED = -1999922,
+ SAY_WRONG = -1999923,
+ SAY_CORRECT = -1999924
+};
+
+#define GOSSIP_ITEM_1 "A quiz: what's your name?"
+#define GOSSIP_ITEM_2 "I'm not interested"
+
+//This function is called when the player opens the gossip menubool
+bool GossipHello_example_gossip_codebox(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->ADD_GOSSIP_ITEM_EXTENDED(0, GOSSIP_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1, "", 0, true);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+
+ pPlayer->PlayerTalkClass->SendGossipMenu(907, pCreature->GetGUID());
+
+ return true;
+}
+
+//This function is called when the player clicks an option on the gossip menubool
+bool GossipSelect_example_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+2)
+ {
+ DoScriptText(SAY_NOT_INTERESTED, pCreature);
+ pPlayer->CLOSE_GOSSIP_MENU();
+ }
+
+ return true;
+}
+
+bool GossipSelectWithCode_example_gossip_codebox(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction, const char* sCode)
+{
+ if (uiSender == GOSSIP_SENDER_MAIN)
+ {
+ switch (uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ if (std::strcmp(sCode, pPlayer->GetName())!=0)
+ {
+ DoScriptText(SAY_WRONG, pCreature);
+ pCreature->CastSpell(pPlayer, SPELL_POLYMORPH, true);
+ }
+ else
+ {
+ DoScriptText(SAY_CORRECT, pCreature);
+ pCreature->CastSpell(pPlayer, SPELL_MARK_OF_THE_WILD, true);
+ }
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void AddSC_example_gossip_codebox()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "example_gossip_codebox";
+ newscript->pGossipHello = &GossipHello_example_gossip_codebox;
+ newscript->pGossipSelect = &GossipSelect_example_gossip_codebox;
+ newscript->pGossipSelectWithCode = &GossipSelectWithCode_example_gossip_codebox;
+ newscript->RegisterSelf(false);
+}
diff --git a/scripts/examples/example_misc.cpp b/scripts/examples/example_misc.cpp
new file mode 100644
index 0000000..de4437d
--- /dev/null
+++ b/scripts/examples/example_misc.cpp
@@ -0,0 +1,68 @@
+/* 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: Example_Misc
+SD%Complete: 100
+SDComment: Item, Areatrigger and other small code examples
+SDCategory: Script Examples
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_HI = -1999925
+};
+
+bool AT_example_areatrigger(Player* pPlayer, AreaTriggerEntry const* pAt)
+{
+ DoScriptText(SAY_HI, pPlayer);
+ return true;
+}
+
+extern void LoadDatabase();
+bool ItemUse_example_item(Player* pPlayer, Item* pItem, SpellCastTargets const& scTargets)
+{
+ LoadDatabase();
+ return true;
+}
+
+bool GOHello_example_go_teleporter(Player* pPlayer, GameObject* pGo)
+{
+ pPlayer->TeleportTo(0, 1807.07f, 336.105f, 70.3975f, 0.0f);
+ return false;
+}
+
+void AddSC_example_misc()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "example_areatrigger";
+ newscript->pAreaTrigger = &AT_example_areatrigger;
+ newscript->RegisterSelf(false);
+
+ newscript = new Script;
+ newscript->Name = "example_item";
+ newscript->pItemUse = &ItemUse_example_item;
+ newscript->RegisterSelf(false);
+
+ newscript = new Script;
+ newscript->Name = "example_go_teleporter";
+ newscript->pGOHello = &GOHello_example_go_teleporter;
+ newscript->RegisterSelf(false);
+}
diff --git a/scripts/kalimdor/ashenvale.cpp b/scripts/kalimdor/ashenvale.cpp
new file mode 100644
index 0000000..4512d3c
--- /dev/null
+++ b/scripts/kalimdor/ashenvale.cpp
@@ -0,0 +1,447 @@
+/* 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: Ashenvale
+SD%Complete: 70
+SDComment: Quest support: 6482, 6544, 6641
+SDCategory: Ashenvale Forest
+EndScriptData */
+
+/* ContentData
+npc_muglash
+npc_ruul_snowhoof
+npc_torek
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*####
+# npc_muglash
+####*/
+
+enum
+{
+ SAY_MUG_START1 = -1000501,
+ SAY_MUG_START2 = -1000502,
+ SAY_MUG_BRAZIER = -1000503,
+ SAY_MUG_BRAZIER_WAIT = -1000504,
+ SAY_MUG_ON_GUARD = -1000505,
+ SAY_MUG_REST = -1000506,
+ SAY_MUG_DONE = -1000507,
+ SAY_MUG_GRATITUDE = -1000508,
+ SAY_MUG_PATROL = -1000509,
+ SAY_MUG_RETURN = -1000510,
+
+ QUEST_VORSHA = 6641,
+
+ GO_NAGA_BRAZIER = 178247,
+ NPC_MUGLASH = 12717,
+
+ NPC_WRATH_RIDER = 3713,
+ NPC_WRATH_SORCERESS = 3717,
+ NPC_WRATH_RAZORTAIL = 3712,
+
+ NPC_WRATH_PRIESTESS = 3944,
+ NPC_WRATH_MYRMIDON = 3711,
+ NPC_WRATH_SEAWITCH = 3715,
+
+ NPC_VORSHA = 12940
+};
+
+static float m_afFirstNagaCoord[3][3]=
+{
+ {3603.504150f, 1122.631104f, 1.635f}, // rider
+ {3589.293945f, 1148.664063f, 5.565f}, // sorceress
+ {3609.925537f, 1168.759521f, -1.168f} // razortail
+};
+
+static float m_afSecondNagaCoord[3][3]=
+{
+ {3609.925537f, 1168.759521f, -1.168f}, // witch
+ {3645.652100f, 1139.425415f, 1.322f}, // priest
+ {3583.602051f, 1128.405762f, 2.347f} // myrmidon
+};
+
+static float m_fVorshaCoord[] = {3633.056885f, 1172.924072f, -5.388f};
+
+struct MANGOS_DLL_DECL npc_muglashAI : public npc_escortAI
+{
+ npc_muglashAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_uiWaveId = 0;
+ m_bIsBrazierExtinguished = false;
+ Reset();
+ }
+
+ bool m_bIsBrazierExtinguished;
+
+ uint32 m_uiWaveId;
+ uint32 m_uiEventTimer;
+
+ void Reset()
+ {
+ m_uiEventTimer = 10000;
+
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ m_uiWaveId = 0;
+ m_bIsBrazierExtinguished = false;
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ if (HasEscortState(STATE_ESCORT_PAUSED))
+ {
+ if (urand(0, 1))
+ return;
+
+ if (Player* pPlayer = GetPlayerForEscort())
+ DoScriptText(SAY_MUG_ON_GUARD, m_creature, pPlayer);
+ }
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 0:
+ if (Player* pPlayer = GetPlayerForEscort())
+ DoScriptText(SAY_MUG_START2, m_creature, pPlayer);
+ break;
+ case 24:
+ if (Player* pPlayer = GetPlayerForEscort())
+ DoScriptText(SAY_MUG_BRAZIER, m_creature, pPlayer);
+
+ if (GameObject* pGo = GetClosestGameObjectWithEntry(m_creature, GO_NAGA_BRAZIER, INTERACTION_DISTANCE*2))
+ {
+ //some kind of event flag? Update to player/group only?
+ pGo->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_UNK1);
+ SetEscortPaused(true);
+ }
+ break;
+ case 25:
+ DoScriptText(SAY_MUG_GRATITUDE, m_creature);
+
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_VORSHA, m_creature);
+ break;
+ case 26:
+ DoScriptText(SAY_MUG_PATROL, m_creature);
+ break;
+ case 27:
+ DoScriptText(SAY_MUG_RETURN, m_creature);
+ break;
+ }
+ }
+
+ void DoWaveSummon()
+ {
+ switch(m_uiWaveId)
+ {
+ case 1:
+ m_creature->SummonCreature(NPC_WRATH_RIDER, m_afFirstNagaCoord[0][0], m_afFirstNagaCoord[0][1], m_afFirstNagaCoord[0][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
+ m_creature->SummonCreature(NPC_WRATH_SORCERESS, m_afFirstNagaCoord[1][0], m_afFirstNagaCoord[1][1], m_afFirstNagaCoord[1][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
+ m_creature->SummonCreature(NPC_WRATH_RAZORTAIL, m_afFirstNagaCoord[2][0], m_afFirstNagaCoord[2][1], m_afFirstNagaCoord[2][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
+ break;
+ case 2:
+ m_creature->SummonCreature(NPC_WRATH_PRIESTESS, m_afSecondNagaCoord[0][0], m_afSecondNagaCoord[0][1], m_afSecondNagaCoord[0][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
+ m_creature->SummonCreature(NPC_WRATH_MYRMIDON, m_afSecondNagaCoord[1][0], m_afSecondNagaCoord[1][1], m_afSecondNagaCoord[1][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
+ m_creature->SummonCreature(NPC_WRATH_SEAWITCH, m_afSecondNagaCoord[2][0], m_afSecondNagaCoord[2][1], m_afSecondNagaCoord[2][2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
+ break;
+ case 3:
+ m_creature->SummonCreature(NPC_VORSHA, m_fVorshaCoord[0], m_fVorshaCoord[1], m_fVorshaCoord[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
+ break;
+ case 4:
+ SetEscortPaused(false);
+ DoScriptText(SAY_MUG_DONE, m_creature);
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->AI()->AttackStart(m_creature);
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ if (HasEscortState(STATE_ESCORT_PAUSED) && m_bIsBrazierExtinguished)
+ {
+ if (m_uiEventTimer < uiDiff)
+ {
+ ++m_uiWaveId;
+ DoWaveSummon();
+ m_uiEventTimer = 10000;
+ }
+ else
+ m_uiEventTimer -= uiDiff;
+ }
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool QuestAccept_npc_muglash(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_VORSHA)
+ {
+ if (npc_muglashAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ {
+ DoScriptText(SAY_MUG_START1, pCreature);
+ pCreature->setFaction(FACTION_ESCORT_H_PASSIVE);
+
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ }
+
+ return true;
+}
+
+CreatureAI* GetAI_npc_muglash(Creature* pCreature)
+{
+ return new npc_muglashAI(pCreature);
+}
+
+bool GOHello_go_naga_brazier(Player* pPlayer, GameObject* pGo)
+{
+ if (Creature* pCreature = GetClosestCreatureWithEntry(pGo, NPC_MUGLASH, INTERACTION_DISTANCE*2))
+ {
+ if (npc_muglashAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ {
+ DoScriptText(SAY_MUG_BRAZIER_WAIT, pCreature);
+
+ pEscortAI->m_bIsBrazierExtinguished = true;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*####
+# npc_ruul_snowhoof
+####*/
+
+enum
+{
+ QUEST_FREEDOM_TO_RUUL = 6482,
+ NPC_T_URSA = 3921,
+ NPC_T_TOTEMIC = 3922,
+ NPC_T_PATHFINDER = 3926
+};
+
+struct MANGOS_DLL_DECL npc_ruul_snowhoofAI : public npc_escortAI
+{
+ npc_ruul_snowhoofAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void Reset() {}
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 13:
+ m_creature->SummonCreature(NPC_T_TOTEMIC, 3449.218018f, -587.825073f, 174.978867f, 4.714445f, TEMPSUMMON_DEAD_DESPAWN, 60000);
+ m_creature->SummonCreature(NPC_T_URSA, 3446.384521f, -587.830872f, 175.186279f, 4.714445f, TEMPSUMMON_DEAD_DESPAWN, 60000);
+ m_creature->SummonCreature(NPC_T_PATHFINDER, 3444.218994f, -587.835327f, 175.380600f, 4.714445f, TEMPSUMMON_DEAD_DESPAWN, 60000);
+ break;
+ case 19:
+ m_creature->SummonCreature(NPC_T_TOTEMIC, 3508.344482f, -492.024261f, 186.929031f, 4.145029f, TEMPSUMMON_DEAD_DESPAWN, 60000);
+ m_creature->SummonCreature(NPC_T_URSA, 3506.265625f, -490.531006f, 186.740128f, 4.239277f, TEMPSUMMON_DEAD_DESPAWN, 60000);
+ m_creature->SummonCreature(NPC_T_PATHFINDER, 3503.682373f, -489.393799f, 186.629684f, 4.349232f, TEMPSUMMON_DEAD_DESPAWN, 60000);
+ break;
+ case 21:
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_FREEDOM_TO_RUUL, m_creature);
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* summoned)
+ {
+ summoned->AI()->AttackStart(m_creature);
+ }
+};
+
+bool QuestAccept_npc_ruul_snowhoof(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_FREEDOM_TO_RUUL)
+ {
+ pCreature->setFaction(FACTION_ESCORT_N_NEUTRAL_PASSIVE);
+ pCreature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ if (npc_ruul_snowhoofAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_ruul_snowhoofAI(Creature* pCreature)
+{
+ return new npc_ruul_snowhoofAI(pCreature);
+}
+
+/*####
+# npc_torek
+####*/
+
+enum
+{
+ SAY_READY = -1000106,
+ SAY_MOVE = -1000107,
+ SAY_PREPARE = -1000108,
+ SAY_WIN = -1000109,
+ SAY_END = -1000110,
+
+ SPELL_REND = 11977,
+ SPELL_THUNDERCLAP = 8078,
+
+ QUEST_TOREK_ASSULT = 6544,
+
+ NPC_SPLINTERTREE_RAIDER = 12859,
+ NPC_DURIEL = 12860,
+ NPC_SILVERWING_SENTINEL = 12896,
+ NPC_SILVERWING_WARRIOR = 12897
+};
+
+struct MANGOS_DLL_DECL npc_torekAI : public npc_escortAI
+{
+ npc_torekAI(Creature* pCreature) : npc_escortAI(pCreature) {Reset();}
+
+ uint32 m_uiRend_Timer;
+ uint32 m_uiThunderclap_Timer;
+
+ void Reset()
+ {
+ m_uiRend_Timer = 5000;
+ m_uiThunderclap_Timer = 8000;
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch(uiPointId)
+ {
+ case 1:
+ DoScriptText(SAY_MOVE, m_creature, pPlayer);
+ break;
+ case 8:
+ DoScriptText(SAY_PREPARE, m_creature, pPlayer);
+ break;
+ case 19:
+ //TODO: verify location and creatures amount.
+ m_creature->SummonCreature(NPC_DURIEL, 1776.73f, -2049.06f, 109.83f, 1.54f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000);
+ m_creature->SummonCreature(NPC_SILVERWING_SENTINEL, 1774.64f, -2049.41f, 109.83f, 1.40f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000);
+ m_creature->SummonCreature(NPC_SILVERWING_WARRIOR, 1778.73f, -2049.50f, 109.83f, 1.67f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,25000);
+ break;
+ case 20:
+ DoScriptText(SAY_WIN, m_creature, pPlayer);
+ pPlayer->GroupEventHappens(QUEST_TOREK_ASSULT, m_creature);
+ break;
+ case 21:
+ DoScriptText(SAY_END, m_creature, pPlayer);
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->AI()->AttackStart(m_creature);
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiRend_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_REND);
+ m_uiRend_Timer = 20000;
+ }
+ else
+ m_uiRend_Timer -= uiDiff;
+
+ if (m_uiThunderclap_Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_THUNDERCLAP);
+ m_uiThunderclap_Timer = 30000;
+ }
+ else
+ m_uiThunderclap_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool QuestAccept_npc_torek(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_TOREK_ASSULT)
+ {
+ //TODO: find companions, make them follow Torek, at any time (possibly done by mangos/database in future?)
+ DoScriptText(SAY_READY, pCreature, pPlayer);
+
+ if (npc_torekAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(true, pPlayer->GetGUID(), pQuest);
+ }
+
+ return true;
+}
+
+CreatureAI* GetAI_npc_torek(Creature* pCreature)
+{
+ return new npc_torekAI(pCreature);
+}
+
+void AddSC_ashenvale()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_muglash";
+ newscript->GetAI = &GetAI_npc_muglash;
+ newscript->pQuestAccept = &QuestAccept_npc_muglash;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "go_naga_brazier";
+ newscript->pGOHello = &GOHello_go_naga_brazier;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_ruul_snowhoof";
+ newscript->GetAI = &GetAI_npc_ruul_snowhoofAI;
+ newscript->pQuestAccept = &QuestAccept_npc_ruul_snowhoof;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_torek";
+ newscript->GetAI = &GetAI_npc_torek;
+ newscript->pQuestAccept = &QuestAccept_npc_torek;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/azshara.cpp b/scripts/kalimdor/azshara.cpp
new file mode 100644
index 0000000..ac8409b
--- /dev/null
+++ b/scripts/kalimdor/azshara.cpp
@@ -0,0 +1,392 @@
+/* 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: Azshara
+SD%Complete: 90
+SDComment: Quest support: 2744, 3141, 9364, 10994
+SDCategory: Azshara
+EndScriptData */
+
+/* ContentData
+npc_rizzle_sprysprocket
+npc_depth_charge
+go_southfury_moonstone
+mobs_spitelashes
+npc_loramus_thalipedes
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*#####
+## npc_rizzle_sprysprocket
+#####*/
+
+enum
+{
+ SAY_START = -1000351,
+ EMOTE_START = -1000352,
+ SAY_WHISPER_CHILL = -1000353,
+ SAY_GRENADE_FAIL = -1000354,
+ SAY_END = -1000355,
+
+ QUEST_MOONSTONE = 10994,
+ NPC_RIZZLE = 23002,
+ NPC_DEPTH_CHARGE = 23025,
+
+ SPELL_SUMMON_RIZZLE = 39866,
+ SPELL_BLACKJACK = 39865, //stuns player
+ SPELL_ESCAPE = 39871, //teleports to water
+ SPELL_SWIM_SPEED = 40596,
+
+ SPELL_FROST_TRAP = 39902, //not used?
+
+ SPELL_PERIODIC_GRENADE = 40553, //cannot tell who are supposed to have this aura
+ SPELL_FROST_GRENADE = 40525, //triggered by periodic grenade
+
+ SPELL_SUMMON_DEPTH_CHARGE = 39907, //summons the bomb creature
+ SPELL_TRAP = 39899, //knockback
+
+ SPELL_PERIODIC_CHECK = 39888,
+ SPELL_SURRENDER = 39889, //should be triggered by periodic check, if player comes in certain distance with quest incomplete
+
+ SPELL_GIVE_MOONSTONE = 39886
+};
+
+#define GOSSIP_ITEM_MOONSTONE "Hand over the Southfury moonstone and I'll let you go."
+
+struct MANGOS_DLL_DECL npc_rizzle_sprysprocketAI : public npc_escortAI
+{
+ npc_rizzle_sprysprocketAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ pCreature->SetActiveObjectState(true);
+ m_bIsIntro = true;
+ m_uiIntroPhase = 0;
+ m_uiIntroTimer = 0;
+ m_uiDepthChargeTimer = 10000;
+ Reset();
+ }
+
+ bool m_bIsIntro;
+ uint8 m_uiIntroPhase;
+ uint32 m_uiIntroTimer;
+ uint32 m_uiDepthChargeTimer;
+
+ void MoveInLineOfSight(Unit* pUnit)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && pUnit->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (!HasEscortState(STATE_ESCORT_PAUSED) && m_creature->IsWithinDistInMap(pUnit, INTERACTION_DISTANCE) && m_creature->IsWithinLOSInMap(pUnit))
+ {
+ if (((Player*)pUnit)->GetQuestStatus(QUEST_MOONSTONE) == QUEST_STATUS_INCOMPLETE)
+ m_creature->CastSpell(m_creature, SPELL_SURRENDER, true);
+ }
+ }
+
+ npc_escortAI::MoveInLineOfSight(pUnit);
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 0:
+ m_creature->CastSpell(m_creature,SPELL_PERIODIC_CHECK,true);
+ break;
+ }
+ }
+
+ void Reset() { }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (pSpell->Id == SPELL_SURRENDER)
+ {
+ SetEscortPaused(true);
+ DoScriptText(SAY_END, m_creature);
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
+ }
+
+ //this may be wrong (and doesn't work)
+ void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell)
+ {
+ if (pTarget->GetTypeId() == TYPEID_PLAYER && pSpell->Id == SPELL_FROST_GRENADE)
+ DoScriptText(SAY_WHISPER_CHILL, m_creature, pTarget);
+ }
+
+ //this may be wrong
+ void JustSummoned(Creature* pSummoned)
+ {
+ //pSummoned->CastSpell(pSummoned,SPELL_PERIODIC_GRENADE,false,0,0,m_creature->GetGUID());
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (m_bIsIntro)
+ {
+ if (m_uiIntroTimer < uiDiff)
+ m_uiIntroTimer = 1500;
+ else
+ {
+ m_uiIntroTimer -= uiDiff;
+ return;
+ }
+
+ switch(m_uiIntroPhase)
+ {
+ case 0:
+ DoScriptText(SAY_START, m_creature);
+ DoScriptText(EMOTE_START, m_creature);
+ break;
+ case 1:
+ //teleports to water _before_ we Start()
+ m_creature->CastSpell(m_creature, SPELL_ESCAPE, false);
+ break;
+ case 2:
+ m_creature->CastSpell(m_creature, SPELL_SWIM_SPEED, false);
+ m_bIsIntro = false;
+ Start(true);
+ break;
+ }
+
+ ++m_uiIntroPhase;
+ return;
+ }
+
+ if (m_uiDepthChargeTimer < uiDiff)
+ {
+ if (!HasEscortState(STATE_ESCORT_PAUSED))
+ m_creature->CastSpell(m_creature, SPELL_SUMMON_DEPTH_CHARGE, false);
+
+ m_uiDepthChargeTimer = urand(10000, 15000);
+ }
+ else
+ m_uiDepthChargeTimer -= uiDiff;
+ }
+};
+
+CreatureAI* GetAI_npc_rizzle_sprysprocket(Creature* pCreature)
+{
+ return new npc_rizzle_sprysprocketAI(pCreature);
+}
+
+bool GossipHello_npc_rizzle_sprysprocket(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(QUEST_MOONSTONE) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_MOONSTONE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_rizzle_sprysprocket(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->CastSpell(pPlayer, SPELL_GIVE_MOONSTONE, false);
+ }
+
+ return true;
+}
+
+struct MANGOS_DLL_DECL npc_depth_chargeAI : public ScriptedAI
+{
+ npc_depth_chargeAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ void MoveInLineOfSight(Unit* pUnit)
+ {
+ if (pUnit->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ if (m_creature->IsWithinDistInMap(pUnit, INTERACTION_DISTANCE) && m_creature->IsWithinLOSInMap(pUnit))
+ m_creature->CastSpell(pUnit, SPELL_TRAP, false);
+ }
+
+ void Reset() { }
+};
+
+CreatureAI* GetAI_npc_depth_charge(Creature* pCreature)
+{
+ return new npc_depth_chargeAI(pCreature);
+}
+
+/*######
+## go_southfury_moonstone
+######*/
+
+bool GOHello_go_southfury_moonstone(Player* pPlayer, GameObject* pGo)
+{
+ //implicitTarget=48 not implemented as of writing this code, and manual summon may be just ok for our purpose
+ //pPlayer->CastSpell(pPlayer,SPELL_SUMMON_RIZZLE,false);
+
+ if (Creature* pCreature = pPlayer->SummonCreature(NPC_RIZZLE, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_DEAD_DESPAWN, 0))
+ pCreature->CastSpell(pPlayer, SPELL_BLACKJACK, false);
+
+ return false;
+}
+
+/*######
+## mobs_spitelashes
+######*/
+
+struct MANGOS_DLL_DECL mobs_spitelashesAI : public ScriptedAI
+{
+ mobs_spitelashesAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 morphtimer;
+ bool spellhit;
+
+ void Reset()
+ {
+ morphtimer = 0;
+ spellhit = false;
+ }
+
+ void SpellHit(Unit *Hitter, const SpellEntry *Spellkind)
+ {
+ if (!spellhit &&
+ Hitter->GetTypeId() == TYPEID_PLAYER &&
+ ((Player*)Hitter)->GetQuestStatus(9364) == QUEST_STATUS_INCOMPLETE &&
+ (Spellkind->Id==118 || Spellkind->Id== 12824 || Spellkind->Id== 12825 || Spellkind->Id== 12826))
+ {
+ spellhit=true;
+ DoCastSpellIfCan(m_creature,29124); //become a sheep
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ // we mustn't remove the creature in the same round in which we cast the summon spell, otherwise there will be no summons
+ if (spellhit && morphtimer>=5000)
+ {
+ m_creature->ForcedDespawn();
+ return;
+ }
+
+ // walk 5 seconds before summoning
+ if (spellhit && morphtimer<5000)
+ {
+ morphtimer+=diff;
+ if (morphtimer>=5000)
+ {
+ DoCastSpellIfCan(m_creature,28406); //summon copies
+ DoCastSpellIfCan(m_creature,6924); //visual explosion
+ }
+ }
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //TODO: add abilities for the different creatures
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_mobs_spitelashes(Creature* pCreature)
+{
+ return new mobs_spitelashesAI(pCreature);
+}
+
+/*######
+## npc_loramus_thalipedes
+######*/
+
+bool GossipHello_npc_loramus_thalipedes(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(2744) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Can you help me?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ if (pPlayer->GetQuestStatus(3141) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Tell me your story", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_loramus_thalipedes(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(2744);
+ break;
+
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Please continue", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 21);
+ pPlayer->SEND_GOSSIP_MENU(1813, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+21:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I do not understand", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 22);
+ pPlayer->SEND_GOSSIP_MENU(1814, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+22:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Indeed", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 23);
+ pPlayer->SEND_GOSSIP_MENU(1815, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+23:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I will do this with or your help, Loramus", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 24);
+ pPlayer->SEND_GOSSIP_MENU(1816, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+24:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Yes", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 25);
+ pPlayer->SEND_GOSSIP_MENU(1817, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+25:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(3141);
+ break;
+ }
+ return true;
+}
+
+void AddSC_azshara()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_rizzle_sprysprocket";
+ newscript->GetAI = &GetAI_npc_rizzle_sprysprocket;
+ newscript->pGossipHello = &GossipHello_npc_rizzle_sprysprocket;
+ newscript->pGossipSelect = &GossipSelect_npc_rizzle_sprysprocket;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_depth_charge";
+ newscript->GetAI = &GetAI_npc_depth_charge;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "go_southfury_moonstone";
+ newscript->pGOHello = &GOHello_go_southfury_moonstone;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mobs_spitelashes";
+ newscript->GetAI = &GetAI_mobs_spitelashes;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_loramus_thalipedes";
+ newscript->pGossipHello = &GossipHello_npc_loramus_thalipedes;
+ newscript->pGossipSelect = &GossipSelect_npc_loramus_thalipedes;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/azuremyst_isle.cpp b/scripts/kalimdor/azuremyst_isle.cpp
new file mode 100644
index 0000000..f102f05
--- /dev/null
+++ b/scripts/kalimdor/azuremyst_isle.cpp
@@ -0,0 +1,464 @@
+/* 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: Azuremyst_Isle
+SD%Complete: 75
+SDComment: Quest support: 9283, 9528, 9537, 9554(special flight path, proper model for mount missing). Injured Draenei cosmetic only
+SDCategory: Azuremyst Isle
+EndScriptData */
+
+/* ContentData
+npc_draenei_survivor
+npc_engineer_spark_overgrind
+npc_injured_draenei
+npc_magwin
+npc_susurrus
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+#include
+
+/*######
+## npc_draenei_survivor
+######*/
+
+enum
+{
+ SAY_HEAL1 = -1000176,
+ SAY_HEAL2 = -1000177,
+ SAY_HEAL3 = -1000178,
+ SAY_HEAL4 = -1000179,
+ SAY_HELP1 = -1000180,
+ SAY_HELP2 = -1000181,
+ SAY_HELP3 = -1000182,
+ SAY_HELP4 = -1000183,
+
+ SPELL_IRRIDATION = 35046,
+ SPELL_STUNNED = 28630
+};
+
+struct MANGOS_DLL_DECL npc_draenei_survivorAI : public ScriptedAI
+{
+ npc_draenei_survivorAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint64 m_uiCaster;
+
+ uint32 m_uiSayThanksTimer;
+ uint32 m_uiRunAwayTimer;
+ uint32 m_uiSayHelpTimer;
+
+ bool m_bCanSayHelp;
+
+ void Reset()
+ {
+ m_uiCaster = 0;
+
+ m_uiSayThanksTimer = 0;
+ m_uiRunAwayTimer = 0;
+ m_uiSayHelpTimer = 10000;
+
+ m_bCanSayHelp = true;
+
+ m_creature->CastSpell(m_creature, SPELL_IRRIDATION, true);
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ m_creature->SetHealth(int(m_creature->GetMaxHealth()*.1));
+ m_creature->SetStandState(UNIT_STAND_STATE_SLEEP);
+ }
+
+ void MoveInLineOfSight(Unit* pWho)
+ {
+ if (m_bCanSayHelp && pWho->GetTypeId() == TYPEID_PLAYER && m_creature->IsFriendlyTo(pWho) &&
+ m_creature->IsWithinDistInMap(pWho, 25.0f))
+ {
+ //Random switch between 4 texts
+ switch(urand(0, 3))
+ {
+ case 0: DoScriptText(SAY_HELP1, m_creature, pWho); break;
+ case 1: DoScriptText(SAY_HELP2, m_creature, pWho); break;
+ case 2: DoScriptText(SAY_HELP3, m_creature, pWho); break;
+ case 3: DoScriptText(SAY_HELP4, m_creature, pWho); break;
+ }
+
+ m_uiSayHelpTimer = 20000;
+ m_bCanSayHelp = false;
+ }
+ }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (pSpell->SpellFamilyFlags2 & 0x080000000)
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ m_creature->CastSpell(m_creature, SPELL_STUNNED, true);
+
+ m_uiCaster = pCaster->GetGUID();
+
+ m_uiSayThanksTimer = 5000;
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_uiSayThanksTimer)
+ {
+ if (m_uiSayThanksTimer <= uiDiff)
+ {
+ m_creature->RemoveAurasDueToSpell(SPELL_IRRIDATION);
+
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiCaster))
+ {
+ if (pPlayer->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ switch(urand(0, 3))
+ {
+ case 0: DoScriptText(SAY_HEAL1, m_creature, pPlayer); break;
+ case 1: DoScriptText(SAY_HEAL2, m_creature, pPlayer); break;
+ case 2: DoScriptText(SAY_HEAL3, m_creature, pPlayer); break;
+ case 3: DoScriptText(SAY_HEAL4, m_creature, pPlayer); break;
+ }
+
+ pPlayer->TalkedToCreature(m_creature->GetEntry(),m_creature->GetGUID());
+ }
+
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MovePoint(0, -4115.053711f, -13754.831055f, 73.508949f);
+
+ m_uiRunAwayTimer = 10000;
+ m_uiSayThanksTimer = 0;
+ }else m_uiSayThanksTimer -= uiDiff;
+
+ return;
+ }
+
+ if (m_uiRunAwayTimer)
+ {
+ if (m_uiRunAwayTimer <= uiDiff)
+ m_creature->ForcedDespawn();
+ else
+ m_uiRunAwayTimer -= uiDiff;
+
+ return;
+ }
+
+ if (m_uiSayHelpTimer < uiDiff)
+ {
+ m_bCanSayHelp = true;
+ m_uiSayHelpTimer = 20000;
+ }else m_uiSayHelpTimer -= uiDiff;
+ }
+};
+
+CreatureAI* GetAI_npc_draenei_survivor(Creature* pCreature)
+{
+ return new npc_draenei_survivorAI(pCreature);
+}
+
+/*######
+## npc_engineer_spark_overgrind
+######*/
+
+enum
+{
+ SAY_TEXT = -1000184,
+ EMOTE_SHELL = -1000185,
+ SAY_ATTACK = -1000186,
+
+ AREA_COVE = 3579,
+ AREA_ISLE = 3639,
+ QUEST_GNOMERCY = 9537,
+ FACTION_HOSTILE = 14,
+ SPELL_DYNAMITE = 7978
+};
+
+#define GOSSIP_FIGHT "Traitor! You will be brought to justice!"
+
+struct MANGOS_DLL_DECL npc_engineer_spark_overgrindAI : public ScriptedAI
+{
+ npc_engineer_spark_overgrindAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiNormFaction = pCreature->getFaction();
+ m_uiNpcFlags = pCreature->GetUInt32Value(UNIT_NPC_FLAGS);
+ Reset();
+
+ if (pCreature->GetAreaId() == AREA_COVE || pCreature->GetAreaId() == AREA_ISLE)
+ m_bIsTreeEvent = true;
+ }
+
+ uint32 m_uiNpcFlags;
+ uint32 m_uiNormFaction;
+
+ uint32 m_uiDynamiteTimer;
+ uint32 m_uiEmoteTimer;
+
+ bool m_bIsTreeEvent;
+
+ void Reset()
+ {
+ m_creature->setFaction(m_uiNormFaction);
+ m_creature->SetUInt32Value(UNIT_NPC_FLAGS, m_uiNpcFlags);
+
+ m_uiDynamiteTimer = 8000;
+ m_uiEmoteTimer = urand(120000, 150000);
+
+ m_bIsTreeEvent = false;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_ATTACK, m_creature, who);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->isInCombat() && !m_bIsTreeEvent)
+ {
+ if (m_uiEmoteTimer < diff)
+ {
+ DoScriptText(SAY_TEXT, m_creature);
+ DoScriptText(EMOTE_SHELL, m_creature);
+ m_uiEmoteTimer = urand(120000, 150000);
+ }
+ else m_uiEmoteTimer -= diff;
+ }
+ else if (m_bIsTreeEvent)
+ {
+ //nothing here yet
+ return;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiDynamiteTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_DYNAMITE);
+ m_uiDynamiteTimer = 8000;
+ }
+ else m_uiDynamiteTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_engineer_spark_overgrind(Creature* pCreature)
+{
+ return new npc_engineer_spark_overgrindAI(pCreature);
+}
+
+bool GossipHello_npc_engineer_spark_overgrind(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(QUEST_GNOMERCY) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_FIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_engineer_spark_overgrind(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->setFaction(FACTION_HOSTILE);
+ pCreature->AI()->AttackStart(pPlayer);
+ }
+ return true;
+}
+
+/*######
+## npc_injured_draenei
+######*/
+
+struct MANGOS_DLL_DECL npc_injured_draeneiAI : public ScriptedAI
+{
+ npc_injured_draeneiAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT);
+ m_creature->SetHealth(int(m_creature->GetMaxHealth()*.15));
+ switch(urand(0, 1))
+ {
+ case 0: m_creature->SetStandState(UNIT_STAND_STATE_SIT); break;
+ case 1: m_creature->SetStandState(UNIT_STAND_STATE_SLEEP); break;
+ }
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ return; //ignore everyone around them (won't aggro anything)
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ return;
+ }
+
+};
+CreatureAI* GetAI_npc_injured_draenei(Creature* pCreature)
+{
+ return new npc_injured_draeneiAI(pCreature);
+}
+
+/*######
+## npc_magwin
+######*/
+
+#define SAY_START -1000111
+#define SAY_AGGRO -1000112
+#define SAY_PROGRESS -1000113
+#define SAY_END1 -1000114
+#define SAY_END2 -1000115
+#define EMOTE_HUG -1000116
+
+#define QUEST_A_CRY_FOR_HELP 9528
+
+struct MANGOS_DLL_DECL npc_magwinAI : public npc_escortAI
+{
+ npc_magwinAI(Creature* pCreature) : npc_escortAI(pCreature) {Reset();}
+
+ void WaypointReached(uint32 i)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch(i)
+ {
+ case 0:
+ DoScriptText(SAY_START, m_creature, pPlayer);
+ break;
+ case 17:
+ DoScriptText(SAY_PROGRESS, m_creature, pPlayer);
+ break;
+ case 28:
+ DoScriptText(SAY_END1, m_creature, pPlayer);
+ break;
+ case 29:
+ DoScriptText(EMOTE_HUG, m_creature, pPlayer);
+ DoScriptText(SAY_END2, m_creature, pPlayer);
+ pPlayer->GroupEventHappens(QUEST_A_CRY_FOR_HELP, m_creature);
+ break;
+ }
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature, who);
+ }
+
+ void Reset() { }
+};
+
+bool QuestAccept_npc_magwin(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_A_CRY_FOR_HELP)
+ {
+ pCreature->setFaction(10);
+
+ if (npc_magwinAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+CreatureAI* GetAI_npc_magwinAI(Creature* pCreature)
+{
+ return new npc_magwinAI(pCreature);
+}
+
+/*######
+## npc_susurrus
+######*/
+
+enum
+{
+ ITEM_WHORL_OF_AIR = 23843,
+ SPELL_BUFFETING_WINDS = 32474,
+ TAXI_PATH_ID = 506
+};
+
+#define GOSSIP_ITEM_READY "I am ready."
+
+bool GossipHello_npc_susurrus(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->HasItemCount(ITEM_WHORL_OF_AIR,1,true))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_READY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_susurrus(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF)
+ {
+ //spellId is correct, however it gives flight a somewhat funny effect
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->CastSpell(pPlayer,SPELL_BUFFETING_WINDS,true);
+ }
+ return true;
+}
+
+/*######
+##
+######*/
+
+void AddSC_azuremyst_isle()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_draenei_survivor";
+ newscript->GetAI = &GetAI_npc_draenei_survivor;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_engineer_spark_overgrind";
+ newscript->GetAI = &GetAI_npc_engineer_spark_overgrind;
+ newscript->pGossipHello = &GossipHello_npc_engineer_spark_overgrind;
+ newscript->pGossipSelect = &GossipSelect_npc_engineer_spark_overgrind;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_injured_draenei";
+ newscript->GetAI = &GetAI_npc_injured_draenei;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_magwin";
+ newscript->GetAI = &GetAI_npc_magwinAI;
+ newscript->pQuestAccept = &QuestAccept_npc_magwin;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_susurrus";
+ newscript->pGossipHello = &GossipHello_npc_susurrus;
+ newscript->pGossipSelect = &GossipSelect_npc_susurrus;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/blackfathom_deeps/blackfathom_deeps.h b/scripts/kalimdor/blackfathom_deeps/blackfathom_deeps.h
new file mode 100644
index 0000000..a1474de
--- /dev/null
+++ b/scripts/kalimdor/blackfathom_deeps/blackfathom_deeps.h
@@ -0,0 +1,29 @@
+/* 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 */
+
+#ifndef DEF_BFD_H
+#define DEF_BFD_H
+
+enum
+{
+ MAX_ENCOUNTER = 6,
+
+ TYPE_KELRIS = 1,
+ TYPE_SHRINE = 2,
+
+ NPC_KELRIS = 4832,
+ NPC_SERVANT = 4978,
+
+ GO_PORTAL_DOOR = 21117,
+ GO_SHRINE_1 = 21118,
+ GO_SHRINE_2 = 21119,
+ GO_SHRINE_3 = 21120,
+ GO_SHRINE_4 = 21121,
+
+ DATA_TWILIGHT_LORD_KELRIS = 10,
+ DATA_SHRINE_OF_GELIHAST = 11,
+ DATA_ALTAR_OF_THE_DEEPS = 12
+};
+
+#endif
diff --git a/scripts/kalimdor/blackfathom_deeps/instance_blackfathom_deeps.cpp b/scripts/kalimdor/blackfathom_deeps/instance_blackfathom_deeps.cpp
new file mode 100644
index 0000000..3c3f253
--- /dev/null
+++ b/scripts/kalimdor/blackfathom_deeps/instance_blackfathom_deeps.cpp
@@ -0,0 +1,247 @@
+/* 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_Blackfathom_Deeps
+SD%Complete: 50
+SDComment:
+SDCategory: Blackfathom Deeps
+EndScriptData */
+
+#include "precompiled.h"
+#include "blackfathom_deeps.h"
+
+/* Encounter 0 = Twilight Lord Kelris
+ Encounter 1 = Shrine event
+ Must kill twilight lord for shrine event to be possible
+ */
+
+struct MANGOS_DLL_DECL instance_blackfathom_deeps : public ScriptedInstance
+{
+ instance_blackfathom_deeps(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint64 m_uiKelrisGUID;
+ uint64 m_uiShrineOfGelihastGUID;
+ uint64 m_uiAltarOfTheDeepsGUID;
+ uint64 m_uiPortalGUID;
+ uint32 m_uiSpawnServantTimer;
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiKelrisGUID = 0;
+ m_uiShrineOfGelihastGUID = 0;
+ m_uiAltarOfTheDeepsGUID = 0;
+ m_uiPortalGUID = 0;
+ m_uiSpawnServantTimer = 0;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ if (pCreature->GetEntry() == NPC_KELRIS)
+ m_uiKelrisGUID = pCreature->GetGUID();
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case GO_PORTAL_DOOR:
+ if (m_auiEncounter[1] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+
+ m_uiPortalGUID = pGo->GetGUID();
+ break;
+ case GO_SHRINE_1:
+ if (m_auiEncounter[2] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_SHRINE_2:
+ if (m_auiEncounter[3] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_SHRINE_3:
+ if (m_auiEncounter[4] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+ case GO_SHRINE_4:
+ if (m_auiEncounter[5] == DONE)
+ pGo->SetGoState(GO_STATE_ACTIVE);
+ break;
+
+ case 103015: m_uiShrineOfGelihastGUID = pGo->GetGUID(); break;
+ case 103016: m_uiAltarOfTheDeepsGUID = pGo->GetGUID(); break;
+
+ }
+ }
+
+ bool CanOpenEndDoor()
+ {
+ if (m_auiEncounter[0] != DONE)
+ return false;
+
+ if (m_auiEncounter[2] == DONE && m_auiEncounter[3] == DONE && m_auiEncounter[4] == DONE && m_auiEncounter[5] == DONE)
+ return true;
+
+ return false;
+ }
+
+ void SpawnServants()
+ {
+ if (Creature* pKelris = instance->GetCreature(m_uiKelrisGUID))
+ {
+ float fX_resp, fY_resp, fZ_resp;
+ pKelris->GetRespawnCoord(fX_resp, fY_resp, fZ_resp);
+
+ for(uint8 i = 0; i < 5 ; ++i)
+ {
+ // this part gets a random position at circumference point in a circle
+ // fRadius is how far from center to calculate.
+ // here we use kelris's close point coords as base and then move the summoned to the location of his respawn coords
+ float fRadius = 30.0f;
+ float fAngle = 2.0 * M_PI * rand_norm();
+
+ float fX, fY, fZ;
+
+ fRadius *= sqrt(rand_norm());
+
+ pKelris->GetClosePoint(fX, fY, fZ, 0.0f, fRadius, fAngle);
+
+ if (Creature* pServant = pKelris->SummonCreature(NPC_SERVANT, fX, fY, fZ, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 300000))
+ pServant->GetMotionMaster()->MovePoint(0, fX_resp, fY_resp, fZ_resp);
+ }
+
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_KELRIS: // eventAI must set instance data (1,3) at his death
+ if (m_auiEncounter[0] != DONE && uiData == DONE)
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_SHRINE:
+ {
+ switch(uiData)
+ {
+ case GO_SHRINE_1:
+ m_auiEncounter[2] = DONE;
+ break;
+ case GO_SHRINE_2:
+ m_auiEncounter[3] = DONE;
+ break;
+ case GO_SHRINE_3:
+ m_auiEncounter[4] = DONE;
+ break;
+ case GO_SHRINE_4:
+ m_auiEncounter[5] = DONE;
+ break;
+ }
+
+ m_uiSpawnServantTimer = 7500;
+
+ if (CanOpenEndDoor())
+ {
+ m_auiEncounter[1] = DONE;
+ DoUseDoorOrButton(m_uiPortalGUID);
+ }
+
+ break;
+ }
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_KELRIS:
+ return m_auiEncounter[0];
+ case TYPE_SHRINE:
+ return m_auiEncounter[1];
+ }
+
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_TWILIGHT_LORD_KELRIS:
+ return m_uiKelrisGUID;
+ case DATA_SHRINE_OF_GELIHAST:
+ return m_uiShrineOfGelihastGUID;
+ }
+
+ return 0;
+ }
+
+ void Update(uint32 uiDiff)
+ {
+ if (m_uiSpawnServantTimer)
+ {
+ if (m_uiSpawnServantTimer <= uiDiff)
+ {
+ SpawnServants();
+ m_uiSpawnServantTimer = 0;
+ }
+ else
+ m_uiSpawnServantTimer -= uiDiff;
+ }
+ }
+};
+
+InstanceData* GetInstanceData_instance_blackfathom_deeps(Map* pMap)
+{
+ return new instance_blackfathom_deeps(pMap);
+}
+
+bool GOHello_go_fire_of_akumai(Player* pPlayer, GameObject* pGo)
+{
+ ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData();
+
+ if (!pInstance)
+ return true;
+
+ if (pInstance->GetData(TYPE_KELRIS) == DONE)
+ {
+ pInstance->SetData(TYPE_SHRINE, pGo->GetEntry());
+ return false;
+ }
+
+ return true;
+}
+
+void AddSC_instance_blackfathom_deeps()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "instance_blackfathom_deeps";
+ newscript->GetInstanceData = &GetInstanceData_instance_blackfathom_deeps;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "go_fire_of_akumai";
+ newscript->pGOHello = &GOHello_go_fire_of_akumai;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/bloodmyst_isle.cpp b/scripts/kalimdor/bloodmyst_isle.cpp
new file mode 100644
index 0000000..0785b95
--- /dev/null
+++ b/scripts/kalimdor/bloodmyst_isle.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: Bloodmyst_Isle
+SD%Complete: 80
+SDComment: Quest support: 9670, 9756(gossip items text needed).
+SDCategory: Bloodmyst Isle
+EndScriptData */
+
+/* ContentData
+mob_webbed_creature
+npc_captured_sunhawk_agent
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## mob_webbed_creature
+######*/
+
+//possible creatures to be spawned
+const uint32 possibleSpawns[32] = {17322, 17661, 17496, 17522, 17340, 17352, 17333, 17524, 17654, 17348, 17339, 17345, 17359, 17353, 17336, 17550, 17330, 17701, 17321, 17680, 17325, 17320, 17683, 17342, 17715, 17334, 17341, 17338, 17337, 17346, 17344, 17327};
+
+struct MANGOS_DLL_DECL mob_webbed_creatureAI : public ScriptedAI
+{
+ mob_webbed_creatureAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ uint32 spawnCreatureID = 0;
+
+ switch(urand(0, 2))
+ {
+ case 0:
+ spawnCreatureID = 17681;
+ if (Killer->GetTypeId() == TYPEID_PLAYER)
+ ((Player*)Killer)->KilledMonsterCredit(spawnCreatureID, m_creature->GetGUID());
+ break;
+ case 1:
+ case 2:
+ spawnCreatureID = possibleSpawns[urand(0, 31)];
+ break;
+ }
+
+ if (spawnCreatureID)
+ m_creature->SummonCreature(spawnCreatureID, 0.0f, 0.0f, 0.0f, m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 60000);
+ }
+};
+CreatureAI* GetAI_mob_webbed_creature(Creature* pCreature)
+{
+ return new mob_webbed_creatureAI(pCreature);
+}
+
+/*######
+## npc_captured_sunhawk_agent
+######*/
+
+#define C_SUNHAWK_TRIGGER 17974
+
+bool GossipHello_npc_captured_sunhawk_agent(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->HasAura(31609, EFFECT_INDEX_1) && pPlayer->GetQuestStatus(9756) == QUEST_STATUS_INCOMPLETE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(9136, pCreature->GetGUID());
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(9134, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_captured_sunhawk_agent(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(9137, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->SEND_GOSSIP_MENU(9138, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
+ pPlayer->SEND_GOSSIP_MENU(9139, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(9140, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] ", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
+ pPlayer->SEND_GOSSIP_MENU(9141, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+6:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->TalkedToCreature(C_SUNHAWK_TRIGGER, pCreature->GetGUID());
+ break;
+ }
+ return true;
+}
+
+void AddSC_bloodmyst_isle()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "mob_webbed_creature";
+ newscript->GetAI = &GetAI_mob_webbed_creature;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_captured_sunhawk_agent";
+ newscript->pGossipHello = &GossipHello_npc_captured_sunhawk_agent;
+ newscript->pGossipSelect = &GossipSelect_npc_captured_sunhawk_agent;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/boss_azuregos.cpp b/scripts/kalimdor/boss_azuregos.cpp
new file mode 100644
index 0000000..6784967
--- /dev/null
+++ b/scripts/kalimdor/boss_azuregos.cpp
@@ -0,0 +1,151 @@
+/* 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_Azuregos
+SD%Complete: 90
+SDComment: Teleport not included, spell reflect not effecting dots (Core problem)
+SDCategory: Azshara
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_TELEPORT -1000100
+
+#define SPELL_MARKOFFROST 23182
+#define SPELL_MANASTORM 21097
+#define SPELL_CHILL 21098
+#define SPELL_FROSTBREATH 21099
+#define SPELL_REFLECT 22067
+#define SPELL_CLEAVE 8255 //Perhaps not right ID
+#define SPELL_ENRAGE 23537
+
+struct MANGOS_DLL_DECL boss_azuregosAI : public ScriptedAI
+{
+ boss_azuregosAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 MarkOfFrost_Timer;
+ uint32 ManaStorm_Timer;
+ uint32 Chill_Timer;
+ uint32 Breath_Timer;
+ uint32 Teleport_Timer;
+ uint32 Reflect_Timer;
+ uint32 Cleave_Timer;
+ uint32 Enrage_Timer;
+ bool Enraged;
+
+ void Reset()
+ {
+ MarkOfFrost_Timer = 35000;
+ ManaStorm_Timer = urand(5000, 17000);
+ Chill_Timer = urand(10000, 30000);
+ Breath_Timer = urand(2000, 8000);
+ Teleport_Timer = 30000;
+ Reflect_Timer = urand(15000, 30000);
+ Cleave_Timer = 7000;
+ Enrage_Timer = 0;
+ Enraged = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (Teleport_Timer < diff)
+ {
+ DoScriptText(SAY_TELEPORT, m_creature);
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ if (pUnit && pUnit->GetTypeId() == TYPEID_PLAYER)
+ DoTeleportPlayer(pUnit, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+3, pUnit->GetOrientation());
+ }
+
+ DoResetThreat();
+ Teleport_Timer = 30000;
+ }else Teleport_Timer -= diff;
+
+ // //MarkOfFrost_Timer
+ // if (MarkOfFrost_Timer < diff)
+ // {
+ // DoCastSpellIfCan(m_creature->getVictim(),SPELL_MARKOFFROST);
+ // MarkOfFrost_Timer = 25000;
+ // }else MarkOfFrost_Timer -= diff;
+
+ //Chill_Timer
+ if (Chill_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CHILL);
+ Chill_Timer = urand(13000, 25000);
+ }else Chill_Timer -= diff;
+
+ //Breath_Timer
+ if (Breath_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROSTBREATH);
+ Breath_Timer = urand(10000, 15000);
+ }else Breath_Timer -= diff;
+
+ //ManaStorm_Timer
+ if (ManaStorm_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_MANASTORM);
+ ManaStorm_Timer = urand(7500, 12500);
+ }else ManaStorm_Timer -= diff;
+
+ //Reflect_Timer
+ if (Reflect_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_REFLECT);
+ Reflect_Timer = urand(20000, 35000);
+ }else Reflect_Timer -= diff;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = 7000;
+ }else Cleave_Timer -= diff;
+
+ //Enrage_Timer
+ if (m_creature->GetHealthPercent() < 26.0f && !Enraged)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ Enraged = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_azuregos(Creature* pCreature)
+{
+ return new boss_azuregosAI(pCreature);
+}
+
+void AddSC_boss_azuregos()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_azuregos";
+ newscript->GetAI = &GetAI_boss_azuregos;
+ 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
new file mode 100644
index 0000000..abf2044
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp
@@ -0,0 +1,235 @@
+/* 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: culling_of_stratholme
+SD%Complete: 5%
+SDComment: Placeholder
+SDCategory: Culling of Stratholme
+EndScriptData */
+
+#include "precompiled.h"
+#include "culling_of_stratholme.h"
+
+/* *************
+** npc_chromie (gossip, quest-accept)
+************* */
+
+enum
+{
+ QUEST_DISPELLING_ILLUSIONS = 13149,
+ QUEST_A_ROYAL_ESCORT = 13151,
+
+ ITEM_ARCANE_DISRUPTOR = 37888,
+
+ GOSSIP_ITEM_ENTRANCE_1 = -3595000,
+ GOSSIP_ITEM_ENTRANCE_2 = -3595001,
+ GOSSIP_ITEM_ENTRANCE_3 = -3595002,
+
+ TEXT_ID_ENTRANCE_1 = 12992,
+ TEXT_ID_ENTRANCE_2 = 12993,
+ TEXT_ID_ENTRANCE_3 = 12994,
+ TEXT_ID_ENTRANCE_4 = 12995,
+
+ GOSSIP_ITEM_INN_1 = -3595003,
+ GOSSIP_ITEM_INN_2 = -3595004,
+ GOSSIP_ITEM_INN_3 = -3595005,
+
+ TEXT_ID_INN_1 = 12939,
+ TEXT_ID_INN_2 = 12949,
+ TEXT_ID_INN_3 = 12950,
+ TEXT_ID_INN_4 = 12952,
+};
+
+bool GossipHello_npc_chromie(Player *pPlayer, Creature *pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (instance_culling_of_stratholme* m_pInstance = (instance_culling_of_stratholme*)pCreature->GetInstanceData())
+ {
+ switch (pCreature->GetEntry())
+ {
+ case NPC_CHROMIE_INN:
+ if (m_pInstance->GetData(TYPE_GRAIN_EVENT) != DONE)
+ {
+ 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);
+ }
+ 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;
+ }
+ }
+ return true;
+}
+
+bool GossipSelect_npc_chromie(Player* pPlayer, Creature* pCreature, uint32 sender, uint32 uiAction)
+{
+ switch (pCreature->GetEntry())
+ {
+ 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))
+ {
+ 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);
+ }
+ }
+ }
+ break;
+ }
+ break;
+ case NPC_CHROMIE_ENTRANCE:
+ switch (uiAction)
+ {
+ 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;
+ }
+ break;
+ }
+ return true;
+}
+
+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 (pInstance->GetData(TYPE_GRAIN_EVENT) == NOT_STARTED)
+ pInstance->SetData(TYPE_GRAIN_EVENT, SPECIAL);
+ }
+ break;
+ case QUEST_A_ROYAL_ESCORT:
+ if (instance_culling_of_stratholme* pInstance = (instance_culling_of_stratholme*)pCreature->GetInstanceData())
+ {
+ if (pInstance->GetData(TYPE_ARTHAS_INTRO_EVENT) == NOT_STARTED)
+ pInstance->DoSpawnArthasIfNeeded();
+ }
+ break;
+ }
+ return true;
+}
+
+/* *************
+** npc_crates_bunny (spell aura effect dummy)
+************* */
+
+enum
+{
+ SPELL_ARCANE_DISRUPTION = 49590
+};
+
+bool EffectAuraDummy_spell_aura_dummy_npc_crates_dummy(const Aura* pAura, bool bApply)
+{
+ if (pAura->GetId() == SPELL_ARCANE_DISRUPTION && pAura->GetEffIndex() == EFFECT_INDEX_0 && bApply)
+ {
+ if (Creature* pTarget = (Creature*)pAura->GetTarget())
+ {
+ std::list lCrateBunnyList;
+ if (instance_culling_of_stratholme* pInstance = (instance_culling_of_stratholme*)pTarget->GetInstanceData())
+ {
+ pInstance->GetCratesBunnyOrderedList(lCrateBunnyList);
+ uint8 i = 0;
+ for (std::list::const_iterator itr = lCrateBunnyList.begin(); itr != lCrateBunnyList.end(); ++itr)
+ {
+ i++;
+ if (*itr == pTarget)
+ break;
+ }
+
+ switch (i)
+ {
+ 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;
+ }
+
+ 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
+ }
+ }
+ }
+ return true;
+}
+
+void AddSC_culling_of_stratholme()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_chromie";
+ pNewScript->pGossipHello = &GossipHello_npc_chromie;
+ pNewScript->pGossipSelect = &GossipSelect_npc_chromie;
+ pNewScript->pQuestAccept = &QuestAccept_npc_chromie;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "spell_dummy_npc_crates_bunny";
+ pNewScript->pEffectAuraDummy = &EffectAuraDummy_spell_aura_dummy_npc_crates_dummy;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h
new file mode 100644
index 0000000..cfae166
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h
@@ -0,0 +1,194 @@
+/* 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 */
+
+#ifndef DEF_CULLING_OF_STRATHOLME_H
+#define DEF_CULLING_OF_STRATHOLME_H
+
+enum
+{
+ MAX_ENCOUNTER = 9,
+
+ TYPE_GRAIN_EVENT = 0, // crates with plagued grain identified
+ TYPE_ARTHAS_INTRO_EVENT = 1, // Arhas Speech and Walk to Gates and short intro with MalGanis
+ TYPE_MEATHOOK_EVENT = 2, // Waves 1-5
+ TYPE_SALRAMM_EVENT = 3, // Waves 6-10
+ TYPE_EPOCH_EVENT = 4, // Townhall Event, Boss Killed
+ TYPE_ARTHAS_ESCORT_EVENT = 5, // Townhall to Malganis
+ TYPE_MALGANIS_EVENT = 6, // Malganis
+ TYPE_INFINITE_CORRUPTER_TIME = 7, // Time for 25min Timer
+ TYPE_INFINITE_CORRUPTER = 8,
+
+ // Main Encounter NPCs
+ NPC_CHROMIE_INN = 26527,
+ NPC_CHROMIE_ENTRANCE = 27915,
+ NPC_CHROMIE_END = 30997,
+ NPC_HOURGLASS = 28656,
+ NPC_ARTHAS = 26499,
+ NPC_MEATHOOK = 26529,
+ NPC_SALRAMM_THE_FLESHCRAFTER = 26530,
+ NPC_CHRONO_LORD_EPOCH = 26532,
+ NPC_MALGANIS = 26533,
+ NPC_INFINITE_CORRUPTER = 32273,
+ NPC_LORDAERON_CRIER = 27913,
+ NPC_ZOMBIE = 27737,
+
+ // Inn Event related NPC
+ NPC_MICHAEL_BELFAST = 30571,
+ NPC_HEARTHSINGER_FORRESTEN = 30551,
+ NPC_FRAS_SIABI = 30552,
+ NPC_FOOTMAN_JAMES = 30553,
+ NPC_MAL_CORRICKS = 31017,
+ NPC_GRYAN_STOUTMANTLE = 30561,
+
+ // Grain Event NPCs
+ NPC_ROGER_OWENS = 27903,
+ NPC_SERGEANT_MORIGAN = 27877,
+ NPC_JENA_ANDERSON = 27885,
+ NPC_MALCOM_MOORE = 27891, // Not (yet?) spawned
+ NPC_BARTLEBY_BATTSON = 27907,
+ NPC_CRATES_BUNNY = 30996,
+
+ // Intro Event NPCs
+ NPC_LORDAERON_FOOTMAN = 27745,
+ NPC_STRATHOLME_CITIZEN = 28167,
+ NPC_STRATHOLME_RESIDENT = 28169,
+
+ // Mobs in Stratholme (to despawn) -- only here for sake of completeness handling remains open (mangos feature)
+ NPC_MAGISTRATE_BARTHILAS = 30994,
+ NPC_STEPHANIE_SINDREE = 31019,
+ NPC_LEEKA_TURNER = 31027,
+ NPC_SOPHIE_AAREN = 31021,
+ NPC_ROBERT_PIERCE = 31025,
+ NPC_GEORGE_GOODMAN = 31022,
+
+ // Others NPCs in Stratholme
+ NPC_EMERY_NEILL = 30570,
+ NPC_EDWARD_ORRICK = 31018,
+ NPC_OLIVIA_ZENITH = 31020,
+
+ // Townhall Event NPCs
+ NPC_AGIATED_STRATHOLME_CITIZEN = 31126,
+ NPC_AGIATED_STRATHOLME_RESIDENT = 31127,
+ NPC_PATRICIA_O_REILLY = 31028,
+
+ // Gameobjects
+ GO_DOOR_BOOKCASE = 188686,
+ GO_DARK_RUNED_CHEST = 190663,
+ GO_DARK_RUNED_CHEST_H = 193597,
+
+ // World States
+ WORLD_STATE_CRATES = 3479,
+ WORLD_STATE_CRATES_COUNT = 3480,
+ WORLD_STATE_WAVE = 3504,
+ WORLD_STATE_TIME = 3932,
+ WORLD_STATE_TIME_COUNTER = 3931,
+
+ // Areatrigger
+ AREATRIGGER_INN = 5291,
+ /*
+ 5085 before bridge - could be Uther SpawnPos
+ 5148 ini entrance
+ 5181 ini exit
+ 5249 fras siabis store
+ 5250 leeking shields...(store)
+ 5251 bar in stratholme
+ 5252 Aaren flowers
+ 5253 Angelicas boutique
+ 5256 townhall
+ 5291 Inn */
+};
+
+enum eInstancePosition
+{
+ POS_ARTHAS_INTRO = 1,
+ POS_ARTHAS_WAVES = 2,
+ POS_ARTHAS_TOWNHALL = 3,
+ POS_ARTHAS_ESCORTING = 4,
+ POS_ARTHAS_MALGANIS = 5,
+ POS_INSTANCE_FINISHED = 6
+};
+
+class MANGOS_DLL_DECL instance_culling_of_stratholme : public ScriptedInstance
+{
+ public:
+ instance_culling_of_stratholme(Map* pMap);
+ ~instance_culling_of_stratholme() {}
+
+ void Initialize();
+
+ void OnCreatureCreate(Creature* pCreature);
+ void OnObjectCreate(GameObject* pGo);
+
+ void SetData(uint32 uiType, uint32 uiData);
+ uint32 GetData(uint32 uiType);
+ uint64 GetData64(uint32 uiData);
+
+ const char* Save() { return strInstData.c_str(); }
+ void Load(const char* chrIn);
+
+ void Update(uint32 uiDiff);
+
+ void GetStratAgiatedCitizenList(std::list &lList){ lList = m_lAgiatedCitizenGUIDList; };
+ void GetStratAgiatedResidentList(std::list &lList){ lList = m_lAgiatedResidentGUIDList; };
+
+ void GetCratesBunnyOrderedList(std::list &lList);
+ Creature* GetStratIntroFootman();
+ void GetResidentOrderedList(std::list &lList);
+ void DoSpawnArthasIfNeeded();
+ void DoSpawnChromieIfNeeded();
+ uint8 GetInstancePosition();
+ void ArthasJustDied();
+
+ protected:
+ void OnPlayerEnter(Player* pPlayer);
+ Player* GetPlayerInMap();
+ void UpdateQuestCredit();
+ void DoChromieHurrySpeech();
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint8 m_uiGrainCrateCount;
+ uint32 m_uiRemoveCrateStateTimer;
+ uint32 m_uiArthasRespawnTimer;
+
+ uint64 m_uiChromieInnGUID;
+ uint64 m_uiChromieEntranceGUID;
+ uint64 m_uiChromieEndGUID;
+ uint64 m_uiHourglassGUID;
+ uint64 m_uiArthasGUID;
+ uint64 m_uiMeathookGUID;
+ uint64 m_uiSalrammGUID;
+ uint64 m_uiEpochGUID;
+ uint64 m_uiMalganisGUID;
+ uint64 m_uiCorrupterGUID;
+ uint64 m_uiLordaeronCrierGUID;
+
+ uint64 m_uiBelfastGUID;
+ uint64 m_uiForrestenGUID;
+ uint64 m_uiSiabiGUID;
+ uint64 m_uiJamesGUID;
+ uint64 m_uiCorricksGUID;
+ uint64 m_uiStoutmantleGUID;
+
+ uint64 m_uiOwensGUID;
+ uint64 m_uiMoriganGUID;
+ uint64 m_uiAndersonGUID;
+ uint64 m_uiMooreGUID;
+ uint64 m_uiBattsonGUID;
+
+ uint64 m_uiOReillyGUID;
+
+ std::list m_lCratesBunnyList;
+ std::list m_lFootmanList;
+ std::list m_lResidentList;
+
+ std::list m_lAgiatedCitizenGUIDList;
+ std::list m_lAgiatedResidentGUIDList;
+
+ uint64 m_uiDoorBookcaseGUID;
+ uint64 m_uiDarkRunedChestGUID;
+};
+
+#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
new file mode 100644
index 0000000..706d976
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp
@@ -0,0 +1,558 @@
+/* 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: 80%
+SDComment:
+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}
+};
+
+static sSpawnLocation m_aChromieSpawnLocs[] = // need tuning, escpecially EndPositions!
+{
+ {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_lCratesBunnyList.push_back(pCreature); break;
+ case NPC_LORDAERON_FOOTMAN: m_lFootmanList.push_back(pCreature); break;
+
+ case NPC_STRATHOLME_CITIZEN:
+ case NPC_STRATHOLME_RESIDENT:
+ if (m_auiEncounter[TYPE_ARTHAS_INTRO_EVENT] == DONE)
+ pCreature->UpdateEntry(NPC_ZOMBIE);
+ else
+ m_lResidentList.push_back(pCreature);
+ 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())
+ {
+ 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;
+ }
+}
+
+Player* instance_culling_of_stratholme::GetPlayerInMap()
+{
+ Map::PlayerList const& players = instance->GetPlayers();
+
+ if (!players.isEmpty())
+ {
+ for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ if (Player* plr = itr->getSource())
+ return plr;
+ }
+ }
+ return NULL;
+}
+
+void instance_culling_of_stratholme::UpdateQuestCredit()
+{
+ Map::PlayerList const& players = instance->GetPlayers();
+ if (!players.isEmpty())
+ {
+ for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ if (Player* pPlayer = itr->getSource())
+ pPlayer->KilledMonsterCredit(NPC_CRATES_BUNNY);
+ }
+ }
+}
+
+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);
+ }
+ }
+ }
+}
+
+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;
+
+ ++m_uiGrainCrateCount;
+ DoUpdateWorldState(WORLD_STATE_CRATES_COUNT, m_uiGrainCrateCount);
+
+ 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 (uiData == DONE || (uiType == TYPE_INFINITE_CORRUPTER && uiData == FAIL))
+ {
+ 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];
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+}
+
+void instance_culling_of_stratholme::Load(const char* chrIn)
+{
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
+ >> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] >> m_auiEncounter[8];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (i != TYPE_INFINITE_CORRUPTER_TIME)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+ }
+
+ // 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)
+{
+ m_lCratesBunnyList.sort(sortFromEastToWest);
+ lList = m_lCratesBunnyList;
+}
+
+Creature* instance_culling_of_stratholme::GetStratIntroFootman()
+{
+ m_lFootmanList.sort(sortFromSouthToNorth);
+ if (m_lFootmanList.empty())
+ return NULL;
+ else
+ return *m_lFootmanList.begin();
+}
+
+void instance_culling_of_stratholme::GetResidentOrderedList(std::list &lList)
+{
+ m_lResidentList.sort(sortFromSouthToNorth);
+ lList = m_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);
+ }
+}
+
+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])
+ {
+ if (m_auiEncounter[TYPE_INFINITE_CORRUPTER_TIME] <= uiDiff)
+ SetData(TYPE_INFINITE_CORRUPTER, FAIL);
+ else
+ {
+ 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]);
+ }
+
+ // 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);
+ }
+
+ // Small Timer, to remove Grain-Crate WorldState and Spawn Second Chromie
+ if (m_uiRemoveCrateStateTimer)
+ {
+ if (m_uiRemoveCrateStateTimer <= uiDiff)
+ {
+ DoUpdateWorldState(WORLD_STATE_CRATES, 0);
+ DoSpawnChromieIfNeeded();
+ m_uiRemoveCrateStateTimer = 0;
+ }
+ else
+ m_uiRemoveCrateStateTimer -= uiDiff;
+ }
+
+ // Respawn Arthas after some time
+ if (m_uiArthasRespawnTimer)
+ {
+ if (m_uiArthasRespawnTimer <= uiDiff)
+ {
+ DoSpawnArthasIfNeeded();
+ m_uiArthasRespawnTimer = 0;
+ }
+ else
+ m_uiArthasRespawnTimer -= uiDiff;
+ }
+}
+
+InstanceData* GetInstanceData_instance_culling_of_stratholme(Map* pMap)
+{
+ return new instance_culling_of_stratholme(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();
+}
diff --git a/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp b/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp
new file mode 100644
index 0000000..04d3438
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp
@@ -0,0 +1,144 @@
+/* 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_Aeonus
+SD%Complete: 80
+SDComment: Some spells not implemented
+SDCategory: Caverns of Time, The Dark Portal
+EndScriptData */
+
+#include "precompiled.h"
+#include "dark_portal.h"
+
+enum
+{
+ SAY_ENTER = -1269012,
+ SAY_AGGRO = -1269013,
+ SAY_BANISH = -1269014,
+ SAY_SLAY1 = -1269015,
+ SAY_SLAY2 = -1269016,
+ SAY_DEATH = -1269017,
+ EMOTE_GENERIC_FRENZY = -1000002,
+
+ SPELL_CLEAVE = 40504,
+ SPELL_TIME_STOP = 31422,
+ SPELL_ENRAGE = 37605,
+ SPELL_SAND_BREATH = 31473,
+ H_SPELL_SAND_BREATH = 39049
+};
+
+struct MANGOS_DLL_DECL boss_aeonusAI : public ScriptedAI
+{
+ boss_aeonusAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ bool m_bIsRegularMode;
+
+ uint32 SandBreath_Timer;
+ uint32 TimeStop_Timer;
+ uint32 Frenzy_Timer;
+
+ void Reset()
+ {
+ SandBreath_Timer = urand(15000, 30000);
+ TimeStop_Timer = urand(10000, 15000);
+ Frenzy_Timer = urand(30000, 45000);
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ //Despawn Time Keeper
+ if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
+ {
+ if (m_creature->IsWithinDistInMap(who,20.0f))
+ {
+ DoScriptText(SAY_BANISH, m_creature);
+ m_creature->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ }
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_RIFT,DONE);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Sand Breath
+ if (SandBreath_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_SAND_BREATH : H_SPELL_SAND_BREATH);
+ SandBreath_Timer = urand(15000, 25000);
+ }else SandBreath_Timer -= diff;
+
+ //Time Stop
+ if (TimeStop_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_TIME_STOP);
+ TimeStop_Timer = urand(20000, 35000);
+ }else TimeStop_Timer -= diff;
+
+ //Frenzy
+ if (Frenzy_Timer < diff)
+ {
+ DoScriptText(EMOTE_GENERIC_FRENZY, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ Frenzy_Timer = urand(20000, 35000);
+ }else Frenzy_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_aeonus(Creature* pCreature)
+{
+ return new boss_aeonusAI(pCreature);
+}
+
+void AddSC_boss_aeonus()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_aeonus";
+ newscript->GetAI = &GetAI_boss_aeonus;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp b/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp
new file mode 100644
index 0000000..2ae675f
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp
@@ -0,0 +1,154 @@
+/* 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_Chrono_Lord_Deja
+SD%Complete: 65
+SDComment: All abilities not implemented
+SDCategory: Caverns of Time, The Dark Portal
+EndScriptData */
+
+#include "precompiled.h"
+#include "dark_portal.h"
+
+#define SAY_ENTER -1269006
+#define SAY_AGGRO -1269007
+#define SAY_BANISH -1269008
+#define SAY_SLAY1 -1269009
+#define SAY_SLAY2 -1269010
+#define SAY_DEATH -1269011
+
+#define SPELL_ARCANE_BLAST 31457
+#define H_SPELL_ARCANE_BLAST 38538
+#define SPELL_ARCANE_DISCHARGE 31472
+#define H_SPELL_ARCANE_DISCHARGE 38539
+#define SPELL_TIME_LAPSE 31467
+#define SPELL_ATTRACTION 38540 //Not Implemented (Heroic mode)
+
+struct MANGOS_DLL_DECL boss_chrono_lord_dejaAI : public ScriptedAI
+{
+ boss_chrono_lord_dejaAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ bool m_bIsRegularMode;
+
+ uint32 ArcaneBlast_Timer;
+ uint32 TimeLapse_Timer;
+ uint32 Attraction_Timer;
+ uint32 ArcaneDischarge_Timer;
+
+ void Reset()
+ {
+ ArcaneBlast_Timer = urand(18000, 23000);
+ TimeLapse_Timer = urand(10000, 15000);
+ ArcaneDischarge_Timer = urand(20000, 30000);
+ Attraction_Timer = urand(25000, 35000);
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ //Despawn Time Keeper
+ if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
+ {
+ if (m_creature->IsWithinDistInMap(who,20.0f))
+ {
+ DoScriptText(SAY_BANISH, m_creature);
+ m_creature->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ }
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_RIFT,SPECIAL);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Arcane Blast
+ if (ArcaneBlast_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_ARCANE_BLAST : H_SPELL_ARCANE_BLAST);
+ ArcaneBlast_Timer = urand(15000, 25000);
+ }else ArcaneBlast_Timer -= diff;
+
+ //Arcane Discharge
+ if (ArcaneDischarge_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(target, m_bIsRegularMode ? SPELL_ARCANE_DISCHARGE : H_SPELL_ARCANE_DISCHARGE);
+
+ ArcaneDischarge_Timer = urand(20000, 30000);
+ }else ArcaneDischarge_Timer -= diff;
+
+ //Time Lapse
+ if (TimeLapse_Timer < diff)
+ {
+ DoScriptText(SAY_BANISH, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_TIME_LAPSE);
+ TimeLapse_Timer = urand(15000, 25000);
+ }else TimeLapse_Timer -= diff;
+
+ if (!m_bIsRegularMode)
+ {
+ if (Attraction_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_ATTRACTION);
+ Attraction_Timer = urand(25000, 35000);
+ }else Attraction_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_chrono_lord_deja(Creature* pCreature)
+{
+ return new boss_chrono_lord_dejaAI(pCreature);
+}
+
+void AddSC_boss_chrono_lord_deja()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_chrono_lord_deja";
+ newscript->GetAI = &GetAI_boss_chrono_lord_deja;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp b/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp
new file mode 100644
index 0000000..ed44d79
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp
@@ -0,0 +1,150 @@
+/* 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_Temporus
+SD%Complete: 75
+SDComment: More abilities need to be implemented
+SDCategory: Caverns of Time, The Dark Portal
+EndScriptData */
+
+#include "precompiled.h"
+#include "dark_portal.h"
+
+#define SAY_ENTER -1269000
+#define SAY_AGGRO -1269001
+#define SAY_BANISH -1269002
+#define SAY_SLAY1 -1269003
+#define SAY_SLAY2 -1269004
+#define SAY_DEATH -1269005
+
+#define SPELL_HASTE 31458
+#define SPELL_MORTAL_WOUND 31464
+#define SPELL_WING_BUFFET 31475
+#define H_SPELL_WING_BUFFET 38593
+#define SPELL_REFLECT 38592 //Not Implemented (Heroic mod)
+
+struct MANGOS_DLL_DECL boss_temporusAI : public ScriptedAI
+{
+ boss_temporusAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ bool m_bIsRegularMode;
+
+ uint32 Haste_Timer;
+ uint32 SpellReflection_Timer;
+ uint32 MortalWound_Timer;
+ uint32 WingBuffet_Timer;
+
+ void Reset()
+ {
+ Haste_Timer = urand(15000, 23000);
+ SpellReflection_Timer = 30000;
+ MortalWound_Timer = 8000;
+ WingBuffet_Timer = urand(25000, 35000);
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_RIFT,SPECIAL);
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ //Despawn Time Keeper
+ if (who->GetTypeId() == TYPEID_UNIT && who->GetEntry() == NPC_TIME_KEEPER)
+ {
+ if (m_creature->IsWithinDistInMap(who,20.0f))
+ {
+ DoScriptText(SAY_BANISH, m_creature);
+ m_creature->DealDamage(who, who->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+ }
+
+ ScriptedAI::MoveInLineOfSight(who);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Attack Haste
+ if (Haste_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HASTE);
+ Haste_Timer = urand(20000, 25000);
+ }else Haste_Timer -= diff;
+
+ //MortalWound_Timer
+ if (MortalWound_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_WOUND);
+ MortalWound_Timer = urand(10000, 20000);
+ }else MortalWound_Timer -= diff;
+
+ //Wing ruffet
+ if (WingBuffet_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_WING_BUFFET : H_SPELL_WING_BUFFET);
+ WingBuffet_Timer = urand(20000, 30000);
+ }else WingBuffet_Timer -= diff;
+
+ if (!m_bIsRegularMode)
+ {
+ if (SpellReflection_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_REFLECT);
+ SpellReflection_Timer = urand(25000, 35000);
+ }else SpellReflection_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_temporus(Creature* pCreature)
+{
+ return new boss_temporusAI(pCreature);
+}
+
+void AddSC_boss_temporus()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_temporus";
+ newscript->GetAI = &GetAI_boss_temporus;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp b/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp
new file mode 100644
index 0000000..74db120
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp
@@ -0,0 +1,416 @@
+/* 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: Dark_Portal
+SD%Complete: 30
+SDComment: Misc NPC's and mobs for instance. Most here far from complete.
+SDCategory: Caverns of Time, The Dark Portal
+EndScriptData */
+
+/* ContentData
+npc_medivh_bm
+npc_time_rift
+npc_saat
+EndContentData */
+
+#include "precompiled.h"
+#include "dark_portal.h"
+
+#define SAY_ENTER -1269020 //where does this belong?
+#define SAY_INTRO -1269021
+#define SAY_WEAK75 -1269022
+#define SAY_WEAK50 -1269023
+#define SAY_WEAK25 -1269024
+#define SAY_DEATH -1269025
+#define SAY_WIN -1269026
+#define SAY_ORCS_ENTER -1269027
+#define SAY_ORCS_ANSWER -1269028
+
+#define SPELL_CHANNEL 31556
+#define SPELL_PORTAL_RUNE 32570 //aura(portal on ground effect)
+
+#define SPELL_BLACK_CRYSTAL 32563 //aura
+#define SPELL_PORTAL_CRYSTAL 32564 //summon
+
+#define SPELL_BANISH_PURPLE 32566 //aura
+#define SPELL_BANISH_GREEN 32567 //aura
+
+#define SPELL_CORRUPT 31326
+#define SPELL_CORRUPT_AEONUS 37853
+
+#define C_COUNCIL_ENFORCER 17023
+
+struct MANGOS_DLL_DECL npc_medivh_bmAI : public ScriptedAI
+{
+ npc_medivh_bmAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 SpellCorrupt_Timer;
+ uint32 Check_Timer;
+
+ bool Life75;
+ bool Life50;
+ bool Life25;
+
+ void Reset()
+ {
+ SpellCorrupt_Timer = 0;
+ Check_Timer = 0;
+
+ Life75 = true;
+ Life50 = true;
+ Life25 = true;
+
+ if (!m_pInstance)
+ return;
+
+ if (m_pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS)
+ m_creature->CastSpell(m_creature, SPELL_CHANNEL, true);
+ else if (m_creature->HasAura(SPELL_CHANNEL, EFFECT_INDEX_0))
+ m_creature->RemoveAurasDueToSpell(SPELL_CHANNEL);
+
+ m_creature->CastSpell(m_creature, SPELL_PORTAL_RUNE, true);
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (who->GetTypeId() == TYPEID_PLAYER && m_creature->IsWithinDistInMap(who, 10.0f))
+ {
+ if (m_pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS || m_pInstance->GetData(TYPE_MEDIVH) == DONE)
+ return;
+
+ DoScriptText(SAY_INTRO, m_creature);
+ m_pInstance->SetData(TYPE_MEDIVH, IN_PROGRESS);
+ m_creature->CastSpell(m_creature, SPELL_CHANNEL, false);
+ Check_Timer = 5000;
+ }
+ else if (who->GetTypeId() == TYPEID_UNIT && m_creature->IsWithinDistInMap(who, 15.0f))
+ {
+ if (m_pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS)
+ return;
+
+ uint32 entry = who->GetEntry();
+ if (entry == NPC_ASSAS || entry == NPC_WHELP || entry == NPC_CHRON || entry == NPC_EXECU || entry == NPC_VANQU)
+ {
+ who->StopMoving();
+ who->CastSpell(m_creature, SPELL_CORRUPT, false);
+ }
+ else if (entry == NPC_AEONUS)
+ {
+ who->StopMoving();
+ who->CastSpell(m_creature, SPELL_CORRUPT_AEONUS, false);
+ }
+ }
+ }
+
+ void AttackStart(Unit *who)
+ {
+ //if (m_pInstance && m_pInstance->GetData(TYPE_MEDIVH) == IN_PROGRESS)
+ //return;
+
+ //ScriptedAI::AttackStart(who);
+ }
+
+ void SpellHit(Unit* caster, const SpellEntry* spell)
+ {
+ if (SpellCorrupt_Timer)
+ return;
+
+ if (spell->Id == SPELL_CORRUPT_AEONUS)
+ SpellCorrupt_Timer = 1000;
+
+ if (spell->Id == SPELL_CORRUPT)
+ SpellCorrupt_Timer = 3000;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (Killer->GetEntry() == m_creature->GetEntry())
+ return;
+
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (SpellCorrupt_Timer)
+ {
+ if (SpellCorrupt_Timer <= diff)
+ {
+ m_pInstance->SetData(TYPE_MEDIVH, SPECIAL);
+
+ if (m_creature->HasAura(SPELL_CORRUPT_AEONUS, EFFECT_INDEX_0))
+ SpellCorrupt_Timer = 1000;
+ else if (m_creature->HasAura(SPELL_CORRUPT, EFFECT_INDEX_0))
+ SpellCorrupt_Timer = 3000;
+ else
+ SpellCorrupt_Timer = 0;
+ }
+ else
+ SpellCorrupt_Timer -= diff;
+ }
+
+ if (Check_Timer)
+ {
+ if (Check_Timer <= diff)
+ {
+ uint32 pct = m_pInstance->GetData(DATA_SHIELD);
+
+ Check_Timer = 5000;
+
+ if (Life25 && pct <= 25)
+ {
+ DoScriptText(SAY_WEAK25, m_creature);
+ Life25 = false;
+ }
+ else if (Life50 && pct <= 50)
+ {
+ DoScriptText(SAY_WEAK50, m_creature);
+ Life50 = false;
+ }
+ else if (Life75 && pct <= 75)
+ {
+ DoScriptText(SAY_WEAK75, m_creature);
+ Life75 = false;
+ }
+
+ //if we reach this it means event was running but at some point reset.
+ if (m_pInstance->GetData(TYPE_MEDIVH) == NOT_STARTED)
+ {
+ m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ m_creature->RemoveCorpse();
+ m_creature->Respawn();
+ return;
+ }
+
+ if (m_pInstance->GetData(TYPE_RIFT) == DONE)
+ {
+ DoScriptText(SAY_WIN, m_creature);
+ Check_Timer = 0;
+
+ if (m_creature->HasAura(SPELL_CHANNEL, EFFECT_INDEX_0))
+ m_creature->RemoveAurasDueToSpell(SPELL_CHANNEL);
+
+ //TODO: start the post-event here
+ m_pInstance->SetData(TYPE_MEDIVH,DONE);
+ }
+ }
+ else
+ Check_Timer -= diff;
+ }
+
+ //if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ //return;
+
+ //DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_medivh_bm(Creature* pCreature)
+{
+ return new npc_medivh_bmAI(pCreature);
+}
+
+struct Wave
+{
+ uint32 PortalMob[4]; //spawns for portal waves (in order)
+};
+
+static Wave PortalWaves[]=
+{
+ {NPC_ASSAS, NPC_WHELP, NPC_CHRON, 0},
+ {NPC_EXECU, NPC_CHRON, NPC_WHELP, NPC_ASSAS},
+ {NPC_EXECU, NPC_VANQU, NPC_CHRON, NPC_ASSAS}
+};
+
+struct MANGOS_DLL_DECL npc_time_riftAI : public ScriptedAI
+{
+ npc_time_riftAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 TimeRiftWave_Timer;
+ uint8 mRiftWaveCount;
+ uint8 mPortalCount;
+ uint8 mWaveId;
+
+ void Reset()
+ {
+ TimeRiftWave_Timer = 15000;
+ mRiftWaveCount = 0;
+
+ if (!m_pInstance)
+ return;
+
+ mPortalCount = m_pInstance->GetData(DATA_PORTAL_COUNT);
+
+ if (mPortalCount < 6)
+ mWaveId = 0;
+ else if (mPortalCount > 12)
+ mWaveId = 2;
+ else
+ mWaveId = 1;
+
+ }
+
+ void DoSummonAtRift(uint32 creature_entry)
+ {
+ if (!creature_entry)
+ return;
+
+ if (m_pInstance->GetData(TYPE_MEDIVH) != IN_PROGRESS)
+ {
+ m_creature->InterruptNonMeleeSpells(true);
+ m_creature->RemoveAllAuras();
+ return;
+ }
+
+ float x, y, z;
+ m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 10.0f, x, y, z);
+ // uncomment the following if something doesn't work correctly, otherwise just delete
+ // m_creature->UpdateAllowedPositionZ(x, y, z);
+
+ if (Unit *Summon = m_creature->SummonCreature(creature_entry, x, y, z, m_creature->GetOrientation(), TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000))
+ {
+ if (Creature *temp = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_MEDIVH)))
+ Summon->AddThreat(temp);
+ }
+ }
+
+ void DoSelectSummon()
+ {
+ uint32 entry = 0;
+
+ if ((mRiftWaveCount > 2 && mWaveId < 1) || mRiftWaveCount > 3)
+ mRiftWaveCount = 0;
+
+ entry = PortalWaves[mWaveId].PortalMob[mRiftWaveCount];
+ debug_log("SD2: npc_time_rift: summoning wave creature (Wave %u, Entry %u).", mRiftWaveCount, entry);
+
+ ++mRiftWaveCount;
+
+ if (entry == NPC_WHELP)
+ {
+ for(uint8 i = 0; i < 3; ++i)
+ DoSummonAtRift(entry);
+ }
+ else
+ DoSummonAtRift(entry);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (TimeRiftWave_Timer < diff)
+ {
+ DoSelectSummon();
+ TimeRiftWave_Timer = 15000;
+ }
+ else
+ TimeRiftWave_Timer -= diff;
+
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ return;
+
+ debug_log("SD2: npc_time_rift: not casting anylonger, i need to die.");
+ m_creature->SetDeathState(JUST_DIED);
+
+ if (m_pInstance->GetData(TYPE_RIFT) == IN_PROGRESS)
+ m_pInstance->SetData(TYPE_RIFT, SPECIAL);
+ }
+};
+
+CreatureAI* GetAI_npc_time_rift(Creature* pCreature)
+{
+ return new npc_time_riftAI(pCreature);
+}
+
+#define SAY_SAAT_WELCOME -1269019
+
+#define GOSSIP_ITEM_OBTAIN "[PH] Obtain Chrono-Beacon"
+#define SPELL_CHRONO_BEACON 34975
+#define ITEM_CHRONO_BEACON 24289
+
+bool GossipHello_npc_saat(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_OBTAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(10000, pCreature->GetGUID());
+ return true;
+ }
+ else if (pPlayer->GetQuestRewardStatus(QUEST_OPENING_PORTAL) && !pPlayer->HasItemCount(ITEM_CHRONO_BEACON,1))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_OBTAIN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(10001, pCreature->GetGUID());
+ return true;
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(10002, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_saat(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer,SPELL_CHRONO_BEACON,false);
+ }
+ return true;
+}
+
+void AddSC_dark_portal()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_medivh_bm";
+ newscript->GetAI = &GetAI_npc_medivh_bm;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_time_rift";
+ newscript->GetAI = &GetAI_npc_time_rift;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_saat";
+ newscript->pGossipHello = &GossipHello_npc_saat;
+ newscript->pGossipSelect = &GossipSelect_npc_saat;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h b/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h
new file mode 100644
index 0000000..46ca3af
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h
@@ -0,0 +1,45 @@
+/* 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 */
+
+#ifndef DEF_DARKPORTAL_H
+#define DEF_DARKPORTAL_H
+
+enum
+{
+ MAX_ENCOUNTER = 2,
+
+ TYPE_MEDIVH = 1,
+ TYPE_RIFT = 2,
+
+ DATA_MEDIVH = 10,
+ DATA_PORTAL_COUNT = 11,
+ DATA_SHIELD = 12,
+
+ WORLD_STATE_BM = 2541,
+ WORLD_STATE_BM_SHIELD = 2540,
+ WORLD_STATE_BM_RIFT = 2784,
+
+ QUEST_OPENING_PORTAL = 10297,
+ QUEST_MASTER_TOUCH = 9836,
+
+ NPC_TIME_KEEPER = 17918,
+ NPC_RKEEP = 21104,
+ NPC_RLORD = 17839,
+ NPC_DEJA = 17879,
+ NPC_TEMPO = 17880,
+ NPC_AEONUS = 17881,
+ NPC_ASSAS = 17835,
+ NPC_WHELP = 21818,
+ NPC_CHRON = 17892,
+ NPC_EXECU = 18994,
+ NPC_VANQU = 18995,
+ NPC_MEDIVH = 15608,
+ NPC_TIME_RIFT = 17838,
+
+ SPELL_RIFT_CHANNEL = 31387,
+
+ RIFT_BOSS = 1
+};
+
+#endif
diff --git a/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp b/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp
new file mode 100644
index 0000000..4cb9ba4
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp
@@ -0,0 +1,334 @@
+/* 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_Dark_Portal
+SD%Complete: 50
+SDComment: Quest support: 9836, 10297. Currently in progress.
+SDCategory: Caverns of Time, The Dark Portal
+EndScriptData */
+
+#include "precompiled.h"
+#include "dark_portal.h"
+
+inline uint32 RandRiftBoss() { return (urand(0, 1) ? NPC_RKEEP : NPC_RLORD); }
+
+float PortalLocation[4][4]=
+{
+ {-2041.06f, 7042.08f, 29.99f, 1.30f},
+ {-1968.18f, 7042.11f, 21.93f, 2.12f},
+ {-1885.82f, 7107.36f, 22.32f, 3.07f},
+ {-1928.11f, 7175.95f, 22.11f, 3.44f}
+};
+
+struct Wave
+{
+ uint32 PortalBoss; // protector of current portal
+ uint32 NextPortalTime; // time to next portal, or 0 if portal boss need to be killed
+};
+
+static Wave RiftWaves[]=
+{
+ {RIFT_BOSS, 0},
+ {NPC_DEJA, 0},
+ {RIFT_BOSS, 120000},
+ {NPC_TEMPO, 140000},
+ {RIFT_BOSS, 120000},
+ {NPC_AEONUS, 0}
+};
+
+struct MANGOS_DLL_DECL instance_dark_portal : public ScriptedInstance
+{
+ instance_dark_portal(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ uint32 m_uiRiftPortalCount;
+ uint32 m_uiShieldPercent;
+ uint8 m_uiRiftWaveCount;
+ uint8 m_uiRiftWaveId;
+
+ uint32 m_uiNextPortal_Timer;
+
+ uint64 m_uiMedivhGUID;
+ uint8 m_uiCurrentRiftId;
+
+ void Initialize()
+ {
+ m_uiMedivhGUID = 0;
+ Clear();
+ }
+
+ void Clear()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiRiftPortalCount = 0;
+ m_uiShieldPercent = 100;
+ m_uiRiftWaveCount = 0;
+ m_uiRiftWaveId = 0;
+
+ m_uiCurrentRiftId = 0;
+
+ m_uiNextPortal_Timer = 0;
+ }
+
+ void InitWorldState(bool Enable = true)
+ {
+ DoUpdateWorldState(WORLD_STATE_BM,Enable ? 1 : 0);
+ DoUpdateWorldState(WORLD_STATE_BM_SHIELD, 100);
+ DoUpdateWorldState(WORLD_STATE_BM_RIFT, 0);
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ if (m_auiEncounter[0] == IN_PROGRESS)
+ return true;
+
+ return false;
+ }
+
+ void OnPlayerEnter(Player* pPlayer)
+ {
+ if (m_auiEncounter[0] == IN_PROGRESS)
+ return;
+
+ pPlayer->SendUpdateWorldState(WORLD_STATE_BM, 0);
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ if (pCreature->GetEntry() == NPC_MEDIVH)
+ m_uiMedivhGUID = pCreature->GetGUID();
+ }
+
+ // what other conditions to check?
+ bool CanProgressEvent()
+ {
+ if (instance->GetPlayers().isEmpty())
+ return false;
+
+ return true;
+ }
+
+ uint8 GetRiftWaveId()
+ {
+ switch(m_uiRiftPortalCount)
+ {
+ case 6:
+ m_uiRiftWaveId = 2;
+ return 1;
+ case 12:
+ m_uiRiftWaveId = 4;
+ return 3;
+ case 18:
+ return 5;
+ default:
+ return m_uiRiftWaveId;
+ }
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_MEDIVH:
+ if (uiData == SPECIAL && m_auiEncounter[0] == IN_PROGRESS)
+ {
+ --m_uiShieldPercent;
+
+ DoUpdateWorldState(WORLD_STATE_BM_SHIELD, m_uiShieldPercent);
+
+ if (!m_uiShieldPercent)
+ {
+ if (Creature* pMedivh = instance->GetCreature(m_uiMedivhGUID))
+ {
+ if (pMedivh->isAlive())
+ {
+ pMedivh->DealDamage(pMedivh, pMedivh->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ m_auiEncounter[0] = FAIL;
+ m_auiEncounter[1] = NOT_STARTED;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (uiData == IN_PROGRESS)
+ {
+ debug_log("SD2: Instance Dark Portal: Starting event.");
+ InitWorldState();
+ m_auiEncounter[1] = IN_PROGRESS;
+ m_uiNextPortal_Timer = 15000;
+ }
+
+ if (uiData == DONE)
+ {
+ // this may be completed further out in the post-event
+ debug_log("SD2: Instance Dark Portal: Event completed.");
+
+ Map::PlayerList const& players = instance->GetPlayers();
+
+ if (!players.isEmpty())
+ {
+ for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ if (Player* pPlayer = itr->getSource())
+ {
+ if (pPlayer->GetQuestStatus(QUEST_OPENING_PORTAL) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->AreaExploredOrEventHappens(QUEST_OPENING_PORTAL);
+
+ if (pPlayer->GetQuestStatus(QUEST_MASTER_TOUCH) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->AreaExploredOrEventHappens(QUEST_MASTER_TOUCH);
+ }
+ }
+ }
+ }
+
+ m_auiEncounter[0] = uiData;
+ }
+ break;
+ case TYPE_RIFT:
+ if (uiData == SPECIAL)
+ {
+ if (m_uiRiftPortalCount < 7)
+ m_uiNextPortal_Timer = 5000;
+ }
+ else
+ m_auiEncounter[1] = uiData;
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_MEDIVH:
+ return m_auiEncounter[0];
+ case TYPE_RIFT:
+ return m_auiEncounter[1];
+ case DATA_PORTAL_COUNT:
+ return m_uiRiftPortalCount;
+ case DATA_SHIELD:
+ return m_uiShieldPercent;
+ }
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ if (uiData == DATA_MEDIVH)
+ return m_uiMedivhGUID;
+
+ return 0;
+ }
+
+ Creature* SummonedPortalBoss(Creature* pSource)
+ {
+ uint32 uiEntry = RiftWaves[GetRiftWaveId()].PortalBoss;
+
+ if (uiEntry == RIFT_BOSS)
+ uiEntry = RandRiftBoss();
+
+ float x, y, z;
+ pSource->GetRandomPoint(pSource->GetPositionX(), pSource->GetPositionY(), pSource->GetPositionZ(), 10.0f, x, y, z);
+ // uncomment the following if something doesn't work correctly, otherwise just delete
+ // pSource->UpdateAllowedPositionZ(x, y, z);
+
+ debug_log("SD2: Instance Dark Portal: Summoning rift boss uiEntry %u.", uiEntry);
+
+ if (Creature* pSummoned = pSource->SummonCreature(uiEntry, x, y, z, pSource->GetOrientation(), TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 600000))
+ return pSummoned;
+
+ debug_log("SD2: Instance Dark Portal: what just happened there? No boss, no loot, no fun...");
+ return NULL;
+ }
+
+ void DoSpawnPortal()
+ {
+ if (Creature* pMedivh = instance->GetCreature(m_uiMedivhGUID))
+ {
+ uint8 uiTmp = urand(0, 2);
+
+ if (uiTmp >= m_uiCurrentRiftId)
+ ++uiTmp;
+
+ debug_log("SD2: Instance Dark Portal: Creating Time Rift at locationId %i (old locationId was %u).", uiTmp, m_uiCurrentRiftId);
+
+ m_uiCurrentRiftId = uiTmp;
+
+ if (Creature* pTemp = pMedivh->SummonCreature(NPC_TIME_RIFT, PortalLocation[uiTmp][0], PortalLocation[uiTmp][1], PortalLocation[uiTmp][2], PortalLocation[uiTmp][3], TEMPSUMMON_CORPSE_DESPAWN, 0))
+ {
+ pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ pTemp->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ if (Creature* pBoss = SummonedPortalBoss(pTemp))
+ {
+ if (pBoss->GetEntry() == NPC_AEONUS)
+ pBoss->AddThreat(pMedivh);
+ else
+ {
+ pBoss->AddThreat(pTemp);
+ pTemp->CastSpell(pBoss, SPELL_RIFT_CHANNEL, false);
+ }
+ }
+ }
+ }
+ }
+
+ void Update(uint32 uiDiff)
+ {
+ if (m_auiEncounter[1] != IN_PROGRESS)
+ return;
+
+ //add delay timer?
+ if (!CanProgressEvent())
+ {
+ Clear();
+ return;
+ }
+
+ if (m_uiNextPortal_Timer)
+ {
+ if (m_uiNextPortal_Timer <= uiDiff)
+ {
+ ++m_uiRiftPortalCount;
+
+ DoUpdateWorldState(WORLD_STATE_BM_RIFT, m_uiRiftPortalCount);
+
+ DoSpawnPortal();
+ m_uiNextPortal_Timer = RiftWaves[GetRiftWaveId()].NextPortalTime;
+ }
+ else
+ m_uiNextPortal_Timer -= uiDiff;
+ }
+ }
+};
+
+InstanceData* GetInstanceData_instance_dark_portal(Map* pMap)
+{
+ return new instance_dark_portal(pMap);
+}
+
+void AddSC_instance_dark_portal()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "instance_dark_portal";
+ newscript->GetInstanceData = &GetInstanceData_instance_dark_portal;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp b/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp
new file mode 100644
index 0000000..f56b1b6
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp
@@ -0,0 +1,586 @@
+/* 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_Archimonde
+SD%Complete: 85
+SDComment: Doomfires not completely offlike due to core limitations for random moving. Tyrande and second phase not fully implemented.
+SDCategory: Caverns of Time, Mount Hyjal
+EndScriptData */
+
+#include "precompiled.h"
+#include "hyjal.h"
+#include "SpellAuras.h"
+
+//text id -1534018 are the text used when previous events complete. Not part of this script.
+#define SAY_AGGRO -1534019
+#define SAY_DOOMFIRE1 -1534020
+#define SAY_DOOMFIRE2 -1534021
+#define SAY_AIR_BURST1 -1534022
+#define SAY_AIR_BURST2 -1534023
+#define SAY_SLAY1 -1534024
+#define SAY_SLAY2 -1534025
+#define SAY_SLAY3 -1534026
+#define SAY_ENRAGE -1534027
+#define SAY_DEATH -1534028
+#define SAY_SOUL_CHARGE1 -1534029
+#define SAY_SOUL_CHARGE2 -1534030
+
+#define SPELL_DENOUEMENT_WISP 32124
+#define SPELL_ANCIENT_SPARK 39349
+#define SPELL_PROTECTION_OF_ELUNE 38528
+
+#define SPELL_DRAIN_WORLD_TREE 39140
+#define SPELL_DRAIN_WORLD_TREE_2 39141
+
+#define SPELL_FINGER_OF_DEATH 31984
+#define SPELL_HAND_OF_DEATH 35354
+#define SPELL_AIR_BURST 32014
+#define SPELL_GRIP_OF_THE_LEGION 31972
+#define SPELL_DOOMFIRE_STRIKE 31903 //summons two creatures
+#define SPELL_DOOMFIRE_SPAWN 32074
+#define SPELL_DOOMFIRE 31945
+#define SPELL_SOUL_CHARGE_YELLOW 32045
+#define SPELL_SOUL_CHARGE_GREEN 32051
+#define SPELL_SOUL_CHARGE_RED 32052
+#define SPELL_UNLEASH_SOUL_YELLOW 32054
+#define SPELL_UNLEASH_SOUL_GREEN 32057
+#define SPELL_UNLEASH_SOUL_RED 32053
+#define SPELL_FEAR 31970
+
+#define CREATURE_ARCHIMONDE 17968
+#define CREATURE_DOOMFIRE 18095
+#define CREATURE_DOOMFIRE_SPIRIT 18104
+#define CREATURE_ANCIENT_WISP 17946
+#define CREATURE_CHANNEL_TARGET 22418
+
+#define NORDRASSIL_X 5503.713f
+#define NORDRASSIL_Y -3523.436f
+#define NORDRASSIL_Z 1608.781f
+
+struct mob_ancient_wispAI : public ScriptedAI
+{
+ mob_ancient_wispAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ ArchimondeGUID = 0;
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+ uint64 ArchimondeGUID;
+ uint32 CheckTimer;
+
+ void Reset()
+ {
+ CheckTimer = 1000;
+
+ if (m_pInstance)
+ ArchimondeGUID = m_pInstance->GetData64(DATA_ARCHIMONDE);
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ }
+
+ void DamageTaken(Unit* done_by, uint32 &damage) { damage = 0; }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (CheckTimer < diff)
+ {
+ if (Creature* Archimonde = m_creature->GetMap()->GetCreature(ArchimondeGUID))
+ {
+ if (Archimonde->GetHealthPercent() < 2.0f || !Archimonde->isAlive())
+ DoCastSpellIfCan(m_creature, SPELL_DENOUEMENT_WISP);
+ else
+ DoCastSpellIfCan(Archimonde, SPELL_ANCIENT_SPARK);
+ }
+ CheckTimer = 1000;
+ }else CheckTimer -= diff;
+ }
+};
+
+/* This script is merely a placeholder for the Doomfire that triggers Doomfire spell. It will
+ MoveChase the Doomfire Spirit always, until despawn (AttackStart is called upon it's spawn) */
+struct MANGOS_DLL_DECL mob_doomfireAI : public ScriptedAI
+{
+ mob_doomfireAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ void Reset() { }
+
+ void MoveInLineOfSight(Unit* who) { }
+ void DamageTaken(Unit *done_by, uint32 &damage) { damage = 0; }
+};
+
+/* This is the script for the Doomfire Spirit Mob. This mob simply follow players or
+ travels in random directions if target cannot be found. */
+struct MANGOS_DLL_DECL mob_doomfire_targettingAI : public ScriptedAI
+{
+ mob_doomfire_targettingAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ uint64 TargetGUID;
+ uint32 ChangeTargetTimer;
+
+ void Reset()
+ {
+ TargetGUID = 0;
+ ChangeTargetTimer = 5000;
+ }
+
+ void MoveInLineOfSight(Unit* who)
+ {
+ //will update once TargetGUID is 0. In case noone actually moves(not likely) and this is 0
+ //when UpdateAI needs it, it will be forced to select randomPoint
+ if (!TargetGUID && who->GetTypeId() == TYPEID_PLAYER)
+ TargetGUID = who->GetGUID();
+ }
+
+ void DamageTaken(Unit *done_by, uint32 &damage) { damage = 0; }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (ChangeTargetTimer < diff)
+ {
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(TargetGUID))
+ {
+ m_creature->GetMotionMaster()->MoveFollow(pPlayer, 0.0f, 0.0f);
+ TargetGUID = 0;
+ }
+ else
+ {
+ float x,y,z = 0.0;
+ m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 40, x, y, z);
+ m_creature->GetMotionMaster()->MovePoint(0, x, y, z);
+ }
+
+ ChangeTargetTimer = 5000;
+ }else ChangeTargetTimer -= diff;
+ }
+};
+
+/* Finally, Archimonde's script. His script isn't extremely complex, most are simply spells on timers.
+ The only complicated aspect of the battle is Finger of Death and Doomfire, with Doomfire being the
+ hardest bit to code. Finger of Death is simply a distance check - if no one is in melee range, then
+ select a random target and cast the spell on them. However, if someone IS in melee range, and this
+ is NOT the main tank (creature's victim), then we aggro that player and they become the new victim.
+ For Doomfire, we summon a mob (Doomfire Spirit) for the Doomfire mob to follow. It's spirit will
+ randomly select it's target to follow and then we create the random movement making it unpredictable. */
+
+struct MANGOS_DLL_DECL boss_archimondeAI : public ScriptedAI
+{
+ boss_archimondeAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint64 DoomfireSpiritGUID;
+ uint64 WorldTreeGUID;
+
+ uint32 DrainNordrassilTimer;
+ uint32 FearTimer;
+ uint32 AirBurstTimer;
+ uint32 GripOfTheLegionTimer;
+ uint32 DoomfireTimer;
+ uint32 MeleeRangeCheckTimer;
+ uint32 HandOfDeathTimer;
+ uint32 SummonWispTimer;
+ uint32 WispCount;
+ uint32 EnrageTimer;
+ uint32 CheckDistanceTimer;
+
+ bool Enraged;
+ bool BelowTenPercent;
+ bool HasProtected;
+ bool IsChanneling;
+
+ void Reset()
+ {
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARCHIMONDE, NOT_STARTED);
+
+ DoomfireSpiritGUID = 0;
+ WorldTreeGUID = 0;
+
+ DrainNordrassilTimer = 0;
+ FearTimer = 42000;
+ AirBurstTimer = 30000;
+ GripOfTheLegionTimer = urand(5000, 25000);
+ DoomfireTimer = 20000;
+ MeleeRangeCheckTimer = 15000;
+ HandOfDeathTimer = 2000;
+ WispCount = 0; // When ~30 wisps are summoned, Archimonde dies
+ EnrageTimer = 600000; // 10 minutes
+ CheckDistanceTimer = 30000; // This checks if he's too close to the World Tree (75 yards from a point on the tree), if true then he will enrage
+
+ Enraged = false;
+ BelowTenPercent = false;
+ HasProtected = false;
+ IsChanneling = false;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ DoScriptText(SAY_AGGRO, m_creature);
+
+ m_creature->SetInCombatWithZone();
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARCHIMONDE, IN_PROGRESS);
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_SLAY1, m_creature); break;
+ case 1: DoScriptText(SAY_SLAY2, m_creature); break;
+ case 2: DoScriptText(SAY_SLAY3, m_creature); break;
+ }
+
+ if (pVictim->GetTypeId() != TYPEID_PLAYER)
+ return;
+
+ switch(pVictim->getClass())
+ {
+ case CLASS_PRIEST:
+ case CLASS_PALADIN:
+ case CLASS_WARLOCK:
+ pVictim->CastSpell(m_creature, SPELL_SOUL_CHARGE_RED, true);
+ break;
+ case CLASS_MAGE:
+ case CLASS_ROGUE:
+ case CLASS_WARRIOR:
+ pVictim->CastSpell(m_creature, SPELL_SOUL_CHARGE_YELLOW, true);
+ break;
+ case CLASS_DRUID:
+ case CLASS_SHAMAN:
+ case CLASS_HUNTER:
+ pVictim->CastSpell(m_creature, SPELL_SOUL_CHARGE_GREEN, true);
+ break;
+ }
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_ARCHIMONDE, DONE);
+ }
+
+ bool CanUseFingerOfDeath()
+ {
+ // First we check if our current victim is in melee range or not.
+ Unit* victim = m_creature->getVictim();
+ if (victim && m_creature->IsWithinDistInMap(victim, m_creature->GetAttackDistance(victim)))
+ return false;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ if (tList.empty())
+ return false;
+
+ std::list targets;
+
+ for (ThreatList::const_iterator itr = tList.begin();itr != tList.end(); ++itr)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
+
+ if (pUnit && pUnit->isAlive())
+ targets.push_back(pUnit);
+ }
+
+ if (targets.empty())
+ return false;
+
+ targets.sort(ObjectDistanceOrder(m_creature));
+ Unit* target = targets.front();
+ if (target)
+ {
+ if (!m_creature->IsWithinDistInMap(target, m_creature->GetAttackDistance(target)))
+ return true; // Cast Finger of Death
+ else // This target is closest, he is our new tank
+ m_creature->AddThreat(target, m_creature->getThreatManager().getThreat(m_creature->getVictim()));
+ }
+
+ return false;
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (pSummoned->GetEntry() == CREATURE_ANCIENT_WISP)
+ pSummoned->AI()->AttackStart(m_creature);
+ else
+ {
+ pSummoned->setFaction(m_creature->getFaction());
+ pSummoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ pSummoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ }
+
+ if (pSummoned->GetEntry() == CREATURE_DOOMFIRE_SPIRIT)
+ {
+ DoomfireSpiritGUID = pSummoned->GetGUID();
+ }
+
+ if (pSummoned->GetEntry() == CREATURE_DOOMFIRE)
+ {
+ pSummoned->CastSpell(pSummoned,SPELL_DOOMFIRE_SPAWN,false);
+ pSummoned->CastSpell(pSummoned,SPELL_DOOMFIRE,true,0,0,m_creature->GetGUID());
+
+ if (Creature* pDoomfireSpirit = m_creature->GetMap()->GetCreature(DoomfireSpiritGUID))
+ {
+ pSummoned->GetMotionMaster()->MoveFollow(pDoomfireSpirit,0.0f,0.0f);
+ DoomfireSpiritGUID = 0;
+ }
+ }
+ }
+
+ //this is code doing close to what the summoning spell would do (spell 31903)
+ void SummonDoomfire(Unit* target)
+ {
+ m_creature->SummonCreature(CREATURE_DOOMFIRE_SPIRIT,
+ target->GetPositionX()+15.0,target->GetPositionY()+15.0,target->GetPositionZ(),0,
+ TEMPSUMMON_TIMED_DESPAWN, 27000);
+
+ m_creature->SummonCreature(CREATURE_DOOMFIRE,
+ target->GetPositionX()-15.0,target->GetPositionY()-15.0,target->GetPositionZ(),0,
+ TEMPSUMMON_TIMED_DESPAWN, 27000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->isInCombat())
+ {
+ if (m_pInstance)
+ {
+ // Do not let the raid skip straight to Archimonde. Visible and hostile ONLY if Azagalor is finished.
+ if ((m_pInstance->GetData(TYPE_AZGALOR) < DONE) && ((m_creature->GetVisibility() != VISIBILITY_OFF) || (m_creature->getFaction() != 35)))
+ {
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ m_creature->setFaction(35);
+ }
+ else if ((m_pInstance->GetData(TYPE_AZGALOR) >= DONE) && ((m_creature->GetVisibility() != VISIBILITY_ON) || (m_creature->getFaction() == 35)))
+ {
+ m_creature->setFaction(1720);
+ m_creature->SetVisibility(VISIBILITY_ON);
+ }
+ }
+
+ if (DrainNordrassilTimer < diff)
+ {
+ if (!IsChanneling)
+ {
+ Creature *temp = m_creature->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0.0f, TEMPSUMMON_TIMED_DESPAWN, 1200000);
+
+ if (temp)
+ WorldTreeGUID = temp->GetGUID();
+
+ if (Creature *Nordrassil = m_creature->GetMap()->GetCreature(WorldTreeGUID))
+ {
+ Nordrassil->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ Nordrassil->SetDisplayId(11686);
+ DoCastSpellIfCan(Nordrassil, SPELL_DRAIN_WORLD_TREE);
+ IsChanneling = true;
+ }
+ }
+
+ if (Creature *Nordrassil = m_creature->GetMap()->GetCreature(WorldTreeGUID))
+ {
+ Nordrassil->CastSpell(m_creature, SPELL_DRAIN_WORLD_TREE_2, true);
+ DrainNordrassilTimer = 1000;
+ }
+ }else DrainNordrassilTimer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_creature->GetHealthPercent() < 10.0f && !BelowTenPercent && !Enraged)
+ BelowTenPercent = true;
+
+ if (!Enraged)
+ {
+ if (EnrageTimer < diff)
+ {
+ if (m_creature->GetHealthPercent() > 10.0f)
+ {
+ m_creature->GetMotionMaster()->Clear(false);
+ m_creature->GetMotionMaster()->MoveIdle();
+ Enraged = true;
+ DoScriptText(SAY_ENRAGE, m_creature);
+ }
+ }else EnrageTimer -= diff;
+
+ if (CheckDistanceTimer < diff)
+ {
+ // To simplify the check, we simply summon a creature in the location and then check how far we are from the creature
+ Creature* Check = m_creature->SummonCreature(CREATURE_CHANNEL_TARGET, NORDRASSIL_X, NORDRASSIL_Y, NORDRASSIL_Z, 0, TEMPSUMMON_TIMED_DESPAWN, 2000);
+ if (Check)
+ {
+ Check->SetVisibility(VISIBILITY_OFF);
+
+ if (m_creature->IsWithinDistInMap(Check, 75))
+ {
+ m_creature->GetMotionMaster()->Clear(false);
+ m_creature->GetMotionMaster()->MoveIdle();
+ Enraged = true;
+ DoScriptText(SAY_ENRAGE, m_creature);
+ }
+ }
+ CheckDistanceTimer = 5000;
+ }else CheckDistanceTimer -= diff;
+ }
+
+ if (BelowTenPercent)
+ {
+ if (!HasProtected)
+ {
+ m_creature->GetMotionMaster()->Clear(false);
+ m_creature->GetMotionMaster()->MoveIdle();
+
+ //all members of raid must get this buff
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_PROTECTION_OF_ELUNE);
+ HasProtected = true;
+ Enraged = true;
+ }
+
+ if (SummonWispTimer < diff)
+ {
+ DoSpawnCreature(CREATURE_ANCIENT_WISP, rand()%40, rand()%40, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ SummonWispTimer = 1500;
+ ++WispCount;
+ }else SummonWispTimer -= diff;
+
+ if (WispCount >= 30)
+ m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
+ }
+
+ if (Enraged)
+ {
+ if (HandOfDeathTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAND_OF_DEATH);
+ HandOfDeathTimer = 2000;
+ }else HandOfDeathTimer -= diff;
+ return; // Don't do anything after this point.
+ }
+
+ if (GripOfTheLegionTimer < diff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_GRIP_OF_THE_LEGION);
+
+ GripOfTheLegionTimer = urand(5000, 25000);
+ }else GripOfTheLegionTimer -= diff;
+
+ if (AirBurstTimer < diff)
+ {
+ if (!urand(0, 1))
+ DoScriptText(SAY_AIR_BURST1, m_creature);
+ else
+ DoScriptText(SAY_AIR_BURST2, m_creature);
+
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
+ DoCastSpellIfCan(pTarget, SPELL_AIR_BURST);
+ AirBurstTimer = urand(25000, 40000);
+ }else AirBurstTimer -= diff;
+
+ if (FearTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FEAR);
+ FearTimer = 42000;
+ }else FearTimer -= diff;
+
+ if (DoomfireTimer < diff)
+ {
+ if (!urand(0, 1))
+ DoScriptText(SAY_DOOMFIRE1, m_creature);
+ else
+ DoScriptText(SAY_DOOMFIRE2, m_creature);
+
+ Unit *temp = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1);
+ if (!temp)
+ temp = m_creature->getVictim();
+
+ //replace with spell cast 31903 once implicitTarget 73 implemented
+ SummonDoomfire(temp);
+
+ //supposedly three doomfire can be up at the same time
+ DoomfireTimer = 20000;
+ }else DoomfireTimer -= diff;
+
+ if (MeleeRangeCheckTimer < diff)
+ {
+ if (CanUseFingerOfDeath())
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ DoCastSpellIfCan(pTarget, SPELL_FINGER_OF_DEATH);
+
+ MeleeRangeCheckTimer = 1000;
+ }
+
+ MeleeRangeCheckTimer = 5000;
+ }else MeleeRangeCheckTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_archimonde(Creature* pCreature)
+{
+ return new boss_archimondeAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_doomfire(Creature* pCreature)
+{
+ return new mob_doomfireAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_doomfire_targetting(Creature* pCreature)
+{
+ return new mob_doomfire_targettingAI(pCreature);
+}
+
+CreatureAI* GetAI_mob_ancient_wisp(Creature* pCreature)
+{
+ return new mob_ancient_wispAI(pCreature);
+}
+
+void AddSC_boss_archimonde()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_archimonde";
+ newscript->GetAI = &GetAI_boss_archimonde;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_doomfire";
+ newscript->GetAI = &GetAI_mob_doomfire;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_doomfire_targetting";
+ newscript->GetAI = &GetAI_mob_doomfire_targetting;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_ancient_wisp";
+ newscript->GetAI = &GetAI_mob_ancient_wisp;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp b/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp
new file mode 100644
index 0000000..e14b280
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp
@@ -0,0 +1,238 @@
+/* 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: Hyjal
+SD%Complete: 80
+SDComment: gossip text id's unknown
+SDCategory: Caverns of Time, Mount Hyjal
+EndScriptData */
+
+/* ContentData
+npc_jaina_proudmoore
+npc_thrall
+npc_tyrande_whisperwind
+EndContentData */
+
+#include "precompiled.h"
+#include "hyjalAI.h"
+
+#define GOSSIP_ITEM_BEGIN_ALLY "My companions and I are with you, Lady Proudmoore."
+#define GOSSIP_ITEM_ANETHERON "We are ready for whatever Archimonde might send our way, Lady Proudmoore."
+#define GOSSIP_ITEM_BEGIN_HORDE "I am with you, Thrall."
+#define GOSSIP_ITEM_AZGALOR "We have nothing to fear."
+
+#define GOSSIP_ITEM_RETREAT "We can't keep this up. Let's retreat!"
+
+#define GOSSIP_ITEM_TYRANDE "Aid us in defending Nordrassil"
+
+CreatureAI* GetAI_npc_jaina_proudmoore(Creature* pCreature)
+{
+ hyjalAI* pTempAI = new hyjalAI(pCreature);
+
+ pTempAI->m_aSpells[0].m_uiSpellId = SPELL_BLIZZARD;
+ pTempAI->m_aSpells[0].m_uiCooldown = urand(15000, 35000);
+ pTempAI->m_aSpells[0].m_pType = TARGETTYPE_RANDOM;
+
+ pTempAI->m_aSpells[1].m_uiSpellId = SPELL_PYROBLAST;
+ pTempAI->m_aSpells[1].m_uiCooldown = urand(2000, 9000);
+ pTempAI->m_aSpells[1].m_pType = TARGETTYPE_RANDOM;
+
+ pTempAI->m_aSpells[2].m_uiSpellId = SPELL_SUMMON_ELEMENTALS;
+ pTempAI->m_aSpells[2].m_uiCooldown = urand(15000, 45000);
+ pTempAI->m_aSpells[2].m_pType = TARGETTYPE_SELF;
+
+ return pTempAI;
+}
+
+bool GossipHello_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ {
+ if (hyjalAI* pJainaAI = dynamic_cast(pCreature->AI()))
+ {
+ if (!pJainaAI->m_bIsEventInProgress)
+ {
+ // Should not happen that jaina is here now, but for safe we check
+ if (pInstance->GetData(TYPE_KAZROGAL) != DONE)
+ {
+ if (pInstance->GetData(TYPE_WINTERCHILL) == NOT_STARTED)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_ALLY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ else if (pInstance->GetData(TYPE_WINTERCHILL) == DONE && pInstance->GetData(TYPE_ANETHERON) == NOT_STARTED)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_ANETHERON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ else if (pInstance->GetData(TYPE_ANETHERON) == DONE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+
+ if (pPlayer->isGameMaster())
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "[GM] Toggle Debug Timers", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ }
+ }
+ }
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (hyjalAI* pJainaAI = dynamic_cast(pCreature->AI()))
+ {
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF + 1:
+ pJainaAI->StartEvent();
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 2:
+ pJainaAI->m_bIsFirstBossDead = true;
+ pJainaAI->m_uiWaveCount = 9;
+ pJainaAI->StartEvent();
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 3:
+ pJainaAI->Retreat();
+ break;
+ case GOSSIP_ACTION_INFO_DEF:
+ pJainaAI->m_bDebugMode = !pJainaAI->m_bDebugMode;
+ debug_log("SD2: HyjalAI - Debug mode has been toggled");
+ break;
+ }
+ }
+
+ pPlayer->CLOSE_GOSSIP_MENU();
+ return true;
+}
+
+CreatureAI* GetAI_npc_thrall(Creature* pCreature)
+{
+ hyjalAI* pTempAI = new hyjalAI(pCreature);
+
+ pTempAI->m_aSpells[0].m_uiSpellId = SPELL_CHAIN_LIGHTNING;
+ pTempAI->m_aSpells[0].m_uiCooldown = urand(2000, 7000);
+ pTempAI->m_aSpells[0].m_pType = TARGETTYPE_VICTIM;
+
+ pTempAI->m_aSpells[1].m_uiSpellId = SPELL_FERAL_SPIRIT;
+ pTempAI->m_aSpells[1].m_uiCooldown = urand(6000, 41000);
+ pTempAI->m_aSpells[1].m_pType = TARGETTYPE_RANDOM;
+
+ return pTempAI;
+}
+
+bool GossipHello_npc_thrall(Player* pPlayer, Creature* pCreature)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ {
+ if (hyjalAI* pThrallAI = dynamic_cast(pCreature->AI()))
+ {
+ if (!pThrallAI->m_bIsEventInProgress)
+ {
+ // Only let them start the Horde phases if Anetheron is dead.
+ if (pInstance->GetData(TYPE_ANETHERON) == DONE)
+ {
+ if (pInstance->GetData(TYPE_KAZROGAL) == NOT_STARTED)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEGIN_HORDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ else if (pInstance->GetData(TYPE_KAZROGAL) == DONE && pInstance->GetData(TYPE_AZGALOR) == NOT_STARTED)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AZGALOR, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ else if (pInstance->GetData(TYPE_AZGALOR) == DONE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RETREAT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+
+ if (pPlayer->isGameMaster())
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_DOT, "[GM] Toggle Debug Timers", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ }
+ }
+ }
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_thrall(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (hyjalAI* pThrallAI = dynamic_cast(pCreature->AI()))
+ {
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF + 1:
+ pThrallAI->StartEvent();
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 2:
+ pThrallAI->m_bIsFirstBossDead = true;
+ pThrallAI->m_uiWaveCount = 9;
+ pThrallAI->StartEvent();
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 3:
+ pThrallAI->Retreat();
+ break;
+ case GOSSIP_ACTION_INFO_DEF:
+ pThrallAI->m_bDebugMode = !pThrallAI->m_bDebugMode;
+ debug_log("SD2: HyjalAI - Debug mode has been toggled");
+ break;
+ }
+ }
+
+ pPlayer->CLOSE_GOSSIP_MENU();
+ return true;
+}
+
+bool GossipHello_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData())
+ {
+ // Only let them get item if Azgalor is dead.
+ if (pInstance->GetData(TYPE_AZGALOR) == DONE && !pPlayer->HasItemCount(ITEM_TEAR_OF_GODDESS,1))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TYRANDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(907, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_tyrande_whisperwind(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF)
+ {
+ if (Item* pItem = pPlayer->StoreNewItemInInventorySlot(ITEM_TEAR_OF_GODDESS, 1))
+ pPlayer->SendNewItem(pItem, 1, true, false);
+ }
+
+ pPlayer->CLOSE_GOSSIP_MENU();
+ return true;
+}
+
+void AddSC_hyjal()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_jaina_proudmoore";
+ newscript->GetAI = &GetAI_npc_jaina_proudmoore;
+ newscript->pGossipHello = &GossipHello_npc_jaina_proudmoore;
+ newscript->pGossipSelect = &GossipSelect_npc_jaina_proudmoore;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_thrall";
+ newscript->GetAI = &GetAI_npc_thrall;
+ newscript->pGossipHello = &GossipHello_npc_thrall;
+ newscript->pGossipSelect = &GossipSelect_npc_thrall;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_tyrande_whisperwind";
+ newscript->pGossipHello = &GossipHello_npc_tyrande_whisperwind;
+ newscript->pGossipSelect = &GossipSelect_npc_tyrande_whisperwind;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h b/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h
new file mode 100644
index 0000000..f4e03fa
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h
@@ -0,0 +1,71 @@
+/* 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 */
+
+#ifndef DEF_HYJAL_H
+#define DEF_HYJAL_H
+
+#define ERROR_INST_DATA "SD2: Instance data not set properly for Mount Hyjal. Encounters will be buggy"
+
+enum eNPC
+{
+ NPC_JAINA = 17772,
+ NPC_THRALL = 17852,
+ NPC_TYRANDE = 17948,
+
+ // Bosses summoned after every 8 waves
+ NPC_WINTERCHILL = 17767,
+ NPC_ANETHERON = 17808,
+ NPC_KAZROGAL = 17888,
+ NPC_AZGALOR = 17842,
+ NPC_ARCHIMONDE = 17968,
+
+ // Trash Mobs summoned in waves
+ NPC_NECRO = 17899,
+ NPC_ABOMI = 17898,
+ NPC_GHOUL = 17895,
+ NPC_BANSH = 17905,
+ NPC_CRYPT = 17897,
+ NPC_GARGO = 17906,
+ NPC_FROST = 17907,
+ NPC_GIANT = 17908,
+ NPC_STALK = 17916,
+
+ NPC_WATER_ELEMENTAL = 18001,
+ NPC_DIRE_WOLF = 17854,
+
+ GO_ANCIENT_GEM = 185557
+};
+
+enum
+{
+ MAX_ENCOUNTER = 5,
+
+ WORLD_STATE_WAVES = 2842,
+ WORLD_STATE_ENEMY = 2453,
+ WORLD_STATE_ENEMYCOUNT = 2454,
+
+ // ACID scripted, don't touch id's (or provide update for ACID)
+ TYPE_WINTERCHILL = 11,
+ TYPE_ANETHERON = 2,
+ TYPE_KAZROGAL = 9,
+ TYPE_AZGALOR = 6,
+
+ TYPE_ARCHIMONDE = 4,
+
+ DATA_ANETHERON = 1,
+ DATA_RAGEWINTERCHILL = 10,
+ DATA_AZGALOR = 5,
+ DATA_KAZROGAL = 8,
+
+ DATA_ARCHIMONDE = 3,
+ DATA_JAINAPROUDMOORE = 7,
+ DATA_THRALL = 12,
+ DATA_TYRANDEWHISPERWIND = 13,
+
+ DATA_TRASH = 14,
+ DATA_RESET_TRASH_COUNT = 15,
+ TYPE_RETREAT = 16
+};
+
+#endif
diff --git a/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp b/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp
new file mode 100644
index 0000000..ba755d4
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp
@@ -0,0 +1,496 @@
+/* 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: HyjalAI
+SD%Complete: 90
+SDComment:
+SDCategory: Caverns of Time, Mount Hyjal
+EndScriptData */
+
+#include "precompiled.h"
+#include "hyjalAI.h"
+
+struct sHyjalLocation
+{
+ eBaseArea m_pBaseArea;
+ float m_fX, m_fY, m_fZ;
+};
+
+// Locations for summoning waves
+sHyjalLocation m_aHyjalSpawnLoc[]=
+{
+ {BASE_ALLY, 4979.010f, -1709.134f, 1339.674f},
+ {BASE_ALLY, 4969.123f, -1705.904f, 1341.363f},
+ {BASE_ALLY, 4970.260f, -1698.546f, 1341.200f},
+ {BASE_ALLY, 4975.262f, -1698.239f, 1341.427f},
+ {BASE_HORDE, 5557.582f, -2587.159f, 1481.644f},
+ {BASE_HORDE, 5545.901f, -2582.246f, 1479.256f},
+ {BASE_HORDE, 5565.642f, -2565.666f, 1481.635f},
+ {BASE_HORDE, 5547.218f, -2574.589f, 1479.194f}
+};
+
+// used to inform the wave where to move
+sHyjalLocation m_aHyjalWaveMoveTo[]=
+{
+ {BASE_ALLY, 5018.654f, -1752.074f, 1322.203f},
+ {BASE_HORDE, 5504.569f, -2688.489f, 1479.991f}
+};
+
+struct sHyjalYells
+{
+ uint32 uiCreatureEntry;
+ YellType m_pYellType; // Used to determine the type of yell (attack, rally, etc)
+ int32 m_iTextId; // The text id to be yelled
+};
+
+sHyjalYells m_aHyjalYell[]=
+{
+ {NPC_JAINA, ATTACKED, -1534000},
+ {NPC_JAINA, ATTACKED, -1534001},
+ {NPC_JAINA, INCOMING, -1534002},
+ {NPC_JAINA, BEGIN, -1534003},
+ {NPC_JAINA, RALLY, -1534004},
+ {NPC_JAINA, RALLY, -1534005},
+ {NPC_JAINA, FAILURE, -1534006},
+ {NPC_JAINA, SUCCESS, -1534007},
+ {NPC_JAINA, DEATH, -1534008},
+
+ {NPC_THRALL, ATTACKED, -1534009},
+ {NPC_THRALL, ATTACKED, -1534010},
+ {NPC_THRALL, INCOMING, -1534011},
+ {NPC_THRALL, BEGIN, -1534012},
+ {NPC_THRALL, RALLY, -1534013},
+ {NPC_THRALL, RALLY, -1534014},
+ {NPC_THRALL, FAILURE, -1534015},
+ {NPC_THRALL, SUCCESS, -1534016},
+ {NPC_THRALL, DEATH, -1534017}
+};
+
+void hyjalAI::Reset()
+{
+ // GUIDs
+ m_uiBossGUID[0] = 0;
+ m_uiBossGUID[1] = 0;
+
+ // Timers
+ m_uiNextWaveTimer = 10000;
+ m_uiWaveMoveTimer = 15000;
+ m_uiCheckTimer = 0;
+ m_uiRetreatTimer = 25000;
+
+ // Misc
+ m_uiWaveCount = 0;
+ m_uiEnemyCount = 0;
+
+ // Set base area based on creature entry
+ switch(m_creature->GetEntry())
+ {
+ case NPC_JAINA:
+ m_uiBase = BASE_ALLY;
+ DoCastSpellIfCan(m_creature, SPELL_BRILLIANCE_AURA, CAST_TRIGGERED);
+ break;
+ case NPC_THRALL:
+ m_uiBase = BASE_HORDE;
+ break;
+ }
+
+ // Bools
+ m_bIsEventInProgress = false;
+ m_bIsSummoningWaves = false;
+
+ m_bIsRetreating = false;
+ m_bDebugMode = false;
+
+ // Flags
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+
+ // Reset World States
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0);
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0);
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0);
+
+ if (!m_pInstance)
+ return;
+
+ m_bIsFirstBossDead = m_uiBase ? m_pInstance->GetData(TYPE_KAZROGAL) : m_pInstance->GetData(TYPE_WINTERCHILL);
+ m_bIsSecondBossDead = m_uiBase ? m_pInstance->GetData(TYPE_AZGALOR) : m_pInstance->GetData(TYPE_ANETHERON);
+
+ // Reset Instance Data for trash count
+ m_pInstance->SetData(DATA_RESET_TRASH_COUNT, 0);
+}
+
+void hyjalAI::EnterEvadeMode()
+{
+ 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);
+}
+
+void hyjalAI::JustReachedHome()
+{
+ if (m_uiBase == BASE_ALLY)
+ DoCastSpellIfCan(m_creature, SPELL_BRILLIANCE_AURA, CAST_TRIGGERED);
+
+ m_bIsFirstBossDead = m_uiBase ? m_pInstance->GetData(TYPE_KAZROGAL) : m_pInstance->GetData(TYPE_WINTERCHILL);
+ m_bIsSecondBossDead = m_uiBase ? m_pInstance->GetData(TYPE_AZGALOR) : m_pInstance->GetData(TYPE_ANETHERON);
+}
+
+void hyjalAI::Aggro(Unit *who)
+{
+ for(uint8 i = 0; i < MAX_SPELL; ++i)
+ if (m_aSpells[i].m_uiCooldown)
+ m_uiSpellTimer[i] = m_aSpells[i].m_uiCooldown;
+
+ DoTalk(ATTACKED);
+}
+
+void hyjalAI::SpawnCreatureForWave(uint32 uiMobEntry)
+{
+ sHyjalLocation* pSpawn = NULL;
+
+ uint32 uiMaxCount = sizeof(m_aHyjalSpawnLoc)/sizeof(sHyjalLocation);
+ uint32 uiRandId = urand(1, uiMaxCount/2); //unsafe, if array becomes uneven.
+
+ uint32 uiJ = 0;
+
+ for (uint32 i = 0; i < uiMaxCount; ++i)
+ {
+ if (m_aHyjalSpawnLoc[i].m_pBaseArea != m_uiBase)
+ continue;
+
+ ++uiJ;
+
+ if (uiJ == uiRandId)
+ {
+ pSpawn = &m_aHyjalSpawnLoc[i];
+ break;
+ }
+ }
+
+ if (pSpawn)
+ m_creature->SummonCreature(uiMobEntry, pSpawn->m_fX, pSpawn->m_fY, pSpawn->m_fZ, 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000);
+}
+
+void hyjalAI::JustSummoned(Creature* pSummoned)
+{
+ // not interesting for us
+ if (pSummoned->GetEntry() == NPC_WATER_ELEMENTAL || pSummoned->GetEntry() == NPC_DIRE_WOLF)
+ return;
+
+ // Increment Enemy Count to be used in World States and instance script
+ ++m_uiEnemyCount;
+
+ sHyjalLocation* pMove = NULL;
+
+ uint32 uiMaxCount = sizeof(m_aHyjalWaveMoveTo)/sizeof(sHyjalLocation);
+
+ for (uint32 i = 0; i < uiMaxCount; ++i)
+ {
+ if (m_aHyjalWaveMoveTo[i].m_pBaseArea != m_uiBase)
+ continue;
+
+ pMove = &m_aHyjalWaveMoveTo[i];
+ break;
+ }
+
+ if (pMove)
+ {
+ float fX, fY, fZ;
+ pSummoned->GetRandomPoint(pMove->m_fX, pMove->m_fY, pMove->m_fZ, 10.0f, fX, fY, fZ);
+
+ pSummoned->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pSummoned->GetMotionMaster()->MovePoint(0, fX, fY, fZ);
+ }
+
+ // Check if creature is a boss.
+ if (pSummoned->IsWorldBoss())
+ {
+ if (!m_bIsFirstBossDead)
+ m_uiBossGUID[0] = pSummoned->GetGUID();
+ else
+ m_uiBossGUID[1] = pSummoned->GetGUID();
+
+ m_uiCheckTimer = 5000;
+ }
+ else
+ lWaveMobGUIDList.push_back(pSummoned->GetGUID());
+}
+
+void hyjalAI::SummonNextWave()
+{
+ // 1 in 4 chance we give a rally yell. Not sure if the chance is offilike.
+ if (!urand(0, 3))
+ DoTalk(RALLY);
+
+ if (!m_pInstance)
+ {
+ error_log(ERROR_INST_DATA);
+ return;
+ }
+
+ sHyjalWave* pWaveData = m_uiBase ? &m_aHyjalWavesHorde[m_uiWaveCount] : &m_aHyjalWavesAlliance[m_uiWaveCount];
+
+ if (!pWaveData)
+ {
+ error_log("SD2: hyjalAI not able to obtain wavedata for SummonNextWave.");
+ return;
+ }
+
+ m_uiEnemyCount = m_pInstance->GetData(DATA_TRASH);
+
+ for(uint8 i = 0; i < MAX_WAVE_MOB; ++i)
+ {
+ if (pWaveData->m_auiMobEntry[i])
+ SpawnCreatureForWave(pWaveData->m_auiMobEntry[i]);
+ }
+
+ if (!pWaveData->m_bIsBoss)
+ {
+ uint32 stateValue = m_uiWaveCount+1;
+
+ if (m_bIsFirstBossDead)
+ stateValue -= MAX_WAVES; // Subtract 9 from it to give the proper wave number if we are greater than 8
+
+ // Set world state to our current wave number
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, stateValue);
+ // Enable world state
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1);
+
+ m_pInstance->SetData(DATA_TRASH, m_uiEnemyCount); // Send data for instance script to update count
+
+ if (!m_bDebugMode)
+ m_uiNextWaveTimer = pWaveData->m_uiWaveTimer;
+ else
+ {
+ m_uiNextWaveTimer = 15000;
+ debug_log("SD2: HyjalAI: debug mode is enabled. Next Wave in 15 seconds");
+ }
+ }
+ else
+ {
+ // Set world state for waves to 0 to disable it.
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0);
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 1);
+
+ // Set World State for enemies invading to 1.
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 1);
+
+ m_bIsSummoningWaves = false;
+ }
+
+ m_uiWaveMoveTimer = 15000;
+ m_uiCheckTimer = 5000;
+ ++m_uiWaveCount;
+}
+
+void hyjalAI::StartEvent()
+{
+ if (!m_pInstance)
+ return;
+
+ DoTalk(BEGIN);
+
+ m_bIsEventInProgress = true;
+ m_bIsSummoningWaves = true;
+
+ m_uiNextWaveTimer = 10000;
+ m_uiCheckTimer = 5000;
+
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_WAVES, 0);
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0);
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, 0);
+}
+
+void hyjalAI::DoTalk(YellType pYellType)
+{
+ sHyjalYells* pYell = NULL;
+
+ uint32 uiMaxCount = sizeof(m_aHyjalYell)/sizeof(sHyjalYells);
+ bool bGetNext = false;
+
+ for (uint32 i = 0; i < uiMaxCount; ++i)
+ {
+ if (m_aHyjalYell[i].uiCreatureEntry == m_creature->GetEntry() && m_aHyjalYell[i].m_pYellType == pYellType)
+ {
+ //this would not be safe unless we knew these had two entries in m_aYell
+ if (pYellType == ATTACKED || pYellType== RALLY)
+ {
+ if (!bGetNext && urand(0, 1))
+ {
+ bGetNext = true;
+ continue;
+ }
+ }
+
+ pYell = &m_aHyjalYell[i];
+ break;
+ }
+ }
+
+ if (pYell)
+ DoScriptText(pYell->m_iTextId, m_creature);
+}
+
+void hyjalAI::SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell)
+{
+ //TODO: this spell should cause misc mobs to despawn
+ //if (pSpell->Id == SPELL_MASS_TELEPORT && pTarget->GetTypeId() != TYPEID_PLAYER)
+ //{
+ //despawn;
+ //}
+}
+
+void hyjalAI::Retreat()
+{
+ //this will trigger ancient gem respawn
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_RETREAT, SPECIAL);
+
+ DoCastSpellIfCan(m_creature, SPELL_MASS_TELEPORT);
+
+ m_bIsRetreating = true;
+}
+
+void hyjalAI::JustDied(Unit* pKiller)
+{
+ DoTalk(DEATH);
+
+ //TODO: in case they die during boss encounter, then what? despawn boss?
+}
+
+void hyjalAI::UpdateAI(const uint32 uiDiff)
+{
+ if (!m_bIsEventInProgress)
+ return;
+
+ if (m_bIsSummoningWaves && m_pInstance)
+ {
+ if (m_uiWaveMoveTimer < uiDiff)
+ {
+ // Skip the master timer, and start next wave in 5. Clear the list, it should not be any here now.
+ if (!m_pInstance->GetData(DATA_TRASH))
+ {
+ lWaveMobGUIDList.clear();
+ m_uiNextWaveTimer = 5000;
+ }
+
+ if (!lWaveMobGUIDList.empty())
+ {
+ for(std::list::iterator itr = lWaveMobGUIDList.begin(); itr != lWaveMobGUIDList.end(); ++itr)
+ {
+ if (Creature* pTemp = m_pInstance->instance->GetCreature(*itr))
+ {
+ if (!pTemp->isAlive() || pTemp->getVictim())
+ continue;
+
+ pTemp->RemoveSplineFlag(SPLINEFLAG_WALKMODE);
+ pTemp->GetMotionMaster()->MovePoint(1, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
+ }
+ }
+ }
+ m_uiWaveMoveTimer = 10000;
+ }
+ else
+ m_uiWaveMoveTimer -= uiDiff;
+
+ if (m_uiNextWaveTimer < uiDiff)
+ SummonNextWave();
+ else
+ m_uiNextWaveTimer -= uiDiff;
+ }
+
+ if (m_uiCheckTimer < uiDiff)
+ {
+ for(uint8 i = 0; i < 2; ++i)
+ {
+ if (m_uiBossGUID[i])
+ {
+ Creature* pBoss = m_creature->GetMap()->GetCreature(m_uiBossGUID[i]);
+
+ if (pBoss && !pBoss->isAlive())
+ {
+ if (m_uiBossGUID[i] == m_uiBossGUID[0])
+ {
+ DoTalk(INCOMING);
+ m_bIsFirstBossDead = true;
+ }
+ else if (m_uiBossGUID[i] == m_uiBossGUID[1])
+ {
+ DoTalk(SUCCESS);
+ m_bIsSecondBossDead = true;
+ }
+
+ m_bIsEventInProgress = false;
+ m_uiCheckTimer = 0;
+
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+
+ m_uiBossGUID[i] = 0;
+
+ // Reset world state for enemies to disable it
+ m_pInstance->DoUpdateWorldState(WORLD_STATE_ENEMY, 0);
+ }
+ }
+ }
+
+ m_uiCheckTimer = 5000;
+ }
+ else
+ m_uiCheckTimer -= uiDiff;
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ for(uint8 i = 0; i < MAX_SPELL; ++i)
+ {
+ if (m_aSpells[i].m_uiSpellId)
+ {
+ if (m_uiSpellTimer[i] < uiDiff)
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ Unit* pTarget = NULL;
+
+ switch(m_aSpells[i].m_pType)
+ {
+ case TARGETTYPE_SELF: pTarget = m_creature; break;
+ case TARGETTYPE_RANDOM: pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0); break;
+ case TARGETTYPE_VICTIM: pTarget = m_creature->getVictim(); break;
+ }
+
+ if (pTarget)
+ {
+ DoCastSpellIfCan(pTarget, m_aSpells[i].m_uiSpellId);
+ m_uiSpellTimer[i] = m_aSpells[i].m_uiCooldown;
+ }
+ }
+ else
+ m_uiSpellTimer[i] -= uiDiff;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+}
diff --git a/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h b/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h
new file mode 100644
index 0000000..7bbc024
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h
@@ -0,0 +1,199 @@
+/* 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 */
+
+#ifndef SC_HYJALAI_H
+#define SC_HYJALAI_H
+
+#include "hyjal.h"
+
+enum eBaseArea
+{
+ BASE_ALLY = 0,
+ BASE_HORDE = 1
+};
+
+enum eMisc
+{
+ MAX_SPELL = 3,
+ MAX_WAVES = 9,
+ MAX_WAVE_MOB = 18,
+
+ ITEM_TEAR_OF_GODDESS = 24494
+};
+
+enum eSpell
+{
+ SPELL_MASS_TELEPORT = 16807,
+
+ // Spells for Jaina
+ SPELL_BRILLIANCE_AURA = 31260,
+ SPELL_BLIZZARD = 31266,
+ SPELL_PYROBLAST = 31263,
+ SPELL_SUMMON_ELEMENTALS = 31264,
+
+ // Thrall spells
+ SPELL_CHAIN_LIGHTNING = 31330,
+ SPELL_FERAL_SPIRIT = 31331
+};
+
+struct sHyjalWave
+{
+ uint32 m_auiMobEntry[MAX_WAVE_MOB]; // Stores Creature Entries to be summoned in Waves
+ uint32 m_uiWaveTimer; // The timer before the next wave is summoned
+ bool m_bIsBoss; // Simply used to inform the wave summoner that the next wave contains a boss to halt all waves after that
+};
+
+// Waves that will be summoned in the Alliance Base
+static sHyjalWave m_aHyjalWavesAlliance[]=
+{
+ // Rage Winterchill Wave 1-8
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_ABOMI, NPC_ABOMI, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 180000, false},
+ // All 8 Waves are summoned, summon Rage Winterchill, next few waves are for Anetheron
+ {NPC_WINTERCHILL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true},
+ // Anetheron Wave 1-8
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, 0, 0, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_BANSH, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_NECRO, NPC_NECRO, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_BANSH, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_ABOMI, NPC_ABOMI, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_BANSH, NPC_BANSH, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 180000, false},
+ // All 8 Waves are summoned, summon Anatheron
+ {NPC_ANETHERON, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}
+};
+
+// Waves that are summoned in the Horde base
+static sHyjalWave m_aHyjalWavesHorde[]=
+{
+ // Kaz'Rogal Wave 1-8
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_BANSH, NPC_BANSH, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 120000, false},
+ {NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_FROST, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_FROST, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_NECRO, NPC_NECRO, NPC_BANSH, NPC_BANSH, 180000, false},
+ // All 8 Waves are summoned, summon Kaz'Rogal, next few waves are for Azgalor
+ {NPC_KAZROGAL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true},
+ // Azgalor Wave 1-8
+ {NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_FROST, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, NPC_GARGO, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GHOUL, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, 0, 0, 0, 0, 120000, false},
+ {NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_STALK, NPC_STALK, NPC_STALK, NPC_STALK, NPC_STALK, NPC_STALK, 0, 0, 0, 0, 120000, false},
+ {NPC_STALK, NPC_STALK, NPC_STALK, NPC_STALK, NPC_STALK, NPC_STALK, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, 0, 0, 0, 0, 120000, false},
+ {NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_NECRO, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_BANSH, 0, 0, 0, 0, 120000, false},
+ {NPC_GHOUL, NPC_GHOUL, NPC_CRYPT, NPC_CRYPT, NPC_STALK, NPC_STALK, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, NPC_GIANT, 0, 0, 0, 0, 0, 0, 120000, false},
+ {NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_CRYPT, NPC_STALK, NPC_STALK, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_ABOMI, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_BANSH, NPC_NECRO, NPC_NECRO, 0, 0, 180000, false},
+ // All 8 Waves are summoned, summon Azgalor
+ {NPC_AZGALOR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, true}
+};
+
+enum TargetType // Used in the spell cast system for the AI
+{
+ TARGETTYPE_SELF = 0,
+ TARGETTYPE_RANDOM = 1,
+ TARGETTYPE_VICTIM = 2,
+};
+
+enum YellType
+{
+ ATTACKED = 0, // Used when attacked and set in combat
+ BEGIN = 1, // Used when the event is begun
+ INCOMING = 2, // Used to warn the raid that another wave phase is coming
+ RALLY = 3, // Used to rally the raid and warn that the next wave has been summoned
+ FAILURE = 4, // Used when raid has failed (unsure where to place)
+ SUCCESS = 5, // Used when the raid has sucessfully defeated a wave phase
+ DEATH = 6, // Used on death
+};
+
+struct MANGOS_DLL_DECL hyjalAI : public ScriptedAI
+{
+ hyjalAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ memset(m_aSpells, 0, sizeof(m_aSpells));
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ // Generically used to reset our variables. Do *not* call in EnterEvadeMode as this may make problems if the raid is still in combat
+ void Reset();
+
+ // Send creature back to spawn location and evade.
+ void EnterEvadeMode();
+
+ // Called when creature reached home location after evade.
+ void JustReachedHome();
+
+ // Used to reset cooldowns for our spells and to inform the raid that we're under attack
+ void Aggro(Unit* pWho);
+
+ // Called to summon waves, check for boss deaths and to cast our spells.
+ void UpdateAI(const uint32 uiDiff);
+
+ // Called on death, informs the raid that they have failed.
+ void JustDied(Unit* pKiller);
+
+ // "Teleport" all friendly creatures away from the base.
+ void Retreat();
+
+ // Summons a creature for that wave in that base
+ void SpawnCreatureForWave(uint32 uiMobEntry);
+
+ void JustSummoned(Creature*);
+
+ // Summons the next wave, calls SummonCreature
+ void SummonNextWave();
+
+ // Begins the event by gossip click
+ void StartEvent();
+
+ // Searches for the appropriate yell and sound and uses it to inform the raid of various things
+ void DoTalk(YellType pYellType);
+
+ // Used to filter who to despawn after mass teleport
+ void SpellHitTarget(Unit*, const SpellEntry*);
+
+ public:
+
+ ScriptedInstance* m_pInstance;
+
+ uint64 m_uiBossGUID[2];
+
+ uint32 m_uiNextWaveTimer;
+ uint32 m_uiWaveCount;
+ uint32 m_uiWaveMoveTimer;
+ uint32 m_uiCheckTimer;
+ uint32 m_uiEnemyCount;
+ uint32 m_uiRetreatTimer;
+ uint32 m_uiBase;
+
+ bool m_bIsEventInProgress;
+ bool m_bIsFirstBossDead;
+ bool m_bIsSecondBossDead;
+ bool m_bIsSummoningWaves;
+ bool m_bIsRetreating;
+ bool m_bDebugMode;
+
+ struct sSpells
+ {
+ uint32 m_uiSpellId;
+ uint32 m_uiCooldown;
+ TargetType m_pType;
+ } m_aSpells[MAX_SPELL];
+
+ private:
+ uint32 m_uiSpellTimer[MAX_SPELL];
+ std::list lWaveMobGUIDList;
+};
+
+#endif
diff --git a/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp b/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp
new file mode 100644
index 0000000..ef4fcb6
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp
@@ -0,0 +1,244 @@
+/* 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_Mount_Hyjal
+SD%Complete: 100
+SDComment: Instance Data Scripts and functions to acquire mobs and set encounter status for use in various Hyjal Scripts
+SDCategory: Caverns of Time, Mount Hyjal
+EndScriptData */
+
+#include "precompiled.h"
+#include "hyjal.h"
+
+/* Battle of Mount Hyjal encounters:
+0 - Rage Winterchill event
+1 - Anetheron event
+2 - Kaz'rogal event
+3 - Azgalor event
+4 - Archimonde event
+*/
+
+struct MANGOS_DLL_DECL instance_mount_hyjal : public ScriptedInstance
+{
+ instance_mount_hyjal(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strSaveData;
+
+ std::list lAncientGemGUIDList;
+
+ uint64 m_uiRageWinterchill;
+ uint64 m_uiAnetheron;
+ uint64 m_uiKazrogal;
+ uint64 m_uiAzgalor;
+ uint64 m_uiArchimonde;
+ uint64 m_uiJainaProudmoore;
+ uint64 m_uiThrall;
+ uint64 m_uiTyrandeWhisperwind;
+
+ uint32 m_uiTrashCount;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ lAncientGemGUIDList.clear();
+
+ m_uiRageWinterchill = 0;
+ m_uiAnetheron = 0;
+ m_uiKazrogal = 0;
+ m_uiAzgalor = 0;
+ m_uiArchimonde = 0;
+ m_uiJainaProudmoore = 0;
+ m_uiThrall = 0;
+ m_uiTyrandeWhisperwind = 0;
+
+ m_uiTrashCount = 0;
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS) return true;
+
+ return false;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case NPC_WINTERCHILL: m_uiRageWinterchill = pCreature->GetGUID(); break;
+ case NPC_ANETHERON: m_uiAnetheron = pCreature->GetGUID(); break;
+ case NPC_KAZROGAL: m_uiKazrogal = pCreature->GetGUID(); break;
+ case NPC_AZGALOR: m_uiAzgalor = pCreature->GetGUID(); break;
+ case NPC_ARCHIMONDE: m_uiArchimonde = pCreature->GetGUID(); break;
+ case NPC_JAINA: m_uiJainaProudmoore = pCreature->GetGUID(); break;
+ case NPC_THRALL: m_uiThrall = pCreature->GetGUID(); break;
+ case NPC_TYRANDE: m_uiTyrandeWhisperwind = pCreature->GetGUID(); break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ if (pGo->GetEntry() == GO_ANCIENT_GEM)
+ lAncientGemGUIDList.push_back(pGo->GetGUID());
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_RAGEWINTERCHILL: return m_uiRageWinterchill;
+ case DATA_ANETHERON: return m_uiAnetheron;
+ case DATA_KAZROGAL: return m_uiKazrogal;
+ case DATA_AZGALOR: return m_uiAzgalor;
+ case DATA_ARCHIMONDE: return m_uiArchimonde;
+ case DATA_JAINAPROUDMOORE: return m_uiJainaProudmoore;
+ case DATA_THRALL: return m_uiThrall;
+ case DATA_TYRANDEWHISPERWIND: return m_uiTyrandeWhisperwind;
+ }
+
+ return 0;
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_WINTERCHILL:
+ if (m_auiEncounter[0] == DONE)
+ return;
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_ANETHERON:
+ if (m_auiEncounter[1] == DONE)
+ return;
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_KAZROGAL:
+ if (m_auiEncounter[2] == DONE)
+ return;
+ m_auiEncounter[2] = uiData;
+ break;
+ case TYPE_AZGALOR:
+ if (m_auiEncounter[3] == DONE)
+ return;
+ m_auiEncounter[3] = uiData;
+ break;
+ case TYPE_ARCHIMONDE:
+ m_auiEncounter[4] = uiData;
+ break;
+
+ case DATA_RESET_TRASH_COUNT:
+ m_uiTrashCount = 0;
+ break;
+
+ case DATA_TRASH:
+ if (uiData)
+ m_uiTrashCount = uiData;
+ else
+ --m_uiTrashCount;
+
+ DoUpdateWorldState(WORLD_STATE_ENEMYCOUNT, m_uiTrashCount);
+ break;
+
+ case TYPE_RETREAT:
+ if (uiData == SPECIAL)
+ {
+ if (!lAncientGemGUIDList.empty())
+ {
+ for(std::list::iterator itr = lAncientGemGUIDList.begin(); itr != lAncientGemGUIDList.end(); ++itr)
+ {
+ //don't know how long it expected
+ DoRespawnGameObject(*itr,DAY);
+ }
+ }
+ }
+ break;
+ }
+
+ debug_log("SD2: Instance Hyjal: Instance data updated for event %u (Data=%u)", uiType, uiData);
+
+ if (uiData == DONE)
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " "
+ << m_auiEncounter[3] << " " << m_auiEncounter[4];
+
+ strSaveData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_WINTERCHILL: return m_auiEncounter[0];
+ case TYPE_ANETHERON: return m_auiEncounter[1];
+ case TYPE_KAZROGAL: return m_auiEncounter[2];
+ case TYPE_AZGALOR: return m_auiEncounter[3];
+ case TYPE_ARCHIMONDE: return m_auiEncounter[4];
+ case DATA_TRASH: return m_uiTrashCount;
+ }
+ return 0;
+ }
+
+ const char* Save()
+ {
+ return strSaveData.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] >> m_auiEncounter[4];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS) // Do not load an encounter as IN_PROGRESS - reset it instead.
+ m_auiEncounter[i] = NOT_STARTED;
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+ }
+};
+
+InstanceData* GetInstanceData_instance_mount_hyjal(Map* pMap)
+{
+ return new instance_mount_hyjal(pMap);
+}
+
+void AddSC_instance_mount_hyjal()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_hyjal";
+ newscript->GetInstanceData = &GetInstanceData_instance_mount_hyjal;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp b/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp
new file mode 100644
index 0000000..0952e4f
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp
@@ -0,0 +1,152 @@
+/* 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_Captain_Skarloc
+SD%Complete: 75
+SDComment: Missing adds, missing waypoints to move up to Thrall once spawned + speech before enter combat.
+SDCategory: Caverns of Time, Old Hillsbrad Foothills
+EndScriptData */
+
+#include "precompiled.h"
+#include "old_hillsbrad.h"
+
+#define SAY_ENTER -1560000
+#define SAY_TAUNT1 -1560001
+#define SAY_TAUNT2 -1560002
+#define SAY_SLAY1 -1560003
+#define SAY_SLAY2 -1560004
+#define SAY_DEATH -1560005
+
+#define SPELL_HOLY_LIGHT 29427
+#define SPELL_CLEANSE 29380
+#define SPELL_HAMMER_OF_JUSTICE 13005
+#define SPELL_HOLY_SHIELD 31904
+#define SPELL_DEVOTION_AURA 8258
+#define SPELL_CONSECRATION 38385
+
+struct MANGOS_DLL_DECL boss_captain_skarlocAI : public ScriptedAI
+{
+ boss_captain_skarlocAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 Holy_Light_Timer;
+ uint32 Cleanse_Timer;
+ uint32 HammerOfJustice_Timer;
+ uint32 HolyShield_Timer;
+ uint32 DevotionAura_Timer;
+ uint32 Consecration_Timer;
+
+ void Reset()
+ {
+ Holy_Light_Timer = 30000;
+ Cleanse_Timer = 10000;
+ HammerOfJustice_Timer = 60000;
+ HolyShield_Timer = 240000;
+ DevotionAura_Timer = 3000;
+ Consecration_Timer = 8000;
+ }
+
+ void Aggro(Unit *who)
+ {
+ //This is not correct. Should taunt Thrall before engage in combat
+ DoScriptText(SAY_TAUNT1, m_creature);
+ DoScriptText(SAY_TAUNT2, m_creature);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance && m_pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS)
+ m_pInstance->SetData(TYPE_THRALL_PART1, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Holy_Light
+ if (Holy_Light_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HOLY_LIGHT);
+ Holy_Light_Timer = urand(20000, 30000);
+ }else Holy_Light_Timer -= diff;
+
+ //Cleanse
+ if (Cleanse_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_CLEANSE);
+ Cleanse_Timer = 10000;
+ } else Cleanse_Timer -= diff;
+
+ //Hammer of Justice
+ if (HammerOfJustice_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAMMER_OF_JUSTICE);
+ HammerOfJustice_Timer = urand(20000, 35000);
+ }else HammerOfJustice_Timer -= diff;
+
+ //Holy Shield
+ if (HolyShield_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_HOLY_SHIELD);
+ HolyShield_Timer = 240000;
+ }else HolyShield_Timer -= diff;
+
+ //Devotion_Aura
+ if (DevotionAura_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_DEVOTION_AURA);
+ DevotionAura_Timer = urand(45000, 55000);
+ }else DevotionAura_Timer -= diff;
+
+ //Consecration
+ if (Consecration_Timer < diff)
+ {
+ //DoCastSpellIfCan(m_creature->getVictim(), SPELL_CONSECRATION);
+ Consecration_Timer = urand(5000, 10000);
+ }else Consecration_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_captain_skarloc(Creature* pCreature)
+{
+ return new boss_captain_skarlocAI(pCreature);
+}
+
+void AddSC_boss_captain_skarloc()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_captain_skarloc";
+ newscript->GetAI = &GetAI_boss_captain_skarloc;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp b/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp
new file mode 100644
index 0000000..f12fe25
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp
@@ -0,0 +1,138 @@
+/* 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_Epoch_Hunter
+SD%Complete: 60
+SDComment: Missing spawns pre-event, missing speech to be coordinated with rest of escort event.
+SDCategory: Caverns of Time, Old Hillsbrad Foothills
+EndScriptData */
+
+#include "precompiled.h"
+#include "old_hillsbrad.h"
+
+#define SAY_ENTER1 -1560013
+#define SAY_ENTER2 -1560014
+#define SAY_ENTER3 -1560015
+#define SAY_AGGRO1 -1560016
+#define SAY_AGGRO2 -1560017
+#define SAY_SLAY1 -1560018
+#define SAY_SLAY2 -1560019
+#define SAY_BREATH1 -1560020
+#define SAY_BREATH2 -1560021
+#define SAY_DEATH -1560022
+
+#define SPELL_SAND_BREATH 31914
+#define SPELL_IMPENDING_DEATH 31916
+#define SPELL_MAGIC_DISRUPTION_AURA 33834
+#define SPELL_WING_BUFFET 31475
+
+struct MANGOS_DLL_DECL boss_epoch_hunterAI : public ScriptedAI
+{
+ boss_epoch_hunterAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 SandBreath_Timer;
+ uint32 ImpendingDeath_Timer;
+ uint32 WingBuffet_Timer;
+ uint32 Mda_Timer;
+
+ void Reset()
+ {
+ SandBreath_Timer = urand(8000, 16000);
+ ImpendingDeath_Timer = urand(25000, 30000);
+ WingBuffet_Timer = 35000;
+ Mda_Timer = 40000;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(urand(0, 1) ? SAY_AGGRO1 : SAY_AGGRO2, m_creature);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+
+ if (m_pInstance && m_pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS)
+ m_pInstance->SetData(TYPE_THRALL_PART4, DONE);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Sand Breath
+ if (SandBreath_Timer < diff)
+ {
+ if (m_creature->IsNonMeleeSpellCasted(false))
+ m_creature->InterruptNonMeleeSpells(false);
+
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SAND_BREATH);
+
+ DoScriptText(urand(0, 1) ? SAY_BREATH1 : SAY_BREATH2, m_creature);
+
+ SandBreath_Timer = urand(10000, 20000);
+ }else SandBreath_Timer -= diff;
+
+ if (ImpendingDeath_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_IMPENDING_DEATH);
+ ImpendingDeath_Timer = urand(25000, 30000);
+ }else ImpendingDeath_Timer -= diff;
+
+ if (WingBuffet_Timer < diff)
+ {
+ if (Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_WING_BUFFET);
+ WingBuffet_Timer = urand(25000, 35000);
+ }else WingBuffet_Timer -= diff;
+
+ if (Mda_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_MAGIC_DISRUPTION_AURA);
+ Mda_Timer = 15000;
+ }else Mda_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_epoch_hunter(Creature* pCreature)
+{
+ return new boss_epoch_hunterAI(pCreature);
+}
+
+void AddSC_boss_epoch_hunter()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_epoch_hunter";
+ newscript->GetAI = &GetAI_boss_epoch_hunter;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp b/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp
new file mode 100644
index 0000000..571db42
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp
@@ -0,0 +1,188 @@
+/* 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_Luetenant_Drake
+SD%Complete: 70
+SDComment: Missing proper code for patrolling area after being spawned. Script for GO (barrels) quest 10283
+SDCategory: Caverns of Time, Old Hillsbrad Foothills
+EndScriptData */
+
+#include "precompiled.h"
+#include "old_hillsbrad.h"
+#include "escort_ai.h"
+
+/*######
+## go_barrel_old_hillsbrad
+######*/
+
+bool GOHello_go_barrel_old_hillsbrad(Player* pPlayer, GameObject* pGo)
+{
+ if (ScriptedInstance* pInstance = (ScriptedInstance*)pGo->GetInstanceData())
+ {
+ if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE)
+ return false;
+
+ pInstance->SetData(TYPE_BARREL_DIVERSION, IN_PROGRESS);
+ }
+ return false;
+}
+
+/*######
+## boss_lieutenant_drake
+######*/
+
+#define SAY_ENTER -1560006
+#define SAY_AGGRO -1560007
+#define SAY_SLAY1 -1560008
+#define SAY_SLAY2 -1560009
+#define SAY_MORTAL -1560010
+#define SAY_SHOUT -1560011
+#define SAY_DEATH -1560012
+
+#define SPELL_WHIRLWIND 31909
+#define SPELL_HAMSTRING 9080
+#define SPELL_MORTAL_STRIKE 31911
+#define SPELL_FRIGHTENING_SHOUT 33789
+
+struct Location
+{
+ uint32 wpId;
+ float x;
+ float y;
+ float z;
+};
+
+static Location DrakeWP[]=
+{
+ {0, 2125.84f, 88.2535f, 54.8830f},
+ {1, 2111.01f, 93.8022f, 52.6356f},
+ {2, 2106.70f, 114.753f, 53.1965f},
+ {3, 2107.76f, 138.746f, 52.5109f},
+ {4, 2114.83f, 160.142f, 52.4738f},
+ {5, 2125.24f, 178.909f, 52.7283f},
+ {6, 2151.02f, 208.901f, 53.1551f},
+ {7, 2177.00f, 233.069f, 52.4409f},
+ {8, 2190.71f, 227.831f, 53.2742f},
+ {9, 2178.14f, 214.219f, 53.0779f},
+ {10, 2154.99f, 202.795f, 52.6446f},
+ {11, 2132.00f, 191.834f, 52.5709f},
+ {12, 2117.59f, 166.708f, 52.7686f},
+ {13, 2093.61f, 139.441f, 52.7616f},
+ {14, 2086.29f, 104.950f, 52.9246f},
+ {15, 2094.23f, 81.2788f, 52.6946f},
+ {16, 2108.70f, 85.3075f, 53.3294f},
+ {17, 2125.50f, 88.9481f, 54.7953f},
+ {18, 2128.20f, 70.9763f, 64.4221f}
+};
+
+struct MANGOS_DLL_DECL boss_lieutenant_drakeAI : public ScriptedAI
+{
+ boss_lieutenant_drakeAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ bool CanPatrol;
+ uint32 wpId;
+
+ uint32 Whirlwind_Timer;
+ uint32 Fear_Timer;
+ uint32 MortalStrike_Timer;
+ uint32 ExplodingShout_Timer;
+
+ void Reset()
+ {
+ CanPatrol = true;
+ wpId = 0;
+
+ Whirlwind_Timer = 20000;
+ Fear_Timer = 30000;
+ MortalStrike_Timer = 45000;
+ ExplodingShout_Timer = 25000;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void KilledUnit(Unit *victim)
+ {
+ DoScriptText(urand(0, 1) ? SAY_SLAY1 : SAY_SLAY2, m_creature);
+ }
+
+ void JustDied(Unit *victim)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //TODO: make this work
+ if (CanPatrol && wpId == 0)
+ {
+ m_creature->GetMotionMaster()->MovePoint(DrakeWP[0].wpId, DrakeWP[0].x, DrakeWP[0].y, DrakeWP[0].z);
+ ++wpId;
+ }
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Whirlwind
+ if (Whirlwind_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_WHIRLWIND);
+ Whirlwind_Timer = urand(20000, 25000);
+ }else Whirlwind_Timer -= diff;
+
+ //Fear
+ if (Fear_Timer < diff)
+ {
+ DoScriptText(SAY_SHOUT, m_creature);
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_FRIGHTENING_SHOUT);
+ Fear_Timer = urand(25000, 35000);
+ }else Fear_Timer -= diff;
+
+ //Mortal Strike
+ if (MortalStrike_Timer < diff)
+ {
+ DoScriptText(SAY_MORTAL, m_creature);
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_STRIKE);
+ MortalStrike_Timer = urand(20000, 30000);
+ }else MortalStrike_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_lieutenant_drake(Creature* pCreature)
+{
+ return new boss_lieutenant_drakeAI(pCreature);
+}
+
+void AddSC_boss_lieutenant_drake()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "go_barrel_old_hillsbrad";
+ newscript->pGOHello = &GOHello_go_barrel_old_hillsbrad;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_lieutenant_drake";
+ newscript->GetAI = &GetAI_boss_lieutenant_drake;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp b/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp
new file mode 100644
index 0000000..8ed4831
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp
@@ -0,0 +1,253 @@
+/* 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_Old_Hillsbrad
+SD%Complete: 75
+SDComment: If thrall escort fail, all parts will reset. In future, save sub-parts and continue from last known.
+SDCategory: Caverns of Time, Old Hillsbrad Foothills
+EndScriptData */
+
+#include "precompiled.h"
+#include "old_hillsbrad.h"
+
+instance_old_hillsbrad::instance_old_hillsbrad(Map* pMap) : ScriptedInstance(pMap),
+ m_uiBarrelCount(0),
+ m_uiThrallEventCount(0),
+ m_uiThrallGUID(0),
+ m_uiTarethaGUID(0),
+ m_uiScarlocGUID(0),
+ m_uiEpochGUID(0)
+{
+ Initialize();
+}
+
+void instance_old_hillsbrad::Initialize()
+{
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+}
+
+Player* instance_old_hillsbrad::GetPlayerInMap()
+{
+ Map::PlayerList const& players = instance->GetPlayers();
+
+ if (!players.isEmpty())
+ {
+ for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ if (Player* plr = itr->getSource())
+ return plr;
+ }
+ }
+
+ debug_log("SD2: Instance Old Hillsbrad: GetPlayerInMap, but PlayerList is empty!");
+ return NULL;
+}
+
+void instance_old_hillsbrad::OnCreatureCreate(Creature* pCreature)
+{
+ switch(pCreature->GetEntry())
+ {
+ case NPC_THRALL:
+ m_uiThrallGUID = pCreature->GetGUID();
+ break;
+ case NPC_TARETHA:
+ m_uiTarethaGUID = pCreature->GetGUID();
+ break;
+ case NPC_EPOCH:
+ m_uiEpochGUID = pCreature->GetGUID();
+ break;
+ }
+}
+
+void instance_old_hillsbrad::OnCreatureDeath(Creature* pCreature)
+{
+ if (pCreature->GetEntry() == NPC_EPOCH)
+ {
+ // notify thrall so he can continue
+ if (Creature* pThrall = instance->GetCreature(m_uiThrallGUID))
+ pThrall->AI()->KilledUnit(pCreature);
+ }
+}
+
+void instance_old_hillsbrad::HandleThrallRelocation()
+{
+ if (Creature* pThrall = instance->GetCreature(m_uiThrallGUID))
+ {
+ debug_log("SD2: Instance Old Hillsbrad: Thrall relocation");
+
+ if (m_auiEncounter[TYPE_THRALL_PART4] == IN_PROGRESS)
+ {
+ // boss failed, reloc to inn
+ pThrall->GetMap()->CreatureRelocation(pThrall, 2660.57f, 659.173f, 61.9370f, 0.0f);
+ m_auiEncounter[TYPE_THRALL_PART4] = NOT_STARTED;
+ }
+ else if (m_auiEncounter[TYPE_THRALL_PART3] == IN_PROGRESS)
+ {
+ // barn to inn failed, reloc to inn
+ pThrall->GetMap()->CreatureRelocation(pThrall, 2660.57f, 659.173f, 61.9370f, 0.0f);
+ m_auiEncounter[TYPE_THRALL_PART3] = DONE;
+ }
+ else if (m_auiEncounter[TYPE_THRALL_PART2] == IN_PROGRESS)
+ {
+ // keep to barn failed, reloc to barn
+ pThrall->GetMap()->CreatureRelocation(pThrall, 2486.91f, 626.356f, 58.0761f, 0.0f);
+ m_auiEncounter[TYPE_THRALL_PART2] = DONE;
+ }
+ else if (m_auiEncounter[TYPE_THRALL_PART1] == IN_PROGRESS)
+ {
+ // didn't reach very far, back to the basement using default
+ m_auiEncounter[TYPE_THRALL_PART1] = NOT_STARTED;
+ }
+ }
+}
+
+void instance_old_hillsbrad::SetData(uint32 uiType, uint32 uiData)
+{
+ switch(uiType)
+ {
+ case TYPE_BARREL_DIVERSION:
+ {
+ if (uiData == IN_PROGRESS)
+ {
+ if (m_uiBarrelCount >= 5)
+ return;
+
+ ++m_uiBarrelCount;
+ DoUpdateWorldState(WORLD_STATE_OH, m_uiBarrelCount);
+
+ debug_log("SD2: Instance Old Hillsbrad: go_barrel_old_hillsbrad count %u", m_uiBarrelCount);
+
+ m_auiEncounter[TYPE_BARREL_DIVERSION] = IN_PROGRESS;
+
+ if (m_uiBarrelCount == 5)
+ {
+ UpdateLodgeQuestCredit();
+
+ if (Player* pPlayer = GetPlayerInMap())
+ pPlayer->SummonCreature(NPC_DRAKE, 2128.43f, 71.01f, 64.42f, 1.74f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 1800000);
+ else
+ debug_log("SD2: Instance Old Hillsbrad: SetData (Type: %u Data %u) cannot find any pPlayer.", uiType, uiData);
+
+ m_auiEncounter[TYPE_BARREL_DIVERSION] = DONE;
+ }
+ }
+ break;
+ }
+ case TYPE_THRALL_EVENT:
+ {
+ // nothing to do if already done and thrall respawn
+ if (m_auiEncounter[TYPE_THRALL_EVENT] == DONE)
+ return;
+
+ if (uiData == FAIL)
+ {
+ if (m_uiThrallEventCount <= 20)
+ {
+ ++m_uiThrallEventCount;
+ debug_log("SD2: Instance Old Hillsbrad: Thrall event failed %u times.", m_uiThrallEventCount);
+
+ HandleThrallRelocation();
+ }
+ else if (m_uiThrallEventCount > 20)
+ {
+ m_auiEncounter[TYPE_THRALL_EVENT] = uiData;
+ m_auiEncounter[TYPE_THRALL_PART1] = uiData;
+ m_auiEncounter[TYPE_THRALL_PART2] = uiData;
+ m_auiEncounter[TYPE_THRALL_PART3] = uiData;
+ m_auiEncounter[TYPE_THRALL_PART4] = uiData;
+ debug_log("SD2: Instance Old Hillsbrad: Thrall event failed %u times. Reset instance required.", m_uiThrallEventCount);
+ }
+ }
+ else
+ m_auiEncounter[TYPE_THRALL_EVENT] = uiData;
+
+ debug_log("SD2: Instance Old Hillsbrad: Thrall escort event adjusted to data %u.",uiData);
+ break;
+ }
+ case TYPE_THRALL_PART1:
+ m_auiEncounter[TYPE_THRALL_PART1] = uiData;
+ debug_log("SD2: Instance Old Hillsbrad: Thrall event part I adjusted to data %u.",uiData);
+ break;
+ case TYPE_THRALL_PART2:
+ m_auiEncounter[TYPE_THRALL_PART2] = uiData;
+ debug_log("SD2: Instance Old Hillsbrad: Thrall event part II adjusted to data %u.",uiData);
+ break;
+ case TYPE_THRALL_PART3:
+ m_auiEncounter[TYPE_THRALL_PART3] = uiData;
+ debug_log("SD2: Instance Old Hillsbrad: Thrall event part III adjusted to data %u.",uiData);
+ break;
+ case TYPE_THRALL_PART4:
+ m_auiEncounter[TYPE_THRALL_PART4] = uiData;
+ debug_log("SD2: Instance Old Hillsbrad: Thrall event part IV adjusted to data %u.",uiData);
+ break;
+ }
+}
+
+uint32 instance_old_hillsbrad::GetData(uint32 uiData)
+{
+ switch(uiData)
+ {
+ case TYPE_BARREL_DIVERSION:
+ return m_auiEncounter[TYPE_BARREL_DIVERSION];
+ case TYPE_THRALL_EVENT:
+ return m_auiEncounter[TYPE_THRALL_EVENT];
+ case TYPE_THRALL_PART1:
+ return m_auiEncounter[TYPE_THRALL_PART1];
+ case TYPE_THRALL_PART2:
+ return m_auiEncounter[TYPE_THRALL_PART2];
+ case TYPE_THRALL_PART3:
+ return m_auiEncounter[TYPE_THRALL_PART3];
+ case TYPE_THRALL_PART4:
+ return m_auiEncounter[TYPE_THRALL_PART4];
+ default:
+ return 0;
+ }
+}
+
+uint64 instance_old_hillsbrad::GetData64(uint32 uiData)
+{
+ return 0;
+}
+
+void instance_old_hillsbrad::UpdateLodgeQuestCredit()
+{
+ Map::PlayerList const& players = instance->GetPlayers();
+
+ if (!players.isEmpty())
+ {
+ for(Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
+ {
+ if (Player* pPlayer = itr->getSource())
+ pPlayer->KilledMonsterCredit(NPC_LODGE_QUEST_TRIGGER);
+ }
+ }
+}
+
+InstanceData* GetInstanceData_instance_old_hillsbrad(Map* pMap)
+{
+ return new instance_old_hillsbrad(pMap);
+}
+
+void AddSC_instance_old_hillsbrad()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "instance_old_hillsbrad";
+ pNewScript->GetInstanceData = &GetInstanceData_instance_old_hillsbrad;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp b/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp
new file mode 100644
index 0000000..dd5908f
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp
@@ -0,0 +1,902 @@
+/* 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: Old_Hillsbrad
+SD%Complete: 60
+SDComment: Quest support: 10283, 10284. All friendly NPC's. Thrall waypoints fairly complete, missing many details, but possible to complete escort.
+SDCategory: Caverns of Time, Old Hillsbrad Foothills
+EndScriptData */
+
+/* ContentData
+npc_brazen
+npc_erozion
+npc_thrall_old_hillsbrad
+npc_taretha
+EndContentData */
+
+#include "precompiled.h"
+#include "old_hillsbrad.h"
+#include "escort_ai.h"
+
+struct MANGOS_DLL_DECL npc_tarethaAI : public npc_escortAI
+{
+ npc_tarethaAI(Creature* pCreature);
+
+ instance_old_hillsbrad* m_pInstance;
+ uint64 m_uiErozionGUID;
+ uint32 m_uiErozionEventTimer;
+ uint32 m_uiErozionPhase;
+
+ void Reset() {}
+ void JustSummoned(Creature* pSummoned);
+ void WaypointReached(uint32 uiPoint);
+ void UpdateEscortAI(const uint32 uiDiff);
+};
+
+/*######
+## npc_brazen
+######*/
+
+enum
+{
+ GOSSIP_ID_UNKNOWN_TEXT = -1000000,
+ GOSSIP_ITEM_READY = -3560000,
+
+ TEXT_ID_HAS_BOMBS = 9780,
+ ITEM_ENTRY_BOMBS = 25853,
+
+ TAXI_PATH_ID = 534
+};
+
+bool GossipHello_npc_brazen(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_READY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_brazen(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ if (!pPlayer->HasItemCount(ITEM_ENTRY_BOMBS, 1))
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_HAS_BOMBS, pCreature->GetGUID());
+ else
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID);
+ }
+ }
+ return true;
+}
+
+/*######
+## npc_erozion
+######*/
+
+enum
+{
+ GOSSIP_ITEM_NEED_BOMBS = -3560001,
+ TEXT_ID_DEFAULT = 9778,
+ TEXT_ID_GOT_ITEM = 9515,
+};
+
+bool GossipHello_npc_erozion(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ ScriptedInstance* pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+
+ if (pInstance && pInstance->GetData(TYPE_BARREL_DIVERSION) != DONE && !pPlayer->HasItemCount(ITEM_ENTRY_BOMBS,1))
+ pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NEED_BOMBS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ // Need info, should have option to teleport or not
+ /*if (!pPlayer->GetQuestRewardStatus(QUEST_ENTRY_RETURN) && pPlayer->GetQuestStatus(QUEST_ENTRY_RETURN) == QUEST_STATUS_COMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] Teleport please, i'm tired.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);*/
+
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_DEFAULT, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_erozion(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ if (Item* pItem = pPlayer->StoreNewItemInInventorySlot(ITEM_ENTRY_BOMBS, 1))
+ pPlayer->SendNewItem(pItem, 1, true, false);
+
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_GOT_ITEM, pCreature->GetGUID());
+ }
+
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+2)
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ return true;
+}
+
+/*######
+## npc_thrall_old_hillsbrad
+######*/
+
+enum
+{
+ // Thrall texts
+ SAY_TH_START_EVENT_PART1 = -1560023,
+ SAY_TH_ARMORY = -1560024,
+ SAY_TH_SKARLOC_MEET = -1560025,
+ SAY_TH_SKARLOC_TAUNT = -1560026,
+ SAY_TH_START_EVENT_PART2 = -1560027,
+ SAY_TH_MOUNTS_UP = -1560028,
+ SAY_TH_CHURCH_END = -1560029,
+ SAY_TH_MEET_TARETHA = -1560030,
+
+ SAY_EPOCH_ENTER1 = -1560013,
+ SAY_EPOCH_ENTER2 = -1560014,
+ SAY_EPOCH_ENTER3 = -1560015,
+
+ SAY_TH_EPOCH_WONDER = -1560031,
+ SAY_TH_EPOCH_KILL_TARETHA = -1560032,
+
+ SAY_TH_RANDOM_LOW_HP1 = -1560034,
+ SAY_TH_RANDOM_LOW_HP2 = -1560035,
+
+ SAY_TH_RANDOM_DIE1 = -1560036,
+ SAY_TH_RANDOM_DIE2 = -1560037,
+
+ SAY_TH_RANDOM_AGGRO1 = -1560038,
+ SAY_TH_RANDOM_AGGRO2 = -1560039,
+ SAY_TH_RANDOM_AGGRO3 = -1560040,
+ SAY_TH_RANDOM_AGGRO4 = -1560041,
+
+ SAY_TH_RANDOM_KILL1 = -1560042,
+ SAY_TH_RANDOM_KILL2 = -1560043,
+ SAY_TH_RANDOM_KILL3 = -1560044,
+
+ SAY_TH_KILL_ARMORER = -1560050,
+
+ SAY_TH_LEAVE_COMBAT1 = -1560045,
+ SAY_TH_LEAVE_COMBAT2 = -1560046,
+ SAY_TH_LEAVE_COMBAT3 = -1560047,
+
+ // Taretha texts
+ SAY_TA_ESCAPED = -1560049,
+
+ // end event texts
+ SAY_TA_FREE = -1560048,
+ SAY_TR_GLAD_SAFE = -1560054,
+ SAY_TA_NEVER_MET = -1560055,
+ SAY_TR_THEN_WHO = -1560056,
+ SAY_PRE_WIPE = -1560057,
+ SAY_WIPE_MEMORY = -1560051,
+ SAY_AFTER_WIPE = -1560058,
+ SAY_ABOUT_TARETHA = -1560052,
+ SAY_TH_EVENT_COMPLETE = -1560033,
+ SAY_TA_FAREWELL = -1560053,
+
+ // Misc for Thrall
+ SPELL_STRIKE = 14516,
+ SPELL_SHIELD_BLOCK = 12169,
+ SPELL_SUMMON_EROZION_IMAGE = 33954, // if thrall dies during escort?
+
+ EQUIP_ID_WEAPON = 927,
+ EQUIP_ID_SHIELD = 20913,
+ MODEL_THRALL_UNEQUIPPED = 17292,
+ MODEL_THRALL_EQUIPPED = 18165,
+
+ // misc creature entries
+ NPC_ARMORER = 18764,
+ NPC_SCARLOC = 17862,
+
+ NPC_RIFLE = 17820,
+ NPC_WARDEN = 17833,
+ NPC_VETERAN = 17860,
+ NPC_WATCHMAN = 17814,
+ NPC_SENTRY = 17815,
+
+ NPC_BARN_GUARDSMAN = 18092,
+ NPC_BARN_PROTECTOR = 18093,
+ NPC_BARN_LOOKOUT = 18094,
+
+ NPC_CHURCH_GUARDSMAN = 23175,
+ NPC_CHURCH_PROTECTOR = 23179,
+ NPC_CHURCH_LOOKOUT = 23177,
+
+ NPC_INN_GUARDSMAN = 23176,
+ NPC_INN_PROTECTOR = 23180,
+ NPC_INN_LOOKOUT = 23178,
+
+ NPC_SKARLOC_MOUNT = 18798,
+ MODEL_SKARLOC_MOUNT = 18223,
+ NPC_EROZION = 18723,
+ NPC_THRALL_QUEST_TRIGGER = 20156,
+
+ // gossip
+ TEXT_ID_START = 9568,
+ TEXT_ID_SKARLOC1 = 9614, // I'm glad Taretha is alive. We now must find a way to free her...
+ GOSSIP_ITEM_SKARLOC1 = -3560002, // "Taretha cannot see you, Thrall."
+ TEXT_ID_SKARLOC2 = 9579, // What do you mean by this? Is Taretha in danger?
+ GOSSIP_ITEM_SKARLOC2 = -3560003, // "The situation is rather complicated, Thrall. It would be best for you to head into the mountains now, before more of Blackmoore's men show up. We'll make sure Taretha is safe."
+ TEXT_ID_SKARLOC3 = 9580,
+
+ TEXT_ID_TARREN = 9597, // tarren mill is beyond these trees
+ GOSSIP_ITEM_TARREN = -3560004, // "We're ready, Thrall."
+
+ TEXT_ID_COMPLETE = 9578, // Thank you friends, I owe my freedom to you. Where is Taretha? I hoped to see her
+};
+
+const float SPEED_WALK = 0.5f;
+const float SPEED_RUN = 1.0f;
+const float SPEED_MOUNT = 1.6f;
+
+struct MANGOS_DLL_DECL npc_thrall_old_hillsbradAI : public npc_escortAI
+{
+ npc_thrall_old_hillsbradAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_pInstance = (instance_old_hillsbrad*)pCreature->GetInstanceData();
+ m_bHadMount = false;
+ pCreature->SetActiveObjectState(true); // required for proper relocation
+ Reset();
+ }
+
+ instance_old_hillsbrad* m_pInstance;
+
+ uint64 m_uiScarlocMountGUID;
+
+ bool m_bIsLowHp;
+ bool m_bHadMount;
+
+ void Reset()
+ {
+ m_uiScarlocMountGUID = 0;
+
+ m_bIsLowHp = false;
+
+ if (m_bHadMount)
+ DoMount();
+
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ DoUnmount();
+ m_bHadMount = false;
+ SetEquipmentSlots(true);
+ m_creature->SetDisplayId(MODEL_THRALL_UNEQUIPPED);
+ }
+ }
+
+ void EnterEvadeMode()
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_TH_LEAVE_COMBAT1, m_creature); break;
+ case 1: DoScriptText(SAY_TH_LEAVE_COMBAT2, m_creature); break;
+ case 2: DoScriptText(SAY_TH_LEAVE_COMBAT3, m_creature); break;
+ }
+ }
+
+ npc_escortAI::EnterEvadeMode();
+ }
+
+ void WaypointReached(uint32 uiPoint)
+ {
+ if (!m_pInstance)
+ return;
+
+ switch(uiPoint)
+ {
+ case 8:
+ SetRun(false);
+ m_creature->SummonCreature(NPC_ARMORER, 2181.87f, 112.46f, 89.45f, 0.26f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,5000);
+ break;
+ case 9:
+ DoScriptText(SAY_TH_ARMORY, m_creature);
+ SetEquipmentSlots(false, EQUIP_ID_WEAPON, EQUIP_ID_SHIELD, EQUIP_NO_CHANGE);
+ break;
+ case 10:
+ m_creature->SetDisplayId(MODEL_THRALL_EQUIPPED);
+ break;
+ case 11:
+ SetRun();
+ break;
+ case 15:
+ m_creature->SummonCreature(NPC_RIFLE, 2200.28f, 137.37f, 87.93f, 5.07f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_WARDEN, 2197.44f, 131.83f, 87.93f, 0.78f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_VETERAN, 2203.62f, 135.40f, 87.93f, 3.70f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_VETERAN, 2200.75f, 130.13f, 87.93f, 1.48f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ break;
+ case 21:
+ m_creature->SummonCreature(NPC_RIFLE, 2135.80f, 154.01f, 67.45f, 4.98f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_WARDEN, 2144.36f, 151.87f, 67.74f, 4.46f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_VETERAN, 2142.12f, 154.41f, 67.12f, 4.56f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_VETERAN, 2138.08f, 155.38f, 67.24f, 4.60f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ break;
+ case 25:
+ m_creature->SummonCreature(NPC_RIFLE, 2102.98f, 192.17f, 65.24f, 6.02f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_WARDEN, 2108.48f, 198.75f, 65.18f, 5.15f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_VETERAN, 2106.11f, 197.29f, 65.18f, 5.63f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_VETERAN, 2104.18f, 194.82f, 65.18f, 5.75f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ break;
+ case 29:
+ DoScriptText(SAY_TH_SKARLOC_MEET, m_creature);
+ m_creature->SummonCreature(NPC_SCARLOC, 2036.48f, 271.22f, 63.43f, 5.27f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ break;
+ case 30:
+ SetEscortPaused(true);
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ SetRun(false);
+ break;
+ case 31:
+ DoScriptText(SAY_TH_MOUNTS_UP, m_creature);
+ DoMount();
+ SetRun();
+ break;
+ case 37:
+ // possibly regular patrollers? If so, remove this and let database handle them
+ m_creature->SummonCreature(NPC_WATCHMAN, 2124.26f, 522.16f, 56.87f, 3.99f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_WATCHMAN, 2121.69f, 525.37f, 57.11f, 4.01f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_SENTRY, 2124.65f, 524.55f, 56.63f, 3.98f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ break;
+ case 59:
+ m_creature->SummonCreature(NPC_SKARLOC_MOUNT, 2488.64f, 625.77f, 58.26f, 4.71f, TEMPSUMMON_TIMED_DESPAWN, 10000);
+ DoUnmount();
+ m_bHadMount = false;
+ SetRun(false);
+ break;
+ case 60:
+ m_creature->HandleEmote(EMOTE_ONESHOT_EXCLAMATION);
+ // make horsie run off
+ SetEscortPaused(true);
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ m_pInstance->SetData(TYPE_THRALL_PART2, DONE);
+ SetRun();
+ break;
+ case 64:
+ SetRun(false);
+ break;
+ case 68:
+ m_creature->SummonCreature(NPC_BARN_PROTECTOR, 2500.22f, 692.60f, 55.50f, 2.84f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_BARN_LOOKOUT, 2500.13f, 696.55f, 55.51f, 3.38f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_BARN_GUARDSMAN, 2500.55f, 693.64f, 55.50f, 3.14f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_BARN_GUARDSMAN, 2500.94f, 695.81f, 55.50f, 3.14f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ break;
+ case 71:
+ SetRun();
+ break;
+ case 81:
+ SetRun(false);
+ break;
+ case 83:
+ m_creature->SummonCreature(NPC_CHURCH_PROTECTOR, 2627.33f, 646.82f, 56.03f, 4.28f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000);
+ m_creature->SummonCreature(NPC_CHURCH_LOOKOUT, 2624.14f, 648.03f, 56.03f, 4.50f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000);
+ m_creature->SummonCreature(NPC_CHURCH_GUARDSMAN, 2625.32f, 649.60f, 56.03f, 4.38f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000);
+ m_creature->SummonCreature(NPC_CHURCH_GUARDSMAN, 2627.22f, 649.00f, 56.03f, 4.34f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 5000);
+ break;
+ case 84:
+ DoScriptText(SAY_TH_CHURCH_END, m_creature);
+ SetRun();
+ break;
+ case 91:
+ SetRun(false);
+ break;
+ case 93:
+ m_creature->SummonCreature(NPC_INN_PROTECTOR, 2652.71f, 660.31f, 61.93f, 1.67f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_INN_LOOKOUT, 2648.96f, 662.59f, 61.93f, 0.79f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_INN_GUARDSMAN, 2657.36f, 662.34f, 61.93f, 2.68f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ m_creature->SummonCreature(NPC_INN_GUARDSMAN, 2656.39f, 659.77f, 61.93f, 2.61f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 5000);
+ break;
+ case 94:
+ if (Creature* pTaretha = m_pInstance->GetTaretha())
+ DoScriptText(SAY_TA_ESCAPED, pTaretha, m_creature);
+
+ break;
+ case 95:
+ DoScriptText(SAY_TH_MEET_TARETHA, m_creature);
+ m_pInstance->SetData(TYPE_THRALL_PART3, DONE);
+ SetEscortPaused(true);
+ break;
+ case 96:
+ DoScriptText(SAY_TH_EPOCH_WONDER, m_creature);
+ break;
+ case 97:
+ DoScriptText(SAY_TH_EPOCH_KILL_TARETHA, m_creature);
+ SetRun();
+ break;
+ case 104:
+ if (Creature* pEpoch = m_pInstance->GetEpoch())
+ DoScriptText(SAY_EPOCH_ENTER3, pEpoch);
+
+ break;
+ case 105: // outside inn, meeting the dragon
+ SetEscortPaused(true);
+
+ if (Creature* pEpoch = m_pInstance->GetEpoch())
+ m_creature->SetFacingToObject(pEpoch);
+
+ break;
+ case 106: // epoch is dead, proceeding with cheering
+ {
+ // trigger taretha to run down outside
+ if (Creature* pTaretha = m_pInstance->GetTaretha())
+ {
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ if (npc_tarethaAI* pTarethaAI = dynamic_cast(pTaretha->AI()))
+ pTarethaAI->Start(true, pPlayer->GetGUID());
+ }
+ }
+
+ // kill credit creature for quest
+ Map::PlayerList const& lPlayerList = m_pInstance->instance->GetPlayers();
+
+ if (!lPlayerList.isEmpty())
+ {
+ for(Map::PlayerList::const_iterator itr = lPlayerList.begin(); itr != lPlayerList.end(); ++itr)
+ {
+ if (Player* pPlayer = itr->getSource())
+ pPlayer->KilledMonsterCredit(NPC_THRALL_QUEST_TRIGGER, m_creature->GetGUID());
+ }
+ }
+
+ // a lot will happen here, thrall and taretha talk, erozion appear at spot to explain
+ // handled by taretha script
+ SetEscortPaused(true);
+ break;
+ }
+ case 107:
+ m_creature->SetActiveObjectState(false);
+ break;
+ }
+ }
+
+ void WaypointStart(uint32 uiPointId)
+ {
+ if (!m_pInstance)
+ return;
+
+ if (uiPointId == 97)
+ {
+ if (Creature* pEpoch = m_pInstance->GetEpoch())
+ DoScriptText(SAY_EPOCH_ENTER2, pEpoch);
+ }
+ }
+
+ void StartWP()
+ {
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ SetEscortPaused(false);
+ }
+
+ void DoMount()
+ {
+ m_creature->Mount(MODEL_SKARLOC_MOUNT);
+ m_creature->SetSpeedRate(MOVE_RUN, SPEED_MOUNT);
+ }
+
+ void DoUnmount()
+ {
+ m_creature->Unmount();
+ m_creature->SetSpeedRate(MOVE_RUN, SPEED_RUN);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ switch(urand(0, 3))
+ {
+ case 0: DoScriptText(SAY_TH_RANDOM_AGGRO1, m_creature); break;
+ case 1: DoScriptText(SAY_TH_RANDOM_AGGRO2, m_creature); break;
+ case 2: DoScriptText(SAY_TH_RANDOM_AGGRO3, m_creature); break;
+ case 3: DoScriptText(SAY_TH_RANDOM_AGGRO4, m_creature); break;
+ }
+
+ if (m_creature->IsMounted())
+ {
+ DoUnmount();
+ m_bHadMount = true;
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ switch(pSummoned->GetEntry())
+ {
+ // TODO: make Scarloc start into event instead, and not start attack directly
+ case NPC_BARN_GUARDSMAN:
+ case NPC_BARN_PROTECTOR:
+ case NPC_BARN_LOOKOUT:
+ break;
+ case NPC_SKARLOC_MOUNT:
+ m_uiScarlocMountGUID = pSummoned->GetGUID();
+ break;
+ default:
+ pSummoned->AI()->AttackStart(m_creature);
+ break;
+ }
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_TH_RANDOM_KILL1, m_creature); break;
+ case 1: DoScriptText(SAY_TH_RANDOM_KILL2, m_creature); break;
+ case 2: DoScriptText(SAY_TH_RANDOM_KILL3, m_creature); break;
+ }
+
+ // Death called from instance script (or if he has the killing blow of course)
+ // Thrall should normally always be the one killing, but no support for this yet.
+ if (pVictim->GetEntry() == NPC_EPOCH)
+ SetEscortPaused(false);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoScriptText(urand(0, 1) ? SAY_TH_RANDOM_DIE1 : SAY_TH_RANDOM_DIE2, m_creature);
+ }
+
+ void CorpseRemoved(uint32 &uiRespawnDelay)
+ {
+ uiRespawnDelay = 0;
+
+ // if we're done, just set some high so he never really respawn
+ if (m_pInstance && m_pInstance->GetData(TYPE_THRALL_EVENT) == DONE)
+ uiRespawnDelay = 4 * HOUR;
+ }
+
+ void JustRespawned()
+ {
+ if (!m_pInstance)
+ return;
+
+ Reset();
+
+ if (m_pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS)
+ {
+ SetEscortPaused(true);
+
+ m_bHadMount = false;
+ DoUnmount();
+
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+
+ // check current states before fail and set spesific for the part
+ if (m_pInstance->GetData(TYPE_THRALL_PART1) == IN_PROGRESS)
+ {
+ SetCurrentWaypoint(1); // basement
+
+ SetEquipmentSlots(true);
+ m_creature->SetDisplayId(MODEL_THRALL_UNEQUIPPED);
+
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
+ else if (m_pInstance->GetData(TYPE_THRALL_PART2) == IN_PROGRESS)
+ {
+ SetCurrentWaypoint(61); // barn
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
+ else if (m_pInstance->GetData(TYPE_THRALL_PART3) == IN_PROGRESS || m_pInstance->GetData(TYPE_THRALL_PART4) == IN_PROGRESS)
+ SetCurrentWaypoint(96); // inn
+
+ // fail, and relocation handled in instance script
+ m_pInstance->SetData(TYPE_THRALL_EVENT, FAIL);
+ }
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // TODO: add his abilities'n-crap here
+
+ if (!m_bIsLowHp && m_creature->GetHealthPercent() < 20.0f)
+ {
+ DoScriptText(urand(0, 1) ? SAY_TH_RANDOM_LOW_HP1 : SAY_TH_RANDOM_LOW_HP2, m_creature);
+ m_bIsLowHp = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_thrall_old_hillsbrad(Creature* pCreature)
+{
+ return new npc_thrall_old_hillsbradAI(pCreature);
+}
+
+bool GossipHello_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ {
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+ pPlayer->SendPreparedQuest(pCreature->GetGUID());
+ }
+
+ if (instance_old_hillsbrad* pInstance = (instance_old_hillsbrad*)pCreature->GetInstanceData())
+ {
+ if (pInstance->GetData(TYPE_BARREL_DIVERSION) == DONE && !pInstance->GetData(TYPE_THRALL_EVENT))
+ {
+ pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ID_UNKNOWN_TEXT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_START, pCreature->GetGUID());
+ }
+
+ if (pInstance->GetData(TYPE_THRALL_PART1) == DONE && !pInstance->GetData(TYPE_THRALL_PART2))
+ {
+ pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_SKARLOC1, pCreature->GetGUID());
+ }
+
+ if (pInstance->GetData(TYPE_THRALL_PART2) == DONE && !pInstance->GetData(TYPE_THRALL_PART3))
+ {
+ pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TARREN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_TARREN, pCreature->GetGUID());
+ }
+ }
+ return true;
+}
+
+bool GossipSelect_npc_thrall_old_hillsbrad(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ instance_old_hillsbrad* pInstance = (instance_old_hillsbrad*)pCreature->GetInstanceData();
+
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ pInstance->SetData(TYPE_THRALL_EVENT, IN_PROGRESS);
+ pInstance->SetData(TYPE_THRALL_PART1, IN_PROGRESS);
+
+ DoScriptText(SAY_TH_START_EVENT_PART1, pCreature);
+
+ if (npc_thrall_old_hillsbradAI* pThrallAI = dynamic_cast(pCreature->AI()))
+ pThrallAI->Start(true, pPlayer->GetGUID());
+
+ break;
+ }
+ case GOSSIP_ACTION_INFO_DEF+2:
+ {
+ pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SKARLOC2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+20);
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_SKARLOC2, pCreature->GetGUID());
+ break;
+ }
+ case GOSSIP_ACTION_INFO_DEF+20:
+ {
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_SKARLOC3, pCreature->GetGUID());
+
+ pCreature->SummonCreature(NPC_SKARLOC_MOUNT, 2038.81f, 270.26f, 63.20f, 5.41f, TEMPSUMMON_TIMED_DESPAWN,12000);
+ pInstance->SetData(TYPE_THRALL_PART2, IN_PROGRESS);
+
+ DoScriptText(SAY_TH_START_EVENT_PART2, pCreature);
+
+ if (npc_thrall_old_hillsbradAI* pThrallAI = dynamic_cast(pCreature->AI()))
+ pThrallAI->StartWP();
+
+ break;
+ }
+ case GOSSIP_ACTION_INFO_DEF+3:
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ pInstance->SetData(TYPE_THRALL_PART3, IN_PROGRESS);
+
+ if (npc_thrall_old_hillsbradAI* pThrallAI = dynamic_cast(pCreature->AI()))
+ pThrallAI->StartWP();
+
+ break;
+ }
+ }
+ return true;
+}
+
+/*######
+## npc_taretha
+######*/
+
+enum
+{
+ TEXT_ID_EPOCH1 = 9610, // Thank you for helping Thrall escape, friends. Now I only hope
+ GOSSIP_ITEM_EPOCH1 = -3560005, // "Strange wizard?"
+ TEXT_ID_EPOCH2 = 9613, // Yes, friends. This man was no wizard of
+ GOSSIP_ITEM_EPOCH2 = -3560006, // "We'll get you out. Taretha. Don't worry. I doubt the wizard would wander too far away."
+};
+
+npc_tarethaAI::npc_tarethaAI(Creature* pCreature) : npc_escortAI(pCreature)
+{
+ m_pInstance = (instance_old_hillsbrad*)pCreature->GetInstanceData();
+ m_uiErozionGUID = 0;
+ m_uiErozionEventTimer = 5000;
+ m_uiErozionPhase = 0;
+ Reset();
+}
+
+void npc_tarethaAI::JustSummoned(Creature* pSummoned)
+{
+ if (pSummoned->GetEntry() == NPC_EROZION)
+ m_uiErozionGUID = pSummoned->GetGUID();
+ else
+ DoScriptText(SAY_EPOCH_ENTER1, pSummoned);
+}
+
+void npc_tarethaAI::WaypointReached(uint32 uiPoint)
+{
+ switch(uiPoint)
+ {
+ case 6:
+ DoScriptText(SAY_TA_FREE, m_creature);
+ break;
+ case 7:
+ m_creature->HandleEmote(EMOTE_ONESHOT_CHEER);
+ m_creature->SummonCreature(NPC_EROZION, 2646.47f, 680.416f, 55.38f, 4.16f, TEMPSUMMON_TIMED_DESPAWN, 120000);
+ SetEscortPaused(true);
+ SetRun(false);
+ break;
+ }
+}
+
+void npc_tarethaAI::UpdateEscortAI(const uint32 uiDiff)
+{
+ if (!HasEscortState(STATE_ESCORT_PAUSED))
+ return;
+
+ if (m_uiErozionEventTimer < uiDiff)
+ {
+ ++m_uiErozionPhase;
+ m_uiErozionEventTimer = 5000;
+
+ switch(m_uiErozionPhase)
+ {
+ case 1:
+ if (Creature* pThrall = m_pInstance->GetThrall())
+ {
+ pThrall->SetFacingToObject(m_creature);
+ DoScriptText(SAY_TR_GLAD_SAFE, pThrall);
+ }
+ break;
+ case 2:
+ DoScriptText(SAY_TA_NEVER_MET, m_creature);
+ break;
+ case 3:
+ if (Creature* pThrall = m_pInstance->GetThrall())
+ DoScriptText(SAY_TR_THEN_WHO, pThrall);
+ break;
+ case 4:
+ if (Creature* pErozion = m_creature->GetMap()->GetCreature(m_uiErozionGUID))
+ DoScriptText(SAY_PRE_WIPE, pErozion);
+ break;
+ case 5:
+ //if (Creature* pErozion = m_creature->GetMap()->GetCreature(m_uiErozionGUID))
+ //pErozion->AI()->DoCastSpellIfCan();
+ break;
+ case 6:
+ if (Creature* pErozion = m_creature->GetMap()->GetCreature(m_uiErozionGUID))
+ DoScriptText(SAY_WIPE_MEMORY, pErozion);
+ break;
+ case 7:
+ if (Creature* pErozion = m_creature->GetMap()->GetCreature(m_uiErozionGUID))
+ DoScriptText(SAY_ABOUT_TARETHA, pErozion);
+ break;
+ case 8:
+ if (Creature* pErozion = m_creature->GetMap()->GetCreature(m_uiErozionGUID))
+ DoScriptText(SAY_AFTER_WIPE, pErozion);
+ break;
+ case 9:
+ if (Creature* pThrall = m_pInstance->GetThrall())
+ DoScriptText(SAY_TH_EVENT_COMPLETE, pThrall);
+ break;
+ case 10:
+ DoScriptText(SAY_TA_FAREWELL, m_creature);
+ SetEscortPaused(false);
+
+ if (Creature* pThrall = m_pInstance->GetThrall())
+ {
+ if (npc_thrall_old_hillsbradAI* pThrallAI = dynamic_cast(pThrall->AI()))
+ pThrallAI->SetEscortPaused(false);
+ }
+
+ break;
+ }
+ }
+ else
+ m_uiErozionEventTimer -= uiDiff;
+}
+
+CreatureAI* GetAI_npc_taretha(Creature* pCreature)
+{
+ return new npc_tarethaAI(pCreature);
+}
+
+bool GossipHello_npc_taretha(Player* pPlayer, Creature* pCreature)
+{
+ instance_old_hillsbrad* pInstance = (instance_old_hillsbrad*)pCreature->GetInstanceData();
+
+ if (pInstance && pInstance->GetData(TYPE_THRALL_PART3) == DONE && pInstance->GetData(TYPE_THRALL_PART4) == NOT_STARTED)
+ {
+ pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_EPOCH1, pCreature->GetGUID());
+ }
+
+ return true;
+}
+
+bool GossipSelect_npc_taretha(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ instance_old_hillsbrad* pInstance = (instance_old_hillsbrad*)pCreature->GetInstanceData();
+
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_EPOCH2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(TEXT_ID_EPOCH2, pCreature->GetGUID());
+ }
+
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+2)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (pInstance && pInstance->GetData(TYPE_THRALL_EVENT) == IN_PROGRESS)
+ {
+ pInstance->SetData(TYPE_THRALL_PART4, IN_PROGRESS);
+ pCreature->SummonCreature(NPC_EPOCH, 2639.13f, 698.55f, 65.43f, 4.59f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 120000);
+
+ if (Creature* pThrall = pInstance->GetThrall())
+ {
+ if (npc_thrall_old_hillsbradAI* pThrallAI = dynamic_cast(pThrall->AI()))
+ pThrallAI->StartWP();
+ }
+ }
+ }
+
+ return true;
+}
+
+/*######
+## AddSC
+######*/
+
+void AddSC_old_hillsbrad()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_brazen";
+ pNewScript->pGossipHello = &GossipHello_npc_brazen;
+ pNewScript->pGossipSelect = &GossipSelect_npc_brazen;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_erozion";
+ pNewScript->pGossipHello = &GossipHello_npc_erozion;
+ pNewScript->pGossipSelect = &GossipSelect_npc_erozion;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_thrall_old_hillsbrad";
+ pNewScript->pGossipHello = &GossipHello_npc_thrall_old_hillsbrad;
+ pNewScript->pGossipSelect = &GossipSelect_npc_thrall_old_hillsbrad;
+ pNewScript->GetAI = &GetAI_npc_thrall_old_hillsbrad;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_taretha";
+ pNewScript->pGossipHello = &GossipHello_npc_taretha;
+ pNewScript->pGossipSelect = &GossipSelect_npc_taretha;
+ pNewScript->GetAI = &GetAI_npc_taretha;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h b/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h
new file mode 100644
index 0000000..d209eb0
--- /dev/null
+++ b/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h
@@ -0,0 +1,70 @@
+/* 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 */
+
+#ifndef DEF_OLD_HILLSBRAD_H
+#define DEF_OLD_HILLSBRAD_H
+
+enum
+{
+ MAX_ENCOUNTER = 6,
+
+ TYPE_BARREL_DIVERSION = 0,
+ TYPE_THRALL_EVENT = 1,
+ TYPE_THRALL_PART1 = 2, // prison to keep
+ TYPE_THRALL_PART2 = 3, // keep to barn
+ TYPE_THRALL_PART3 = 4, // barn to inn
+ TYPE_THRALL_PART4 = 5, // inn to boss
+
+ NPC_THRALL = 17876,
+ NPC_TARETHA = 18887,
+ NPC_DRAKE = 17848,
+ NPC_LODGE_QUEST_TRIGGER = 20155,
+ NPC_EPOCH = 18096,
+
+ QUEST_ENTRY_HILLSBRAD = 10282,
+ QUEST_ENTRY_DIVERSION = 10283,
+ QUEST_ENTRY_ESCAPE = 10284,
+ QUEST_ENTRY_RETURN = 10285,
+
+ WORLD_STATE_OH = 2436,
+};
+
+class MANGOS_DLL_DECL instance_old_hillsbrad : public ScriptedInstance
+{
+ public:
+ instance_old_hillsbrad(Map* pMap);
+ ~instance_old_hillsbrad() {}
+
+ void Initialize();
+
+ Player* GetPlayerInMap();
+
+ void OnCreatureCreate(Creature* pCreature);
+ void OnCreatureDeath(Creature* pCreature);
+
+ void SetData(uint32 uiType, uint32 uiData);
+ uint32 GetData(uint32 uiType);
+ uint64 GetData64(uint32 uiData);
+
+ void HandleThrallRelocation();
+
+ void UpdateLodgeQuestCredit();
+
+ Creature* GetThrall() { return instance->GetCreature(m_uiThrallGUID); }
+ Creature* GetTaretha() { return instance->GetCreature(m_uiTarethaGUID); }
+ Creature* GetScarloc() { return instance->GetCreature(m_uiScarlocGUID); }
+ Creature* GetEpoch() { return instance->GetCreature(m_uiEpochGUID); }
+
+ protected:
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ uint32 m_uiBarrelCount;
+ uint32 m_uiThrallEventCount;
+ uint64 m_uiThrallGUID;
+ uint64 m_uiTarethaGUID;
+ uint64 m_uiScarlocGUID;
+ uint64 m_uiEpochGUID;
+};
+
+#endif
diff --git a/scripts/kalimdor/darkshore.cpp b/scripts/kalimdor/darkshore.cpp
new file mode 100644
index 0000000..daa3ca6
--- /dev/null
+++ b/scripts/kalimdor/darkshore.cpp
@@ -0,0 +1,405 @@
+/* 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: Darkshore
+SD%Complete: 100
+SDComment: Quest support: 731, 2078, 5321
+SDCategory: Darkshore
+EndScriptData */
+
+/* ContentData
+npc_kerlonian
+npc_prospector_remtravel
+npc_threshwackonator
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+#include "follower_ai.h"
+
+/*####
+# npc_kerlonian
+####*/
+
+enum
+{
+ SAY_KER_START = -1000434,
+
+ EMOTE_KER_SLEEP_1 = -1000435,
+ EMOTE_KER_SLEEP_2 = -1000436,
+ EMOTE_KER_SLEEP_3 = -1000437,
+
+ SAY_KER_SLEEP_1 = -1000438,
+ SAY_KER_SLEEP_2 = -1000439,
+ SAY_KER_SLEEP_3 = -1000440,
+ SAY_KER_SLEEP_4 = -1000441,
+
+ EMOTE_KER_AWAKEN = -1000445,
+
+ SAY_KER_ALERT_1 = -1000442,
+ SAY_KER_ALERT_2 = -1000443,
+
+ SAY_KER_END = -1000444,
+
+ SPELL_SLEEP_VISUAL = 25148,
+ SPELL_AWAKEN = 17536,
+ QUEST_SLEEPER_AWAKENED = 5321,
+ NPC_LILADRIS = 11219 //attackers entries unknown
+};
+
+//TODO: make concept similar as "ringo" -escort. Find a way to run the scripted attacks, _if_ player are choosing road.
+struct MANGOS_DLL_DECL npc_kerlonianAI : public FollowerAI
+{
+ npc_kerlonianAI(Creature* pCreature) : FollowerAI(pCreature) { Reset(); }
+
+ uint32 m_uiFallAsleepTimer;
+
+ void Reset()
+ {
+ m_uiFallAsleepTimer = urand(10000, 45000);
+ }
+
+ void MoveInLineOfSight(Unit *pWho)
+ {
+ FollowerAI::MoveInLineOfSight(pWho);
+
+ if (!m_creature->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_LILADRIS)
+ {
+ if (m_creature->IsWithinDistInMap(pWho, INTERACTION_DISTANCE*5))
+ {
+ if (Player* pPlayer = GetLeaderForFollower())
+ {
+ if (pPlayer->GetQuestStatus(QUEST_SLEEPER_AWAKENED) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->GroupEventHappens(QUEST_SLEEPER_AWAKENED, m_creature);
+
+ DoScriptText(SAY_KER_END, m_creature);
+ }
+
+ SetFollowComplete();
+ }
+ }
+ }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (HasFollowState(STATE_FOLLOW_INPROGRESS | STATE_FOLLOW_PAUSED) && pSpell->Id == SPELL_AWAKEN)
+ ClearSleeping();
+ }
+
+ void SetSleeping()
+ {
+ SetFollowPaused(true);
+
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(EMOTE_KER_SLEEP_1, m_creature); break;
+ case 1: DoScriptText(EMOTE_KER_SLEEP_2, m_creature); break;
+ case 2: DoScriptText(EMOTE_KER_SLEEP_3, m_creature); break;
+ }
+
+ switch(urand(0, 3))
+ {
+ case 0: DoScriptText(SAY_KER_SLEEP_1, m_creature); break;
+ case 1: DoScriptText(SAY_KER_SLEEP_2, m_creature); break;
+ case 2: DoScriptText(SAY_KER_SLEEP_3, m_creature); break;
+ case 3: DoScriptText(SAY_KER_SLEEP_4, m_creature); break;
+ }
+
+ m_creature->SetStandState(UNIT_STAND_STATE_SLEEP);
+ m_creature->CastSpell(m_creature, SPELL_SLEEP_VISUAL, false);
+ }
+
+ void ClearSleeping()
+ {
+ m_creature->RemoveAurasDueToSpell(SPELL_SLEEP_VISUAL);
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ DoScriptText(EMOTE_KER_AWAKEN, m_creature);
+
+ SetFollowPaused(false);
+ }
+
+ void UpdateFollowerAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ if (!HasFollowState(STATE_FOLLOW_INPROGRESS))
+ return;
+
+ if (!HasFollowState(STATE_FOLLOW_PAUSED))
+ {
+ if (m_uiFallAsleepTimer < uiDiff)
+ {
+ SetSleeping();
+ m_uiFallAsleepTimer = urand(25000, 90000);
+ }
+ else
+ m_uiFallAsleepTimer -= uiDiff;
+ }
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_kerlonian(Creature* pCreature)
+{
+ return new npc_kerlonianAI(pCreature);
+}
+
+bool QuestAccept_npc_kerlonian(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_SLEEPER_AWAKENED)
+ {
+ if (npc_kerlonianAI* pKerlonianAI = dynamic_cast(pCreature->AI()))
+ {
+ pCreature->SetStandState(UNIT_STAND_STATE_STAND);
+ DoScriptText(SAY_KER_START, pCreature, pPlayer);
+ pKerlonianAI->StartFollow(pPlayer, FACTION_ESCORT_N_FRIEND_PASSIVE, pQuest);
+ }
+ }
+
+ return true;
+}
+
+/*####
+# npc_prospector_remtravel
+####*/
+
+enum
+{
+ SAY_REM_START = -1000327,
+ SAY_REM_AGGRO = -1000339,
+ SAY_REM_RAMP1_1 = -1000328,
+ SAY_REM_RAMP1_2 = -1000329,
+ SAY_REM_BOOK = -1000330,
+ SAY_REM_TENT1_1 = -1000331,
+ SAY_REM_TENT1_2 = -1000332,
+ SAY_REM_MOSS = -1000333,
+ EMOTE_REM_MOSS = -1000334,
+ SAY_REM_MOSS_PROGRESS = -1000335,
+ SAY_REM_PROGRESS = -1000336,
+ SAY_REM_REMEMBER = -1000337,
+ EMOTE_REM_END = -1000338,
+
+ QUEST_ABSENT_MINDED_PT2 = 731,
+ NPC_GRAVEL_SCOUT = 2158,
+ NPC_GRAVEL_BONE = 2159,
+ NPC_GRAVEL_GEO = 2160
+};
+
+struct MANGOS_DLL_DECL npc_prospector_remtravelAI : public npc_escortAI
+{
+ npc_prospector_remtravelAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch(uiPointId)
+ {
+ case 0:
+ DoScriptText(SAY_REM_START, m_creature, pPlayer);
+ break;
+ case 5:
+ DoScriptText(SAY_REM_RAMP1_1, m_creature, pPlayer);
+ break;
+ case 6:
+ DoSpawnCreature(NPC_GRAVEL_SCOUT, -10.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ DoSpawnCreature(NPC_GRAVEL_BONE, -10.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ break;
+ case 9:
+ DoScriptText(SAY_REM_RAMP1_2, m_creature, pPlayer);
+ break;
+ case 14:
+ //depend quest rewarded?
+ DoScriptText(SAY_REM_BOOK, m_creature, pPlayer);
+ break;
+ case 15:
+ DoScriptText(SAY_REM_TENT1_1, m_creature, pPlayer);
+ break;
+ case 16:
+ DoSpawnCreature(NPC_GRAVEL_SCOUT, -10.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ DoSpawnCreature(NPC_GRAVEL_BONE, -10.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ break;
+ case 17:
+ DoScriptText(SAY_REM_TENT1_2, m_creature, pPlayer);
+ break;
+ case 26:
+ DoScriptText(SAY_REM_MOSS, m_creature, pPlayer);
+ break;
+ case 27:
+ DoScriptText(EMOTE_REM_MOSS, m_creature, pPlayer);
+ break;
+ case 28:
+ DoScriptText(SAY_REM_MOSS_PROGRESS, m_creature, pPlayer);
+ break;
+ case 29:
+ DoSpawnCreature(NPC_GRAVEL_SCOUT, -15.0f, 3.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ DoSpawnCreature(NPC_GRAVEL_BONE, -15.0f, 5.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ DoSpawnCreature(NPC_GRAVEL_GEO, -15.0f, 7.0f, 0.0f, 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ break;
+ case 31:
+ DoScriptText(SAY_REM_PROGRESS, m_creature, pPlayer);
+ break;
+ case 41:
+ DoScriptText(SAY_REM_REMEMBER, m_creature, pPlayer);
+ break;
+ case 42:
+ DoScriptText(EMOTE_REM_END, m_creature, pPlayer);
+ pPlayer->GroupEventHappens(QUEST_ABSENT_MINDED_PT2, m_creature);
+ break;
+ }
+ }
+
+ void Reset() { }
+
+ void Aggro(Unit* pWho)
+ {
+ if (urand(0, 1))
+ DoScriptText(SAY_REM_AGGRO, m_creature, pWho);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ //unsure if it should be any
+ //pSummoned->AI()->AttackStart(m_creature);
+ }
+};
+
+CreatureAI* GetAI_npc_prospector_remtravel(Creature* pCreature)
+{
+ return new npc_prospector_remtravelAI(pCreature);
+}
+
+bool QuestAccept_npc_prospector_remtravel(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_ABSENT_MINDED_PT2)
+ {
+ pCreature->setFaction(FACTION_ESCORT_A_NEUTRAL_PASSIVE);
+
+ if (npc_prospector_remtravelAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest, true);
+ }
+
+ return true;
+}
+
+/*####
+# npc_threshwackonator
+####*/
+
+enum
+{
+ EMOTE_START = -1000325,
+ SAY_AT_CLOSE = -1000326,
+ QUEST_GYROMAST_REV = 2078,
+ NPC_GELKAK = 6667,
+ FACTION_HOSTILE = 14
+};
+
+#define GOSSIP_ITEM_INSERT_KEY "[PH] Insert key"
+
+struct MANGOS_DLL_DECL npc_threshwackonatorAI : public FollowerAI
+{
+ npc_threshwackonatorAI(Creature* pCreature) : FollowerAI(pCreature) { Reset(); }
+
+ void Reset() {}
+
+ void MoveInLineOfSight(Unit* pWho)
+ {
+ FollowerAI::MoveInLineOfSight(pWho);
+
+ if (!m_creature->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_GELKAK)
+ {
+ if (m_creature->IsWithinDistInMap(pWho, 10.0f))
+ {
+ DoScriptText(SAY_AT_CLOSE, pWho);
+ DoAtEnd();
+ }
+ }
+ }
+
+ void DoAtEnd()
+ {
+ m_creature->setFaction(FACTION_HOSTILE);
+
+ if (Player* pHolder = GetLeaderForFollower())
+ m_creature->AI()->AttackStart(pHolder);
+
+ SetFollowComplete();
+ }
+};
+
+CreatureAI* GetAI_npc_threshwackonator(Creature* pCreature)
+{
+ return new npc_threshwackonatorAI(pCreature);
+}
+
+bool GossipHello_npc_threshwackonator(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(QUEST_GYROMAST_REV) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_INSERT_KEY, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_threshwackonator(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (npc_threshwackonatorAI* pThreshAI = dynamic_cast(pCreature->AI()))
+ {
+ DoScriptText(EMOTE_START, pCreature);
+ pThreshAI->StartFollow(pPlayer);
+ }
+ }
+
+ return true;
+}
+
+void AddSC_darkshore()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_kerlonian";
+ pNewScript->GetAI = &GetAI_npc_kerlonian;
+ pNewScript->pQuestAccept = &QuestAccept_npc_kerlonian;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_prospector_remtravel";
+ pNewScript->GetAI = &GetAI_npc_prospector_remtravel;
+ pNewScript->pQuestAccept = &QuestAccept_npc_prospector_remtravel;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_threshwackonator";
+ pNewScript->GetAI = &GetAI_npc_threshwackonator;
+ pNewScript->pGossipHello = &GossipHello_npc_threshwackonator;
+ pNewScript->pGossipSelect = &GossipSelect_npc_threshwackonator;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/desolace.cpp b/scripts/kalimdor/desolace.cpp
new file mode 100644
index 0000000..1d45c14
--- /dev/null
+++ b/scripts/kalimdor/desolace.cpp
@@ -0,0 +1,212 @@
+/* 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: Desolace
+SD%Complete: 100
+SDComment: Quest support: 5561
+SDCategory: Desolace
+EndScriptData */
+
+/* ContentData
+npc_aged_dying_ancient_kodo
+EndContentData */
+
+#include "precompiled.h"
+
+enum
+{
+ SAY_SMEED_HOME_1 = -1000348,
+ SAY_SMEED_HOME_2 = -1000349,
+ SAY_SMEED_HOME_3 = -1000350,
+
+ QUEST_KODO = 5561,
+
+ NPC_SMEED = 11596,
+ NPC_AGED_KODO = 4700,
+ NPC_DYING_KODO = 4701,
+ NPC_ANCIENT_KODO = 4702,
+ NPC_TAMED_KODO = 11627,
+
+ SPELL_KODO_KOMBO_ITEM = 18153,
+ SPELL_KODO_KOMBO_PLAYER_BUFF = 18172, //spells here have unclear function, but using them at least for visual parts and checks
+ SPELL_KODO_KOMBO_DESPAWN_BUFF = 18377,
+ SPELL_KODO_KOMBO_GOSSIP = 18362
+
+};
+
+struct MANGOS_DLL_DECL npc_aged_dying_ancient_kodoAI : public ScriptedAI
+{
+ npc_aged_dying_ancient_kodoAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ uint32 m_uiDespawnTimer;
+
+ void Reset()
+ {
+ m_uiDespawnTimer = 0;
+ }
+
+ void MoveInLineOfSight(Unit* pWho)
+ {
+ if (pWho->GetEntry() == NPC_SMEED)
+ {
+ if (m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP))
+ return;
+
+ if (m_creature->IsWithinDistInMap(pWho, 10.0f))
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_SMEED_HOME_1, pWho); break;
+ case 1: DoScriptText(SAY_SMEED_HOME_2, pWho); break;
+ case 2: DoScriptText(SAY_SMEED_HOME_3, pWho); break;
+ }
+
+ //spell have no implemented effect (dummy), so useful to notify spellHit
+ m_creature->CastSpell(m_creature,SPELL_KODO_KOMBO_GOSSIP,true);
+ }
+ }
+ }
+
+ void SpellHit(Unit* pCaster, SpellEntry const* pSpell)
+ {
+ if (pSpell->Id == SPELL_KODO_KOMBO_GOSSIP)
+ {
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ m_uiDespawnTimer = 60000;
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //timer should always be == 0 unless we already updated entry of creature. Then not expect this updated to ever be in combat.
+ if (m_uiDespawnTimer && m_uiDespawnTimer <= diff)
+ {
+ if (!m_creature->getVictim() && m_creature->isAlive())
+ {
+ Reset();
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->Respawn();
+ return;
+ }
+ } else m_uiDespawnTimer -= diff;
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_aged_dying_ancient_kodo(Creature* pCreature)
+{
+ return new npc_aged_dying_ancient_kodoAI(pCreature);
+}
+
+bool EffectDummyCreature_npc_aged_dying_ancient_kodo(Unit *pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature *pCreatureTarget)
+{
+ //always check spellid and effectindex
+ if (spellId == SPELL_KODO_KOMBO_ITEM && effIndex == EFFECT_INDEX_0)
+ {
+ //no effect if player/creature already have aura from spells
+ if (pCaster->HasAura(SPELL_KODO_KOMBO_PLAYER_BUFF) || pCreatureTarget->HasAura(SPELL_KODO_KOMBO_DESPAWN_BUFF))
+ return true;
+
+ if (pCreatureTarget->GetEntry() == NPC_AGED_KODO ||
+ pCreatureTarget->GetEntry() == NPC_DYING_KODO ||
+ pCreatureTarget->GetEntry() == NPC_ANCIENT_KODO)
+ {
+ pCaster->CastSpell(pCaster,SPELL_KODO_KOMBO_PLAYER_BUFF,true);
+
+ pCreatureTarget->UpdateEntry(NPC_TAMED_KODO);
+ pCreatureTarget->CastSpell(pCreatureTarget,SPELL_KODO_KOMBO_DESPAWN_BUFF,false);
+
+ if (pCreatureTarget->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
+ pCreatureTarget->GetMotionMaster()->MoveIdle();
+
+ pCreatureTarget->GetMotionMaster()->MoveFollow(pCaster, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
+ }
+
+ //always return true when we are handling this spell and effect
+ return true;
+ }
+ return false;
+}
+
+bool GossipHello_npc_aged_dying_ancient_kodo(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->HasAura(SPELL_KODO_KOMBO_PLAYER_BUFF) && pCreature->HasAura(SPELL_KODO_KOMBO_DESPAWN_BUFF))
+ {
+ //the expected quest objective
+ pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID());
+
+ pPlayer->RemoveAurasDueToSpell(SPELL_KODO_KOMBO_PLAYER_BUFF);
+ pCreature->GetMotionMaster()->MoveIdle();
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+enum
+{
+ QUEST_GHOST_O_PLASM_ROUND_UP = 6134,
+ GAMEOBJECT_GHOST_MAGNET = 177746,
+ MOB_MAGRAMI_SPECTRE = 11560
+};
+struct Locations
+{
+ float x, y, z;
+};
+static Locations SpawnP[]=
+{
+ {-3009.97f, 2560.86f, 39.05f}, // Start
+ {-3009.17f, 2684.55f, 42.42f},
+ {-3159.04f, 2485.20f, 95.52f},
+ {-2864.91f, 2699.52f, 74.07f}
+};
+
+bool GOHello_go_ghost_magnet (Player* pPlayer, GameObject* pGo)
+{
+ if ( pPlayer->GetQuestStatus(QUEST_GHOST_O_PLASM_ROUND_UP) == QUEST_STATUS_INCOMPLETE)
+ if (pGo->GetEntry()== GAMEOBJECT_GHOST_MAGNET)
+ {
+ for (int i = 0; i < 3; ++i)
+ {
+ pGo->SummonCreature(MOB_MAGRAMI_SPECTRE, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000);
+ }
+ return true;
+ }
+ return false;
+
+
+}
+void AddSC_desolace()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_aged_dying_ancient_kodo";
+ newscript->GetAI = &GetAI_npc_aged_dying_ancient_kodo;
+ newscript->pEffectDummyCreature = &EffectDummyCreature_npc_aged_dying_ancient_kodo;
+ newscript->pGossipHello = &GossipHello_npc_aged_dying_ancient_kodo;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "go_ghost_magnet";
+ newscript->pGOHello = &GOHello_go_ghost_magnet;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/dustwallow_marsh.cpp b/scripts/kalimdor/dustwallow_marsh.cpp
new file mode 100644
index 0000000..d1d5486
--- /dev/null
+++ b/scripts/kalimdor/dustwallow_marsh.cpp
@@ -0,0 +1,897 @@
+/* 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: Dustwallow_Marsh
+SD%Complete: 95
+SDComment: Quest support: 558, 1173, 1273, 1324, 11209, 11126, 11142, 11180. Vendor Nat Pagle
+SDCategory: Dustwallow Marsh
+EndScriptData */
+
+/* ContentData
+mobs_risen_husk_spirit
+npc_restless_apparition
+npc_deserter_agitator
+npc_lady_jaina_proudmoore
+npc_morokk
+npc_nat_pagle
+npc_ogron
+npc_private_hendel
+npc_cassa_crimsonwing
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## mobs_risen_husk_spirit
+######*/
+
+enum
+{
+ QUEST_WHATS_HAUNTING_WITCH_HILL = 11180,
+ SPELL_SUMMON_RESTLESS_APPARITION = 42511,
+ SPELL_CONSUME_FLESH = 37933, //Risen Husk
+ SPELL_INTANGIBLE_PRESENCE = 43127, //Risen Spirit
+ NPC_RISEN_HUSK = 23555,
+ NPC_RISEN_SPIRIT = 23554
+};
+
+
+struct MANGOS_DLL_DECL mobs_risen_husk_spiritAI : public ScriptedAI
+{
+ mobs_risen_husk_spiritAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiConsumeFlesh_Timer;
+ uint32 m_uiIntangiblePresence_Timer;
+
+ Player* m_pCreditPlayer;
+
+ void Reset()
+ {
+ m_uiConsumeFlesh_Timer = 10000;
+ m_uiIntangiblePresence_Timer = 5000;
+
+ m_pCreditPlayer = NULL;
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ if (m_pCreditPlayer)
+ m_pCreditPlayer->KilledMonsterCredit(pSummoned->GetEntry(), pSummoned->GetGUID());
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (uiDamage < m_creature->GetHealth())
+ return;
+
+ if (Player* pPlayer = pDoneBy->GetCharmerOrOwnerPlayerOrPlayerItself())
+ {
+ if (pPlayer->GetQuestStatus(QUEST_WHATS_HAUNTING_WITCH_HILL) == QUEST_STATUS_INCOMPLETE)
+ {
+ m_pCreditPlayer = pPlayer;
+ m_creature->CastSpell(pDoneBy, SPELL_SUMMON_RESTLESS_APPARITION, true);
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiConsumeFlesh_Timer < uiDiff)
+ {
+ if (m_creature->GetEntry() == NPC_RISEN_HUSK)
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CONSUME_FLESH);
+
+ m_uiConsumeFlesh_Timer = 15000;
+ }
+ else
+ m_uiConsumeFlesh_Timer -= uiDiff;
+
+ if (m_uiIntangiblePresence_Timer < uiDiff)
+ {
+ if (m_creature->GetEntry() == NPC_RISEN_SPIRIT)
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_INTANGIBLE_PRESENCE);
+
+ m_uiIntangiblePresence_Timer = 20000;
+ }
+ else
+ m_uiIntangiblePresence_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mobs_risen_husk_spirit(Creature* pCreature)
+{
+ return new mobs_risen_husk_spiritAI(pCreature);
+}
+
+/*######
+## npc_restless_apparition
+######*/
+
+enum
+{
+ SAY_RAND_1 = -1000543,
+ SAY_RAND_2 = -1000544,
+ SAY_RAND_3 = -1000545,
+ SAY_RAND_4 = -1000546,
+ SAY_RAND_5 = -1000547,
+ SAY_RAND_6 = -1000548,
+ SAY_RAND_7 = -1000549,
+ SAY_RAND_8 = -1000550
+};
+
+struct MANGOS_DLL_DECL npc_restless_apparitionAI : public ScriptedAI
+{
+ npc_restless_apparitionAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiTalk_Timer;
+
+ void Reset()
+ {
+ m_uiTalk_Timer = 1000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_uiTalk_Timer)
+ return;
+
+ if (m_uiTalk_Timer <= uiDiff)
+ {
+ switch(urand(0, 7))
+ {
+ case 0: DoScriptText(SAY_RAND_1, m_creature); break;
+ case 1: DoScriptText(SAY_RAND_2, m_creature); break;
+ case 2: DoScriptText(SAY_RAND_3, m_creature); break;
+ case 3: DoScriptText(SAY_RAND_4, m_creature); break;
+ case 4: DoScriptText(SAY_RAND_5, m_creature); break;
+ case 5: DoScriptText(SAY_RAND_6, m_creature); break;
+ case 6: DoScriptText(SAY_RAND_7, m_creature); break;
+ case 7: DoScriptText(SAY_RAND_8, m_creature); break;
+ }
+
+ m_uiTalk_Timer = 0;
+ }
+ else
+ m_uiTalk_Timer -= uiDiff;
+ }
+};
+
+CreatureAI* GetAI_npc_restless_apparition(Creature* pCreature)
+{
+ return new npc_restless_apparitionAI(pCreature);
+}
+
+/*######
+## npc_deserter_agitator
+######*/
+
+enum
+{
+ QUEST_TRAITORS_AMONG_US = 11126,
+ FACTION_THER_DESERTER = 1883
+};
+
+struct MANGOS_DLL_DECL npc_deserter_agitatorAI : public ScriptedAI
+{
+ npc_deserter_agitatorAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ void Reset()
+ {
+ m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A);
+ }
+};
+
+CreatureAI* GetAI_npc_deserter_agitator(Creature* pCreature)
+{
+ return new npc_deserter_agitatorAI(pCreature);
+}
+
+bool GossipHello_npc_deserter_agitator(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(QUEST_TRAITORS_AMONG_US) == QUEST_STATUS_INCOMPLETE)
+ {
+ pCreature->setFaction(FACTION_THER_DESERTER);
+ pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID());
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+/*######
+## npc_lady_jaina_proudmoore
+######*/
+
+enum
+{
+ QUEST_JAINAS_AUTOGRAPH = 558,
+ SPELL_JAINAS_AUTOGRAPH = 23122
+};
+
+#define GOSSIP_ITEM_JAINA "I know this is rather silly but i have a young ward who is a bit shy and would like your autograph."
+
+bool GossipHello_npc_lady_jaina_proudmoore(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(QUEST_JAINAS_AUTOGRAPH) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_JAINA, GOSSIP_SENDER_MAIN, GOSSIP_SENDER_INFO);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_lady_jaina_proudmoore(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_SENDER_INFO)
+ {
+ pPlayer->SEND_GOSSIP_MENU(7012, pCreature->GetGUID());
+ pPlayer->CastSpell(pPlayer, SPELL_JAINAS_AUTOGRAPH, false);
+ }
+ return true;
+}
+
+/*######
+## npc_morokk
+######*/
+
+enum
+{
+ SAY_MOR_CHALLENGE = -1000499,
+ SAY_MOR_SCARED = -1000500,
+
+ QUEST_CHALLENGE_MOROKK = 1173,
+
+ FACTION_MOR_HOSTILE = 168,
+ FACTION_MOR_RUNNING = 35
+};
+
+struct MANGOS_DLL_DECL npc_morokkAI : public npc_escortAI
+{
+ npc_morokkAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ m_bIsSuccess = false;
+ Reset();
+ }
+
+ bool m_bIsSuccess;
+
+ void Reset() {}
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 0:
+ SetEscortPaused(true);
+ break;
+ case 1:
+ if (m_bIsSuccess)
+ DoScriptText(SAY_MOR_SCARED, m_creature);
+ else
+ {
+ m_creature->SetDeathState(JUST_DIED);
+ m_creature->Respawn();
+ }
+ break;
+ }
+ }
+
+ void AttackedBy(Unit* pAttacker)
+ {
+ if (m_creature->getVictim())
+ return;
+
+ if (m_creature->IsFriendlyTo(pAttacker))
+ return;
+
+ AttackStart(pAttacker);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ if (m_creature->GetHealthPercent() < 30.0f)
+ {
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_CHALLENGE_MOROKK, m_creature);
+
+ m_creature->setFaction(FACTION_MOR_RUNNING);
+
+ m_bIsSuccess = true;
+ EnterEvadeMode();
+
+ uiDamage = 0;
+ }
+ }
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ if (HasEscortState(STATE_ESCORT_PAUSED))
+ {
+ if (Player* pPlayer = GetPlayerForEscort())
+ {
+ m_bIsSuccess = false;
+ DoScriptText(SAY_MOR_CHALLENGE, m_creature, pPlayer);
+ m_creature->setFaction(FACTION_MOR_HOSTILE);
+ AttackStart(pPlayer);
+ }
+
+ SetEscortPaused(false);
+ }
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_morokk(Creature* pCreature)
+{
+ return new npc_morokkAI(pCreature);
+}
+
+bool QuestAccept_npc_morokk(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_CHALLENGE_MOROKK)
+ {
+ if (npc_morokkAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(true, pPlayer->GetGUID(), pQuest);
+
+ return true;
+ }
+
+ return false;
+}
+/*######
+## npc_nat_pagle
+######*/
+
+enum
+{
+ QUEST_NATS_MEASURING_TAPE = 8227
+};
+
+bool GossipHello_npc_nat_pagle(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(QUEST_NATS_MEASURING_TAPE))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+ pPlayer->SEND_GOSSIP_MENU(7640, pCreature->GetGUID());
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(7638, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_nat_pagle(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_TRADE)
+ pPlayer->SEND_VENDORLIST(pCreature->GetGUID());
+
+ return true;
+}
+
+/*######
+## npc_ogron
+######*/
+
+enum
+{
+ SAY_OGR_START = -1000452,
+ SAY_OGR_SPOT = -1000453,
+ SAY_OGR_RET_WHAT = -1000454,
+ SAY_OGR_RET_SWEAR = -1000455,
+ SAY_OGR_REPLY_RET = -1000456,
+ SAY_OGR_RET_TAKEN = -1000457,
+ SAY_OGR_TELL_FIRE = -1000458,
+ SAY_OGR_RET_NOCLOSER = -1000459,
+ SAY_OGR_RET_NOFIRE = -1000460,
+ SAY_OGR_RET_HEAR = -1000461,
+ SAY_OGR_CAL_FOUND = -1000462,
+ SAY_OGR_CAL_MERCY = -1000463,
+ SAY_OGR_HALL_GLAD = -1000464,
+ EMOTE_OGR_RET_ARROW = -1000465,
+ SAY_OGR_RET_ARROW = -1000466,
+ SAY_OGR_CAL_CLEANUP = -1000467,
+ SAY_OGR_NODIE = -1000468,
+ SAY_OGR_SURVIVE = -1000469,
+ SAY_OGR_RET_LUCKY = -1000470,
+ SAY_OGR_THANKS = -1000471,
+
+ QUEST_QUESTIONING = 1273,
+
+ FACTION_GENERIC_FRIENDLY = 35,
+ FACTION_THER_HOSTILE = 151,
+
+ NPC_REETHE = 4980,
+ NPC_CALDWELL = 5046,
+ NPC_HALLAN = 5045,
+ NPC_SKIRMISHER = 5044,
+
+ SPELL_FAKE_SHOT = 7105,
+
+ PHASE_INTRO = 0,
+ PHASE_GUESTS = 1,
+ PHASE_FIGHT = 2,
+ PHASE_COMPLETE = 3
+};
+
+static float m_afSpawn[] = {-3383.501953f, -3203.383301f, 36.149f};
+static float m_afMoveTo[] = {-3371.414795f, -3212.179932f, 34.210f};
+
+struct MANGOS_DLL_DECL npc_ogronAI : public npc_escortAI
+{
+ npc_ogronAI(Creature* pCreature) : npc_escortAI(pCreature)
+ {
+ lCreatureList.clear();
+ m_uiPhase = 0;
+ m_uiPhaseCounter = 0;
+ Reset();
+ }
+
+ std::list lCreatureList;
+
+ uint32 m_uiPhase;
+ uint32 m_uiPhaseCounter;
+ uint32 m_uiGlobalTimer;
+
+ void Reset()
+ {
+ m_uiGlobalTimer = 5000;
+
+ if (HasEscortState(STATE_ESCORT_PAUSED) && m_uiPhase == PHASE_FIGHT)
+ m_uiPhase = PHASE_COMPLETE;
+
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ {
+ lCreatureList.clear();
+ m_uiPhase = 0;
+ m_uiPhaseCounter = 0;
+ }
+ }
+
+ void MoveInLineOfSight(Unit* pWho)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING) && pWho->GetEntry() == NPC_REETHE && lCreatureList.empty())
+ lCreatureList.push_back((Creature*)pWho);
+
+ npc_escortAI::MoveInLineOfSight(pWho);
+ }
+
+ Creature* GetCreature(uint32 uiCreatureEntry)
+ {
+ if (!lCreatureList.empty())
+ {
+ for(std::list::iterator itr = lCreatureList.begin(); itr != lCreatureList.end(); ++itr)
+ {
+ if ((*itr)->GetEntry() == uiCreatureEntry && (*itr)->isAlive())
+ return (*itr);
+ }
+ }
+
+ return NULL;
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ case 9:
+ DoScriptText(SAY_OGR_SPOT, m_creature);
+ break;
+ case 10:
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ DoScriptText(SAY_OGR_RET_WHAT, pReethe);
+ break;
+ case 11:
+ SetEscortPaused(true);
+ break;
+ }
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ lCreatureList.push_back(pSummoned);
+
+ pSummoned->setFaction(FACTION_GENERIC_FRIENDLY);
+
+ if (pSummoned->GetEntry() == NPC_CALDWELL)
+ pSummoned->GetMotionMaster()->MovePoint(0, m_afMoveTo[0], m_afMoveTo[1], m_afMoveTo[2]);
+ else
+ {
+ if (Creature* pCaldwell = GetCreature(NPC_CALDWELL))
+ {
+ //will this conversion work without compile warning/error?
+ size_t iSize = lCreatureList.size();
+ pSummoned->GetMotionMaster()->MoveFollow(pCaldwell, 0.5f, (M_PI/2)*(int)iSize);
+ }
+ }
+ }
+
+ void DoStartAttackMe()
+ {
+ if (!lCreatureList.empty())
+ {
+ for(std::list::iterator itr = lCreatureList.begin(); itr != lCreatureList.end(); ++itr)
+ {
+ if ((*itr)->GetEntry() == NPC_REETHE)
+ continue;
+
+ if ((*itr)->isAlive())
+ {
+ (*itr)->setFaction(FACTION_THER_HOSTILE);
+ (*itr)->AI()->AttackStart(m_creature);
+ }
+ }
+ }
+ }
+
+ void UpdateEscortAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ if (HasEscortState(STATE_ESCORT_PAUSED))
+ {
+ if (m_uiGlobalTimer < uiDiff)
+ {
+ m_uiGlobalTimer = 5000;
+
+ switch(m_uiPhase)
+ {
+ case PHASE_INTRO:
+ {
+ switch(m_uiPhaseCounter)
+ {
+ case 0:
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ DoScriptText(SAY_OGR_RET_SWEAR, pReethe);
+ break;
+ case 1:
+ DoScriptText(SAY_OGR_REPLY_RET, m_creature);
+ break;
+ case 2:
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ DoScriptText(SAY_OGR_RET_TAKEN, pReethe);
+ break;
+ case 3:
+ DoScriptText(SAY_OGR_TELL_FIRE, m_creature);
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ DoScriptText(SAY_OGR_RET_NOCLOSER, pReethe);
+ break;
+ case 4:
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ DoScriptText(SAY_OGR_RET_NOFIRE, pReethe);
+ break;
+ case 5:
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ DoScriptText(SAY_OGR_RET_HEAR, pReethe);
+
+ m_creature->SummonCreature(NPC_CALDWELL, m_afSpawn[0], m_afSpawn[1], m_afSpawn[2], 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000);
+ m_creature->SummonCreature(NPC_HALLAN, m_afSpawn[0], m_afSpawn[1], m_afSpawn[2], 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000);
+ m_creature->SummonCreature(NPC_SKIRMISHER, m_afSpawn[0], m_afSpawn[1], m_afSpawn[2], 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000);
+ m_creature->SummonCreature(NPC_SKIRMISHER, m_afSpawn[0], m_afSpawn[1], m_afSpawn[2], 0.0f, TEMPSUMMON_TIMED_OR_DEAD_DESPAWN, 300000);
+
+ m_uiPhase = PHASE_GUESTS;
+ break;
+ }
+ break;
+ }
+ case PHASE_GUESTS:
+ {
+ switch(m_uiPhaseCounter)
+ {
+ case 6:
+ if (Creature* pCaldwell = GetCreature(NPC_CALDWELL))
+ DoScriptText(SAY_OGR_CAL_FOUND, pCaldwell);
+ break;
+ case 7:
+ if (Creature* pCaldwell = GetCreature(NPC_CALDWELL))
+ DoScriptText(SAY_OGR_CAL_MERCY, pCaldwell);
+ break;
+ case 8:
+ if (Creature* pHallan = GetCreature(NPC_HALLAN))
+ {
+ DoScriptText(SAY_OGR_HALL_GLAD, pHallan);
+
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ pHallan->CastSpell(pReethe, SPELL_FAKE_SHOT, false);
+ }
+ break;
+ case 9:
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ {
+ DoScriptText(EMOTE_OGR_RET_ARROW, pReethe);
+ DoScriptText(SAY_OGR_RET_ARROW, pReethe);
+ }
+ break;
+ case 10:
+ if (Creature* pCaldwell = GetCreature(NPC_CALDWELL))
+ DoScriptText(SAY_OGR_CAL_CLEANUP, pCaldwell);
+
+ DoScriptText(SAY_OGR_NODIE, m_creature);
+ break;
+ case 11:
+ DoStartAttackMe();
+ m_uiPhase = PHASE_FIGHT;
+ break;
+ }
+ break;
+ }
+ case PHASE_COMPLETE:
+ {
+ switch(m_uiPhaseCounter)
+ {
+ case 12:
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_QUESTIONING, m_creature);
+
+ DoScriptText(SAY_OGR_SURVIVE, m_creature);
+ break;
+ case 13:
+ if (Creature* pReethe = GetCreature(NPC_REETHE))
+ DoScriptText(SAY_OGR_RET_LUCKY, pReethe);
+ break;
+ case 14:
+ DoScriptText(SAY_OGR_THANKS, m_creature);
+ SetRun();
+ SetEscortPaused(false);
+ break;
+ }
+ break;
+ }
+ }
+
+ if (m_uiPhase != PHASE_FIGHT)
+ ++m_uiPhaseCounter;
+ }
+ else
+ m_uiGlobalTimer -= uiDiff;
+ }
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+bool QuestAccept_npc_ogron(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_QUESTIONING)
+ {
+ if (npc_ogronAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ {
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest, true);
+ pCreature->setFaction(FACTION_ESCORT_N_FRIEND_PASSIVE);
+ DoScriptText(SAY_OGR_START, pCreature, pPlayer);
+ }
+ }
+
+ return true;
+}
+
+CreatureAI* GetAI_npc_ogron(Creature* pCreature)
+{
+ return new npc_ogronAI(pCreature);
+}
+
+/*######
+## npc_private_hendel
+######*/
+
+enum
+{
+ SAY_PROGRESS_1_TER = -1000411,
+ SAY_PROGRESS_2_HEN = -1000412,
+ SAY_PROGRESS_3_TER = -1000413,
+ SAY_PROGRESS_4_TER = -1000414,
+ EMOTE_SURRENDER = -1000415,
+
+ QUEST_MISSING_DIPLO_PT16 = 1324,
+ FACTION_HOSTILE = 168, //guessed, may be different
+
+ NPC_SENTRY = 5184, //helps hendel
+ NPC_JAINA = 4968, //appears once hendel gives up
+ NPC_TERVOSH = 4967
+};
+
+//TODO: develop this further, end event not created
+struct MANGOS_DLL_DECL npc_private_hendelAI : public ScriptedAI
+{
+ npc_private_hendelAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ void Reset()
+ {
+ if (m_creature->getFaction() != m_creature->GetCreatureInfo()->faction_A)
+ m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A);
+ }
+
+ void AttackedBy(Unit* pAttacker)
+ {
+ if (m_creature->getVictim())
+ return;
+
+ if (m_creature->IsFriendlyTo(pAttacker))
+ return;
+
+ AttackStart(pAttacker);
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ if (uiDamage > m_creature->GetHealth() || m_creature->GetHealthPercent() < 20.0f)
+ {
+ uiDamage = 0;
+
+ if (Player* pPlayer = pDoneBy->GetCharmerOrOwnerPlayerOrPlayerItself())
+ pPlayer->GroupEventHappens(QUEST_MISSING_DIPLO_PT16, m_creature);
+
+ DoScriptText(EMOTE_SURRENDER, m_creature);
+ EnterEvadeMode();
+ }
+ }
+};
+
+bool QuestAccept_npc_private_hendel(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_MISSING_DIPLO_PT16)
+ pCreature->setFaction(FACTION_HOSTILE);
+
+ return true;
+}
+
+CreatureAI* GetAI_npc_private_hendel(Creature* pCreature)
+{
+ return new npc_private_hendelAI(pCreature);
+}
+
+/*######
+## npc_cassa_crimsonwing
+######*/
+
+enum
+{
+ QUEST_SURVEY_ALCAZ = 11142,
+ SPELL_ALCAZ_SURVEY = 42295
+};
+
+#define GOSSIP_RIDE ""
+
+bool GossipHello_npc_cassa_crimsonwing(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(QUEST_SURVEY_ALCAZ) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_RIDE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_cassa_crimsonwing(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->CastSpell(pPlayer, SPELL_ALCAZ_SURVEY, false);
+ }
+ return true;
+}
+
+/*######
+## at_nats_landing
+######*/
+enum
+{
+ QUEST_NATS_BARGAIN = 11209,
+ SPELL_FISH_PASTE = 42644,
+ NPC_LURKING_SHARK = 23928
+};
+
+bool AreaTrigger_at_nats_landing(Player* pPlayer, const AreaTriggerEntry* pAt)
+{
+ if (pPlayer->GetQuestStatus(QUEST_NATS_BARGAIN) == QUEST_STATUS_INCOMPLETE && pPlayer->HasAura(SPELL_FISH_PASTE))
+ {
+ Creature* pShark = GetClosestCreatureWithEntry(pPlayer, NPC_LURKING_SHARK, 20.0f);
+
+ if (!pShark)
+ pShark = pPlayer->SummonCreature(NPC_LURKING_SHARK, -4246.243f, -3922.356f, -7.488f, 5.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 100000);
+
+ pShark->AI()->AttackStart(pPlayer);
+ return false;
+ }
+ return true;
+}
+
+void AddSC_dustwallow_marsh()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "mobs_risen_husk_spirit";
+ pNewScript->GetAI = &GetAI_mobs_risen_husk_spirit;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_restless_apparition";
+ pNewScript->GetAI = &GetAI_npc_restless_apparition;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_deserter_agitator";
+ pNewScript->GetAI = &GetAI_npc_deserter_agitator;
+ pNewScript->pGossipHello = &GossipHello_npc_deserter_agitator;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_lady_jaina_proudmoore";
+ pNewScript->pGossipHello = &GossipHello_npc_lady_jaina_proudmoore;
+ pNewScript->pGossipSelect = &GossipSelect_npc_lady_jaina_proudmoore;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_morokk";
+ pNewScript->GetAI = &GetAI_npc_morokk;
+ pNewScript->pQuestAccept = &QuestAccept_npc_morokk;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_nat_pagle";
+ pNewScript->pGossipHello = &GossipHello_npc_nat_pagle;
+ pNewScript->pGossipSelect = &GossipSelect_npc_nat_pagle;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_ogron";
+ pNewScript->GetAI = &GetAI_npc_ogron;
+ pNewScript->pQuestAccept = &QuestAccept_npc_ogron;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_private_hendel";
+ pNewScript->GetAI = &GetAI_npc_private_hendel;
+ pNewScript->pQuestAccept = &QuestAccept_npc_private_hendel;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_cassa_crimsonwing";
+ pNewScript->pGossipHello = &GossipHello_npc_cassa_crimsonwing;
+ pNewScript->pGossipSelect = &GossipSelect_npc_cassa_crimsonwing;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "at_nats_landing";
+ pNewScript->pAreaTrigger = &AreaTrigger_at_nats_landing;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/felwood.cpp b/scripts/kalimdor/felwood.cpp
new file mode 100644
index 0000000..d58dd93
--- /dev/null
+++ b/scripts/kalimdor/felwood.cpp
@@ -0,0 +1,506 @@
+/* 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: Felwood
+SD%Complete: 95
+SDComment: Quest support: related to 4101/4102 (To obtain Cenarion Beacon), 4506, 7603, 7603 (Summon Pollo Grande)
+SDCategory: Felwood
+EndScriptData */
+
+/* ContentData
+npc_kitten
+npcs_riverbreeze_and_silversky
+npc_niby_the_almighty
+npc_kroshius
+EndContentData */
+
+#include "precompiled.h"
+#include "follower_ai.h"
+#include "ObjectMgr.h"
+
+/*####
+# npc_kitten
+####*/
+
+enum
+{
+ EMOTE_SAB_JUMP = -1000541,
+ EMOTE_SAB_FOLLOW = -1000542,
+
+ SPELL_CORRUPT_SABER_VISUAL = 16510,
+
+ QUEST_CORRUPT_SABER = 4506,
+ NPC_WINNA = 9996,
+ NPC_CORRUPT_SABER = 10042
+};
+
+#define GOSSIP_ITEM_RELEASE "I want to release the corrupted saber to Winna."
+
+struct MANGOS_DLL_DECL npc_kittenAI : public FollowerAI
+{
+ npc_kittenAI(Creature* pCreature) : FollowerAI(pCreature)
+ {
+ if (pCreature->GetOwner() && pCreature->GetOwner()->GetTypeId() == TYPEID_PLAYER)
+ {
+ StartFollow((Player*)pCreature->GetOwner());
+ SetFollowPaused(true);
+ DoScriptText(EMOTE_SAB_JUMP, m_creature);
+
+ pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+
+ //find a decent way to move to center of moonwell
+ }
+
+ m_uiMoonwellCooldown = 7500;
+ Reset();
+ }
+
+ uint32 m_uiMoonwellCooldown;
+
+ void Reset() { }
+
+ void MoveInLineOfSight(Unit* pWho)
+ {
+ //should not have npcflag by default, so set when expected
+ if (!m_creature->getVictim() && !m_creature->HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP) && HasFollowState(STATE_FOLLOW_INPROGRESS) && pWho->GetEntry() == NPC_WINNA)
+ {
+ if (m_creature->IsWithinDistInMap(pWho, INTERACTION_DISTANCE))
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
+ }
+ }
+
+ void UpdateFollowerAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ if (HasFollowState(STATE_FOLLOW_PAUSED))
+ {
+ if (m_uiMoonwellCooldown < uiDiff)
+ {
+ m_creature->CastSpell(m_creature, SPELL_CORRUPT_SABER_VISUAL, false);
+ SetFollowPaused(false);
+ }
+ else
+ m_uiMoonwellCooldown -= uiDiff;
+ }
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_kitten(Creature* pCreature)
+{
+ return new npc_kittenAI(pCreature);
+}
+
+bool EffectDummyCreature_npc_kitten(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Creature* pCreatureTarget)
+{
+ //always check spellid and effectindex
+ if (uiSpellId == SPELL_CORRUPT_SABER_VISUAL && uiEffIndex == EFFECT_INDEX_0)
+ {
+ // Not nice way, however using UpdateEntry will not be correct.
+ if (const CreatureInfo* pTemp = GetCreatureTemplateStore(NPC_CORRUPT_SABER))
+ {
+ pCreatureTarget->SetEntry(pTemp->Entry);
+ pCreatureTarget->SetDisplayId(Creature::ChooseDisplayId(pTemp));
+ pCreatureTarget->SetName(pTemp->Name);
+ pCreatureTarget->SetFloatValue(OBJECT_FIELD_SCALE_X, pTemp->scale);
+ }
+
+ if (Unit* pOwner = pCreatureTarget->GetOwner())
+ DoScriptText(EMOTE_SAB_FOLLOW, pCreatureTarget, pOwner);
+
+ //always return true when we are handling this spell and effect
+ return true;
+ }
+ return false;
+}
+
+bool GossipHello_npc_corrupt_saber(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetQuestStatus(QUEST_CORRUPT_SABER) == QUEST_STATUS_INCOMPLETE)
+ {
+ if (GetClosestCreatureWithEntry(pCreature, NPC_WINNA, INTERACTION_DISTANCE))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RELEASE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ }
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_corrupt_saber(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (npc_kittenAI* pKittenAI = dynamic_cast(pCreature->AI()))
+ pKittenAI->SetFollowComplete();
+
+ pPlayer->AreaExploredOrEventHappens(QUEST_CORRUPT_SABER);
+ }
+
+ return true;
+}
+
+/*######
+## npcs_riverbreeze_and_silversky
+######*/
+
+enum
+{
+ QUEST_CLEANSING_FELWOOD_A = 4101,
+ QUEST_CLEANSING_FELWOOD_H = 4102,
+
+ NPC_ARATHANDIS_SILVERSKY = 9528,
+ NPC_MAYBESS_RIVERBREEZE = 9529,
+
+ SPELL_CENARION_BEACON = 15120
+};
+
+#define GOSSIP_ITEM_BEACON "Please make me a Cenarion Beacon"
+
+bool GossipHello_npcs_riverbreeze_and_silversky(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ switch (pCreature->GetEntry())
+ {
+ case NPC_ARATHANDIS_SILVERSKY:
+ if (pPlayer->GetQuestRewardStatus(QUEST_CLEANSING_FELWOOD_A))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(2848, pCreature->GetGUID());
+ }else if (pPlayer->GetTeam() == HORDE)
+ pPlayer->SEND_GOSSIP_MENU(2845, pCreature->GetGUID());
+ else
+ pPlayer->SEND_GOSSIP_MENU(2844, pCreature->GetGUID());
+ break;
+ case NPC_MAYBESS_RIVERBREEZE:
+ if (pPlayer->GetQuestRewardStatus(QUEST_CLEANSING_FELWOOD_H))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_BEACON, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(2849, pCreature->GetGUID());
+ }else if (pPlayer->GetTeam() == ALLIANCE)
+ pPlayer->SEND_GOSSIP_MENU(2843, pCreature->GetGUID());
+ else
+ pPlayer->SEND_GOSSIP_MENU(2842, pCreature->GetGUID());
+ break;
+ }
+
+ return true;
+}
+
+bool GossipSelect_npcs_riverbreeze_and_silversky(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer, SPELL_CENARION_BEACON, false);
+ }
+ return true;
+}
+
+/*######
+## npc_niby_the_almighty (summons el pollo grande)
+######*/
+
+enum
+{
+ QUEST_KROSHIUS = 7603,
+
+ NPC_IMPSY = 14470,
+
+ SPELL_SUMMON_POLLO = 23056,
+
+ SAY_NIBY_1 = -1000566,
+ SAY_NIBY_2 = -1000567,
+ EMOTE_IMPSY_1 = -1000568,
+ SAY_IMPSY_1 = -1000569,
+ SAY_NIBY_3 = -1000570
+};
+
+struct MANGOS_DLL_DECL npc_niby_the_almightyAI : public ScriptedAI
+{
+ npc_niby_the_almightyAI(Creature* pCreature) : ScriptedAI(pCreature){ Reset(); }
+
+ uint32 m_uiSummonTimer;
+ uint8 m_uiSpeech;
+
+ bool m_bEventStarted;
+
+ void Reset()
+ {
+ m_uiSummonTimer = 500;
+ m_uiSpeech = 0;
+
+ m_bEventStarted = false;
+ }
+
+ void StartEvent()
+ {
+ Reset();
+ m_bEventStarted = true;
+ m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (m_bEventStarted)
+ {
+ if (m_uiSummonTimer <= uiDiff)
+ {
+ switch (m_uiSpeech)
+ {
+ case 1:
+ m_creature->GetMotionMaster()->Clear();
+ m_creature->GetMotionMaster()->MovePoint(0, 5407.19f, -753.00f, 350.82f);
+ m_uiSummonTimer = 6200;
+ break;
+ case 2:
+ m_creature->SetFacingTo(1.2f);
+ DoScriptText(SAY_NIBY_1, m_creature);
+ m_uiSummonTimer = 3000;
+ break;
+ case 3:
+ DoScriptText(SAY_NIBY_2, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_SUMMON_POLLO);
+ m_uiSummonTimer = 2000;
+ break;
+ case 4:
+ if (Creature* pImpsy = GetClosestCreatureWithEntry(m_creature, NPC_IMPSY, 20.0))
+ {
+ DoScriptText(EMOTE_IMPSY_1, pImpsy);
+ DoScriptText(SAY_IMPSY_1, pImpsy);
+ m_uiSummonTimer = 2500;
+ }
+ else
+ {
+ //Skip Speech 5
+ m_uiSummonTimer = 40000;
+ ++m_uiSpeech;
+ }
+ break;
+ case 5:
+ DoScriptText(SAY_NIBY_3, m_creature);
+ m_uiSummonTimer = 40000;
+ break;
+ case 6:
+ m_creature->GetMotionMaster()->MoveTargetedHome();
+ m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
+ m_bEventStarted = false;
+ break;
+ }
+ ++m_uiSpeech;
+ }
+ else
+ m_uiSummonTimer -= uiDiff;
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_niby_the_almighty(Creature* pCreature)
+{
+ return new npc_niby_the_almightyAI(pCreature);
+}
+
+bool ChooseReward_npc_niby_the_almighty(Player* pPlayer, Creature* pCreature, const Quest* pQuest, uint32 slot)
+{
+ if (pQuest->GetQuestId() == QUEST_KROSHIUS)
+ {
+ if (npc_niby_the_almightyAI* pNibyAI = dynamic_cast(pCreature->AI()))
+ {
+ pNibyAI->StartEvent();
+ }
+ }
+ return true;
+}
+
+/*######
+## npc_kroshius
+######*/
+
+enum
+{
+ NPC_KROSHIUS = 14467,
+ SPELL_KNOCKBACK = 10101,
+ SAY_KROSHIUS_REVIVE = -1000589,
+ EVENT_KROSHIUS_REVIVE = 8328,
+ FACTION_HOSTILE = 16,
+};
+
+struct MANGOS_DLL_DECL npc_kroshiusAI : public ScriptedAI
+{
+ npc_kroshiusAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_uiPhase = 0;
+ Reset();
+ }
+
+ uint64 m_uiPlayerGUID;
+ uint32 m_uiKnockBackTimer;
+ uint32 m_uiPhaseTimer;
+
+ uint8 m_uiPhase;
+
+ void Reset()
+ {
+ m_uiKnockBackTimer = urand(5000, 8000);
+ m_uiPlayerGUID = 0;
+
+ if (!m_uiPhase)
+ {
+ m_creature->setFaction(m_creature->GetCreatureInfo()->faction_A);
+ // TODO: Workaround? till better solution
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
+ m_creature->SetStandState(UNIT_STAND_STATE_DEAD);
+ }
+ }
+
+ void DoRevive(Player* pSource)
+ {
+ if (m_uiPhase)
+ return;
+
+ m_uiPhase = 1;
+ m_uiPhaseTimer = 2500;
+ m_uiPlayerGUID = pSource->GetGUID();
+
+ // TODO: A visual Flame Circle around the mob still missing
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ m_uiPhase = 0;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_uiPhase)
+ return;
+
+ if (m_uiPhase < 4)
+ {
+ if (m_uiPhaseTimer < uiDiff)
+ {
+ switch (m_uiPhase)
+ {
+ case 1: // Revived
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ m_uiPhaseTimer = 1000;
+ break;
+ case 2:
+ DoScriptText(SAY_KROSHIUS_REVIVE, m_creature);
+ m_uiPhaseTimer = 3500;
+ break;
+ case 3: // Attack
+ m_creature->setFaction(FACTION_HOSTILE);
+ // TODO workaround will better idea
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID))
+ {
+ if (m_creature->IsWithinDistInMap(pPlayer, 30.0f))
+ AttackStart(pPlayer);
+ }
+ break;
+ }
+ m_uiPhase++;
+ }
+ else
+ m_uiPhaseTimer -= uiDiff;
+ }
+ else
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (m_uiKnockBackTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_KNOCKBACK);
+ m_uiKnockBackTimer = urand(9000, 12000);
+ }
+ else
+ m_uiKnockBackTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_kroshius(Creature* pCreature)
+{
+ return new npc_kroshiusAI(pCreature);
+}
+
+bool ProcessEventId_npc_kroshius(uint32 uiEventId, Object* pSource, Object* pTarget, bool bIsStart)
+{
+ if (uiEventId == EVENT_KROSHIUS_REVIVE)
+ {
+ if (pSource->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (Creature* pKroshius = GetClosestCreatureWithEntry((Player*)pSource, NPC_KROSHIUS, 20.0f))
+ {
+ if (npc_kroshiusAI* pKroshiusAI = dynamic_cast(pKroshius->AI()))
+ pKroshiusAI->DoRevive((Player*)pSource);
+ }
+ }
+
+ return true;
+ }
+ return false;
+}
+
+void AddSC_felwood()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_kitten";
+ pNewScript->GetAI = &GetAI_npc_kitten;
+ pNewScript->pEffectDummyCreature = &EffectDummyCreature_npc_kitten;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_corrupt_saber";
+ pNewScript->pGossipHello = &GossipHello_npc_corrupt_saber;
+ pNewScript->pGossipSelect = &GossipSelect_npc_corrupt_saber;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npcs_riverbreeze_and_silversky";
+ pNewScript->pGossipHello = &GossipHello_npcs_riverbreeze_and_silversky;
+ pNewScript->pGossipSelect = &GossipSelect_npcs_riverbreeze_and_silversky;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_niby_the_almighty";
+ pNewScript->GetAI = &GetAI_npc_niby_the_almighty;
+ pNewScript->pChooseReward = &ChooseReward_npc_niby_the_almighty;
+ pNewScript->RegisterSelf();
+
+ pNewScript = new Script;
+ pNewScript->Name = "npc_kroshius";
+ pNewScript->GetAI = &GetAI_npc_kroshius;
+ pNewScript->pProcessEventId = &ProcessEventId_npc_kroshius;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/feralas.cpp b/scripts/kalimdor/feralas.cpp
new file mode 100644
index 0000000..70b95a6
--- /dev/null
+++ b/scripts/kalimdor/feralas.cpp
@@ -0,0 +1,327 @@
+/* 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: Feralas
+SD%Complete: 100
+SDComment: Quest support: 3520, 2767,2845 Special vendor Gregan Brewspewer
+SDCategory: Feralas
+EndScriptData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+#include "follower_ai.h"
+
+/*######
+## npc_shay_leafrunner
+######*/
+enum
+{
+ SPELL_STANDUP = 11402,
+ QUEST_WANDERING_SHAY = 2845,
+ NPC_ROCKBITER = 7765
+};
+struct Locations
+{
+ float x, y, z;
+};
+static Locations ShayWP[]=
+{
+ {-3009.97f, 2560.86f, 39.05f}, // Start
+ {-3009.17f, 2684.55f, 42.42f},
+ {-3159.04f, 2485.20f, 95.52f},
+ {-2864.91f, 2699.52f, 74.07f},
+};
+struct MANGOS_DLL_DECL npc_shayAI : public FollowerAI
+{
+ npc_shayAI(Creature* pCreature) : FollowerAI(pCreature) { Reset();}
+
+ uint32 m_uiSitdownTimer;
+
+ void Reset()
+ {
+ m_uiSitdownTimer = urand(45000, 75000);
+ }
+
+ void MoveInLineOfSight(Unit *pWho)
+ {
+ FollowerAI::MoveInLineOfSight(pWho);
+
+ if (!m_creature->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_ROCKBITER)
+ {
+ if (m_creature->IsWithinDistInMap(pWho, INTERACTION_DISTANCE*2))
+ {
+ if (Player* pPlayer = GetLeaderForFollower())
+ {
+ if (pPlayer->GetQuestStatus(QUEST_WANDERING_SHAY) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->GroupEventHappens(QUEST_WANDERING_SHAY, m_creature);
+ }
+
+ SetFollowComplete();
+ }
+ }
+ }
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (HasFollowState(STATE_FOLLOW_INPROGRESS | STATE_FOLLOW_PAUSED) && pSpell->Id == SPELL_STANDUP)
+ StandUp();
+ }
+
+ void SetSiting()
+ {
+ m_creature->SetStandState(UNIT_STAND_STATE_SIT);
+ }
+
+ void StandUp()
+ {
+ m_creature->SetStandState(UNIT_STAND_STATE_STAND);
+ SetFollowPaused(false);
+ }
+
+ void GoAway()
+ {
+ SetFollowPaused(true);
+ uint32 id = urand(0,3);
+ m_creature->GetMotionMaster()->MovePoint(id, ShayWP[id].x, ShayWP[id].y, ShayWP[id].z);
+ }
+ void MovementInform(uint32 type, uint32 id)
+ {
+ if ( id == 0 || id == 1 || id == 2 || id == 3 )
+ SetSiting();
+ }
+ void UpdateFollowerAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ if (!HasFollowState(STATE_FOLLOW_INPROGRESS))
+ return;
+
+ if (!HasFollowState(STATE_FOLLOW_PAUSED))
+ {
+ if (m_uiSitdownTimer < uiDiff)
+ {
+ GoAway();
+ m_uiSitdownTimer = urand(45000, 75000);
+ }
+ else
+ m_uiSitdownTimer -= uiDiff;
+ }
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_shay(Creature* pCreature)
+{
+ return new npc_shayAI(pCreature);
+}
+
+bool QuestAccept_npc_shay(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_WANDERING_SHAY)
+ {
+ if (npc_shayAI* pshayAI = dynamic_cast(pCreature->AI()))
+ {
+ pCreature->SetStandState(UNIT_STAND_STATE_STAND);
+ pshayAI->StartFollow(pPlayer, FACTION_ESCORT_N_FRIEND_PASSIVE, pQuest);
+ }
+ }
+
+ return true;
+}
+/*######
+## npc_gregan_brewspewer
+######*/
+
+bool GossipHello_npc_gregan_brewspewer(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pCreature->isVendor() && pPlayer->GetQuestStatus(3909) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Buy somethin', will ya?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(2433, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_gregan_brewspewer(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+ pPlayer->SEND_GOSSIP_MENU(2434, pCreature->GetGUID());
+ }
+ if (uiAction == GOSSIP_ACTION_TRADE)
+ pPlayer->SEND_VENDORLIST(pCreature->GetGUID());
+ return true;
+}
+
+/*######
+## npc_oox22fe
+######*/
+
+enum
+{
+ SAY_OOX_START = -1000287,
+ SAY_OOX_AGGRO1 = -1000288,
+ SAY_OOX_AGGRO2 = -1000289,
+ SAY_OOX_AMBUSH = -1000290,
+ SAY_OOX_END = -1000292,
+
+ NPC_YETI = 7848,
+ NPC_GORILLA = 5260,
+ NPC_WOODPAW_REAVER = 5255,
+ NPC_WOODPAW_BRUTE = 5253,
+ NPC_WOODPAW_ALPHA = 5258,
+ NPC_WOODPAW_MYSTIC = 5254,
+
+ QUEST_RESCUE_OOX22FE = 2767
+};
+
+struct MANGOS_DLL_DECL npc_oox22feAI : public npc_escortAI
+{
+ npc_oox22feAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void WaypointReached(uint32 i)
+ {
+ switch (i)
+ {
+ // First Ambush(3 Yetis)
+ case 11:
+ DoScriptText(SAY_OOX_AMBUSH,m_creature);
+ m_creature->SummonCreature(NPC_YETI, -4841.01f, 1593.91f, 73.42f, 3.98f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ m_creature->SummonCreature(NPC_YETI, -4837.61f, 1568.58f, 78.21f, 3.13f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ m_creature->SummonCreature(NPC_YETI, -4841.89f, 1569.95f, 76.53f, 0.68f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ break;
+ //Second Ambush(3 Gorillas)
+ case 21:
+ DoScriptText(SAY_OOX_AMBUSH,m_creature);
+ m_creature->SummonCreature(NPC_GORILLA, -4595.81f, 2005.99f, 53.08f, 3.74f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ m_creature->SummonCreature(NPC_GORILLA, -4597.53f, 2008.31f, 52.70f, 3.78f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ m_creature->SummonCreature(NPC_GORILLA, -4599.37f, 2010.59f, 52.77f, 3.84f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ break;
+ //Third Ambush(4 Gnolls)
+ case 30:
+ DoScriptText(SAY_OOX_AMBUSH,m_creature);
+ m_creature->SummonCreature(NPC_WOODPAW_REAVER, -4425.14f, 2075.87f, 47.77f, 3.77f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ m_creature->SummonCreature(NPC_WOODPAW_BRUTE , -4426.68f, 2077.98f, 47.57f, 3.77f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ m_creature->SummonCreature(NPC_WOODPAW_MYSTIC, -4428.33f, 2080.24f, 47.43f, 3.87f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ m_creature->SummonCreature(NPC_WOODPAW_ALPHA , -4430.04f, 2075.54f, 46.83f, 3.81f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ break;
+ case 37:
+ DoScriptText(SAY_OOX_END,m_creature);
+ // Award quest credit
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_RESCUE_OOX22FE, m_creature);
+ break;
+ }
+ }
+
+ void Reset()
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ m_creature->SetStandState(UNIT_STAND_STATE_DEAD);
+ }
+
+ void Aggro(Unit* who)
+ {
+ //For an small probability the npc says something when he get aggro
+ switch(urand(0, 9))
+ {
+ case 0: DoScriptText(SAY_OOX_AGGRO1, m_creature); break;
+ case 1: DoScriptText(SAY_OOX_AGGRO2, m_creature); break;
+ }
+ }
+
+ void JustSummoned(Creature* summoned)
+ {
+ summoned->AI()->AttackStart(m_creature);
+ }
+};
+
+CreatureAI* GetAI_npc_oox22fe(Creature* pCreature)
+{
+ return new npc_oox22feAI(pCreature);
+}
+
+bool QuestAccept_npc_oox22fe(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_RESCUE_OOX22FE)
+ {
+ DoScriptText(SAY_OOX_START, pCreature);
+ //change that the npc is not lying dead on the ground
+ pCreature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ if (pPlayer->GetTeam() == ALLIANCE)
+ pCreature->setFaction(FACTION_ESCORT_A_PASSIVE);
+
+ if (pPlayer->GetTeam() == HORDE)
+ pCreature->setFaction(FACTION_ESCORT_H_PASSIVE);
+
+ if (npc_oox22feAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+/*######
+## npc_screecher_spirit
+######*/
+
+bool GossipHello_npc_screecher_spirit(Player* pPlayer, Creature* pCreature)
+{
+ pPlayer->SEND_GOSSIP_MENU(2039, pCreature->GetGUID());
+ pPlayer->TalkedToCreature(pCreature->GetEntry(), pCreature->GetGUID());
+ pCreature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ return true;
+}
+
+/*######
+## AddSC
+######*/
+
+void AddSC_feralas()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_shay";
+ newscript->GetAI = &GetAI_npc_shay;
+ newscript->pQuestAccept = &QuestAccept_npc_shay;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_gregan_brewspewer";
+ newscript->pGossipHello = &GossipHello_npc_gregan_brewspewer;
+ newscript->pGossipSelect = &GossipSelect_npc_gregan_brewspewer;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_oox22fe";
+ newscript->GetAI = &GetAI_npc_oox22fe;
+ newscript->pQuestAccept = &QuestAccept_npc_oox22fe;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_screecher_spirit";
+ newscript->pGossipHello = &GossipHello_npc_screecher_spirit;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp b/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp
new file mode 100644
index 0000000..2fbdfd9
--- /dev/null
+++ b/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp
@@ -0,0 +1,167 @@
+/* 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_Celebras_the_Cursed
+SD%Complete: 100
+SDComment:
+SDCategory: Maraudon
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_WRATH 21807
+#define SPELL_ENTANGLINGROOTS 12747
+#define SPELL_CORRUPT_FORCES 21968
+#define QUEST_THE_SCEPTER_OF_CELEBRAS 7046
+
+struct MANGOS_DLL_DECL celebras_the_cursedAI : public ScriptedAI
+{
+ celebras_the_cursedAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Wrath_Timer;
+ uint32 EntanglingRoots_Timer;
+ uint32 CorruptForces_Timer;
+
+ void Reset()
+ {
+ Wrath_Timer = 8000;
+ EntanglingRoots_Timer = 2000;
+ CorruptForces_Timer = 30000;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ m_creature->SummonCreature(13716, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 0, TEMPSUMMON_TIMED_DESPAWN, 600000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Wrath
+ if (Wrath_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target)
+ DoCastSpellIfCan(target,SPELL_WRATH);
+ Wrath_Timer = 8000;
+ }else Wrath_Timer -= diff;
+
+ //EntanglingRoots
+ if (EntanglingRoots_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ENTANGLINGROOTS);
+ EntanglingRoots_Timer = 20000;
+ }else EntanglingRoots_Timer -= diff;
+
+ //CorruptForces
+ if (CorruptForces_Timer < diff)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(m_creature,SPELL_CORRUPT_FORCES);
+ CorruptForces_Timer = 20000;
+ }else CorruptForces_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_celebras_the_cursed(Creature* pCreature)
+{
+ return new celebras_the_cursedAI(pCreature);
+}
+struct Locations
+{
+ float x, y, z;
+};
+static Locations CelebrasWP[] =
+{
+ {653.61f, 73.41f, -85.86f},
+};
+struct MANGOS_DLL_DECL npc_celebrasAI : public ScriptedAI
+{
+ npc_celebrasAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ float x;
+ float y;
+ float z;
+ uint32 m_uiWalkTimer;
+
+ void MovementInform(uint32 type, uint32 tempid)
+ {
+ if (tempid == 0)
+ if(Player* pPlayer = GetPlayerAtMinimumRange( 50))
+ if (pPlayer->GetQuestStatus(QUEST_THE_SCEPTER_OF_CELEBRAS) == QUEST_STATUS_INCOMPLETE)
+ {
+ pPlayer->GroupEventHappens(QUEST_THE_SCEPTER_OF_CELEBRAS, m_creature);
+ m_uiWalkTimer = 200;
+ }
+ }
+
+ void Reset()
+ {
+ }
+ void GoToStone()
+ {
+ m_uiWalkTimer = 200;
+ }
+ void UpdateAI(const uint32 diff)
+ {
+ if (m_uiWalkTimer)
+ {
+ if (m_uiWalkTimer <= diff)
+ {
+ m_creature->GetMotionMaster()->MovePoint(0,CelebrasWP[0].x, CelebrasWP[0].y, CelebrasWP[0].z);
+ m_uiWalkTimer = 0;
+
+ }else m_uiWalkTimer -= diff;
+ }
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_celebras(Creature* pCreature)
+{
+ return new npc_celebrasAI(pCreature);
+}
+
+bool QuestAccept_npc_celebras(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_THE_SCEPTER_OF_CELEBRAS)
+ {
+ if (npc_celebrasAI* pCreatureAI = dynamic_cast(pCreature->AI()))
+ pCreatureAI->GoToStone();
+ }
+ return true;
+}
+
+void AddSC_boss_celebras_the_cursed()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "celebras_the_cursed";
+ newscript->GetAI = &GetAI_celebras_the_cursed;
+ newscript->RegisterSelf();
+
+ //quest from his ghost
+ newscript = new Script;
+ newscript->Name = "npc_celebras_the_redeemed";
+ newscript->GetAI = &GetAI_npc_celebras;
+ newscript->pQuestAccept = &QuestAccept_npc_celebras;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/maraudon/boss_landslide.cpp b/scripts/kalimdor/maraudon/boss_landslide.cpp
new file mode 100644
index 0000000..35ee503
--- /dev/null
+++ b/scripts/kalimdor/maraudon/boss_landslide.cpp
@@ -0,0 +1,90 @@
+/* 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_Landslide
+SD%Complete: 100
+SDComment:
+SDCategory: Maraudon
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_KNOCKAWAY 18670
+#define SPELL_TRAMPLE 5568
+#define SPELL_LANDSLIDE 21808
+
+struct MANGOS_DLL_DECL boss_landslideAI : public ScriptedAI
+{
+ boss_landslideAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 KnockAway_Timer;
+ uint32 Trample_Timer;
+ uint32 Landslide_Timer;
+
+ void Reset()
+ {
+ KnockAway_Timer = 8000;
+ Trample_Timer = 2000;
+ Landslide_Timer = 0;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //KnockAway_Timer
+ if (KnockAway_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KNOCKAWAY);
+ KnockAway_Timer = 15000;
+ }else KnockAway_Timer -= diff;
+
+ //Trample_Timer
+ if (Trample_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_TRAMPLE);
+ Trample_Timer = 8000;
+ }else Trample_Timer -= diff;
+
+ //Landslide
+ if (m_creature->GetHealthPercent() < 50.0f)
+ {
+ if (Landslide_Timer < diff)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(m_creature,SPELL_LANDSLIDE);
+ Landslide_Timer = 60000;
+ } else Landslide_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_landslide(Creature* pCreature)
+{
+ return new boss_landslideAI(pCreature);
+}
+
+void AddSC_boss_landslide()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_landslide";
+ newscript->GetAI = &GetAI_boss_landslide;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/maraudon/boss_noxxion.cpp b/scripts/kalimdor/maraudon/boss_noxxion.cpp
new file mode 100644
index 0000000..fc0070a
--- /dev/null
+++ b/scripts/kalimdor/maraudon/boss_noxxion.cpp
@@ -0,0 +1,145 @@
+/* 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_Noxxion
+SD%Complete: 100
+SDComment:
+SDCategory: Maraudon
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_TOXICVOLLEY 21687
+#define SPELL_UPPERCUT 22916
+
+struct MANGOS_DLL_DECL boss_noxxionAI : public ScriptedAI
+{
+ boss_noxxionAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 ToxicVolley_Timer;
+ uint32 Uppercut_Timer;
+ uint32 Adds_Timer;
+ uint32 Invisible_Timer;
+ bool Invisible;
+ int Rand;
+ int RandX;
+ int RandY;
+ Creature* Summoned;
+
+ void Reset()
+ {
+ ToxicVolley_Timer = 7000;
+ Uppercut_Timer = 16000;
+ Adds_Timer = 19000;
+ Invisible_Timer = 15000; //Too much too low?
+ Invisible = false;
+ }
+
+ void SummonAdds(Unit* victim)
+ {
+ Rand = rand()%8;
+ switch(urand(0, 1))
+ {
+ case 0: RandX = 0 - Rand; break;
+ case 1: RandX = 0 + Rand; break;
+ }
+ Rand = 0;
+ Rand = rand()%8;
+ switch(urand(0, 1))
+ {
+ case 0: RandY = 0 - Rand; break;
+ case 1: RandY = 0 + Rand; break;
+ }
+ Rand = 0;
+ Summoned = DoSpawnCreature(13456, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 90000);
+ if (Summoned)
+ Summoned->AI()->AttackStart(victim);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (Invisible && Invisible_Timer < diff)
+ {
+ //Become visible again
+ m_creature->setFaction(14);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ //Noxxion model
+ m_creature->SetDisplayId(11172);
+ Invisible = false;
+ //m_creature->m_canMove = true;
+ } else if (Invisible)
+ {
+ Invisible_Timer -= diff;
+ //Do nothing while invisible
+ return;
+ }
+
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ToxicVolley_Timer
+ if (ToxicVolley_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_TOXICVOLLEY);
+ ToxicVolley_Timer = 9000;
+ }else ToxicVolley_Timer -= diff;
+
+ //Uppercut_Timer
+ if (Uppercut_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_UPPERCUT);
+ Uppercut_Timer = 12000;
+ }else Uppercut_Timer -= diff;
+
+ //Adds_Timer
+ if (!Invisible && Adds_Timer < diff)
+ {
+ //Inturrupt any spell casting
+ //m_creature->m_canMove = true;
+ m_creature->InterruptNonMeleeSpells(false);
+ m_creature->setFaction(35);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ // Invisible Model
+ m_creature->SetDisplayId(11686);
+ SummonAdds(m_creature->getVictim());
+ SummonAdds(m_creature->getVictim());
+ SummonAdds(m_creature->getVictim());
+ SummonAdds(m_creature->getVictim());
+ SummonAdds(m_creature->getVictim());
+ Invisible = true;
+ Invisible_Timer = 15000;
+
+ Adds_Timer = 40000;
+ }else Adds_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_noxxion(Creature* pCreature)
+{
+ return new boss_noxxionAI(pCreature);
+}
+
+void AddSC_boss_noxxion()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_noxxion";
+ newscript->GetAI = &GetAI_boss_noxxion;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/maraudon/boss_princess_theradras.cpp b/scripts/kalimdor/maraudon/boss_princess_theradras.cpp
new file mode 100644
index 0000000..2340082
--- /dev/null
+++ b/scripts/kalimdor/maraudon/boss_princess_theradras.cpp
@@ -0,0 +1,104 @@
+/* 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_Princess_Theradras
+SD%Complete: 100
+SDComment:
+SDCategory: Maraudon
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_DUSTFIELD 21909
+#define SPELL_BOULDER 21832
+#define SPELL_THRASH 3391
+#define SPELL_REPULSIVEGAZE 21869
+
+struct MANGOS_DLL_DECL boss_ptheradrasAI : public ScriptedAI
+{
+ boss_ptheradrasAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Dustfield_Timer;
+ uint32 Boulder_Timer;
+ uint32 Thrash_Timer;
+ uint32 RepulsiveGaze_Timer;
+
+ void Reset()
+ {
+ Dustfield_Timer = 8000;
+ Boulder_Timer = 2000;
+ Thrash_Timer = 5000;
+ RepulsiveGaze_Timer = 23000;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ m_creature->SummonCreature(12238,28.067f, 61.875f, -123.405f, 4.67f, TEMPSUMMON_TIMED_DESPAWN, 600000);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Dustfield_Timer
+ if (Dustfield_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_DUSTFIELD);
+ Dustfield_Timer = 14000;
+ }else Dustfield_Timer -= diff;
+
+ //Boulder_Timer
+ if (Boulder_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target)
+ DoCastSpellIfCan(target,SPELL_BOULDER);
+ Boulder_Timer = 10000;
+ }else Boulder_Timer -= diff;
+
+ //RepulsiveGaze_Timer
+ if (RepulsiveGaze_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_REPULSIVEGAZE);
+ RepulsiveGaze_Timer = 20000;
+ }else RepulsiveGaze_Timer -= diff;
+
+ //Thrash_Timer
+ if (Thrash_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_THRASH);
+ Thrash_Timer = 18000;
+ }else Thrash_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_boss_ptheradras(Creature* pCreature)
+{
+ return new boss_ptheradrasAI(pCreature);
+}
+
+void AddSC_boss_ptheradras()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_princess_theradras";
+ newscript->GetAI = &GetAI_boss_ptheradras;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/moonglade.cpp b/scripts/kalimdor/moonglade.cpp
new file mode 100644
index 0000000..4f08965
--- /dev/null
+++ b/scripts/kalimdor/moonglade.cpp
@@ -0,0 +1,363 @@
+/* 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: Moonglade
+SD%Complete: 100
+SDComment: Quest support: 30, 272, 5929, 5930, 10965. Special Flight Paths for Druid class.
+SDCategory: Moonglade
+EndScriptData */
+
+/* ContentData
+npc_bunthen_plainswind
+npc_clintar_dw_spirit
+npc_great_bear_spirit
+npc_silva_filnaveth
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+#include "ObjectMgr.h"
+
+/*######
+## npc_bunthen_plainswind
+######*/
+
+enum
+{
+ QUEST_SEA_LION_HORDE = 30,
+ QUEST_SEA_LION_ALLY = 272,
+ TAXI_PATH_ID_ALLY = 315,
+ TAXI_PATH_ID_HORDE = 316
+};
+
+#define GOSSIP_ITEM_THUNDER "I'd like to fly to Thunder Bluff."
+#define GOSSIP_ITEM_AQ_END "Do you know where I can find Half Pendant of Aquatic Endurance?"
+
+bool GossipHello_npc_bunthen_plainswind(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->getClass() != CLASS_DRUID)
+ pPlayer->SEND_GOSSIP_MENU(4916, pCreature->GetGUID());
+ else if (pPlayer->GetTeam() != HORDE)
+ {
+ if (pPlayer->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+
+ pPlayer->SEND_GOSSIP_MENU(4917, pCreature->GetGUID());
+ }
+ else if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == HORDE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_THUNDER, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+
+ if (pPlayer->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_END, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+
+ pPlayer->SEND_GOSSIP_MENU(4918, pCreature->GetGUID());
+ }
+ return true;
+}
+
+bool GossipSelect_npc_bunthen_plainswind(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF + 1:
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == HORDE)
+ pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID_HORDE);
+
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 2:
+ pPlayer->SEND_GOSSIP_MENU(5373, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 3:
+ pPlayer->SEND_GOSSIP_MENU(5376, pCreature->GetGUID());
+ break;
+ }
+ return true;
+}
+
+/*####
+# npc_clintar_dw_spirit
+####*/
+
+enum
+{
+ SAY_START = -1000280,
+ SAY_AGGRO_1 = -1000281,
+ SAY_AGGRO_2 = -1000282,
+ SAY_RELIC1 = -1000283,
+ SAY_RELIC2 = -1000284,
+ SAY_RELIC3 = -1000285,
+ SAY_END = -1000286,
+
+ QUEST_MERE_DREAM = 10965,
+ SPELL_EMERALD_DREAM = 39601,
+ NPC_CLINTAR_DW_SPIRIT = 22916,
+ NPC_CLINTAR_SPIRIT = 22901,
+ NPC_ASPECT_OF_RAVEN = 22915,
+};
+
+struct MANGOS_DLL_DECL npc_clintar_dw_spiritAI : public npc_escortAI
+{
+ npc_clintar_dw_spiritAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void WaypointReached(uint32 i)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ //visual details here probably need refinement
+ switch(i)
+ {
+ case 0:
+ DoScriptText(SAY_START, m_creature, pPlayer);
+ break;
+ case 13:
+ m_creature->HandleEmote(EMOTE_STATE_USESTANDING_NOSHEATHE);
+ break;
+ case 14:
+ DoScriptText(SAY_RELIC1, m_creature, pPlayer);
+ break;
+ case 26:
+ m_creature->HandleEmote(EMOTE_STATE_USESTANDING_NOSHEATHE);
+ break;
+ case 27:
+ DoScriptText(SAY_RELIC2, m_creature, pPlayer);
+ break;
+ case 31:
+ m_creature->SummonCreature(NPC_ASPECT_OF_RAVEN, 7465.321f, -3088.515f, 429.006f, 5.550f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 10000);
+ break;
+ case 35:
+ m_creature->HandleEmote(EMOTE_STATE_USESTANDING_NOSHEATHE);
+ break;
+ case 36:
+ DoScriptText(SAY_RELIC3, m_creature, pPlayer);
+ break;
+ case 49:
+ DoScriptText(SAY_END, m_creature, pPlayer);
+ pPlayer->TalkedToCreature(m_creature->GetEntry(), m_creature->GetGUID());
+ break;
+ }
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(urand(0, 1) ? SAY_AGGRO_1 : SAY_AGGRO_2, m_creature);
+ }
+
+ void Reset()
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ return;
+
+ //m_creature are expected to always be spawned, but not visible for player
+ //spell casted from quest_template.SrcSpell require this to be this way
+ //we handle the triggered spell to get a "hook" to our guy so he can be escorted on quest accept
+
+ if (CreatureInfo const* pTemp = GetCreatureTemplateStore(m_creature->GetEntry()))
+ m_creature->SetDisplayId(Creature::ChooseDisplayId(pTemp));
+
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetVisibility(VISIBILITY_OFF);
+ }
+
+ //called only from EffectDummy
+ void DoStart(uint64 uiPlayerGuid)
+ {
+ //not the best way, maybe check in DummyEffect if this creature are "free" and not in escort.
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ return;
+
+ m_creature->SetVisibility(VISIBILITY_ON);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ Start(false, uiPlayerGuid);
+ }
+
+ void JustSummoned(Creature* summoned)
+ {
+ summoned->AI()->AttackStart(m_creature);
+ }
+};
+
+CreatureAI* GetAI_npc_clintar_dw_spirit(Creature* pCreature)
+{
+ return new npc_clintar_dw_spiritAI(pCreature);
+}
+
+//we expect this spell to be triggered from spell casted at questAccept
+bool EffectDummyCreature_npc_clintar_dw_spirit(Unit *pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature *pCreatureTarget)
+{
+ //always check spellid and effectindex
+ if (spellId == SPELL_EMERALD_DREAM && effIndex == EFFECT_INDEX_0)
+ {
+ if (pCaster->GetTypeId() != TYPEID_PLAYER || pCaster->HasAura(SPELL_EMERALD_DREAM))
+ return true;
+
+ if (pCreatureTarget->GetEntry() != NPC_CLINTAR_DW_SPIRIT)
+ return true;
+
+ if (CreatureInfo const* pTemp = GetCreatureTemplateStore(NPC_CLINTAR_SPIRIT))
+ pCreatureTarget->SetDisplayId(Creature::ChooseDisplayId(pTemp));
+ else
+ return true;
+
+ //done here, escort can start
+ if (npc_clintar_dw_spiritAI* pSpiritAI = dynamic_cast(pCreatureTarget->AI()))
+ pSpiritAI->DoStart(pCaster->GetGUID());
+
+ //always return true when we are handling this spell and effect
+ return true;
+ }
+ return true;
+}
+
+/*######
+## npc_great_bear_spirit
+######*/
+
+#define GOSSIP_BEAR1 "What do you represent, spirit?"
+#define GOSSIP_BEAR2 "I seek to understand the importance of strength of the body."
+#define GOSSIP_BEAR3 "I seek to understand the importance of strength of the heart."
+#define GOSSIP_BEAR4 "I have heard your words, Great Bear Spirit, and I understand. I now seek your blessings to fully learn the way of the Claw."
+
+bool GossipHello_npc_great_bear_spirit(Player* pPlayer, Creature* pCreature)
+{
+ //ally or horde quest
+ if (pPlayer->GetQuestStatus(5929) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestStatus(5930) == QUEST_STATUS_INCOMPLETE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+ pPlayer->SEND_GOSSIP_MENU(4719, pCreature->GetGUID());
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(4718, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_great_bear_spirit(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(4721, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(4733, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_BEAR4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->SEND_GOSSIP_MENU(4734, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 3:
+ pPlayer->SEND_GOSSIP_MENU(4735, pCreature->GetGUID());
+ if (pPlayer->GetQuestStatus(5929)==QUEST_STATUS_INCOMPLETE)
+ pPlayer->AreaExploredOrEventHappens(5929);
+ if (pPlayer->GetQuestStatus(5930)==QUEST_STATUS_INCOMPLETE)
+ pPlayer->AreaExploredOrEventHappens(5930);
+ break;
+ }
+ return true;
+}
+
+/*######
+## npc_silva_filnaveth
+######*/
+
+#define GOSSIP_ITEM_RUTHERAN "I'd like to fly to Rut'theran Village."
+#define GOSSIP_ITEM_AQ_AGI "Do you know where I can find Half Pendant of Aquatic Agility?"
+
+bool GossipHello_npc_silva_filnaveth(Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->getClass() != CLASS_DRUID)
+ pPlayer->SEND_GOSSIP_MENU(4913, pCreature->GetGUID());
+ else if (pPlayer->GetTeam() != ALLIANCE)
+ {
+ if (pPlayer->GetQuestStatus(QUEST_SEA_LION_HORDE) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+
+ pPlayer->SEND_GOSSIP_MENU(4915, pCreature->GetGUID());
+ }
+ else if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == ALLIANCE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTHERAN, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+
+ if (pPlayer->GetQuestStatus(QUEST_SEA_LION_ALLY) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_AQ_AGI, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+
+ pPlayer->SEND_GOSSIP_MENU(4914, pCreature->GetGUID());
+ }
+ return true;
+}
+
+bool GossipSelect_npc_silva_filnaveth(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF + 1:
+ pPlayer->CLOSE_GOSSIP_MENU();
+
+ if (pPlayer->getClass() == CLASS_DRUID && pPlayer->GetTeam() == ALLIANCE)
+ pPlayer->ActivateTaxiPathTo(TAXI_PATH_ID_ALLY);
+
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 2:
+ pPlayer->SEND_GOSSIP_MENU(5374, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 3:
+ pPlayer->SEND_GOSSIP_MENU(5375, pCreature->GetGUID());
+ break;
+ }
+ return true;
+}
+
+/*######
+##
+######*/
+
+void AddSC_moonglade()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_bunthen_plainswind";
+ newscript->pGossipHello = &GossipHello_npc_bunthen_plainswind;
+ newscript->pGossipSelect = &GossipSelect_npc_bunthen_plainswind;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_clintar_dw_spirit";
+ newscript->GetAI = &GetAI_npc_clintar_dw_spirit;
+ newscript->pEffectDummyCreature = &EffectDummyCreature_npc_clintar_dw_spirit;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_great_bear_spirit";
+ newscript->pGossipHello = &GossipHello_npc_great_bear_spirit;
+ newscript->pGossipSelect = &GossipSelect_npc_great_bear_spirit;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_silva_filnaveth";
+ newscript->pGossipHello = &GossipHello_npc_silva_filnaveth;
+ newscript->pGossipSelect = &GossipSelect_npc_silva_filnaveth;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/mulgore.cpp b/scripts/kalimdor/mulgore.cpp
new file mode 100644
index 0000000..ff4d119
--- /dev/null
+++ b/scripts/kalimdor/mulgore.cpp
@@ -0,0 +1,194 @@
+/* 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: Mulgore
+SD%Complete: 100
+SDComment: Quest support: 11129. Skorn Whitecloud: Just a story if not rewarded for quest
+SDCategory: Mulgore
+EndScriptData */
+
+/* ContentData
+npc_kyle_the_frenzied
+npc_skorn_whitecloud
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+# npc_kyle_the_frenzied
+######*/
+
+enum
+{
+ EMOTE_SEE_LUNCH = -1000340,
+ EMOTE_EAT_LUNCH = -1000341,
+ EMOTE_DANCE = -1000342,
+
+ SPELL_LUNCH = 42222,
+ NPC_KYLE_FRENZIED = 23616,
+ NPC_KYLE_FRIENDLY = 23622,
+ POINT_ID = 1
+};
+
+struct MANGOS_DLL_DECL npc_kyle_the_frenziedAI : public ScriptedAI
+{
+ npc_kyle_the_frenziedAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ bool m_bEvent;
+ bool m_bIsMovingToLunch;
+ uint64 m_uiPlayerGUID;
+ uint32 m_uiEventTimer;
+ uint8 m_uiEventPhase;
+
+ void Reset()
+ {
+ m_bEvent = false;
+ m_bIsMovingToLunch = false;
+ m_uiPlayerGUID = 0;
+ m_uiEventTimer = 5000;
+ m_uiEventPhase = 0;
+
+ if (m_creature->GetEntry() == NPC_KYLE_FRIENDLY)
+ m_creature->UpdateEntry(NPC_KYLE_FRENZIED);
+ }
+
+ void SpellHit(Unit* pCaster, SpellEntry const* pSpell)
+ {
+ if (!m_creature->getVictim() && !m_bEvent && pSpell->Id == SPELL_LUNCH)
+ {
+ if (pCaster->GetTypeId() == TYPEID_PLAYER)
+ m_uiPlayerGUID = pCaster->GetGUID();
+
+ if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
+ {
+ m_creature->GetMotionMaster()->MovementExpired();
+ m_creature->GetMotionMaster()->MoveIdle();
+ m_creature->StopMoving();
+ }
+
+ m_bEvent = true;
+ DoScriptText(EMOTE_SEE_LUNCH, m_creature);
+ m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_CREATURE_SPECIAL);
+ }
+ }
+
+ void MovementInform(uint32 uiType, uint32 uiPointId)
+ {
+ if (uiType != POINT_MOTION_TYPE || !m_bEvent)
+ return;
+
+ if (uiPointId == POINT_ID)
+ m_bIsMovingToLunch = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (m_bEvent)
+ {
+ if (m_bIsMovingToLunch)
+ return;
+
+ if (m_uiEventTimer < diff)
+ {
+ m_uiEventTimer = 5000;
+ ++m_uiEventPhase;
+
+ switch(m_uiEventPhase)
+ {
+ case 1:
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID))
+ {
+ if (GameObject* pGo = pPlayer->GetGameObject(SPELL_LUNCH))
+ {
+ m_bIsMovingToLunch = true;
+ m_creature->GetMotionMaster()->MovePoint(POINT_ID, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ());
+ }
+ }
+ break;
+ case 2:
+ DoScriptText(EMOTE_EAT_LUNCH, m_creature);
+ m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_USESTANDING);
+ break;
+ case 3:
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_uiPlayerGUID))
+ pPlayer->TalkedToCreature(m_creature->GetEntry(), m_creature->GetGUID());
+
+ m_creature->UpdateEntry(NPC_KYLE_FRIENDLY);
+ break;
+ case 4:
+ m_uiEventTimer = 30000;
+ DoScriptText(EMOTE_DANCE, m_creature);
+ m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_DANCESPECIAL);
+ break;
+ case 5:
+ m_creature->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_NONE);
+ Reset();
+ m_creature->GetMotionMaster()->Clear();
+ break;
+ }
+ }
+ else
+ m_uiEventTimer -= diff;
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_kyle_the_frenzied(Creature* pCreature)
+{
+ return new npc_kyle_the_frenziedAI(pCreature);
+}
+
+/*######
+# npc_skorn_whitecloud
+######*/
+
+bool GossipHello_npc_skorn_whitecloud(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (!pPlayer->GetQuestRewardStatus(770))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Tell me a story, Skorn.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(522, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_skorn_whitecloud(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF)
+ pPlayer->SEND_GOSSIP_MENU(523, pCreature->GetGUID());
+
+ return true;
+}
+
+void AddSC_mulgore()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_kyle_the_frenzied";
+ newscript->GetAI = &GetAI_npc_kyle_the_frenzied;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_skorn_whitecloud";
+ newscript->pGossipHello = &GossipHello_npc_skorn_whitecloud;
+ newscript->pGossipSelect = &GossipSelect_npc_skorn_whitecloud;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp b/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp
new file mode 100644
index 0000000..83e6b22
--- /dev/null
+++ b/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp
@@ -0,0 +1,544 @@
+/* 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_Onyxia
+SD%Complete: 70
+SDComment: Phase 3 need additional code. The spawning Whelps need GO-Support. Erruption needs GO-Support
+SDCategory: Onyxia's Lair
+EndScriptData */
+
+#include "precompiled.h"
+#include "onyxias_lair.h"
+
+enum
+{
+ SAY_AGGRO = -1249000,
+ SAY_KILL = -1249001,
+ SAY_PHASE_2_TRANS = -1249002,
+ SAY_PHASE_3_TRANS = -1249003,
+ EMOTE_BREATH = -1249004,
+
+ SPELL_WINGBUFFET = 18500,
+ SPELL_WINGBUFFET_H = 69293,
+ SPELL_FLAMEBREATH = 18435,
+ SPELL_FLAMEBREATH_H = 68970,
+ SPELL_CLEAVE = 68868,
+ SPELL_TAILSWEEP = 68867,
+ SPELL_TAILSWEEP_H = 69286,
+ SPELL_KNOCK_AWAY = 19633,
+ SPELL_FIREBALL = 18392,
+ SPELL_FIREBALL_H = 68926,
+ SPELL_ERRUPTION = 17731, // does not work
+ SPELL_ERRUPTION_H = 69294, // does not work
+
+ //Not much choise about these. We have to make own defintion on the direction/start-end point
+ SPELL_BREATH_NORTH_TO_SOUTH = 17086, // 20x in "array"
+ SPELL_BREATH_SOUTH_TO_NORTH = 18351, // 11x in "array"
+
+ SPELL_BREATH_EAST_TO_WEST = 18576, // 7x in "array"
+ SPELL_BREATH_WEST_TO_EAST = 18609, // 7x in "array"
+
+ SPELL_BREATH_SE_TO_NW = 18564, // 12x in "array"
+ SPELL_BREATH_NW_TO_SE = 18584, // 12x in "array"
+ SPELL_BREATH_SW_TO_NE = 18596, // 12x in "array"
+ SPELL_BREATH_NE_TO_SW = 18617, // 12x in "array"
+
+ //SPELL_BREATH = 21131, // 8x in "array", different initial cast than the other arrays
+
+ SPELL_BELLOWINGROAR = 18431,
+ SPELL_HEATED_GROUND = 22191, // TODO
+
+ SPELL_SUMMONWHELP = 17646, // TODO this spell is only a summon spell, but would need a spell to activate the eggs
+ SPELL_SUMMON_LAIR_GUARD = 68968,
+
+ MAX_WHELPS_PER_PACK = 40,
+ NPC_WHELP = 11262,
+
+ PHASE_START = 1,
+ PHASE_BREATH = 2,
+ PHASE_END = 3,
+ PHASE_BREATH_PRE = 4,
+ PHASE_BREATH_POST = 5
+};
+
+struct sOnyxMove
+{
+ uint32 uiLocId;
+ uint32 uiLocIdEnd;
+ uint32 uiSpellId;
+ float fX, fY, fZ;
+};
+
+static sOnyxMove aMoveData[]=
+{
+ {0, 4, SPELL_BREATH_NORTH_TO_SOUTH, 22.8763f, -217.152f, -60.0548f}, //north
+ {1, 5, SPELL_BREATH_NE_TO_SW, 10.2191f, -247.912f, -60.896f}, //north-east
+ {2, 6, SPELL_BREATH_EAST_TO_WEST, -31.4963f, -250.123f, -60.1278f}, //east
+ {3, 7, SPELL_BREATH_SE_TO_NW, -63.5156f, -240.096f, -60.477f}, //south-east
+ {4, 0, SPELL_BREATH_SOUTH_TO_NORTH, -65.8444f, -213.809f, -60.2985f}, //south
+ {5, 1, SPELL_BREATH_SW_TO_NE, -58.2509f, -189.020f, -60.790f}, //south-west
+ {6, 2, SPELL_BREATH_WEST_TO_EAST, -33.5561f, -182.682f, -60.9457f}, //west
+ {7, 3, SPELL_BREATH_NW_TO_SE, 6.8951f, -180.246f, -60.896f}, //north-west
+};
+
+static float afSpawnLocations[4][3]=
+{
+ {-30.127f, -254.463f, -89.440f}, // whelps
+ {-30.817f, -177.106f, -89.258f}, // whelps
+ {-126.57f, -214.609f, -71.446f} // guardians
+};
+
+struct MANGOS_DLL_DECL boss_onyxiaAI : public ScriptedAI
+{
+ boss_onyxiaAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (instance_onyxias_lair*)pCreature->GetInstanceData();
+ m_bIsRegularMode = pCreature->GetMap()->IsRegularDifficulty();
+ m_uiMaxBreathPositions = sizeof(aMoveData)/sizeof(sOnyxMove);
+ Reset();
+ }
+
+ bool m_bIsRegularMode;
+ instance_onyxias_lair* m_pInstance;
+
+ uint8 m_uiPhase;
+ uint8 m_uiMaxBreathPositions;
+
+ uint32 m_uiFlameBreathTimer;
+ uint32 m_uiCleaveTimer;
+ uint32 m_uiTailSweepTimer;
+ uint32 m_uiWingBuffetTimer;
+
+ uint32 m_uiMovePoint;
+ uint32 m_uiMovementTimer;
+ sOnyxMove* m_pPointData;
+
+ uint32 m_uiFireballTimer;
+ uint32 m_uiSummonWhelpsTimer;
+ uint32 m_uiBellowingRoarTimer;
+ uint32 m_uiWhelpTimer;
+ uint32 m_uiSummonGuardTimer;
+
+ uint8 m_uiSummonCount;
+
+ bool m_bIsSummoningWhelps;
+
+ void Reset()
+ {
+ if (!IsCombatMovement())
+ SetCombatMovement(true);
+
+ m_uiPhase = PHASE_START;
+
+ m_uiFlameBreathTimer = urand(10000, 20000);
+ m_uiTailSweepTimer = urand(15000, 20000);
+ m_uiCleaveTimer = urand(2000, 5000);
+ m_uiWingBuffetTimer = urand(10000, 20000);
+
+ m_uiMovePoint = urand(0, m_uiMaxBreathPositions - 1);
+ m_uiMovementTimer = 20000;
+ m_pPointData = GetMoveData();
+
+ m_uiFireballTimer = 15000;
+ m_uiSummonWhelpsTimer = 15000;
+ m_uiBellowingRoarTimer = 2000; // Immediately after landing
+ m_uiWhelpTimer = 1000;
+ m_uiSummonGuardTimer = 15000;
+
+ m_uiSummonCount = 0;
+
+ m_bIsSummoningWhelps = false;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ m_creature->SetInCombatWithZone();
+ }
+
+ void JustReachedHome()
+ {
+ // in case evade in phase 2, see comments for hack where phase 2 is set
+ m_creature->RemoveSplineFlag(SPLINEFLAG_FLYING);
+ m_creature->SetByteFlag(UNIT_FIELD_BYTES_1, 3, 0);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->GetMotionMaster()->MovePoint(0, afSpawnLocations[3][0], afSpawnLocations[3][1], afSpawnLocations[3][2]);
+ pSummoned->SetInCombatWithZone();
+
+ if (pSummoned->GetEntry() == NPC_WHELP)
+ ++m_uiSummonCount;
+ }
+
+ void KilledUnit(Unit* pVictim)
+ {
+ DoScriptText(SAY_KILL, m_creature);
+ }
+
+ void SpellHit(Unit* pCaster, const SpellEntry* pSpell)
+ {
+ if (pSpell->Id == SPELL_BREATH_EAST_TO_WEST ||
+ pSpell->Id == SPELL_BREATH_WEST_TO_EAST ||
+ pSpell->Id == SPELL_BREATH_SE_TO_NW ||
+ pSpell->Id == SPELL_BREATH_NW_TO_SE ||
+ pSpell->Id == SPELL_BREATH_SW_TO_NE ||
+ pSpell->Id == SPELL_BREATH_NE_TO_SW ||
+ pSpell->Id == SPELL_BREATH_SOUTH_TO_NORTH ||
+ pSpell->Id == SPELL_BREATH_NORTH_TO_SOUTH)
+ {
+ if (m_pPointData = GetMoveData())
+ {
+ if (!m_pInstance)
+ return;
+
+ if (Creature* pTrigger = m_pInstance->instance->GetCreature(m_pInstance->GetOnyxiaTriggerGUID()))
+ {
+ m_creature->GetMap()->CreatureRelocation(m_creature, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ, m_creature->GetAngle(pTrigger));
+ m_creature->SendMonsterMove(m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ, SPLINETYPE_FACINGTARGET, m_creature->GetSplineFlags(), 1, NULL, pTrigger->GetGUID());
+ }
+ }
+ }
+ }
+
+ sOnyxMove* GetMoveData()
+ {
+ for (uint32 i = 0; i < m_uiMaxBreathPositions; ++i)
+ {
+ if (aMoveData[i].uiLocId == m_uiMovePoint)
+ return &aMoveData[i];
+ }
+
+ return NULL;
+ }
+
+ void MovementInform(uint32 uiMoveType, uint32 uiPointId)
+ {
+ if (uiMoveType != POINT_MOTION_TYPE || !m_pInstance)
+ return;
+
+ if (m_uiPhase == PHASE_BREATH)
+ {
+ if (Creature* pTrigger = m_pInstance->instance->GetCreature(m_pInstance->GetOnyxiaTriggerGUID()))
+ m_creature->SetFacingToObject(pTrigger);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ switch (m_uiPhase)
+ {
+ case PHASE_END: // Here is room for additional summoned whelps and Erruption
+ if (m_uiBellowingRoarTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_BELLOWINGROAR) == CAST_OK)
+ m_uiBellowingRoarTimer = 30000;
+ }
+ else
+ m_uiBellowingRoarTimer -= uiDiff;
+ // no break, phase 3 will use same abilities as in 1
+ case PHASE_START:
+ {
+ if (m_uiFlameBreathTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature->getVictim(), m_bIsRegularMode ? SPELL_FLAMEBREATH : SPELL_FLAMEBREATH_H) == CAST_OK)
+ m_uiFlameBreathTimer = urand(10000, 20000);
+ }
+ else
+ m_uiFlameBreathTimer -= uiDiff;
+
+ if (m_uiTailSweepTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_TAILSWEEP : SPELL_TAILSWEEP_H) == CAST_OK)
+ m_uiTailSweepTimer = urand(15000, 20000);
+ }
+ else
+ m_uiTailSweepTimer -= uiDiff;
+
+ if (m_uiCleaveTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK)
+ m_uiCleaveTimer = urand(2000, 5000);
+ }
+ else
+ m_uiCleaveTimer -= uiDiff;
+
+ if (m_uiWingBuffetTimer < uiDiff)
+ {
+ if (DoCastSpellIfCan(m_creature, m_bIsRegularMode ? SPELL_WINGBUFFET : SPELL_WINGBUFFET_H) == CAST_OK)
+ m_uiWingBuffetTimer = urand(15000, 30000);
+ }
+ else
+ m_uiWingBuffetTimer -= uiDiff;
+
+ if (m_uiPhase == PHASE_START && m_creature->GetHealthPercent() < 65.0f)
+ {
+ m_uiPhase = PHASE_BREATH;
+
+ SetCombatMovement(false);
+ m_creature->GetMotionMaster()->MoveIdle();
+
+ DoScriptText(SAY_PHASE_2_TRANS, m_creature);
+
+ // sort of a hack, it is unclear how this really work but the values appear to be valid
+ m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_UNK_2);
+ m_creature->AddSplineFlag(SPLINEFLAG_FLYING);
+
+ if (m_pPointData)
+ m_creature->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ);
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ break;
+ }
+ case PHASE_BREATH:
+ {
+ if (m_creature->GetHealthPercent() < 40.0f)
+ {
+ m_uiPhase = PHASE_END;
+ DoScriptText(SAY_PHASE_3_TRANS, m_creature);
+
+ // undo flying
+ m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0);
+ m_creature->RemoveSplineFlag(SPLINEFLAG_FLYING);
+
+ SetCombatMovement(true);
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
+ return;
+ }
+
+ if (m_uiMovementTimer < uiDiff)
+ {
+ m_uiMovementTimer = 25000;
+
+ // 3 possible actions
+ switch(urand(0, 2))
+ {
+ case 0: // breath
+ if (m_pPointData = GetMoveData())
+ {
+ DoScriptText(EMOTE_BREATH, m_creature);
+ DoCastSpellIfCan(m_creature, m_pPointData->uiSpellId, CAST_INTERRUPT_PREVIOUS);
+ m_uiMovePoint = m_pPointData->uiLocIdEnd;
+ }
+ return;
+ case 1: // a point on the left side
+ {
+ // C++ is stupid, so add -1 with +7
+ m_uiMovePoint += m_uiMaxBreathPositions - 1;
+ m_uiMovePoint %= m_uiMaxBreathPositions;
+ break;
+ }
+ case 2: // a point on the right side
+ ++m_uiMovePoint %= m_uiMaxBreathPositions;
+ break;
+ }
+
+ if (m_pPointData = GetMoveData())
+ m_creature->GetMotionMaster()->MovePoint(m_pPointData->uiLocId, m_pPointData->fX, m_pPointData->fY, m_pPointData->fZ);
+ }
+ else
+ m_uiMovementTimer -= uiDiff;
+
+ if (m_uiFireballTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ if (DoCastSpellIfCan(pTarget, m_bIsRegularMode ? SPELL_FIREBALL : SPELL_FIREBALL_H) == CAST_OK)
+ m_uiFireballTimer = 8000;
+ }
+ }
+ else
+ m_uiFireballTimer -= uiDiff; //engulfingflames is supposed to be activated by a fireball but haven't come by
+
+ if (m_bIsSummoningWhelps)
+ {
+ if (m_uiSummonCount < MAX_WHELPS_PER_PACK)
+ {
+ if (m_uiWhelpTimer < uiDiff)
+ {
+ m_creature->SummonCreature(NPC_WHELP, afSpawnLocations[0][0], afSpawnLocations[0][1], afSpawnLocations[0][2], 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
+ m_creature->SummonCreature(NPC_WHELP, afSpawnLocations[1][0], afSpawnLocations[1][1], afSpawnLocations[1][2], 0.0f, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
+ m_uiWhelpTimer = 500;
+ }
+ else
+ m_uiWhelpTimer -= uiDiff;
+ }
+ else
+ {
+ m_bIsSummoningWhelps = false;
+ m_uiSummonCount = 0;
+ m_uiSummonWhelpsTimer = 80000; // 90s -10s for summoning
+ }
+ }
+ else
+ {
+ if (m_uiSummonWhelpsTimer < uiDiff)
+ m_bIsSummoningWhelps = true;
+ else
+ m_uiSummonWhelpsTimer -= uiDiff;
+ }
+
+ if (m_uiSummonGuardTimer < uiDiff)
+ {
+ if (!m_creature->IsNonMeleeSpellCasted(false))
+ {
+ m_creature->CastSpell(afSpawnLocations[2][0], afSpawnLocations[2][1], afSpawnLocations[2][2], SPELL_SUMMON_LAIR_GUARD, true);
+ m_uiSummonGuardTimer = 30000;
+ }
+ }
+ else
+ m_uiSummonGuardTimer -= uiDiff;
+
+ break;
+ }
+ }
+ }
+};
+
+CreatureAI* GetAI_boss_onyxia(Creature* pCreature)
+{
+ return new boss_onyxiaAI(pCreature);
+}
+
+void AddSC_boss_onyxia()
+{
+ Script* pNewScript;
+ pNewScript = new Script;
+ pNewScript->Name = "boss_onyxia";
+ pNewScript->GetAI = &GetAI_boss_onyxia;
+ pNewScript->RegisterSelf();
+}
+
+/*
+-- SPELL_BREATH_EAST_TO_WEST
+DELETE FROM spell_target_position WHERE id IN (18576, 18578, 18579, 18580, 18581, 18582, 18583);
+INSERT INTO spell_target_position VALUES (18576, 249, -37.743851, -243.667923, -88.217651, 1.416);
+INSERT INTO spell_target_position VALUES (18578, 249, -35.805332, -232.028900, -87.749153, 1.416);
+INSERT INTO spell_target_position VALUES (18579, 249, -34.045738, -224.714661, -85.529465, 1.416);
+INSERT INTO spell_target_position VALUES (18580, 249, -32.081570, -214.916962, -88.327438, 1.416);
+INSERT INTO spell_target_position VALUES (18581, 249, -36.611721, -202.684677, -85.653786, 1.416);
+INSERT INTO spell_target_position VALUES (18582, 249, -37.067261, -195.758652, -87.745834, 1.416);
+INSERT INTO spell_target_position VALUES (18583, 249, -37.728523, -188.616806, -88.074898, 1.416);
+-- SPELL_BREATH_WEST_TO_EAST
+DELETE FROM spell_target_position WHERE id IN (18609, 18611, 18612, 18613, 18614, 18615, 18616);
+INSERT INTO spell_target_position VALUES (18609, 249, -37.728523, -188.616806, -88.074898, 4.526);
+INSERT INTO spell_target_position VALUES (18611, 249, -37.067261, -195.758652, -87.745834, 4.526);
+INSERT INTO spell_target_position VALUES (18612, 249, -36.611721, -202.684677, -85.653786, 4.526);
+INSERT INTO spell_target_position VALUES (18613, 249, -32.081570, -214.916962, -88.327438, 4.526);
+INSERT INTO spell_target_position VALUES (18614, 249, -34.045738, -224.714661, -85.529465, 4.526);
+INSERT INTO spell_target_position VALUES (18615, 249, -35.805332, -232.028900, -87.749153, 4.526);
+INSERT INTO spell_target_position VALUES (18616, 249, -37.743851, -243.667923, -88.217651, 4.526);
+-- SPELL_BREATH_NW_TO_SE
+DELETE FROM spell_target_position WHERE id IN (18584, 18585, 18586, 18587, 18588, 18589, 18590, 18591, 18592, 18593, 18594, 18595);
+INSERT INTO spell_target_position VALUES (18584, 249, 6.016711, -181.305771, -85.654648, 3.776);
+INSERT INTO spell_target_position VALUES (18585, 249, 3.860220, -183.227249, -86.375381, 3.776);
+INSERT INTO spell_target_position VALUES (18586, 249, -2.529650, -188.690491, -87.172859, 3.776);
+INSERT INTO spell_target_position VALUES (18587, 249, -8.449303, -193.957962, -87.564957, 3.776);
+INSERT INTO spell_target_position VALUES (18588, 249, -14.321238, -199.462219, -87.922478, 3.776);
+INSERT INTO spell_target_position VALUES (18589, 249, -15.602085, -216.893936, -88.403183, 3.776);
+INSERT INTO spell_target_position VALUES (18590, 249, -23.650263, -221.969086, -89.172699, 3.776);
+INSERT INTO spell_target_position VALUES (18591, 249, -29.495876, -213.014359, -88.910423, 3.776);
+INSERT INTO spell_target_position VALUES (18592, 249, -35.439922, -217.260284, -87.336311, 3.776);
+INSERT INTO spell_target_position VALUES (18593, 249, -41.762104, -221.896545, -86.114113, 3.776);
+INSERT INTO spell_target_position VALUES (18594, 249, -51.067528, -228.909988, -85.765556, 3.776);
+INSERT INTO spell_target_position VALUES (18595, 249, -56.559654, -241.223923, -85.423607, 3.776);
+-- SPELL_BREATH_SE_TO_NW
+DELETE FROM spell_target_position WHERE id IN (18564, 18565, 18566, 18567, 18568, 18569, 18570, 18571, 18572, 18573, 18574, 18575);
+INSERT INTO spell_target_position VALUES (18564, 249, -56.559654, -241.223923, -85.423607, 0.666);
+INSERT INTO spell_target_position VALUES (18565, 249, -51.067528, -228.909988, -85.765556, 0.666);
+INSERT INTO spell_target_position VALUES (18566, 249, -41.762104, -221.896545, -86.114113, 0.666);
+INSERT INTO spell_target_position VALUES (18567, 249, -35.439922, -217.260284, -87.336311, 0.666);
+INSERT INTO spell_target_position VALUES (18568, 249, -29.495876, -213.014359, -88.910423, 0.666);
+INSERT INTO spell_target_position VALUES (18569, 249, -23.650263, -221.969086, -89.172699, 0.666);
+INSERT INTO spell_target_position VALUES (18570, 249, -15.602085, -216.893936, -88.403183, 0.666);
+INSERT INTO spell_target_position VALUES (18571, 249, -14.321238, -199.462219, -87.922478, 0.666);
+INSERT INTO spell_target_position VALUES (18572, 249, -8.449303, -193.957962, -87.564957, 0.666);
+INSERT INTO spell_target_position VALUES (18573, 249, -2.529650, -188.690491, -87.172859, 0.666);
+INSERT INTO spell_target_position VALUES (18574, 249, 3.860220, -183.227249, -86.375381, 0.666);
+INSERT INTO spell_target_position VALUES (18575, 249, 6.016711, -181.305771, -85.654648, 0.666);
+-- SPELL_BREATH_SW_TO_NE
+DELETE FROM spell_target_position WHERE id IN (18596, 18597, 18598, 18599, 18600, 18601, 18602, 18603, 18604, 18605, 18606, 18607);
+INSERT INTO spell_target_position VALUES (18596, 249, -58.250900, -189.020004, -85.292267, 5.587);
+INSERT INTO spell_target_position VALUES (18597, 249, -52.006271, -193.796570, -85.808769, 5.587);
+INSERT INTO spell_target_position VALUES (18598, 249, -46.135464, -198.548553, -85.901764, 5.587);
+INSERT INTO spell_target_position VALUES (18599, 249, -40.500187, -203.001053, -85.555107, 5.587);
+INSERT INTO spell_target_position VALUES (18600, 249, -30.907579, -211.058197, -88.592125, 5.587);
+INSERT INTO spell_target_position VALUES (18601, 249, -20.098139, -218.681427, -88.937088, 5.587);
+INSERT INTO spell_target_position VALUES (18602, 249, -12.223192, -224.666168, -87.856300, 5.587);
+INSERT INTO spell_target_position VALUES (18603, 249, -6.475297, -229.098724, -87.076401, 5.587);
+INSERT INTO spell_target_position VALUES (18604, 249, -2.010256, -232.541992, -86.995140, 5.587);
+INSERT INTO spell_target_position VALUES (18605, 249, 2.736300, -236.202347, -86.790367, 5.587);
+INSERT INTO spell_target_position VALUES (18606, 249, 7.197779, -239.642868, -86.307297, 5.587);
+INSERT INTO spell_target_position VALUES (18607, 249, 12.120926, -243.439407, -85.874260, 5.587);
+-- SPELL_BREATH_NE_TO_SW
+DELETE FROM spell_target_position WHERE id IN (18617, 18619, 18620, 18621, 18622, 18623, 18624, 18625, 18626, 18627, 18628, 18618);
+INSERT INTO spell_target_position VALUES (18617, 249, 12.120926, -243.439407, -85.874260, 2.428);
+INSERT INTO spell_target_position VALUES (18619, 249, 7.197779, -239.642868, -86.307297, 2.428);
+INSERT INTO spell_target_position VALUES (18620, 249, 2.736300, -236.202347, -86.790367, 2.428);
+INSERT INTO spell_target_position VALUES (18621, 249, -2.010256, -232.541992, -86.995140, 2.428);
+INSERT INTO spell_target_position VALUES (18622, 249, -6.475297, -229.098724, -87.076401, 2.428);
+INSERT INTO spell_target_position VALUES (18623, 249, -12.223192, -224.666168, -87.856300, 2.428);
+INSERT INTO spell_target_position VALUES (18624, 249, -20.098139, -218.681427, -88.937088, 2.428);
+INSERT INTO spell_target_position VALUES (18625, 249, -30.907579, -211.058197, -88.592125, 2.428);
+INSERT INTO spell_target_position VALUES (18626, 249, -40.500187, -203.001053, -85.555107, 2.428);
+INSERT INTO spell_target_position VALUES (18627, 249, -46.135464, -198.548553, -85.901764, 2.428);
+INSERT INTO spell_target_position VALUES (18628, 249, -52.006271, -193.796570, -85.808769, 2.428);
+INSERT INTO spell_target_position VALUES (18618, 249, -58.250900, -189.020004, -85.292267, 2.428);
+
+-- SPELL_BREATH_SOUTH_TO_NORTH
+DELETE FROM spell_target_position WHERE id IN (18351, 18352, 18353, 18354, 18355, 18356, 18357, 18358, 18359, 18360, 18361);
+INSERT INTO spell_target_position VALUES (18351, 249, -68.834236, -215.036163, -84.018875, 6.280);
+INSERT INTO spell_target_position VALUES (18352, 249, -61.834255, -215.051910, -84.673416, 6.280);
+INSERT INTO spell_target_position VALUES (18353, 249, -53.343277, -215.071014, -85.597191, 6.280);
+INSERT INTO spell_target_position VALUES (18354, 249, -42.619305, -215.095139, -86.663605, 6.280);
+INSERT INTO spell_target_position VALUES (18355, 249, -35.899323, -215.110245, -87.196548, 6.280);
+INSERT INTO spell_target_position VALUES (18356, 249, -28.248341, -215.127457, -89.191750, 6.280);
+INSERT INTO spell_target_position VALUES (18357, 249, -20.324360, -215.145279, -88.963997, 6.280);
+INSERT INTO spell_target_position VALUES (18358, 249, -11.189384, -215.165833, -87.817093, 6.280);
+INSERT INTO spell_target_position VALUES (18359, 249, -2.047405, -215.186386, -86.279655, 6.280);
+INSERT INTO spell_target_position VALUES (18360, 249, 7.479571, -215.207809, -86.075531, 6.280);
+INSERT INTO spell_target_position VALUES (18361, 249, 20.730539, -215.237610, -85.254387, 6.280);
+-- SPELL_BREATH_NORTH_TO_SOUTH
+DELETE FROM spell_target_position WHERE id IN (17086, 17087, 17088, 17089, 17090, 17091, 17092, 17093, 17094, 17095, 17097, 22267, 22268, 21132, 21133, 21135, 21136, 21137, 21138, 21139);
+INSERT INTO spell_target_position VALUES (17086, 249, 20.730539, -215.237610, -85.254387, 3.142);
+INSERT INTO spell_target_position VALUES (17087, 249, 7.479571, -215.207809, -86.075531, 3.142);
+INSERT INTO spell_target_position VALUES (17088, 249, -2.047405, -215.186386, -86.279655, 3.142);
+INSERT INTO spell_target_position VALUES (17089, 249, -11.189384, -215.165833, -87.817093, 3.142);
+INSERT INTO spell_target_position VALUES (17090, 249, -20.324360, -215.145279, -88.963997, 3.142);
+INSERT INTO spell_target_position VALUES (17091, 249, -28.248341, -215.127457, -89.191750, 3.142);
+INSERT INTO spell_target_position VALUES (17092, 249, -35.899323, -215.110245, -87.196548, 3.142);
+INSERT INTO spell_target_position VALUES (17093, 249, -42.619305, -215.095139, -86.663605, 3.142);
+INSERT INTO spell_target_position VALUES (17094, 249, -53.343277, -215.071014, -85.597191, 3.142);
+INSERT INTO spell_target_position VALUES (17095, 249, -61.834255, -215.051910, -84.673416, 3.142);
+INSERT INTO spell_target_position VALUES (17097, 249, -68.834236, -215.036163, -84.018875, 3.142);
+INSERT INTO spell_target_position VALUES (22267, 249, -75.736046, -214.984970, -83.394188, 3.142);
+INSERT INTO spell_target_position VALUES (22268, 249, -84.087578, -214.857834, -82.640053, 3.142);
+INSERT INTO spell_target_position VALUES (21132, 249, -90.424416, -214.601974, -82.482697, 3.142);
+INSERT INTO spell_target_position VALUES (21133, 249, -96.572411, -214.353745, -82.239967, 3.142);
+INSERT INTO spell_target_position VALUES (21135, 249, -102.069931, -214.131775, -80.571190, 3.142);
+INSERT INTO spell_target_position VALUES (21136, 249, -107.385597, -213.917145, -77.447037, 3.142);
+INSERT INTO spell_target_position VALUES (21137, 249, -114.281258, -213.866486, -73.851128, 3.142);
+INSERT INTO spell_target_position VALUES (21138, 249, -123.328560, -213.607910, -71.559921, 3.142);
+INSERT INTO spell_target_position VALUES (21139, 249, -130.788300, -213.424026, -70.751007, 3.142);
+*/
diff --git a/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp b/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp
new file mode 100644
index 0000000..0aa3490
--- /dev/null
+++ b/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp
@@ -0,0 +1,60 @@
+/* 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_Onyxias_Lair
+SD%Complete: 50%
+SDComment:
+SDCategory: Onyxia's Lair
+EndScriptData */
+
+#include "precompiled.h"
+#include "onyxias_lair.h"
+
+instance_onyxias_lair::instance_onyxias_lair(Map* pMap) : ScriptedInstance(pMap),
+ m_uiOnyxTriggerGUID(0)
+{
+ Initialize();
+}
+
+void instance_onyxias_lair::Initialize()
+{
+}
+
+void instance_onyxias_lair::OnCreatureCreate(Creature* pCreature)
+{
+ switch(pCreature->GetEntry())
+ {
+ case NPC_ONYXIA_TRIGGER:
+ m_uiOnyxTriggerGUID = pCreature->GetGUID();
+ break;
+ }
+}
+
+InstanceData* GetInstanceData_instance_onyxias_lair(Map* pMap)
+{
+ return new instance_onyxias_lair(pMap);
+}
+
+void AddSC_instance_onyxias_lair()
+{
+ Script* pNewScript;
+
+ pNewScript = new Script;
+ pNewScript->Name = "instance_onyxias_lair";
+ pNewScript->GetInstanceData = &GetInstanceData_instance_onyxias_lair;
+ pNewScript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/onyxias_lair/onyxias_lair.h b/scripts/kalimdor/onyxias_lair/onyxias_lair.h
new file mode 100644
index 0000000..536fdcf
--- /dev/null
+++ b/scripts/kalimdor/onyxias_lair/onyxias_lair.h
@@ -0,0 +1,29 @@
+/* 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 */
+
+#ifndef DEF_ONYXIA_H
+#define DEF_ONYXIA_H
+
+enum
+{
+ NPC_ONYXIA_TRIGGER = 12758
+};
+
+class MANGOS_DLL_DECL instance_onyxias_lair : public ScriptedInstance
+{
+ public:
+ instance_onyxias_lair(Map* pMap);
+ ~instance_onyxias_lair() {}
+
+ void Initialize();
+
+ void OnCreatureCreate(Creature* pCreature);
+
+ uint64 GetOnyxiaTriggerGUID() { return m_uiOnyxTriggerGUID; }
+
+ protected:
+ uint64 m_uiOnyxTriggerGUID;
+};
+
+#endif
diff --git a/scripts/kalimdor/orgrimmar.cpp b/scripts/kalimdor/orgrimmar.cpp
new file mode 100644
index 0000000..8262621
--- /dev/null
+++ b/scripts/kalimdor/orgrimmar.cpp
@@ -0,0 +1,274 @@
+/* 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: Orgrimmar
+SD%Complete: 100
+SDComment: Quest support: 2460, 5727, 6566
+SDCategory: Orgrimmar
+EndScriptData */
+
+/* ContentData
+npc_neeru_fireblade npc_text + gossip options text missing
+npc_shenthul
+npc_thrall_warchief
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## npc_neeru_fireblade
+######*/
+
+#define QUEST_5727 5727
+
+bool GossipHello_npc_neeru_fireblade(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(QUEST_5727) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "You may speak frankly, Neeru...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(4513, pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_neeru_fireblade(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "[PH] ...", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(4513, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(QUEST_5727);
+ break;
+ }
+ return true;
+}
+
+/*######
+## npc_shenthul
+######*/
+
+enum
+{
+ QUEST_SHATTERED_SALUTE = 2460
+};
+
+struct MANGOS_DLL_DECL npc_shenthulAI : public ScriptedAI
+{
+ npc_shenthulAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ bool CanTalk;
+ bool CanEmote;
+ uint32 Salute_Timer;
+ uint32 Reset_Timer;
+ uint64 playerGUID;
+
+ void Reset()
+ {
+ CanTalk = false;
+ CanEmote = false;
+ Salute_Timer = 6000;
+ Reset_Timer = 0;
+ playerGUID = 0;
+ }
+
+ void ReceiveEmote(Player* pPlayer, uint32 emote)
+ {
+ if (emote == TEXTEMOTE_SALUTE && pPlayer->GetQuestStatus(QUEST_SHATTERED_SALUTE) == QUEST_STATUS_INCOMPLETE)
+ {
+ if (CanEmote)
+ {
+ pPlayer->AreaExploredOrEventHappens(QUEST_SHATTERED_SALUTE);
+ Reset();
+ }
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (CanEmote)
+ {
+ if (Reset_Timer < diff)
+ {
+ if (Player* pPlayer = m_creature->GetMap()->GetPlayer(playerGUID))
+ {
+ if (pPlayer->GetTypeId() == TYPEID_PLAYER && pPlayer->GetQuestStatus(QUEST_SHATTERED_SALUTE) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->FailQuest(QUEST_SHATTERED_SALUTE);
+ }
+ Reset();
+ } else Reset_Timer -= diff;
+ }
+
+ if (CanTalk && !CanEmote)
+ {
+ if (Salute_Timer < diff)
+ {
+ m_creature->HandleEmote(EMOTE_ONESHOT_SALUTE);
+ CanEmote = true;
+ Reset_Timer = 60000;
+ } else Salute_Timer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_shenthul(Creature* pCreature)
+{
+ return new npc_shenthulAI(pCreature);
+}
+
+bool QuestAccept_npc_shenthul(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_SHATTERED_SALUTE)
+ {
+ if (npc_shenthulAI* pShenAI = dynamic_cast(pCreature->AI()))
+ {
+ pShenAI->CanTalk = true;
+ pShenAI->playerGUID = pPlayer->GetGUID();
+ }
+ }
+ return true;
+}
+
+/*######
+## npc_thrall_warchief
+######*/
+
+#define QUEST_6566 6566
+
+#define SPELL_CHAIN_LIGHTNING 16033
+#define SPELL_SHOCK 16034
+
+//TODO: verify abilities/timers
+struct MANGOS_DLL_DECL npc_thrall_warchiefAI : public ScriptedAI
+{
+ npc_thrall_warchiefAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
+
+ uint32 ChainLightning_Timer;
+ uint32 Shock_Timer;
+
+ void Reset()
+ {
+ ChainLightning_Timer = 2000;
+ Shock_Timer = 8000;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (ChainLightning_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CHAIN_LIGHTNING);
+ ChainLightning_Timer = 9000;
+ }else ChainLightning_Timer -= diff;
+
+ if (Shock_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHOCK);
+ Shock_Timer = 15000;
+ }else Shock_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_npc_thrall_warchief(Creature* pCreature)
+{
+ return new npc_thrall_warchiefAI(pCreature);
+}
+
+bool GossipHello_npc_thrall_warchief(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(QUEST_6566) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Please share your wisdom with me, Warchief.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_thrall_warchief(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "What discoveries?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(5733, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Usurper?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->SEND_GOSSIP_MENU(5734, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "With all due respect, Warchief - why not allow them to be destroyed? Does this not strengthen our position?", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
+ pPlayer->SEND_GOSSIP_MENU(5735, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I... I did not think of it that way, Warchief.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(5736, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "I live only to serve, Warchief! My life is empty and meaningless without your guidance.", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
+ pPlayer->SEND_GOSSIP_MENU(5737, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+6:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Of course, Warchief!", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+7);
+ pPlayer->SEND_GOSSIP_MENU(5738, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+7:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(QUEST_6566);
+ break;
+ }
+ return true;
+}
+
+void AddSC_orgrimmar()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_neeru_fireblade";
+ newscript->pGossipHello = &GossipHello_npc_neeru_fireblade;
+ newscript->pGossipSelect = &GossipSelect_npc_neeru_fireblade;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_shenthul";
+ newscript->GetAI = &GetAI_npc_shenthul;
+ newscript->pQuestAccept = &QuestAccept_npc_shenthul;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_thrall_warchief";
+ newscript->GetAI = &GetAI_npc_thrall_warchief;
+ newscript->pGossipHello = &GossipHello_npc_thrall_warchief;
+ newscript->pGossipSelect = &GossipSelect_npc_thrall_warchief;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp b/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp
new file mode 100644
index 0000000..e6b32e0
--- /dev/null
+++ b/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp
@@ -0,0 +1,129 @@
+/* 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_Amnennar_the_coldbringer
+SD%Complete: 100
+SDComment:
+SDCategory: Razorfen Downs
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_AGGRO -1129000
+#define SAY_SUMMON60 -1129001
+#define SAY_SUMMON30 -1129002
+#define SAY_HP -1129003
+#define SAY_KILL -1129004
+
+#define SPELL_AMNENNARSWRATH 13009
+#define SPELL_FROSTBOLT 15530
+#define SPELL_FROST_NOVA 15531
+#define SPELL_FROST_SPECTRES 12642
+
+struct MANGOS_DLL_DECL boss_amnennar_the_coldbringerAI : public ScriptedAI
+{
+ boss_amnennar_the_coldbringerAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 AmnenarsWrath_Timer;
+ uint32 FrostBolt_Timer;
+ uint32 FrostNova_Timer;
+ bool Spectrals60;
+ bool Spectrals30;
+ bool Hp;
+
+ void Reset()
+ {
+ AmnenarsWrath_Timer = 8000;
+ FrostBolt_Timer = 1000;
+ FrostNova_Timer = urand(10000, 15000);
+ Spectrals30 = false;
+ Spectrals60 = false;
+ Hp = false;
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void KilledUnit()
+ {
+ DoScriptText(SAY_KILL, m_creature);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //AmnenarsWrath_Timer
+ if (AmnenarsWrath_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_AMNENNARSWRATH);
+ AmnenarsWrath_Timer = 12000;
+ } else AmnenarsWrath_Timer -= diff;
+
+ //FrostBolt_Timer
+ if (FrostBolt_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROSTBOLT);
+ FrostBolt_Timer = 8000;
+ } else FrostBolt_Timer -= diff;
+
+ if (FrostNova_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_FROST_NOVA);
+ FrostNova_Timer = 15000;
+ } else FrostNova_Timer -= diff;
+
+ if (!Spectrals60 && m_creature->GetHealthPercent() < 60.0f)
+ {
+ DoScriptText(SAY_SUMMON60, m_creature);
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROST_SPECTRES);
+ Spectrals60 = true;
+ }
+
+ if (!Hp && m_creature->GetHealthPercent() < 50.0f)
+ {
+ DoScriptText(SAY_HP, m_creature);
+ Hp = true;
+ }
+
+ if (!Spectrals30 && m_creature->GetHealthPercent() < 30.0f)
+ {
+ DoScriptText(SAY_SUMMON30, m_creature);
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROST_SPECTRES);
+ Spectrals30 = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_amnennar_the_coldbringer(Creature* pCreature)
+{
+ return new boss_amnennar_the_coldbringerAI(pCreature);
+}
+
+void AddSC_boss_amnennar_the_coldbringer()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_amnennar_the_coldbringer";
+ newscript->GetAI = &GetAI_boss_amnennar_the_coldbringer;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp b/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp
new file mode 100644
index 0000000..c36f862
--- /dev/null
+++ b/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp
@@ -0,0 +1,85 @@
+/* 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: Razorfen_Downs
+SD%Complete: 100
+SDComment: Support for Henry Stern(2 recipes)
+SDCategory: Razorfen Downs
+EndScriptData */
+
+/* ContentData
+npc_henry_stern
+EndContentData */
+
+#include "precompiled.h"
+
+/*###
+# npc_henry_stern
+####*/
+
+enum
+{
+ SPELL_GOLDTHORN_TEA = 13028,
+ SPELL_TEACHING_GOLDTHORN_TEA = 13029,
+ SPELL_MIGHT_TROLLS_BLOOD_POTION = 3451,
+ SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION = 13030,
+ GOSSIP_TEXT_TEA_ANSWER = 2114,
+ GOSSIP_TEXT_POTION_ANSWER = 2115,
+};
+
+#define GOSSIP_ITEM_TEA "Teach me the cooking recipe"
+#define GOSSIP_ITEM_POTION "Teach me the alchemy recipe"
+
+bool GossipHello_npc_henry_stern (Player* pPlayer, Creature* pCreature)
+{
+ if (pPlayer->GetBaseSkillValue(SKILL_COOKING) >= 175 && !pPlayer->HasSpell(SPELL_GOLDTHORN_TEA))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_TEA, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+
+ if (pPlayer->GetBaseSkillValue(SKILL_ALCHEMY) >= 180 && !pPlayer->HasSpell(SPELL_MIGHT_TROLLS_BLOOD_POTION))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_POTION, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+ return true;
+}
+
+bool GossipSelect_npc_henry_stern (Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
+ {
+ pCreature->CastSpell(pPlayer, SPELL_TEACHING_GOLDTHORN_TEA, true);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_TEA_ANSWER, pCreature->GetGUID());
+ }
+
+ if (uiAction == GOSSIP_ACTION_INFO_DEF + 2)
+ {
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_POTION_ANSWER, pCreature->GetGUID());
+ pCreature->CastSpell(pPlayer, SPELL_TEACHING_MIGHTY_TROLLS_BLOOD_POTION, true);
+ }
+
+ return true;
+}
+
+void AddSC_razorfen_downs()
+{
+ Script* newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_henry_stern";
+ newscript->pGossipHello = &GossipHello_npc_henry_stern;
+ newscript->pGossipSelect = &GossipSelect_npc_henry_stern;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp b/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp
new file mode 100644
index 0000000..b374941
--- /dev/null
+++ b/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp
@@ -0,0 +1,134 @@
+/* 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_razorfen_kraul
+SD%Complete: 50
+SDComment:
+SDCategory: Razorfen Kraul
+EndScriptData */
+
+#include "precompiled.h"
+#include "razorfen_kraul.h"
+
+instance_razorfen_kraul::instance_razorfen_kraul(Map* pMap) : ScriptedInstance(pMap),
+ m_uiAgathelosWardGUID(0),
+ m_uiWardKeepersRemaining(0)
+{
+ Initialize();
+}
+
+void instance_razorfen_kraul::Initialize()
+{
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+}
+
+void instance_razorfen_kraul::OnObjectCreate(GameObject* pGo)
+{
+ switch(pGo->GetEntry())
+ {
+ case GO_AGATHELOS_WARD:
+ m_uiAgathelosWardGUID = pGo->GetGUID();
+ if (m_auiEncounter[0] == DONE)
+ DoUseDoorOrButton(m_uiAgathelosWardGUID);
+ break;
+ }
+
+}
+
+void instance_razorfen_kraul::OnCreatureCreate(Creature* pCreature)
+{
+ switch(pCreature->GetEntry())
+ {
+ case NPC_WARD_KEEPER:
+ ++m_uiWardKeepersRemaining;
+ break;
+ }
+}
+
+void instance_razorfen_kraul::SetData(uint32 uiType, uint32 uiData)
+{
+ switch(uiType)
+ {
+ case TYPE_AGATHELOS:
+ --m_uiWardKeepersRemaining;
+ if (!m_uiWardKeepersRemaining)
+ {
+ m_auiEncounter[0] = uiData;
+ DoUseDoorOrButton(m_uiAgathelosWardGUID);
+ }
+ break;
+ }
+
+ if (uiData == DONE)
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+
+ saveStream << m_auiEncounter[0];
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+}
+
+void instance_razorfen_kraul::Load(const char* chrIn)
+{
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+ loadStream >> m_auiEncounter[0];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+}
+
+uint32 instance_razorfen_kraul::GetData(uint32 uiType)
+{
+ switch(uiType)
+ {
+ case TYPE_AGATHELOS:
+ return m_auiEncounter[0];
+ }
+ return 0;
+}
+
+InstanceData* GetInstanceData_instance_razorfen_kraul(Map* pMap)
+{
+ return new instance_razorfen_kraul(pMap);
+}
+
+void AddSC_instance_razorfen_kraul()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "instance_razorfen_kraul";
+ newscript->GetInstanceData = &GetInstanceData_instance_razorfen_kraul;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h b/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h
new file mode 100644
index 0000000..36378b5
--- /dev/null
+++ b/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h
@@ -0,0 +1,43 @@
+/* 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 */
+
+#ifndef DEF_RFK_H
+#define DEF_RFK_H
+
+enum
+{
+ MAX_ENCOUNTER = 1,
+
+ TYPE_AGATHELOS = 1,
+
+ GO_AGATHELOS_WARD = 21099,
+
+ NPC_WARD_KEEPER = 4625
+};
+
+class MANGOS_DLL_DECL instance_razorfen_kraul : public ScriptedInstance
+{
+ public:
+ instance_razorfen_kraul(Map* pMap);
+ ~instance_razorfen_kraul() {}
+
+ void Initialize();
+
+ void OnObjectCreate(GameObject* pGo);
+ void OnCreatureCreate(Creature* pCreature);
+
+ void SetData(uint32 uiType, uint32 uiData);
+ uint32 GetData(uint32 uiType);
+
+ const char* Save() { return strInstData.c_str(); }
+ void Load(const char* chrIn);
+
+ protected:
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+ std::string strInstData;
+
+ uint64 m_uiAgathelosWardGUID;
+ uint8 m_uiWardKeepersRemaining;
+};
+#endif
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp b/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp
new file mode 100644
index 0000000..4789b02
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.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: Boss_Ayamiss
+SD%Complete: 50
+SDComment: VERIFY SCRIPT
+SDCategory: Ruins of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+/*
+To do:
+make him fly from 70-100%
+*/
+
+enum
+{
+ SPELL_STINGERSPRAY = 25749,
+ SPELL_POISONSTINGER = 25748, //only used in phase1
+ SPELL_SUMMONSWARMER = 25844, //might be 25708
+ //SPELL_PARALYZE 23414 doesnt work correct (core)
+
+ PHASE_AIR = 0,
+ PHASE_GROUND = 1
+};
+
+struct MANGOS_DLL_DECL boss_ayamissAI : public ScriptedAI
+{
+ boss_ayamissAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiStingerSprayTimer;
+ uint32 m_uiPoisonStingerTimer;
+ uint32 m_uiSummonSwarmerTimer;
+ uint8 m_uiPhase;
+
+ void Reset()
+ {
+ m_uiStingerSprayTimer = 30000;
+ m_uiPoisonStingerTimer = 30000;
+ m_uiSummonSwarmerTimer = 60000;
+
+ m_uiPhase = PHASE_AIR;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Stinger Spray
+ if (m_uiStingerSprayTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_STINGERSPRAY);
+ m_uiStingerSprayTimer = 30000;
+ }
+ else
+ m_uiStingerSprayTimer -= uiDiff;
+
+ if (m_uiPhase == PHASE_AIR)
+ {
+ // Start ground phase at 70% of HP
+ if (m_creature->GetHealthPercent() <= 70.0f)
+ {
+ m_uiPhase = PHASE_GROUND;
+ DoResetThreat();
+ }
+
+ // Poison Stinger
+ if (m_uiPoisonStingerTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_POISONSTINGER);
+ m_uiPoisonStingerTimer = 30000;
+ }
+ else
+ m_uiPoisonStingerTimer -= uiDiff;
+ }
+ else
+ {
+ //m_uiSummonSwarmerTimer
+ if (m_uiSummonSwarmerTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUMMONSWARMER);
+ m_uiSummonSwarmerTimer = 60000;
+ }
+ else
+ m_uiSummonSwarmerTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+ }
+};
+CreatureAI* GetAI_boss_ayamiss(Creature* pCreature)
+{
+ return new boss_ayamissAI(pCreature);
+}
+
+void AddSC_boss_ayamiss()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_ayamiss";
+ newscript->GetAI = &GetAI_boss_ayamiss;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp b/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp
new file mode 100644
index 0000000..8fe03e2
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp
@@ -0,0 +1,26 @@
+/* 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_Buru
+SD%Complete: 0
+SDComment: Place Holder
+SDCategory: Ruins of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+#define EMOTE_TARGET -1509002
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp b/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp
new file mode 100644
index 0000000..e258ddb
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp
@@ -0,0 +1,97 @@
+/* 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_Kurinnaxx
+SD%Complete: 100
+SDComment: VERIFY SCRIPT AND SQL
+SDCategory: Ruins of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ SPELL_TRASH = 3391,
+ SPELL_WIDE_SLASH = 25814,
+ SPELL_MORTAL_WOUND = 25646,
+ SPELL_SANDTRAP = 25656,
+ SPELL_ENRAGE = 28798
+};
+
+struct MANGOS_DLL_DECL boss_kurinnaxxAI : public ScriptedAI
+{
+ boss_kurinnaxxAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiMortalWoundTimer;
+ uint32 m_uiSandTrapTimer;
+ bool m_bEnraged;
+
+ void Reset()
+ {
+ m_bEnraged = false;
+
+ m_uiMortalWoundTimer = 30000;
+ m_uiSandTrapTimer = 30000;
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // If we are belowe 30% HP cast enrage
+ if (!m_bEnraged && m_creature->GetHealthPercent() <= 30.0f)
+ {
+ m_bEnraged = true;
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_ENRAGE);
+ }
+
+ // Mortal Wound
+ if (m_uiMortalWoundTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_WOUND);
+ m_uiMortalWoundTimer = 30000;
+ }
+ else
+ m_uiMortalWoundTimer -= uiDiff;
+
+ // Sand Trap
+ if (m_uiSandTrapTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SANDTRAP);
+ m_uiSandTrapTimer = 30000;
+ }
+ else
+ m_uiSandTrapTimer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_kurinnaxx(Creature* pCreature)
+{
+ return new boss_kurinnaxxAI(pCreature);
+}
+
+void AddSC_boss_kurinnaxx()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_kurinnaxx";
+ newscript->GetAI = &GetAI_boss_kurinnaxx;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp b/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp
new file mode 100644
index 0000000..724de86
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.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: Boss_Moam
+SD%Complete: 100
+SDComment:
+SDCategory: Ruins of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ EMOTE_AGGRO = -1509000,
+ EMOTE_MANA_FULL = -1509001,
+ EMOTE_ENERGIZING = -1509028,
+
+ SPELL_TRAMPLE = 15550,
+ SPELL_DRAIN_MANA = 25671,
+ SPELL_ARCANE_ERUPTION = 25672,
+ SPELL_SUMMON_MANAFIEND_1 = 25681,
+ SPELL_SUMMON_MANAFIEND_2 = 25682,
+ SPELL_SUMMON_MANAFIEND_3 = 25683,
+ SPELL_ENERGIZE = 25685,
+
+ PHASE_ATTACKING = 0,
+ PHASE_ENERGIZING = 1
+};
+
+struct MANGOS_DLL_DECL boss_moamAI : public ScriptedAI
+{
+ boss_moamAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint8 m_uiPhase;
+
+ uint32 m_uiTrample_Timer;
+ uint32 m_uiManaDrain_Timer;
+ uint32 m_uiCheckoutMana_Timer;
+ uint32 m_uiSummonManaFiends_Timer;
+
+ void Reset()
+ {
+ m_uiTrample_Timer = 9000;
+ m_uiManaDrain_Timer = 3000;
+ m_uiSummonManaFiends_Timer = 90000;
+ m_uiCheckoutMana_Timer = 1500;
+ m_uiPhase = PHASE_ATTACKING;
+ m_creature->SetPower(POWER_MANA, 0);
+ m_creature->SetMaxPower(POWER_MANA, 0);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoScriptText(EMOTE_AGGRO, m_creature);
+ m_creature->SetMaxPower(POWER_MANA, m_creature->GetCreatureInfo()->maxmana);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ switch(m_uiPhase)
+ {
+ case PHASE_ATTACKING:
+ if (m_uiCheckoutMana_Timer <= uiDiff)
+ {
+ m_uiCheckoutMana_Timer = 1500;
+ if (m_creature->GetPower(POWER_MANA) * 100 / m_creature->GetMaxPower(POWER_MANA) > 75.0f)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENERGIZE);
+ DoScriptText(EMOTE_ENERGIZING, m_creature);
+ m_uiPhase = PHASE_ENERGIZING;
+ return;
+ }
+ }
+ else
+ m_uiCheckoutMana_Timer -= uiDiff;
+
+ if (m_uiSummonManaFiends_Timer <= uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUMMON_MANAFIEND_1, CAST_TRIGGERED);
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUMMON_MANAFIEND_2, CAST_TRIGGERED);
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SUMMON_MANAFIEND_3, CAST_TRIGGERED);
+ m_uiSummonManaFiends_Timer = 90000;
+ }
+ else
+ m_uiSummonManaFiends_Timer -= uiDiff;
+
+ if (m_uiManaDrain_Timer <= uiDiff)
+ {
+ m_uiManaDrain_Timer = urand(2000, 6000);
+ // choose random target with mana
+ std::list lTargets;
+ ThreatList const& threatlist = m_creature->getThreatManager().getThreatList();
+ if (threatlist.empty())
+ return;
+
+ for (ThreatList::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
+
+ if (pUnit && pUnit->isAlive() && pUnit->GetPower(POWER_MANA))
+ lTargets.push_back(pUnit);
+ }
+
+ if (lTargets.empty())
+ return;
+
+ std::list::iterator itr = lTargets.begin();
+ std::advance(itr, urand(0, lTargets.size()-1));
+
+ DoCastSpellIfCan(*itr, SPELL_DRAIN_MANA);
+ }
+ else
+ m_uiManaDrain_Timer -= uiDiff;
+
+ if (m_uiTrample_Timer <= uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_TRAMPLE);
+ m_uiTrample_Timer = 15000;
+ }
+ else
+ m_uiTrample_Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ break;
+ case PHASE_ENERGIZING:
+ if (m_uiCheckoutMana_Timer <= uiDiff)
+ {
+ m_uiCheckoutMana_Timer = 1500;
+ if (m_creature->GetPower(POWER_MANA) == m_creature->GetMaxPower(POWER_MANA))
+ {
+ m_creature->RemoveAurasDueToSpell(SPELL_ENERGIZE);
+ DoCastSpellIfCan(m_creature, SPELL_ARCANE_ERUPTION);
+ DoScriptText(EMOTE_MANA_FULL, m_creature);
+ m_uiPhase = PHASE_ATTACKING;
+ return;
+ }
+ }
+ else
+ m_uiCheckoutMana_Timer -= uiDiff;
+ break;
+ }
+ }
+};
+
+CreatureAI* GetAI_boss_moam(Creature* pCreature)
+{
+ return new boss_moamAI(pCreature);
+}
+
+void AddSC_boss_moam()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_moam";
+ newscript->GetAI = &GetAI_boss_moam;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp b/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp
new file mode 100644
index 0000000..5e282f9
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp
@@ -0,0 +1,38 @@
+/* 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_Ossirian
+SD%Complete: 0
+SDComment: Place holder
+SDCategory: Ruins of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_SURPREME1 -1509018
+#define SAY_SURPREME2 -1509019
+#define SAY_SURPREME3 -1509020
+
+#define SAY_RAND_INTRO1 -1509021
+#define SAY_RAND_INTRO2 -1509022
+#define SAY_RAND_INTRO3 -1509023
+#define SAY_RAND_INTRO4 -1509024 //possibly old?
+
+#define SAY_AGGRO -1509025
+
+#define SAY_SLAY -1509026
+#define SAY_DEATH -1509027
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp b/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp
new file mode 100644
index 0000000..2fe293f
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp
@@ -0,0 +1,44 @@
+/* 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_Rajaxx
+SD%Complete: 0
+SDComment: Place Holder
+SDCategory: Ruins of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_ANDOROV_INTRO -1509003
+#define SAY_ANDOROV_ATTACK -1509004
+
+#define SAY_WAVE3 -1509005
+#define SAY_WAVE4 -1509006
+#define SAY_WAVE5 -1509007
+#define SAY_WAVE6 -1509008
+#define SAY_WAVE7 -1509009
+#define SAY_INTRO -1509010
+
+#define SAY_UNK1 -1509011
+#define SAY_UNK2 -1509012
+#define SAY_UNK3 -1509013
+#define SAY_UNK4 -1509014
+
+#define SAY_DEAGGRO -1509015
+#define SAY_KILLS_ANDOROV -1509016
+
+#define SAY_COMPLETE_QUEST -1509017 //Yell when realm complete quest 8743 for world event
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp b/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp
new file mode 100644
index 0000000..e033266
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp
@@ -0,0 +1,206 @@
+/* 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_Ruins_of_Ahnqiraj
+SD%Complete: 80
+SDComment:
+SDCategory: Ruins of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+#include "ruins_of_ahnqiraj.h"
+
+
+struct MANGOS_DLL_DECL instance_ruins_of_ahnqiraj : public ScriptedInstance
+{
+ instance_ruins_of_ahnqiraj(Map* pMap) : ScriptedInstance(pMap) {Initialize();}
+
+ std::string strInstData;
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ uint64 m_uiOssirianGUID;
+ uint64 m_uiBuruGUID;
+ uint64 m_uiKurinnaxxGUID;
+ uint64 m_uiAndorovGUID;
+ uint64 m_uiRajaxxGUID;
+ uint64 m_uiQeezGUID;
+ uint64 m_uiTuubidGUID;
+ uint64 m_uiDrennGUID;
+ uint64 m_uiXurremGUID;
+ uint64 m_uiYeggethGUID;
+ uint64 m_uiPakkonGUID;
+ uint64 m_uiZerranGUID;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiOssirianGUID = 0;
+ m_uiBuruGUID = 0;
+ m_uiKurinnaxxGUID = 0;
+ m_uiAndorovGUID = 0;
+ m_uiQeezGUID = 0;
+ m_uiTuubidGUID = 0;
+ m_uiDrennGUID = 0;
+ m_uiXurremGUID = 0;
+ m_uiYeggethGUID = 0;
+ m_uiPakkonGUID = 0;
+ m_uiZerranGUID = 0;
+ m_uiRajaxxGUID = 0;
+ }
+
+ void OnCreatureCreate(Creature* pCreature)
+ {
+ switch(pCreature->GetEntry())
+ {
+ case NPC_OSSIRIAN: m_uiOssirianGUID = pCreature->GetGUID(); break;
+ case NPC_BURU: m_uiBuruGUID = pCreature->GetGUID(); break;
+ case NPC_KURINNAXX: m_uiKurinnaxxGUID = pCreature->GetGUID(); break;
+ case NPC_GENERAL_ANDOROV: m_uiAndorovGUID = pCreature->GetGUID(); break;
+ case NPC_CAPTAIN_QEEZ: m_uiQeezGUID = pCreature->GetGUID(); break;
+ case NPC_CAPTAIN_TUUBID: m_uiTuubidGUID = pCreature->GetGUID(); break;
+ case NPC_CAPTAIN_DRENN: m_uiDrennGUID = pCreature->GetGUID(); break;
+ case NPC_CAPTAIN_XURREM: m_uiXurremGUID = pCreature->GetGUID(); break;
+ case NPC_MAJOR_YEGGETH: m_uiYeggethGUID = pCreature->GetGUID(); break;
+ case NPC_MAJOR_PAKKON: m_uiPakkonGUID = pCreature->GetGUID(); break;
+ case NPC_COLONEL_ZERRAN: m_uiZerranGUID = pCreature->GetGUID(); break;
+ case NPC_RAJAXX: m_uiRajaxxGUID = pCreature->GetGUID(); break;
+ }
+ }
+
+ void OnObjectCreate(GameObject* pGo)
+ {
+ switch(pGo->GetEntry())
+ {
+ case GO_OSSIRIAN_CRYSTAL: pGo->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_INTERACT_COND); break; //to make them unusable temporarily
+ }
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ return true;
+
+ return false;
+ }
+
+ const char* Save()
+ {
+ return strInstData.c_str();
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_OSSIRIAN: return m_uiOssirianGUID;
+ case DATA_BURU: return m_uiBuruGUID;
+ case DATA_ANDOROV: return m_uiAndorovGUID;
+ case DATA_KURINNAXX: return m_uiKurinnaxxGUID;
+ case DATA_QEEZ: return m_uiQeezGUID;
+ case DATA_TUUBID: return m_uiTuubidGUID;
+ case DATA_DRENN: return m_uiDrennGUID;
+ case DATA_XURREM: return m_uiXurremGUID;
+ case DATA_YEGGETH: return m_uiYeggethGUID;
+ case DATA_PAKKON: return m_uiPakkonGUID;
+ case DATA_ZERRAN: return m_uiZerranGUID;
+ case DATA_RAJAXX: return m_uiRajaxxGUID;
+ }
+ return 0;
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_RAJAXX:
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_KURINNAXX:
+ m_auiEncounter[1] = uiData;
+ break;
+ }
+
+ if (uiData == DONE)
+ {
+ OUT_SAVE_INST_DATA;
+
+ std::ostringstream saveStream;
+ saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " ";
+
+ strInstData = saveStream.str();
+
+ SaveToDB();
+ OUT_SAVE_INST_DATA_COMPLETE;
+ }
+ }
+
+ void Load(const char* chrIn)
+ {
+ if (!chrIn)
+ {
+ OUT_LOAD_INST_DATA_FAIL;
+ return;
+ }
+
+ OUT_LOAD_INST_DATA(chrIn);
+
+ std::istringstream loadStream(chrIn);
+
+ loadStream >> m_auiEncounter[0] >> m_auiEncounter[1];
+
+ for(uint8 i = 0; i < MAX_ENCOUNTER; ++i)
+ {
+ if (m_auiEncounter[i] == IN_PROGRESS)
+ m_auiEncounter[i] = NOT_STARTED;
+ }
+
+ OUT_LOAD_INST_DATA_COMPLETE;
+
+ //spawn andorov on load
+ if (m_auiEncounter[0] == DONE)
+ if (Creature* pRajaxx = instance->GetCreature(m_uiRajaxxGUID))
+ pRajaxx->SummonCreature(NPC_GENERAL_ANDOROV, -8873.42f, 1647.67f, 21.386f, 5.69141f, TEMPSUMMON_CORPSE_DESPAWN, 0);
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_RAJAXX:
+ return m_auiEncounter[0];
+ case TYPE_KURINNAXX:
+ return m_auiEncounter[1];
+ }
+ return 0;
+ }
+};
+
+InstanceData* GetInstanceData_instance_ruins_of_ahnqiraj(Map* pMap)
+{
+ return new instance_ruins_of_ahnqiraj(pMap);
+}
+
+void AddSC_instance_ruins_of_ahnqiraj()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "instance_ruins_of_ahnqiraj";
+ newscript->GetInstanceData = &GetInstanceData_instance_ruins_of_ahnqiraj;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.cpp b/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.cpp
new file mode 100644
index 0000000..bcaa515
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.cpp
@@ -0,0 +1,170 @@
+/* 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: Ruins of Ahn'Qiraj
+SD%Complete: 40
+SDComment:
+SDCategory: Ruins of Ahn'Qiraj
+EndScriptData */
+
+/* ContentData
+mob_anubisath_guardian
+EndContentData */
+
+#include "precompiled.h"
+
+/*######
+## mob_anubisath_guardian
+######*/
+enum
+{
+ SPELL_METEOR = 24340,
+ SPELL_PLAGUE = 22997,
+ SPELL_SHADOW_STORM = 26546,
+ SPELL_THUNDER_CLAP = 26554,
+ SPELL_REFLECT_ARFR = 13022,
+ SPELL_REFLECT_FSSH = 19595,
+ SPELL_ENRAGE = 8559,
+ SPELL_EXPLODE = 25698,
+
+ SPELL_SUMMON_ANUB_SWARMGUARD = 17430,
+ SPELL_SUMMON_ANUB_WARRIOR = 17431,
+
+ EMOTE_FRENZY = -1000002,
+
+ NPC_ANUB_WARRIOR = 15537,
+ NPC_ANUB_SWARM = 15538
+};
+
+struct MANGOS_DLL_DECL mob_anubisath_guardianAI : public ScriptedAI
+{
+ mob_anubisath_guardianAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiSpell1;
+ uint32 m_uiSpell2;
+ uint32 m_uiSpell3;
+ uint32 m_uiSpell4;
+ uint32 m_uiSpell5;
+
+ uint32 m_uiSpell1Timer;
+ uint32 m_uiSpell2Timer;
+ uint32 m_uiSpell5Timer;
+
+ uint8 m_uiSummonCount;
+
+ bool m_bIsEnraged;
+
+ void Reset()
+ {
+ m_uiSpell1 = urand(0,1) ? SPELL_METEOR : SPELL_PLAGUE;
+ m_uiSpell2 = urand(0,1) ? SPELL_SHADOW_STORM : SPELL_THUNDER_CLAP;
+ m_uiSpell3 = urand(0,1) ? SPELL_REFLECT_ARFR : SPELL_REFLECT_FSSH;
+ m_uiSpell4 = urand(0,1) ? SPELL_ENRAGE : SPELL_EXPLODE;
+ m_uiSpell5 = urand(0,1) ? SPELL_SUMMON_ANUB_SWARMGUARD : SPELL_SUMMON_ANUB_WARRIOR;
+
+ m_uiSpell1Timer = 10000;
+ m_uiSpell2Timer = 20000;
+ m_uiSpell5Timer = 10000;
+ m_uiSummonCount = 0;
+ m_bIsEnraged = false;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ // spell reflection
+ DoCastSpellIfCan(m_creature, m_uiSpell3);
+ }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->AI()->AttackStart(m_creature->getVictim());
+ ++m_uiSummonCount;
+ }
+
+ void SummonedCreatureDespawn(Creature* pDespawned)
+ {
+ --m_uiSummonCount;
+ }
+
+ void DamageTaken(Unit* pDoneBy, uint32 &uiDamage)
+ {
+ // when we reach 10% of HP explode or enrage
+ if (!m_bIsEnraged && m_creature->GetHealthPercent() < 10.0f)
+ {
+ if (m_uiSpell4 == SPELL_ENRAGE)
+ {
+ DoScriptText(EMOTE_FRENZY, m_creature);
+ DoCastSpellIfCan(m_creature, m_uiSpell4);
+ m_bIsEnraged = true;
+ }
+ else
+ DoCastSpellIfCan(m_creature->getVictim(), m_uiSpell4);
+ }
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // Meteor or Plague
+ if (m_uiSpell1Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), m_uiSpell1);
+ m_uiSpell1Timer = 15000;
+ }
+ else
+ m_uiSpell1Timer -= uiDiff;
+
+ // Shadow Storm or Thunder Clap
+ if (m_uiSpell2Timer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), m_uiSpell2);
+ m_uiSpell2Timer = 15000;
+ }
+ else
+ m_uiSpell2Timer -= uiDiff;
+
+ // summon Anubisath Swarmguard or Anubisath Warrior
+ if (m_uiSpell5Timer < uiDiff)
+ {
+ // change for summon spell
+ if (m_uiSummonCount < 4)
+ DoCastSpellIfCan(m_creature->getVictim(), m_uiSpell5);
+
+ m_uiSpell5Timer = 15000;
+ }
+ else
+ m_uiSpell5Timer -= uiDiff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_mob_anubisath_guardian(Creature* pCreature)
+{
+ return new mob_anubisath_guardianAI(pCreature);
+}
+
+void AddSC_ruins_of_ahnqiraj()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "mob_anubisath_guardian";
+ newscript->GetAI = &GetAI_mob_anubisath_guardian;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h b/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h
new file mode 100644
index 0000000..7196b43
--- /dev/null
+++ b/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h
@@ -0,0 +1,44 @@
+/* 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 */
+
+#ifndef DEF_RUINS_OF_AHNQIRAJ_H
+#define DEF_RUINS_OF_AHNQIRAJ_H
+
+enum
+{
+ MAX_ENCOUNTER = 2,
+
+ DATA_OSSIRIAN = 1,
+ DATA_BURU = 2,
+ DATA_ANDOROV = 3,
+ DATA_KURINNAXX = 4,
+ DATA_QEEZ = 5,
+ DATA_TUUBID = 6,
+ DATA_DRENN = 7,
+ DATA_XURREM = 8,
+ DATA_YEGGETH = 9,
+ DATA_PAKKON = 10,
+ DATA_ZERRAN = 11,
+ DATA_RAJAXX = 12,
+
+ TYPE_RAJAXX = 13,
+ TYPE_KURINNAXX = 14,
+
+ NPC_OSSIRIAN = 15339,
+ NPC_BURU = 15370,
+ NPC_KALDOREI_ELITE = 15473,
+ NPC_GENERAL_ANDOROV = 15471,
+ NPC_RAJAXX = 15341,
+ NPC_KURINNAXX = 15348,
+ NPC_COLONEL_ZERRAN = 15385,
+ NPC_MAJOR_PAKKON = 15388,
+ NPC_MAJOR_YEGGETH = 15386,
+ NPC_CAPTAIN_XURREM = 15390,
+ NPC_CAPTAIN_DRENN = 15389,
+ NPC_CAPTAIN_TUUBID = 15392,
+ NPC_CAPTAIN_QEEZ = 15391,
+
+ GO_OSSIRIAN_CRYSTAL = 180619
+};
+#endif
diff --git a/scripts/kalimdor/silithus.cpp b/scripts/kalimdor/silithus.cpp
new file mode 100644
index 0000000..7b801a7
--- /dev/null
+++ b/scripts/kalimdor/silithus.cpp
@@ -0,0 +1,252 @@
+/* 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: Silithus
+SD%Complete: 100
+SDComment: Quest support: 7785, 8304.
+SDCategory: Silithus
+EndScriptData */
+
+/* ContentData
+npc_highlord_demitrian
+npcs_rutgar_and_frankal
+EndContentData */
+
+#include "precompiled.h"
+
+/*###
+## npc_highlord_demitrian
+###*/
+
+#define GOSSIP_ITEM_DEMITRIAN1 "What do you know of it?"
+#define GOSSIP_ITEM_DEMITRIAN2 "I am listening , Demitrian."
+#define GOSSIP_ITEM_DEMITRIAN3 "Continue, please."
+#define GOSSIP_ITEM_DEMITRIAN4 "A battle?"
+#define GOSSIP_ITEM_DEMITRIAN5 ""
+#define GOSSIP_ITEM_DEMITRIAN6 "Caught unaware? How?"
+#define GOSSIP_ITEM_DEMITRIAN7 "So what did Ragnaros do next?"
+
+enum
+{
+ QUEST_EXAMINE_THE_VESSEL = 7785,
+ ITEM_BINDINGS_WINDSEEKER_LEFT = 18563,
+ ITEM_BINDINGS_WINDSEEKER_RIGHT = 18564,
+ ITEM_VESSEL_OF_REBIRTH = 19016,
+ GOSSIP_TEXTID_DEMITRIAN1 = 6842,
+ GOSSIP_TEXTID_DEMITRIAN2 = 6843,
+ GOSSIP_TEXTID_DEMITRIAN3 = 6844,
+ GOSSIP_TEXTID_DEMITRIAN4 = 6867,
+ GOSSIP_TEXTID_DEMITRIAN5 = 6868,
+ GOSSIP_TEXTID_DEMITRIAN6 = 6869,
+ GOSSIP_TEXTID_DEMITRIAN7 = 6870
+};
+
+bool GossipHello_npc_highlord_demitrian(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(QUEST_EXAMINE_THE_VESSEL) == QUEST_STATUS_NONE &&
+ (pPlayer->HasItemCount(ITEM_BINDINGS_WINDSEEKER_LEFT,1,false) || pPlayer->HasItemCount(ITEM_BINDINGS_WINDSEEKER_RIGHT,1,false)))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DEMITRIAN1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_highlord_demitrian(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DEMITRIAN2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEMITRIAN1, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DEMITRIAN3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEMITRIAN2, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DEMITRIAN4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEMITRIAN3, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DEMITRIAN5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEMITRIAN4, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DEMITRIAN6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEMITRIAN5, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_DEMITRIAN7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+6);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEMITRIAN6, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+6:
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_DEMITRIAN7, pCreature->GetGUID());
+
+ if (Item* pItem = pPlayer->StoreNewItemInInventorySlot(ITEM_VESSEL_OF_REBIRTH, 1))
+ pPlayer->SendNewItem(pItem, 1, true, false);
+
+ break;
+ }
+ return true;
+}
+
+/*###
+## npcs_rutgar_and_frankal
+###*/
+
+//gossip item text best guess
+#define GOSSIP_ITEM_SEEK1 "I seek information about Natalia"
+
+#define GOSSIP_ITEM_RUTGAR2 "That sounds dangerous!"
+#define GOSSIP_ITEM_RUTGAR3 "What did you do?"
+#define GOSSIP_ITEM_RUTGAR4 "Who?"
+#define GOSSIP_ITEM_RUTGAR5 "Women do that. What did she demand?"
+#define GOSSIP_ITEM_RUTGAR6 "What do you mean?"
+#define GOSSIP_ITEM_RUTGAR7 "What happened next?"
+
+#define GOSSIP_ITEM_FRANKAL11 "Yes, please continue"
+#define GOSSIP_ITEM_FRANKAL12 "What language?"
+#define GOSSIP_ITEM_FRANKAL13 "The Priestess attacked you?!"
+#define GOSSIP_ITEM_FRANKAL14 "I should ask the monkey about this"
+#define GOSSIP_ITEM_FRANKAL15 "Then what..."
+
+enum
+{
+ QUEST_DEAREST_NATALIA = 8304,
+ NPC_RUTGAR = 15170,
+ NPC_FRANKAL = 15171,
+ TRIGGER_RUTGAR = 15222,
+ TRIGGER_FRANKAL = 15221,
+ GOSSIP_TEXTID_RF = 7754,
+ GOSSIP_TEXTID_RUTGAR1 = 7755,
+ GOSSIP_TEXTID_RUTGAR2 = 7756,
+ GOSSIP_TEXTID_RUTGAR3 = 7757,
+ GOSSIP_TEXTID_RUTGAR4 = 7758,
+ GOSSIP_TEXTID_RUTGAR5 = 7759,
+ GOSSIP_TEXTID_RUTGAR6 = 7760,
+ GOSSIP_TEXTID_RUTGAR7 = 7761,
+ GOSSIP_TEXTID_FRANKAL1 = 7762,
+ GOSSIP_TEXTID_FRANKAL2 = 7763,
+ GOSSIP_TEXTID_FRANKAL3 = 7764,
+ GOSSIP_TEXTID_FRANKAL4 = 7765,
+ GOSSIP_TEXTID_FRANKAL5 = 7766,
+ GOSSIP_TEXTID_FRANKAL6 = 7767
+};
+
+bool GossipHello_npcs_rutgar_and_frankal(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(QUEST_DEAREST_NATALIA) == QUEST_STATUS_INCOMPLETE &&
+ pCreature->GetEntry() == NPC_RUTGAR &&
+ !pPlayer->GetReqKillOrCastCurrentCount(QUEST_DEAREST_NATALIA, TRIGGER_RUTGAR))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SEEK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ if (pPlayer->GetQuestStatus(QUEST_DEAREST_NATALIA) == QUEST_STATUS_INCOMPLETE &&
+ pCreature->GetEntry() == NPC_FRANKAL &&
+ pPlayer->GetReqKillOrCastCurrentCount(QUEST_DEAREST_NATALIA, TRIGGER_RUTGAR))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SEEK1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+9);
+
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RF, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npcs_rutgar_and_frankal(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTGAR2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RUTGAR1, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTGAR3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RUTGAR2, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTGAR4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RUTGAR3, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTGAR5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 4);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RUTGAR4, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTGAR6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 5);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RUTGAR5, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 5:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_RUTGAR7, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 6);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RUTGAR6, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 6:
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_RUTGAR7, pCreature->GetGUID());
+ //'kill' our trigger to update quest status
+ pPlayer->KilledMonsterCredit(TRIGGER_RUTGAR, pCreature->GetGUID());
+ break;
+
+ case GOSSIP_ACTION_INFO_DEF + 9:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FRANKAL11, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_FRANKAL1, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 10:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FRANKAL12, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 11);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_FRANKAL2, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 11:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FRANKAL13, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 12);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_FRANKAL3, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 12:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FRANKAL14, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 13);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_FRANKAL4, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 13:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FRANKAL15, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 14);
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_FRANKAL5, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF + 14:
+ pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXTID_FRANKAL6, pCreature->GetGUID());
+ //'kill' our trigger to update quest status
+ pPlayer->KilledMonsterCredit(TRIGGER_FRANKAL, pCreature->GetGUID());
+ break;
+ }
+ return true;
+}
+
+void AddSC_silithus()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_highlord_demitrian";
+ newscript->pGossipHello = &GossipHello_npc_highlord_demitrian;
+ newscript->pGossipSelect = &GossipSelect_npc_highlord_demitrian;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npcs_rutgar_and_frankal";
+ newscript->pGossipHello = &GossipHello_npcs_rutgar_and_frankal;
+ newscript->pGossipSelect = &GossipSelect_npcs_rutgar_and_frankal;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/stonetalon_mountains.cpp b/scripts/kalimdor/stonetalon_mountains.cpp
new file mode 100644
index 0000000..3944825
--- /dev/null
+++ b/scripts/kalimdor/stonetalon_mountains.cpp
@@ -0,0 +1,160 @@
+/* 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: Stonetalon_Mountains
+SD%Complete: 95
+SDComment: Quest support: 6627 (Braug Dimspirits questions/'answers' might have more to it, need more info),6523
+SDCategory: Stonetalon Mountains
+EndScriptData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+
+/*######
+## npc_braug_dimspirit
+######*/
+
+bool GossipHello_npc_braug_dimspirit(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(6627) == QUEST_STATUS_INCOMPLETE)
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Ysera", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Neltharion", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Nozdormu", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Alexstrasza", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, "Malygos", GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+
+ pPlayer->SEND_GOSSIP_MENU(5820, pCreature->GetGUID());
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(5819, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_braug_dimspirit(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+1)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pCreature->CastSpell(pPlayer,6766,false);
+
+ }
+ if (uiAction == GOSSIP_ACTION_INFO_DEF+2)
+ {
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(6627);
+ }
+ return true;
+}
+
+/*######
+## npc_kaya
+######*/
+
+enum
+{
+ NPC_GRIMTOTEM_RUFFIAN = 11910,
+ NPC_GRIMTOTEM_BRUTE = 11912,
+ NPC_GRIMTOTEM_SORCERER = 11913,
+
+ SAY_START = -1000357,
+ SAY_AMBUSH = -1000358,
+ SAY_END = -1000359,
+
+ QUEST_PROTECT_KAYA = 6523
+};
+
+struct MANGOS_DLL_DECL npc_kayaAI : public npc_escortAI
+{
+ npc_kayaAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void Reset() { }
+
+ void JustSummoned(Creature* pSummoned)
+ {
+ pSummoned->AI()->AttackStart(m_creature);
+ }
+
+ void WaypointReached(uint32 uiPointId)
+ {
+ switch(uiPointId)
+ {
+ //Ambush
+ case 16:
+ //note about event here:
+ //apparently NPC say _after_ the ambush is over, and is most likely a bug at you-know-where.
+ //we simplify this, and make say when the ambush actually start.
+ DoScriptText(SAY_AMBUSH, m_creature);
+ m_creature->SummonCreature(NPC_GRIMTOTEM_RUFFIAN, -50.75f, -500.77f, -46.13f, 0.4f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ m_creature->SummonCreature(NPC_GRIMTOTEM_BRUTE, -40.05f, -510.89f, -46.05f, 1.7f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ m_creature->SummonCreature(NPC_GRIMTOTEM_SORCERER, -32.21f, -499.20f, -45.35f, 2.8f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ break;
+ // Award quest credit
+ case 18:
+ DoScriptText(SAY_END, m_creature);
+
+ if (Player* pPlayer = GetPlayerForEscort())
+ pPlayer->GroupEventHappens(QUEST_PROTECT_KAYA, m_creature);
+ break;
+ }
+ }
+};
+
+CreatureAI* GetAI_npc_kaya(Creature* pCreature)
+{
+ return new npc_kayaAI(pCreature);
+}
+
+bool QuestAccept_npc_kaya(Player* pPlayer, Creature* pCreature, Quest const* pQuest)
+{
+ //Casting Spell and Starting the Escort quest is buggy, so this is a hack. Use the spell when it is possible.
+
+ if (pQuest->GetQuestId() == QUEST_PROTECT_KAYA)
+ {
+ pCreature->setFaction(FACTION_ESCORT_H_PASSIVE);
+ DoScriptText(SAY_START,pCreature);
+
+ if (npc_kayaAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+/*######
+## AddSC
+######*/
+
+void AddSC_stonetalon_mountains()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_braug_dimspirit";
+ newscript->pGossipHello = &GossipHello_npc_braug_dimspirit;
+ newscript->pGossipSelect = &GossipSelect_npc_braug_dimspirit;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_kaya";
+ newscript->GetAI = &GetAI_npc_kaya;
+ newscript->pQuestAccept = &QuestAccept_npc_kaya;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/tanaris.cpp b/scripts/kalimdor/tanaris.cpp
new file mode 100644
index 0000000..d4aa0f3
--- /dev/null
+++ b/scripts/kalimdor/tanaris.cpp
@@ -0,0 +1,637 @@
+/* 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: Tanaris
+SD%Complete: 80
+SDComment: Quest support: 648, 1560, 2954, 4005, 10277, 10279(Special flight path). Noggenfogger vendor
+SDCategory: Tanaris
+EndScriptData */
+
+/* ContentData
+mob_aquementas
+npc_custodian_of_time
+npc_marin_noggenfogger
+npc_oox17tn
+npc_steward_of_time
+npc_stone_watcher_of_norgannon
+npc_tooga
+EndContentData */
+
+#include "precompiled.h"
+#include "escort_ai.h"
+#include "follower_ai.h"
+
+/*######
+## mob_aquementas
+######*/
+
+#define AGGRO_YELL_AQUE -1000168
+
+#define SPELL_AQUA_JET 13586
+#define SPELL_FROST_SHOCK 15089
+
+struct MANGOS_DLL_DECL mob_aquementasAI : public ScriptedAI
+{
+ mob_aquementasAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 SendItem_Timer;
+ uint32 SwitchFaction_Timer;
+ bool isFriendly;
+
+ uint32 FrostShock_Timer;
+ uint32 AquaJet_Timer;
+
+ void Reset()
+ {
+ SendItem_Timer = 0;
+ SwitchFaction_Timer = 10000;
+ m_creature->setFaction(35);
+ isFriendly = true;
+
+ AquaJet_Timer = 5000;
+ FrostShock_Timer = 1000;
+ }
+
+ void SendItem(Unit* receiver)
+ {
+ if (((Player*)receiver)->HasItemCount(11169,1,false) &&
+ ((Player*)receiver)->HasItemCount(11172,11,false) &&
+ ((Player*)receiver)->HasItemCount(11173,1,false) &&
+ !((Player*)receiver)->HasItemCount(11522,1,true))
+ {
+ if (Item* pItem = ((Player*)receiver)->StoreNewItemInInventorySlot(11522, 1))
+ ((Player*)receiver)->SendNewItem(pItem, 1, true, false);
+ }
+ }
+
+ void Aggro(Unit* who)
+ {
+ DoScriptText(AGGRO_YELL_AQUE, m_creature, who);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (isFriendly)
+ {
+ if (SwitchFaction_Timer < diff)
+ {
+ m_creature->setFaction(91);
+ isFriendly = false;
+ }else SwitchFaction_Timer -= diff;
+ }
+
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!isFriendly)
+ {
+ if (SendItem_Timer < diff)
+ {
+ if (m_creature->getVictim()->GetTypeId() == TYPEID_PLAYER)
+ SendItem(m_creature->getVictim());
+ SendItem_Timer = 5000;
+ }else SendItem_Timer -= diff;
+ }
+
+ if (FrostShock_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FROST_SHOCK);
+ FrostShock_Timer = 15000;
+ }else FrostShock_Timer -= diff;
+
+ if (AquaJet_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_AQUA_JET);
+ AquaJet_Timer = 15000;
+ }else AquaJet_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+CreatureAI* GetAI_mob_aquementas(Creature* pCreature)
+{
+ return new mob_aquementasAI(pCreature);
+}
+
+/*######
+## npc_custodian_of_time
+######*/
+
+#define WHISPER_CUSTODIAN_1 -1000217
+#define WHISPER_CUSTODIAN_2 -1000218
+#define WHISPER_CUSTODIAN_3 -1000219
+#define WHISPER_CUSTODIAN_4 -1000220
+#define WHISPER_CUSTODIAN_5 -1000221
+#define WHISPER_CUSTODIAN_6 -1000222
+#define WHISPER_CUSTODIAN_7 -1000223
+#define WHISPER_CUSTODIAN_8 -1000224
+#define WHISPER_CUSTODIAN_9 -1000225
+#define WHISPER_CUSTODIAN_10 -1000226
+#define WHISPER_CUSTODIAN_11 -1000227
+#define WHISPER_CUSTODIAN_12 -1000228
+#define WHISPER_CUSTODIAN_13 -1000229
+#define WHISPER_CUSTODIAN_14 -1000230
+
+struct MANGOS_DLL_DECL npc_custodian_of_timeAI : public npc_escortAI
+{
+ npc_custodian_of_timeAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void WaypointReached(uint32 i)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch(i)
+ {
+ case 0: DoScriptText(WHISPER_CUSTODIAN_1, m_creature, pPlayer); break;
+ case 1: DoScriptText(WHISPER_CUSTODIAN_2, m_creature, pPlayer); break;
+ case 2: DoScriptText(WHISPER_CUSTODIAN_3, m_creature, pPlayer); break;
+ case 3: DoScriptText(WHISPER_CUSTODIAN_4, m_creature, pPlayer); break;
+ case 5: DoScriptText(WHISPER_CUSTODIAN_5, m_creature, pPlayer); break;
+ case 6: DoScriptText(WHISPER_CUSTODIAN_6, m_creature, pPlayer); break;
+ case 7: DoScriptText(WHISPER_CUSTODIAN_7, m_creature, pPlayer); break;
+ case 8: DoScriptText(WHISPER_CUSTODIAN_8, m_creature, pPlayer); break;
+ case 9: DoScriptText(WHISPER_CUSTODIAN_9, m_creature, pPlayer); break;
+ case 10: DoScriptText(WHISPER_CUSTODIAN_4, m_creature, pPlayer); break;
+ case 13: DoScriptText(WHISPER_CUSTODIAN_10, m_creature, pPlayer); break;
+ case 14: DoScriptText(WHISPER_CUSTODIAN_4, m_creature, pPlayer); break;
+ case 16: DoScriptText(WHISPER_CUSTODIAN_11, m_creature, pPlayer); break;
+ case 17: DoScriptText(WHISPER_CUSTODIAN_12, m_creature, pPlayer); break;
+ case 18: DoScriptText(WHISPER_CUSTODIAN_4, m_creature, pPlayer); break;
+ case 22: DoScriptText(WHISPER_CUSTODIAN_13, m_creature, pPlayer); break;
+ case 23: DoScriptText(WHISPER_CUSTODIAN_4, m_creature, pPlayer); break;
+ case 24:
+ DoScriptText(WHISPER_CUSTODIAN_14, m_creature, pPlayer);
+ DoCastSpellIfCan(pPlayer, 34883);
+ //below here is temporary workaround, to be removed when spell works properly
+ pPlayer->AreaExploredOrEventHappens(10277);
+ break;
+ }
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ if (HasEscortState(STATE_ESCORT_ESCORTING))
+ return;
+
+ if (who->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (((Player*)who)->HasAura(34877, EFFECT_INDEX_1) && ((Player*)who)->GetQuestStatus(10277) == QUEST_STATUS_INCOMPLETE)
+ {
+ float Radius = 10.0;
+
+ if (m_creature->IsWithinDistInMap(who, Radius))
+ Start(false, who->GetGUID());
+ }
+ }
+ }
+
+ void Reset() { }
+};
+
+CreatureAI* GetAI_npc_custodian_of_time(Creature* pCreature)
+{
+ return new npc_custodian_of_timeAI(pCreature);
+}
+
+/*######
+## npc_marin_noggenfogger
+######*/
+
+bool GossipHello_npc_marin_noggenfogger(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pCreature->isVendor() && pPlayer->GetQuestRewardStatus(2662))
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
+
+ pPlayer->SEND_GOSSIP_MENU(pPlayer->GetGossipTextId(pCreature), pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_marin_noggenfogger(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_TRADE)
+ pPlayer->SEND_VENDORLIST(pCreature->GetGUID());
+
+ return true;
+}
+
+/*######
+## npc_oox17tn
+######*/
+
+enum
+{
+ SAY_OOX_START = -1000287,
+ SAY_OOX_AGGRO1 = -1000288,
+ SAY_OOX_AGGRO2 = -1000289,
+ SAY_OOX_AMBUSH = -1000290,
+ SAY_OOX17_AMBUSH_REPLY = -1000291,
+ SAY_OOX_END = -1000292,
+
+ QUEST_RESCUE_OOX_17TN = 648,
+
+ NPC_SCORPION = 7803,
+ NPC_SCOFFLAW = 7805,
+ NPC_SHADOW_MAGE = 5617
+};
+
+struct MANGOS_DLL_DECL npc_oox17tnAI : public npc_escortAI
+{
+ npc_oox17tnAI(Creature* pCreature) : npc_escortAI(pCreature) { Reset(); }
+
+ void WaypointReached(uint32 i)
+ {
+ Player* pPlayer = GetPlayerForEscort();
+
+ if (!pPlayer)
+ return;
+
+ switch (i)
+ {
+ //1. Ambush: 3 scorpions
+ case 22:
+ DoScriptText(SAY_OOX_AMBUSH, m_creature);
+ m_creature->SummonCreature(NPC_SCORPION, -8340.70f, -4448.17f, 9.17f, 3.10f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ m_creature->SummonCreature(NPC_SCORPION, -8343.18f, -4444.35f, 9.44f, 2.35f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ m_creature->SummonCreature(NPC_SCORPION, -8348.70f, -4457.80f, 9.58f, 2.02f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+ break;
+ //2. Ambush: 2 Rogues & 1 Shadow Mage
+ case 28:
+ DoScriptText(SAY_OOX_AMBUSH, m_creature);
+
+ m_creature->SummonCreature(NPC_SCOFFLAW, -7488.02f, -4786.56f, 10.67f, 3.74f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 10000);
+ m_creature->SummonCreature(NPC_SHADOW_MAGE, -7486.41f, -4791.55f, 10.54f, 3.26f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000);
+
+ if (Creature* pCreature = m_creature->SummonCreature(NPC_SCOFFLAW, -7488.47f, -4800.77f, 9.77f, 2.50f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 30000))
+ DoScriptText(SAY_OOX17_AMBUSH_REPLY,pCreature);
+
+ break;
+ case 34:
+ DoScriptText(SAY_OOX_END, m_creature);
+ // Award quest credit
+ pPlayer->GroupEventHappens(QUEST_RESCUE_OOX_17TN, m_creature);
+ break;
+ }
+ }
+
+ void Reset() { }
+
+ void Aggro(Unit* who)
+ {
+ //For an small probability he say something when it aggros
+ switch(urand(0, 9))
+ {
+ case 0: DoScriptText(SAY_OOX_AGGRO1, m_creature); break;
+ case 1: DoScriptText(SAY_OOX_AGGRO2, m_creature); break;
+ }
+ }
+
+ void JustSummoned(Creature* summoned)
+ {
+ summoned->AI()->AttackStart(m_creature);
+ }
+};
+
+CreatureAI* GetAI_npc_oox17tn(Creature* pCreature)
+{
+ return new npc_oox17tnAI(pCreature);
+}
+
+bool QuestAccept_npc_oox17tn(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_RESCUE_OOX_17TN)
+ {
+ DoScriptText(SAY_OOX_START, pCreature);
+
+ pCreature->SetStandState(UNIT_STAND_STATE_STAND);
+
+ if (pPlayer->GetTeam() == ALLIANCE)
+ pCreature->setFaction(FACTION_ESCORT_A_PASSIVE);
+
+ if (pPlayer->GetTeam() == HORDE)
+ pCreature->setFaction(FACTION_ESCORT_H_PASSIVE);
+
+ if (npc_oox17tnAI* pEscortAI = dynamic_cast(pCreature->AI()))
+ pEscortAI->Start(false, pPlayer->GetGUID(), pQuest);
+ }
+ return true;
+}
+
+/*######
+## npc_steward_of_time
+######*/
+
+#define GOSSIP_ITEM_FLIGHT "Please take me to the master's lair."
+
+bool GossipHello_npc_steward_of_time(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(10279) == QUEST_STATUS_INCOMPLETE || pPlayer->GetQuestRewardStatus(10279))
+ {
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_FLIGHT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
+ pPlayer->SEND_GOSSIP_MENU(9978, pCreature->GetGUID());
+ }
+ else
+ pPlayer->SEND_GOSSIP_MENU(9977, pCreature->GetGUID());
+
+ return true;
+}
+
+bool QuestAccept_npc_steward_of_time(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == 10279) //Quest: To The Master's Lair
+ pPlayer->CastSpell(pPlayer,34891,true); //(Flight through Caverns)
+
+ return false;
+}
+
+bool GossipSelect_npc_steward_of_time(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ if (uiAction == GOSSIP_ACTION_INFO_DEF + 1)
+ pPlayer->CastSpell(pPlayer,34891,true); //(Flight through Caverns)
+
+ return true;
+}
+
+/*######
+## npc_stone_watcher_of_norgannon
+######*/
+
+#define GOSSIP_ITEM_NORGANNON_1 "What function do you serve?"
+#define GOSSIP_ITEM_NORGANNON_2 "What are the Plates of Uldum?"
+#define GOSSIP_ITEM_NORGANNON_3 "Where are the Plates of Uldum?"
+#define GOSSIP_ITEM_NORGANNON_4 "Excuse me? We've been \"reschedueled for visitations\"? What does that mean?!"
+#define GOSSIP_ITEM_NORGANNON_5 "So, what's inside Uldum?"
+#define GOSSIP_ITEM_NORGANNON_6 "I will return when i have the Plates of Uldum."
+
+bool GossipHello_npc_stone_watcher_of_norgannon(Player* pPlayer, Creature* pCreature)
+{
+ if (pCreature->isQuestGiver())
+ pPlayer->PrepareQuestMenu(pCreature->GetGUID());
+
+ if (pPlayer->GetQuestStatus(2954) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF);
+
+ pPlayer->SEND_GOSSIP_MENU(1674, pCreature->GetGUID());
+
+ return true;
+}
+
+bool GossipSelect_npc_stone_watcher_of_norgannon(Player* pPlayer, Creature* pCreature, uint32 uiSender, uint32 uiAction)
+{
+ switch(uiAction)
+ {
+ case GOSSIP_ACTION_INFO_DEF:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ pPlayer->SEND_GOSSIP_MENU(1675, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+1:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
+ pPlayer->SEND_GOSSIP_MENU(1676, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+2:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_4, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+3);
+ pPlayer->SEND_GOSSIP_MENU(1677, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+3:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_5, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+4);
+ pPlayer->SEND_GOSSIP_MENU(1678, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+4:
+ pPlayer->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NORGANNON_6, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+5);
+ pPlayer->SEND_GOSSIP_MENU(1679, pCreature->GetGUID());
+ break;
+ case GOSSIP_ACTION_INFO_DEF+5:
+ pPlayer->CLOSE_GOSSIP_MENU();
+ pPlayer->AreaExploredOrEventHappens(2954);
+ break;
+ }
+ return true;
+}
+
+/*####
+# npc_tooga
+####*/
+
+enum
+{
+ SAY_TOOG_THIRST = -1000391,
+ SAY_TOOG_WORRIED = -1000392,
+ SAY_TOOG_POST_1 = -1000393,
+ SAY_TORT_POST_2 = -1000394,
+ SAY_TOOG_POST_3 = -1000395,
+ SAY_TORT_POST_4 = -1000396,
+ SAY_TOOG_POST_5 = -1000397,
+ SAY_TORT_POST_6 = -1000398,
+
+ QUEST_TOOGA = 1560,
+ NPC_TORTA = 6015,
+
+ POINT_ID_TO_WATER = 1
+};
+
+const float m_afToWaterLoc[] = {-7032.664551f, -4906.199219f, -1.606446f};
+
+struct MANGOS_DLL_DECL npc_toogaAI : public FollowerAI
+{
+ npc_toogaAI(Creature* pCreature) : FollowerAI(pCreature) { Reset(); }
+
+ uint32 m_uiCheckSpeechTimer;
+ uint32 m_uiPostEventTimer;
+ uint32 m_uiPhasePostEvent;
+
+ Unit* pTorta;
+
+ void Reset()
+ {
+ m_uiCheckSpeechTimer = 2500;
+ m_uiPostEventTimer = 1000;
+ m_uiPhasePostEvent = 0;
+
+ pTorta = NULL;
+ }
+
+ void MoveInLineOfSight(Unit* pWho)
+ {
+ FollowerAI::MoveInLineOfSight(pWho);
+
+ if (!m_creature->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE | STATE_FOLLOW_POSTEVENT) && pWho->GetEntry() == NPC_TORTA)
+ {
+ if (m_creature->IsWithinDistInMap(pWho, INTERACTION_DISTANCE))
+ {
+ if (Player* pPlayer = GetLeaderForFollower())
+ {
+ if (pPlayer->GetQuestStatus(QUEST_TOOGA) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->GroupEventHappens(QUEST_TOOGA, m_creature);
+ }
+
+ pTorta = pWho;
+ SetFollowComplete(true);
+ }
+ }
+ }
+
+ void MovementInform(uint32 uiMotionType, uint32 uiPointId)
+ {
+ FollowerAI::MovementInform(uiMotionType, uiPointId);
+
+ if (uiMotionType != POINT_MOTION_TYPE)
+ return;
+
+ if (uiPointId == POINT_ID_TO_WATER)
+ SetFollowComplete();
+ }
+
+ void UpdateFollowerAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ //we are doing the post-event, or...
+ if (HasFollowState(STATE_FOLLOW_POSTEVENT))
+ {
+ if (m_uiPostEventTimer < uiDiff)
+ {
+ m_uiPostEventTimer = 5000;
+
+ if (!pTorta || !pTorta->isAlive())
+ {
+ //something happened, so just complete
+ SetFollowComplete();
+ return;
+ }
+
+ switch(m_uiPhasePostEvent)
+ {
+ case 1:
+ DoScriptText(SAY_TOOG_POST_1, m_creature);
+ break;
+ case 2:
+ DoScriptText(SAY_TORT_POST_2, pTorta);
+ break;
+ case 3:
+ DoScriptText(SAY_TOOG_POST_3, m_creature);
+ break;
+ case 4:
+ DoScriptText(SAY_TORT_POST_4, pTorta);
+ break;
+ case 5:
+ DoScriptText(SAY_TOOG_POST_5, m_creature);
+ break;
+ case 6:
+ DoScriptText(SAY_TORT_POST_6, pTorta);
+ m_creature->GetMotionMaster()->MovePoint(POINT_ID_TO_WATER, m_afToWaterLoc[0], m_afToWaterLoc[1], m_afToWaterLoc[2]);
+ break;
+ }
+
+ ++m_uiPhasePostEvent;
+ }
+ else
+ m_uiPostEventTimer -= uiDiff;
+ }
+ //...we are doing regular speech check
+ else if (HasFollowState(STATE_FOLLOW_INPROGRESS))
+ {
+ if (m_uiCheckSpeechTimer < uiDiff)
+ {
+ m_uiCheckSpeechTimer = 5000;
+
+ switch(urand(0, 50))
+ {
+ case 10: DoScriptText(SAY_TOOG_THIRST, m_creature); break;
+ case 25: DoScriptText(SAY_TOOG_WORRIED, m_creature); break;
+ }
+ }
+ else
+ m_uiCheckSpeechTimer -= uiDiff;
+ }
+
+ return;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_tooga(Creature* pCreature)
+{
+ return new npc_toogaAI(pCreature);
+}
+
+bool QuestAccept_npc_tooga(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_TOOGA)
+ {
+ if (npc_toogaAI* pToogaAI = dynamic_cast(pCreature->AI()))
+ pToogaAI->StartFollow(pPlayer, FACTION_ESCORT_N_FRIEND_PASSIVE, pQuest);
+ }
+
+ return true;
+}
+
+void AddSC_tanaris()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "mob_aquementas";
+ newscript->GetAI = &GetAI_mob_aquementas;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_custodian_of_time";
+ newscript->GetAI = &GetAI_npc_custodian_of_time;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_marin_noggenfogger";
+ newscript->pGossipHello = &GossipHello_npc_marin_noggenfogger;
+ newscript->pGossipSelect = &GossipSelect_npc_marin_noggenfogger;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_oox17tn";
+ newscript->GetAI = &GetAI_npc_oox17tn;
+ newscript->pQuestAccept = &QuestAccept_npc_oox17tn;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_steward_of_time";
+ newscript->pGossipHello = &GossipHello_npc_steward_of_time;
+ newscript->pGossipSelect = &GossipSelect_npc_steward_of_time;
+ newscript->pQuestAccept = &QuestAccept_npc_steward_of_time;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_stone_watcher_of_norgannon";
+ newscript->pGossipHello = &GossipHello_npc_stone_watcher_of_norgannon;
+ newscript->pGossipSelect = &GossipSelect_npc_stone_watcher_of_norgannon;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "npc_tooga";
+ newscript->GetAI = &GetAI_npc_tooga;
+ newscript->pQuestAccept = &QuestAccept_npc_tooga;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/teldrassil.cpp b/scripts/kalimdor/teldrassil.cpp
new file mode 100644
index 0000000..febc5ae
--- /dev/null
+++ b/scripts/kalimdor/teldrassil.cpp
@@ -0,0 +1,113 @@
+/* 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: Teldrassil
+SD%Complete: 100
+SDComment: Quest support: 938
+SDCategory: Teldrassil
+EndScriptData */
+
+/* ContentData
+npc_mist
+EndContentData */
+
+#include "precompiled.h"
+#include "follower_ai.h"
+
+/*####
+# npc_mist
+####*/
+
+enum
+{
+ SAY_AT_HOME = -1000323,
+ EMOTE_AT_HOME = -1000324,
+ QUEST_MIST = 938,
+ NPC_ARYNIA = 3519,
+ FACTION_DARNASSUS = 79
+};
+
+struct MANGOS_DLL_DECL npc_mistAI : public FollowerAI
+{
+ npc_mistAI(Creature* pCreature) : FollowerAI(pCreature) { Reset(); }
+
+ void Reset() { }
+
+ void MoveInLineOfSight(Unit *pWho)
+ {
+ FollowerAI::MoveInLineOfSight(pWho);
+
+ if (!m_creature->getVictim() && !HasFollowState(STATE_FOLLOW_COMPLETE) && pWho->GetEntry() == NPC_ARYNIA)
+ {
+ if (m_creature->IsWithinDistInMap(pWho, 10.0f))
+ {
+ DoScriptText(SAY_AT_HOME, pWho);
+ DoComplete();
+ }
+ }
+ }
+
+ void DoComplete()
+ {
+ DoScriptText(EMOTE_AT_HOME, m_creature);
+
+ if (Player* pPlayer = GetLeaderForFollower())
+ {
+ if (pPlayer->GetQuestStatus(QUEST_MIST) == QUEST_STATUS_INCOMPLETE)
+ pPlayer->GroupEventHappens(QUEST_MIST, m_creature);
+ }
+
+ //The follow is over (and for later development, run off to the woods before really end)
+ SetFollowComplete();
+ }
+
+ //call not needed here, no known abilities
+ /*void UpdateFollowerAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ DoMeleeAttackIfReady();
+ }*/
+};
+
+CreatureAI* GetAI_npc_mist(Creature* pCreature)
+{
+ return new npc_mistAI(pCreature);
+}
+
+bool QuestAccept_npc_mist(Player* pPlayer, Creature* pCreature, const Quest* pQuest)
+{
+ if (pQuest->GetQuestId() == QUEST_MIST)
+ {
+ if (npc_mistAI* pMistAI = dynamic_cast(pCreature->AI()))
+ pMistAI->StartFollow(pPlayer, FACTION_DARNASSUS, pQuest);
+ }
+
+ return true;
+}
+
+void AddSC_teldrassil()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "npc_mist";
+ newscript->GetAI = &GetAI_npc_mist;
+ newscript->pQuestAccept = &QuestAccept_npc_mist;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp
new file mode 100644
index 0000000..90edbfd
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp
@@ -0,0 +1,332 @@
+/* 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_kri, boss_yauj, boss_vem : The Bug Trio
+SD%Complete: 100
+SDComment:
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+#include "temple_of_ahnqiraj.h"
+
+#define SPELL_CLEAVE 26350
+#define SPELL_TOXIC_VOLLEY 25812
+#define SPELL_POISON_CLOUD 38718 //Only Spell with right dmg.
+#define SPELL_ENRAGE 34624 //Changed cause 25790 is casted on gamers too. Same prob with old explosion of twin emperors.
+
+#define SPELL_CHARGE 26561
+#define SPELL_KNOCKBACK 26027
+
+#define SPELL_HEAL 25807
+#define SPELL_FEAR 19408
+
+struct MANGOS_DLL_DECL boss_kriAI : public ScriptedAI
+{
+ boss_kriAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 Cleave_Timer;
+ uint32 ToxicVolley_Timer;
+ uint32 Check_Timer;
+
+ bool VemDead;
+ bool Death;
+
+ void Reset()
+ {
+ Cleave_Timer = urand(4000, 8000);
+ ToxicVolley_Timer = urand(6000, 12000);
+ Check_Timer = 2000;
+
+ VemDead = false;
+ Death = false;
+ }
+
+ void JustDied(Unit* killer)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2)
+ // Unlootable if death
+ m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+
+ m_pInstance->SetData(DATA_BUG_TRIO_DEATH, 1);
+ }
+ }
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Cleave_Timer
+ if (Cleave_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_CLEAVE);
+ Cleave_Timer = urand(5000, 12000);
+ }else Cleave_Timer -= diff;
+
+ //ToxicVolley_Timer
+ if (ToxicVolley_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_TOXIC_VOLLEY);
+ ToxicVolley_Timer = urand(10000, 15000);
+ }else ToxicVolley_Timer -= diff;
+
+ if (m_creature->GetHealthPercent() < 5.0f && !Death)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_POISON_CLOUD);
+ Death = true;
+ }
+
+ if (!VemDead)
+ {
+ //Checking if Vem is dead. If yes we will enrage.
+ if (Check_Timer < diff)
+ {
+ if (m_pInstance && m_pInstance->GetData(TYPE_VEM) == DONE)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ VemDead = true;
+ }
+ Check_Timer = 2000;
+ }else Check_Timer -=diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_vemAI : public ScriptedAI
+{
+ boss_vemAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 Charge_Timer;
+ uint32 KnockBack_Timer;
+ uint32 Enrage_Timer;
+
+ bool Enraged;
+
+ void Reset()
+ {
+ Charge_Timer = urand(15000, 27000);
+ KnockBack_Timer = urand(8000, 20000);
+ Enrage_Timer = 120000;
+
+ Enraged = false;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (m_pInstance)
+ {
+ m_pInstance->SetData(TYPE_VEM, DONE);
+
+ // Unlootable if death
+ if (m_pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2)
+ m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+
+ m_pInstance->SetData(DATA_BUG_TRIO_DEATH, 1);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Charge_Timer
+ if (Charge_Timer < diff)
+ {
+ if (Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target, SPELL_CHARGE);
+
+ Charge_Timer = urand(8000, 16000);
+ }else Charge_Timer -= diff;
+
+ //KnockBack_Timer
+ if (KnockBack_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_KNOCKBACK);
+ if (m_creature->getThreatManager().getThreat(m_creature->getVictim()))
+ m_creature->getThreatManager().modifyThreatPercent(m_creature->getVictim(),-80);
+ KnockBack_Timer = urand(15000, 25000);
+ }else KnockBack_Timer -= diff;
+
+ //Enrage_Timer
+ if (!Enraged && Enrage_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature,SPELL_ENRAGE);
+ Enraged = true;
+ }else Charge_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_yaujAI : public ScriptedAI
+{
+ boss_yaujAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 Heal_Timer;
+ uint32 Fear_Timer;
+ uint32 Check_Timer;
+
+ bool VemDead;
+
+ void Reset()
+ {
+ Heal_Timer = urand(25000, 40000);
+ Fear_Timer = urand(12000, 24000);
+ Check_Timer = 2000;
+
+ VemDead = false;
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(DATA_BUG_TRIO_DEATH) < 2)
+ // Unlootable if death
+ m_creature->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ m_pInstance->SetData(DATA_BUG_TRIO_DEATH, 1);
+ }
+
+ for(int i = 0; i < 10; ++i)
+ {
+ Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ Creature* Summoned = m_creature->SummonCreature(15621,m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(),0,TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN,90000);
+ if (Summoned && target)
+ Summoned->AI()->AttackStart(target);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Fear_Timer
+ if (Fear_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_FEAR);
+ DoResetThreat();
+ Fear_Timer = 20000;
+ }else Fear_Timer -= diff;
+
+ //Casting Heal to other twins or herself.
+ if (Heal_Timer < diff)
+ {
+ if (m_pInstance)
+ {
+ Creature *pKri = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_KRI));
+ Creature *pVem = m_creature->GetMap()->GetCreature(m_pInstance->GetData64(DATA_VEM));
+
+ switch(urand(0, 2))
+ {
+ case 0:
+ if (pKri)
+ DoCastSpellIfCan(pKri, SPELL_HEAL);
+ break;
+ case 1:
+ if (pVem)
+ DoCastSpellIfCan(pVem, SPELL_HEAL);
+ break;
+ case 2:
+ DoCastSpellIfCan(m_creature, SPELL_HEAL);
+ break;
+ }
+ }
+
+ Heal_Timer = urand(15000, 30000);
+ }else Heal_Timer -= diff;
+
+ //Checking if Vem is dead. If yes we will enrage.
+ if (Check_Timer < diff)
+ {
+ if (!VemDead)
+ {
+ if (m_pInstance)
+ {
+ if (m_pInstance->GetData(TYPE_VEM) == DONE)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ VemDead = true;
+ }
+ }
+ }
+ Check_Timer = 2000;
+ }else Check_Timer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_yauj(Creature* pCreature)
+{
+ return new boss_yaujAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_vem(Creature* pCreature)
+{
+ return new boss_vemAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_kri(Creature* pCreature)
+{
+ return new boss_kriAI(pCreature);
+}
+
+void AddSC_bug_trio()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_kri";
+ newscript->GetAI = &GetAI_boss_kri;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_vem";
+ newscript->GetAI = &GetAI_boss_vem;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_yauj";
+ newscript->GetAI = &GetAI_boss_yauj;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp
new file mode 100644
index 0000000..274d8a6
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp
@@ -0,0 +1,1355 @@
+/* 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_Cthun
+SD%Complete: 95
+SDComment: Darkglare tracking issue
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+#include "temple_of_ahnqiraj.h"
+
+//Text emote
+#define EMOTE_WEAKENED -1531011
+
+#define PI 3.14
+
+//****** Out of Combat ******
+//Random Wispers - No txt only sound
+#define RANDOM_SOUND_WHISPER 8663
+
+//***** Phase 1 ********
+
+//Mobs
+#define BOSS_EYE_OF_CTHUN 15589
+#define MOB_CLAW_TENTACLE 15725
+#define MOB_EYE_TENTACLE 15726
+#define MOB_SMALL_PORTAL 15904
+
+//Eye Spells
+#define SPELL_GREEN_BEAM 26134
+#define SPELL_DARK_GLARE 26029
+#define SPELL_RED_COLORATION 22518 //Probably not the right spell but looks similar
+
+//Eye Tentacles Spells
+#define SPELL_MIND_FLAY 26143
+
+//Claw Tentacles Spells
+#define SPELL_GROUND_RUPTURE 26139
+#define SPELL_HAMSTRING 26141
+
+#define MOB_
+
+//*****Phase 2******
+//Body spells
+//#define SPELL_CARAPACE_CTHUN 26156 //Was removed from client dbcs
+#define SPELL_TRANSFORM 26232
+
+//Eye Tentacles Spells
+//SAME AS PHASE1
+
+//Giant Claw Tentacles
+#define SPELL_MASSIVE_GROUND_RUPTURE 26100
+
+//Also casts Hamstring
+#define SPELL_THRASH 3391
+
+//Giant Eye Tentacles
+//CHAIN CASTS "SPELL_GREEN_BEAM"
+
+//Stomach Spells
+#define SPELL_MOUTH_TENTACLE 26332
+#define SPELL_EXIT_STOMACH_KNOCKBACK 25383
+#define SPELL_DIGESTIVE_ACID 26476
+
+//Mobs
+#define MOB_BODY_OF_CTHUN 15809
+#define MOB_GIANT_CLAW_TENTACLE 15728
+#define MOB_GIANT_EYE_TENTACLE 15334
+#define MOB_FLESH_TENTACLE 15802
+#define MOB_GIANT_PORTAL 15910
+
+//Stomach Teleport positions
+#define STOMACH_X -8562.0f
+#define STOMACH_Y 2037.0f
+#define STOMACH_Z -70.0f
+#define STOMACH_O 5.05f
+
+//Flesh tentacle positions
+#define TENTACLE_POS1_X -8571.0f
+#define TENTACLE_POS1_Y 1990.0f
+#define TENTACLE_POS1_Z -98.0f
+#define TENTACLE_POS1_O 1.22f
+
+#define TENTACLE_POS2_X -8525.0f
+#define TENTACLE_POS2_Y 1994.0f
+#define TENTACLE_POS2_Z -98.0f
+#define TENTACLE_POS2_O 2.12f
+
+//Kick out position
+#define KICK_X -8545.0f
+#define KICK_Y 1984.0f
+#define KICK_Z -96.0f
+
+struct MANGOS_DLL_DECL flesh_tentacleAI : public ScriptedAI
+{
+ flesh_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature), Parent(0)
+ {
+ SetCombatMovement(false);
+ Reset();
+ }
+
+ uint64 Parent;
+ uint32 CheckTimer;
+
+ void SpawnedByCthun(uint64 p)
+ {
+ Parent = p;
+ }
+
+ void Reset()
+ {
+ CheckTimer = 1000;
+ }
+
+ void UpdateAI(const uint32 diff);
+
+ void JustDied(Unit* killer);
+};
+
+struct MANGOS_DLL_DECL eye_of_cthunAI : public ScriptedAI
+{
+ eye_of_cthunAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ SetCombatMovement(false);
+
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ if (!m_pInstance)
+ error_log("SD2: No Instance eye_of_cthunAI");
+
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ //Global variables
+ uint32 PhaseTimer;
+
+ //Eye beam phase
+ uint32 BeamTimer;
+ uint32 EyeTentacleTimer;
+ uint32 ClawTentacleTimer;
+
+ //Dark Glare phase
+ uint32 DarkGlareTick;
+ uint32 DarkGlareTickTimer;
+ float DarkGlareAngle;
+ bool ClockWise;
+
+ void Reset()
+ {
+ //Phase information
+ PhaseTimer = 50000; //First dark glare in 50 seconds
+
+ //Eye beam phase 50 seconds
+ BeamTimer = 3000;
+ EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam
+ ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn durring Dark beam)
+
+ //Dark Beam phase 35 seconds (each tick = 1 second, 35 ticks)
+ DarkGlareTick = 0;
+ DarkGlareTickTimer = 1000;
+ DarkGlareAngle = 0;
+ ClockWise = false;
+
+ //Reset flags
+ m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
+
+ //Reset Phase
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 0);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void SpawnEyeTentacle(float x, float y)
+ {
+ Creature* Spawned;
+ Spawned = (Creature*)m_creature->SummonCreature(MOB_EYE_TENTACLE,m_creature->GetPositionX()+x,m_creature->GetPositionY()+y,m_creature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500);
+ if (Spawned)
+ {
+ Unit* target;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+
+ if (target)
+ Spawned->AI()->AttackStart(target);
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Check if we have a target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //No instance
+ if (!m_pInstance)
+ return;
+
+ switch (m_pInstance->GetData(TYPE_CTHUN_PHASE))
+ {
+ case 0:
+ {
+ //BeamTimer
+ if (BeamTimer < diff)
+ {
+ //SPELL_GREEN_BEAM
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(target,SPELL_GREEN_BEAM);
+
+ //Correctly update our target
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID());
+ }
+
+ //Beam every 3 seconds
+ BeamTimer = 3000;
+ }else BeamTimer -= diff;
+
+ //ClawTentacleTimer
+ if (ClawTentacleTimer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target)
+ {
+ Creature* Spawned = NULL;
+
+ //Spawn claw tentacle on the random target
+ Spawned = (Creature*)m_creature->SummonCreature(MOB_CLAW_TENTACLE,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500);
+
+ if (Spawned)
+ Spawned->AI()->AttackStart(target);
+ }
+
+ //One claw tentacle every 12.5 seconds
+ ClawTentacleTimer = 12500;
+ }else ClawTentacleTimer -= diff;
+
+ //EyeTentacleTimer
+ if (EyeTentacleTimer < diff)
+ {
+ //Spawn the 8 Eye Tentacles in the corret spots
+ SpawnEyeTentacle(0, 20); //south
+ SpawnEyeTentacle(10, 10); //south west
+ SpawnEyeTentacle(20, 0); //west
+ SpawnEyeTentacle(10, -10); //north west
+
+ SpawnEyeTentacle(0, -20); //north
+ SpawnEyeTentacle(-10, -10); //north east
+ SpawnEyeTentacle(-20, 0); // east
+ SpawnEyeTentacle(-10, 10); // south east
+
+ //No point actually putting a timer here since
+ //These shouldn't trigger agian until after phase shifts
+ EyeTentacleTimer = 45000;
+ }else EyeTentacleTimer -= diff;
+
+ //PhaseTimer
+ if (PhaseTimer < diff)
+ {
+ //Switch to Dark Beam
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 1);
+
+ m_creature->InterruptNonMeleeSpells(false);
+
+ //Select random target for dark beam to start on
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+
+ if (target)
+ {
+ //Correctly update our target
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, target->GetGUID());
+
+ //Face our target
+ DarkGlareAngle = m_creature->GetAngle(target);
+ DarkGlareTickTimer = 1000;
+ DarkGlareTick = 0;
+ ClockWise = urand(0, 1);
+ }
+
+ //Add red coloration to C'thun
+ DoCastSpellIfCan(m_creature,SPELL_RED_COLORATION);
+
+ //Freeze animation
+
+ //Darkbeam for 35 seconds
+ PhaseTimer = 35000;
+ }else PhaseTimer -= diff;
+
+ }
+ break;
+ case 1:
+ {
+ //EyeTentacleTimer
+ if (DarkGlareTick < 35)
+ if (DarkGlareTickTimer < diff)
+ {
+ //Remove any target
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
+
+ //Set angle and cast
+ if (ClockWise)
+ m_creature->SetOrientation(DarkGlareAngle + ((float)DarkGlareTick*PI/35));
+ else m_creature->SetOrientation(DarkGlareAngle - ((float)DarkGlareTick*PI/35));
+
+ m_creature->StopMoving();
+
+ //Actual dark glare cast, maybe something missing here?
+ m_creature->CastSpell(NULL, SPELL_DARK_GLARE, false);
+
+ //Increase tick
+ ++DarkGlareTick;
+
+ //1 second per tick
+ DarkGlareTickTimer = 1000;
+ }else DarkGlareTickTimer -= diff;
+
+ //PhaseTimer
+ if (PhaseTimer < diff)
+ {
+ //Switch to Eye Beam
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 0);
+
+ BeamTimer = 3000;
+ EyeTentacleTimer = 45000; //Always spawns 5 seconds before Dark Beam
+ ClawTentacleTimer = 12500; //4 per Eye beam phase (unsure if they spawn durring Dark beam)
+
+ m_creature->InterruptNonMeleeSpells(false);
+
+ //Remove Red coloration from c'thun
+ m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION);
+
+ //Freeze animation
+ m_creature->SetUInt32Value(UNIT_FIELD_FLAGS, 0);
+
+ //Eye Beam for 50 seconds
+ PhaseTimer = 50000;
+ }else PhaseTimer -= diff;
+ }break;
+
+ //Transition phase
+ case 2:
+ {
+ //Remove any target
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
+ m_creature->SetHealth(0);
+ }
+
+ //Dead phase
+ case 5:
+ {
+ m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+ }
+ }
+ }
+
+ void DamageTaken(Unit *done_by, uint32 &damage)
+ {
+ //No instance
+ if (!m_pInstance)
+ return;
+
+ switch (m_pInstance->GetData(TYPE_CTHUN_PHASE))
+ {
+ case 0:
+ case 1:
+ {
+ //Only if it will kill
+ if (damage < m_creature->GetHealth())
+ return;
+
+ //Fake death in phase 0 or 1 (green beam or dark glare phase)
+ m_creature->InterruptNonMeleeSpells(false);
+
+ //Remove Red coloration from c'thun
+ m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION);
+
+ //Reset to normal emote state and prevent select and attack
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
+
+ //Remove Target field
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
+
+ //Death animation/respawning;
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 2);
+
+ m_creature->SetHealth(0);
+ damage = 0;
+
+ m_creature->InterruptNonMeleeSpells(true);
+ m_creature->RemoveAllAuras();
+ }
+ break;
+
+ case 5:
+ {
+ //Allow death here
+ return;
+ }
+
+ default:
+ {
+ //Prevent death in this phase
+ damage = 0;
+ return;
+ }
+ break;
+ }
+ }
+};
+
+struct MANGOS_DLL_DECL cthunAI : public ScriptedAI
+{
+ cthunAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ SetCombatMovement(false);
+
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ if (!m_pInstance)
+ error_log("SD2: No Instance eye_of_cthunAI");
+
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ //Out of combat whisper timer
+ uint32 WisperTimer;
+
+ //Global variables
+ uint32 PhaseTimer;
+
+ //-------------------
+
+ //Phase transition
+ uint64 HoldPlayer;
+
+ //Body Phase
+ uint32 EyeTentacleTimer;
+ uint8 FleshTentaclesKilled;
+ uint32 GiantClawTentacleTimer;
+ uint32 GiantEyeTentacleTimer;
+ uint32 StomachAcidTimer;
+ uint32 StomachEnterTimer;
+ uint32 StomachEnterVisTimer;
+ uint64 StomachEnterTarget;
+
+ //Stomach map, bool = true then in stomach
+ UNORDERED_MAP Stomach_Map;
+
+ void Reset()
+ {
+ //One random wisper every 90 - 300 seconds
+ WisperTimer = 90000;
+
+ //Phase information
+ PhaseTimer = 10000; //Emerge in 10 seconds
+
+ //No hold player for transition
+ HoldPlayer = 0;
+
+ //Body Phase
+ EyeTentacleTimer = 30000;
+ FleshTentaclesKilled = 0;
+ GiantClawTentacleTimer = 15000; //15 seconds into body phase (1 min repeat)
+ GiantEyeTentacleTimer = 45000; //15 seconds into body phase (1 min repeat)
+ StomachAcidTimer = 4000; //Every 4 seconds
+ StomachEnterTimer = 10000; //Every 10 seconds
+ StomachEnterVisTimer = 0; //Always 3.5 seconds after Stomach Enter Timer
+ StomachEnterTarget = 0; //Target to be teleported to stomach
+
+ //Clear players in stomach and outside
+ Stomach_Map.clear();
+
+ //Reset flags
+ m_creature->RemoveAurasDueToSpell(SPELL_TRANSFORM);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
+
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 0);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void SpawnEyeTentacle(float x, float y)
+ {
+ Creature* Spawned;
+ Spawned = (Creature*)m_creature->SummonCreature(MOB_EYE_TENTACLE,m_creature->GetPositionX()+x,m_creature->GetPositionY()+y,m_creature->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500);
+ if (Spawned)
+ {
+ Unit* target;
+
+ target = SelectRandomNotStomach();
+
+ if (target)
+ Spawned->AI()->AttackStart(target);
+ }
+ }
+
+ Unit* SelectRandomNotStomach()
+ {
+ if (Stomach_Map.empty())
+ return NULL;
+
+ UNORDERED_MAP::iterator i = Stomach_Map.begin();
+
+ std::list temp;
+ std::list::iterator j;
+
+ //Get all players in map
+ while (i != Stomach_Map.end())
+ {
+ //Check for valid player
+ Unit* pUnit = m_creature->GetMap()->GetUnit(i->first);
+
+ //Only units out of stomach
+ if (pUnit && i->second == false)
+ {
+ temp.push_back(pUnit);
+ }
+ ++i;
+ }
+
+ if (temp.empty())
+ return NULL;
+
+ j = temp.begin();
+
+ //Get random but only if we have more than one unit on threat list
+ if (temp.size() > 1)
+ advance (j , rand() % (temp.size() - 1));
+
+ return (*j);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Check if we have a target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ {
+ //No target so we'll use this section to do our random wispers instance wide
+ //WisperTimer
+ if (WisperTimer < diff)
+ {
+ Map *map = m_creature->GetMap();
+ if (!map->IsDungeon())
+ return;
+
+ //Play random sound to the zone
+ Map::PlayerList const &PlayerList = map->GetPlayers();
+
+ if (!PlayerList.isEmpty())
+ {
+ for(Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
+ {
+ if (Player* pPlr = itr->getSource())
+ pPlr->PlayDirectSound(RANDOM_SOUND_WHISPER,pPlr);
+ }
+ }
+
+ //One random wisper every 90 - 300 seconds
+ WisperTimer = urand(90000, 300000);
+ }else WisperTimer -= diff;
+
+ return;
+ }
+
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
+
+ //No instance
+ if (!m_pInstance)
+ return;
+
+ switch (m_pInstance->GetData(TYPE_CTHUN_PHASE))
+ {
+ //Transition phase
+ case 2:
+ {
+ //PhaseTimer
+ if (PhaseTimer < diff)
+ {
+ //Switch
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 3);
+
+ //Switch to c'thun model
+ m_creature->InterruptNonMeleeSpells(false);
+ DoCastSpellIfCan(m_creature, SPELL_TRANSFORM);
+ m_creature->SetHealth(m_creature->GetMaxHealth());
+
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_NON_ATTACKABLE);
+
+ //Emerging phase
+ m_creature->SetInCombatWithZone();
+
+ //Place all units in threat list on outside of stomach
+ Stomach_Map.clear();
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ //Outside stomach
+ Stomach_Map[(*i)->getUnitGuid()] = false;
+ }
+
+ //Spawn 2 flesh tentacles
+ FleshTentaclesKilled = 0;
+
+ //Spawn flesh tentacle
+ Creature* pSpawned = m_creature->SummonCreature(MOB_FLESH_TENTACLE, TENTACLE_POS1_X, TENTACLE_POS1_Y, TENTACLE_POS1_Z, TENTACLE_POS1_O, TEMPSUMMON_CORPSE_DESPAWN, 0);
+
+ if (!pSpawned)
+ ++FleshTentaclesKilled;
+ else
+ {
+ if (flesh_tentacleAI* pTentacleAI = dynamic_cast(pSpawned->AI()))
+ pTentacleAI->SpawnedByCthun(m_creature->GetGUID());
+ }
+
+ //Spawn flesh tentacle
+ pSpawned = m_creature->SummonCreature(MOB_FLESH_TENTACLE, TENTACLE_POS2_X, TENTACLE_POS2_Y, TENTACLE_POS2_Z, TENTACLE_POS2_O, TEMPSUMMON_CORPSE_DESPAWN, 0);
+
+ if (!pSpawned)
+ ++FleshTentaclesKilled;
+ else
+ {
+ if (flesh_tentacleAI* pTentacleAI = dynamic_cast(pSpawned->AI()))
+ pTentacleAI->SpawnedByCthun(m_creature->GetGUID());
+ }
+
+ PhaseTimer = 0;
+ }else PhaseTimer -= diff;
+
+ }break;
+
+ //Body Phase
+ case 3:
+ {
+ //Remove Target field
+ m_creature->SetUInt64Value(UNIT_FIELD_TARGET, 0);
+
+ //Weaken
+ if (FleshTentaclesKilled > 1)
+ {
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 4);
+
+ DoScriptText(EMOTE_WEAKENED, m_creature);
+ PhaseTimer = 45000;
+
+ DoCastSpellIfCan(m_creature, SPELL_RED_COLORATION, CAST_TRIGGERED);
+
+ UNORDERED_MAP::iterator i = Stomach_Map.begin();
+
+ //Kick all players out of stomach
+ while (i != Stomach_Map.end())
+ {
+ //Check for valid player
+ Unit* pUnit = m_creature->GetMap()->GetUnit(i->first);
+
+ //Only move units in stomach
+ if (pUnit && i->second == true)
+ {
+ //Teleport each player out
+ DoTeleportPlayer(pUnit, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+10, rand()%6);
+
+ //Cast knockback on them
+ DoCastSpellIfCan(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, CAST_TRIGGERED);
+
+ //Remove the acid debuff
+ pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID);
+
+ i->second = false;
+ }
+ ++i;
+ }
+
+ return;
+ }
+
+ //Stomach acid
+ if (StomachAcidTimer < diff)
+ {
+ //Apply aura to all players in stomach
+ UNORDERED_MAP::iterator i = Stomach_Map.begin();
+
+ while (i != Stomach_Map.end())
+ {
+ //Check for valid player
+ Unit* pUnit = m_creature->GetMap()->GetUnit(i->first);
+
+ //Only apply to units in stomach
+ if (pUnit && i->second == true)
+ {
+ //Cast digestive acid on them
+ DoCastSpellIfCan(pUnit, SPELL_DIGESTIVE_ACID, CAST_TRIGGERED);
+
+ //Check if player should be kicked from stomach
+ if (pUnit->IsWithinDist3d(KICK_X, KICK_Y, KICK_Z, 15.0f))
+ {
+ //Teleport each player out
+ DoTeleportPlayer(pUnit, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ()+10, rand()%6);
+
+ //Cast knockback on them
+ DoCastSpellIfCan(pUnit, SPELL_EXIT_STOMACH_KNOCKBACK, CAST_TRIGGERED);
+
+ //Remove the acid debuff
+ pUnit->RemoveAurasDueToSpell(SPELL_DIGESTIVE_ACID);
+
+ i->second = false;
+ }
+ }
+ ++i;
+ }
+
+ StomachAcidTimer = 4000;
+ }else StomachAcidTimer -= diff;
+
+ //Stomach Enter Timer
+ if (StomachEnterTimer < diff)
+ {
+ Unit* target = NULL;
+ target = SelectRandomNotStomach();
+
+ if (target)
+ {
+ //Set target in stomach
+ Stomach_Map[target->GetGUID()] = true;
+ target->InterruptNonMeleeSpells(false);
+ target->CastSpell(target, SPELL_MOUTH_TENTACLE, true, NULL, NULL, m_creature->GetGUID());
+ StomachEnterTarget = target->GetGUID();
+ StomachEnterVisTimer = 3800;
+ }
+
+ StomachEnterTimer = 13800;
+ }else StomachEnterTimer -= diff;
+
+ if (StomachEnterVisTimer && StomachEnterTarget)
+ if (StomachEnterVisTimer <= diff)
+ {
+ //Check for valid player
+ Unit* pUnit = m_creature->GetMap()->GetUnit(StomachEnterTarget);
+
+ if (pUnit)
+ {
+ DoTeleportPlayer(pUnit, STOMACH_X, STOMACH_Y, STOMACH_Z, STOMACH_O);
+ }
+
+ StomachEnterTarget = 0;
+ StomachEnterVisTimer = 0;
+ }else StomachEnterVisTimer -= diff;
+
+ //GientClawTentacleTimer
+ if (GiantClawTentacleTimer < diff)
+ {
+ Unit* target = NULL;
+ target = SelectRandomNotStomach();
+ if (target)
+ {
+ Creature* Spawned = NULL;
+
+ //Spawn claw tentacle on the random target
+ Spawned = (Creature*)m_creature->SummonCreature(MOB_GIANT_CLAW_TENTACLE,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500);
+
+ if (Spawned)
+ Spawned->AI()->AttackStart(target);
+ }
+
+ //One giant claw tentacle every minute
+ GiantClawTentacleTimer = 60000;
+ }else GiantClawTentacleTimer -= diff;
+
+ //GiantEyeTentacleTimer
+ if (GiantEyeTentacleTimer < diff)
+ {
+ Unit* target = NULL;
+ target = SelectRandomNotStomach();
+ if (target)
+ {
+
+ Creature* Spawned = NULL;
+
+ //Spawn claw tentacle on the random target
+ Spawned = (Creature*)m_creature->SummonCreature(MOB_GIANT_EYE_TENTACLE,target->GetPositionX(),target->GetPositionY(),target->GetPositionZ(),0,TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT,500);
+
+ if (Spawned)
+ Spawned->AI()->AttackStart(target);
+ }
+
+ //One giant eye tentacle every minute
+ GiantEyeTentacleTimer = 60000;
+ }else GiantEyeTentacleTimer -= diff;
+
+ //EyeTentacleTimer
+ if (EyeTentacleTimer < diff)
+ {
+ //Spawn the 8 Eye Tentacles in the corret spots
+ SpawnEyeTentacle(0, 25); //south
+ SpawnEyeTentacle(12, 12); //south west
+ SpawnEyeTentacle(25, 0); //west
+ SpawnEyeTentacle(12, -12); //north west
+
+ SpawnEyeTentacle(0, -25); //north
+ SpawnEyeTentacle(-12, -12); //north east
+ SpawnEyeTentacle(-25, 0); // east
+ SpawnEyeTentacle(-12, 12); // south east
+
+ //These spawn at every 30 seconds
+ EyeTentacleTimer = 30000;
+ }else EyeTentacleTimer -= diff;
+
+ }break;
+
+ //Weakened state
+ case 4:
+ {
+ //PhaseTimer
+ if (PhaseTimer < diff)
+ {
+ //Switch
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 3);
+
+ //Remove red coloration
+ m_creature->RemoveAurasDueToSpell(SPELL_RED_COLORATION);
+
+ //Spawn 2 flesh tentacles
+ FleshTentaclesKilled = 0;
+
+ //Spawn flesh tentacle
+ Creature* pSpawned = m_creature->SummonCreature(MOB_FLESH_TENTACLE, TENTACLE_POS1_X, TENTACLE_POS1_Y, TENTACLE_POS1_Z, TENTACLE_POS1_O, TEMPSUMMON_CORPSE_DESPAWN, 0);
+
+ if (!pSpawned)
+ ++FleshTentaclesKilled;
+ else
+ {
+ if (flesh_tentacleAI* pTentacleAI = dynamic_cast(pSpawned->AI()))
+ pTentacleAI->SpawnedByCthun(m_creature->GetGUID());
+ }
+
+ //Spawn flesh tentacle
+ pSpawned = m_creature->SummonCreature(MOB_FLESH_TENTACLE, TENTACLE_POS2_X, TENTACLE_POS2_Y, TENTACLE_POS2_Z, TENTACLE_POS2_O, TEMPSUMMON_CORPSE_DESPAWN, 0);
+
+ if (!pSpawned)
+ ++FleshTentaclesKilled;
+ else
+ {
+ if (flesh_tentacleAI* pTentacleAI = dynamic_cast(pSpawned->AI()))
+ pTentacleAI->SpawnedByCthun(m_creature->GetGUID());
+ }
+
+ PhaseTimer = 0;
+ }else PhaseTimer -= diff;
+ }
+ }
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ //Switch
+ if (m_pInstance)
+ m_pInstance->SetData(TYPE_CTHUN_PHASE, 5);
+ }
+
+ void DamageTaken(Unit *done_by, uint32 &damage)
+ {
+ //No instance
+ if (!m_pInstance)
+ return;
+
+ switch (m_pInstance->GetData(TYPE_CTHUN_PHASE))
+ {
+ case 3:
+ {
+ //Not weakened so reduce damage by 99%
+ if (damage / 99 > 0) damage/= 99;
+ else damage = 1;
+
+ //Prevent death in non-weakened state
+ if (damage >= m_creature->GetHealth())
+ damage = 0;
+
+ return;
+ }
+ break;
+
+ case 4:
+ {
+ //Weakened - takes normal damage
+ return;
+ }
+
+ default:
+ damage = 0;
+ break;
+ }
+ }
+
+ void FleshTentcleKilled()
+ {
+ ++FleshTentaclesKilled;
+ }
+};
+
+struct MANGOS_DLL_DECL eye_tentacleAI : public ScriptedAI
+{
+ eye_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ SetCombatMovement(false);
+ Reset();
+
+ if (Unit* pPortal = m_creature->SummonCreature(MOB_SMALL_PORTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ Portal = pPortal->GetGUID();
+ }
+
+ uint32 MindflayTimer;
+ uint32 KillSelfTimer;
+ uint64 Portal;
+
+ void JustDied(Unit*)
+ {
+ if (Creature* pCreature = m_creature->GetMap()->GetCreature(Portal))
+ pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+ }
+
+ void Reset()
+ {
+ //Mind flay half a second after we spawn
+ MindflayTimer = 500;
+
+ //This prevents eyes from overlapping
+ KillSelfTimer = 35000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Check if we have a target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //KillSelfTimer
+ if (KillSelfTimer < diff)
+ {
+ m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+
+ return;
+ }else KillSelfTimer -= diff;
+
+ //MindflayTimer
+ if (MindflayTimer < diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target && !target->HasAura(SPELL_DIGESTIVE_ACID, EFFECT_INDEX_0))
+ DoCastSpellIfCan(target,SPELL_MIND_FLAY);
+
+ //Mindflay every 10 seconds
+ MindflayTimer = 10100;
+ }else MindflayTimer -= diff;
+ }
+};
+
+struct MANGOS_DLL_DECL claw_tentacleAI : public ScriptedAI
+{
+ claw_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ SetCombatMovement(false);
+ Reset();
+
+ if (Unit* pPortal = m_creature->SummonCreature(MOB_SMALL_PORTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ Portal = pPortal->GetGUID();
+ }
+
+ uint32 GroundRuptureTimer;
+ uint32 HamstringTimer;
+ uint32 EvadeTimer;
+ uint64 Portal;
+
+ void JustDied(Unit*)
+ {
+ if (Creature* pCreature = m_creature->GetMap()->GetCreature(Portal))
+ pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+ }
+
+ void Reset()
+ {
+ //First rupture should happen half a second after we spawn
+ GroundRuptureTimer = 500;
+ HamstringTimer = 2000;
+ EvadeTimer = 5000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Check if we have a target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //EvadeTimer
+ if (!m_creature->IsWithinDist(m_creature->getVictim(), ATTACK_DISTANCE))
+ if (EvadeTimer < diff)
+ {
+ if (Creature* pCreature = m_creature->GetMap()->GetCreature(Portal))
+ pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+
+ //Dissapear and reappear at new position
+ m_creature->SetVisibility(VISIBILITY_OFF);
+
+ Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (!target)
+ {
+ m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+ return;
+ }
+
+ if (!target->HasAura(SPELL_DIGESTIVE_ACID, EFFECT_INDEX_0))
+ {
+ m_creature->GetMap()->CreatureRelocation(m_creature, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0);
+
+ if (Unit* pPortal = m_creature->SummonCreature(MOB_SMALL_PORTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ Portal = pPortal->GetGUID();
+
+ GroundRuptureTimer = 500;
+ HamstringTimer = 2000;
+ EvadeTimer = 5000;
+ AttackStart(target);
+ }
+
+ m_creature->SetVisibility(VISIBILITY_ON);
+
+ }else EvadeTimer -= diff;
+
+ //GroundRuptureTimer
+ if (GroundRuptureTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_GROUND_RUPTURE);
+ GroundRuptureTimer = 30000;
+ }else GroundRuptureTimer -= diff;
+
+ //HamstringTimer
+ if (HamstringTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_HAMSTRING);
+ HamstringTimer = 5000;
+ }else HamstringTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL giant_claw_tentacleAI : public ScriptedAI
+{
+ giant_claw_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ SetCombatMovement(false);
+ Reset();
+
+ if (Unit* pPortal = m_creature->SummonCreature(MOB_GIANT_PORTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ Portal = pPortal->GetGUID();
+ }
+
+ uint32 GroundRuptureTimer;
+ uint32 ThrashTimer;
+ uint32 HamstringTimer;
+ uint32 EvadeTimer;
+ uint64 Portal;
+
+ void JustDied(Unit*)
+ {
+ if (Creature* pCreature = m_creature->GetMap()->GetCreature(Portal))
+ pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+ }
+
+ void Reset()
+ {
+ //First rupture should happen half a second after we spawn
+ GroundRuptureTimer = 500;
+ HamstringTimer = 2000;
+ ThrashTimer = 5000;
+ EvadeTimer = 5000;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Check if we have a target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //EvadeTimer
+ if (m_creature->IsWithinDist(m_creature->getVictim(), ATTACK_DISTANCE))
+ if (EvadeTimer < diff)
+ {
+ if (Creature* pCreature = m_creature->GetMap()->GetCreature(Portal))
+ pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+
+ //Dissapear and reappear at new position
+ m_creature->SetVisibility(VISIBILITY_OFF);
+
+ Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
+
+ if (!target)
+ {
+ m_creature->DealDamage(m_creature, m_creature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+ return;
+ }
+
+ if (!target->HasAura(SPELL_DIGESTIVE_ACID, EFFECT_INDEX_0))
+ {
+ m_creature->GetMap()->CreatureRelocation(m_creature, target->GetPositionX(), target->GetPositionY(), target->GetPositionZ(), 0);
+
+ if (Unit* pPortal = m_creature->SummonCreature(MOB_GIANT_PORTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ Portal = pPortal->GetGUID();
+
+ GroundRuptureTimer = 500;
+ HamstringTimer = 2000;
+ ThrashTimer = 5000;
+ EvadeTimer = 5000;
+ AttackStart(target);
+ }
+
+ m_creature->SetVisibility(VISIBILITY_ON);
+
+ }else EvadeTimer -= diff;
+
+ //GroundRuptureTimer
+ if (GroundRuptureTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_GROUND_RUPTURE);
+ GroundRuptureTimer = 30000;
+ }else GroundRuptureTimer -= diff;
+
+ //ThrashTimer
+ if (ThrashTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_THRASH);
+ ThrashTimer = 10000;
+ }else ThrashTimer -= diff;
+
+ //HamstringTimer
+ if (HamstringTimer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_HAMSTRING);
+ HamstringTimer = 10000;
+ }else HamstringTimer -= diff;
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL giant_eye_tentacleAI : public ScriptedAI
+{
+ giant_eye_tentacleAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ SetCombatMovement(false);
+ Reset();
+
+ if (Unit* pPortal = m_creature->SummonCreature(MOB_GIANT_PORTAL, 0.0f, 0.0f, 0.0f, 0.0f, TEMPSUMMON_CORPSE_DESPAWN, 0))
+ Portal = pPortal->GetGUID();
+ }
+
+ uint32 BeamTimer;
+ uint64 Portal;
+
+ void JustDied(Unit*)
+ {
+ if (Creature* pCreature = m_creature->GetMap()->GetCreature(Portal))
+ pCreature->DealDamage(pCreature, pCreature->GetMaxHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+ }
+
+ void Reset()
+ {
+ //Green Beam half a second after we spawn
+ BeamTimer = 500;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Check if we have a target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //BeamTimer
+ if (BeamTimer < diff)
+ {
+ Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target && !target->HasAura(SPELL_DIGESTIVE_ACID, EFFECT_INDEX_0))
+ DoCastSpellIfCan(target,SPELL_GREEN_BEAM);
+
+ //Beam every 2 seconds
+ BeamTimer = 2100;
+ }else BeamTimer -= diff;
+ }
+};
+
+//Flesh tentacle functions
+void flesh_tentacleAI::UpdateAI(const uint32 diff)
+{
+ //Check if we have a target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (Parent)
+ if (CheckTimer < diff)
+ {
+ Creature* pParent = m_creature->GetMap()->GetCreature(Parent);
+
+ if (!pParent || !pParent->isAlive() || !pParent->isInCombat())
+ {
+ Parent = 0;
+ m_creature->DealDamage(m_creature, m_creature->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NONE, NULL, false);
+ return;
+ }
+
+ CheckTimer = 1000;
+ }else CheckTimer -= diff;
+
+ DoMeleeAttackIfReady();
+}
+
+void flesh_tentacleAI::JustDied(Unit* killer)
+{
+ if (!Parent)
+ {
+ error_log("SD2: flesh_tentacle: No Parent variable");
+ return;
+ }
+
+ if (Creature* pCthun = m_creature->GetMap()->GetCreature(Parent))
+ {
+ if (cthunAI* pCthunAI = dynamic_cast(pCthun->AI()))
+ pCthunAI->FleshTentcleKilled();
+ }
+ else
+ error_log("SD2: flesh_tentacle: No Cthun");
+}
+
+//GetAIs
+CreatureAI* GetAI_eye_of_cthun(Creature* pCreature)
+{
+ return new eye_of_cthunAI(pCreature);
+}
+
+CreatureAI* GetAI_cthun(Creature* pCreature)
+{
+ return new cthunAI(pCreature);
+}
+
+CreatureAI* GetAI_eye_tentacle(Creature* pCreature)
+{
+ return new eye_tentacleAI(pCreature);
+}
+
+CreatureAI* GetAI_claw_tentacle(Creature* pCreature)
+{
+ return new claw_tentacleAI(pCreature);
+}
+
+CreatureAI* GetAI_giant_claw_tentacle(Creature* pCreature)
+{
+ return new giant_claw_tentacleAI(pCreature);
+}
+
+CreatureAI* GetAI_giant_eye_tentacle(Creature* pCreature)
+{
+ return new giant_eye_tentacleAI(pCreature);
+}
+
+CreatureAI* GetAI_flesh_tentacle(Creature* pCreature)
+{
+ return new flesh_tentacleAI(pCreature);
+}
+
+void AddSC_boss_cthun()
+{
+ Script *newscript;
+
+ //Eye
+ newscript = new Script;
+ newscript->Name = "boss_eye_of_cthun";
+ newscript->GetAI = &GetAI_eye_of_cthun;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_cthun";
+ newscript->GetAI = &GetAI_cthun;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_eye_tentacle";
+ newscript->GetAI = &GetAI_eye_tentacle;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_claw_tentacle";
+ newscript->GetAI = &GetAI_claw_tentacle;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_giant_claw_tentacle";
+ newscript->GetAI = &GetAI_giant_claw_tentacle;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_giant_eye_tentacle";
+ newscript->GetAI = &GetAI_giant_eye_tentacle;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_giant_flesh_tentacle";
+ newscript->GetAI = &GetAI_flesh_tentacle;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp
new file mode 100644
index 0000000..fc7c3fb
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp
@@ -0,0 +1,198 @@
+/* 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_Fankriss
+SD%Complete: 100
+SDComment: sound not implemented
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SOUND_SENTENCE_YOU 8588
+#define SOUND_SERVE_TO 8589
+#define SOUND_LAWS 8590
+#define SOUND_TRESPASS 8591
+#define SOUND_WILL_BE 8592
+
+#define SPELL_MORTAL_WOUND 28467
+#define SPELL_ROOT 28858
+
+// Enrage for his spawns
+#define SPELL_ENRAGE 28798
+
+struct MANGOS_DLL_DECL boss_fankrissAI : public ScriptedAI
+{
+ boss_fankrissAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 MortalWound_Timer;
+ uint32 SpawnHatchlings_Timer;
+ uint32 SpawnSpawns_Timer;
+ int Rand;
+ int RandX;
+ int RandY;
+
+ Creature* Hatchling;
+ Creature* Spawn;
+
+ void Reset()
+ {
+ MortalWound_Timer = urand(10000, 15000);
+ SpawnHatchlings_Timer = urand(6000, 12000);
+ SpawnSpawns_Timer = urand(15000, 45000);
+ }
+
+ void SummonSpawn(Unit* pVictim)
+ {
+ Rand = 10 + (rand()%10);
+ switch(urand(0, 1))
+ {
+ case 0: RandX = 0 - Rand; break;
+ case 1: RandX = 0 + Rand; break;
+ }
+ Rand = 0;
+ Rand = 10 + (rand()%10);
+ switch(urand(0, 1))
+ {
+ case 0: RandY = 0 - Rand; break;
+ case 1: RandY = 0 + Rand; break;
+ }
+ Rand = 0;
+ Spawn = DoSpawnCreature(15630, RandX, RandY, 0, 0, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 30000);
+ if (Spawn && pVictim)
+ Spawn->AI()->AttackStart(pVictim);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //MortalWound_Timer
+ if (MortalWound_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_MORTAL_WOUND);
+ MortalWound_Timer = urand(10000, 20000);
+ }else MortalWound_Timer -= diff;
+
+ //Summon 1-3 Spawns of Fankriss at random time.
+ if (SpawnSpawns_Timer < diff)
+ {
+ switch(urand(0, 2))
+ {
+ case 0:
+ SummonSpawn(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0));
+ break;
+ case 1:
+ SummonSpawn(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0));
+ SummonSpawn(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0));
+ break;
+ case 2:
+ SummonSpawn(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0));
+ SummonSpawn(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0));
+ SummonSpawn(m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0));
+ break;
+ }
+ SpawnSpawns_Timer = urand(30000, 60000);
+ }else SpawnSpawns_Timer -= diff;
+
+ // Teleporting Random Target to one of the three tunnels and spawn 4 hatchlings near the gamer.
+ //We will only telport if fankriss has more than 3% of hp so teleported gamers can always loot.
+ if (m_creature->GetHealthPercent() > 3.0f)
+ {
+ if (SpawnHatchlings_Timer< diff)
+ {
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+ if (target && target->GetTypeId() == TYPEID_PLAYER)
+ {
+ DoCastSpellIfCan(target, SPELL_ROOT);
+
+ if (m_creature->getThreatManager().getThreat(target))
+ m_creature->getThreatManager().modifyThreatPercent(target, -100);
+
+ switch(urand(0, 2))
+ {
+ case 0:
+ DoTeleportPlayer(target, -8106.0142f, 1289.2900f, -74.419533f, 5.112f);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()-3, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ break;
+ case 1:
+ DoTeleportPlayer(target, -7990.135354f, 1155.1907f, -78.849319f, 2.608f);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()-3, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ break;
+ case 2:
+ DoTeleportPlayer(target, -8159.7753f, 1127.9064f, -76.868660f, 0.675f);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()-3, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-3, target->GetPositionY()+3, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()-5, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ Hatchling = m_creature->SummonCreature(15962, target->GetPositionX()-5, target->GetPositionY()+5, target->GetPositionZ(), 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 15000);
+ if (Hatchling)
+ Hatchling->AI()->AttackStart(target);
+ break;
+ }
+ }
+ SpawnHatchlings_Timer = urand(45000, 60000);
+ }else SpawnHatchlings_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_fankriss(Creature* pCreature)
+{
+ return new boss_fankrissAI(pCreature);
+}
+
+void AddSC_boss_fankriss()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_fankriss";
+ newscript->GetAI = &GetAI_boss_fankriss;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp
new file mode 100644
index 0000000..5e60935
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp
@@ -0,0 +1,143 @@
+/* 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_Huhuran
+SD%Complete: 100
+SDComment:
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+#define EMOTE_GENERIC_FRENZY_KILL -1000001
+#define EMOTE_GENERIC_BERSERK -1000004
+
+#define SPELL_FRENZY 26051
+#define SPELL_BERSERK 26068
+#define SPELL_POISONBOLT 26052
+#define SPELL_NOXIOUSPOISON 26053
+#define SPELL_WYVERNSTING 26180
+#define SPELL_ACIDSPIT 26050
+
+struct MANGOS_DLL_DECL boss_huhuranAI : public ScriptedAI
+{
+ boss_huhuranAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 Frenzy_Timer;
+ uint32 Wyvern_Timer;
+ uint32 Spit_Timer;
+ uint32 PoisonBolt_Timer;
+ uint32 NoxiousPoison_Timer;
+ uint32 FrenzyBack_Timer;
+
+ bool Frenzy;
+ bool Berserk;
+
+ void Reset()
+ {
+ Frenzy_Timer = urand(25000, 35000);
+ Wyvern_Timer = urand(18000, 28000);
+ Spit_Timer = 8000;
+ PoisonBolt_Timer = 4000;
+ NoxiousPoison_Timer = urand(10000, 20000);
+ FrenzyBack_Timer = 15000;
+
+ Frenzy = false;
+ Berserk = false;
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //Frenzy_Timer
+ if (!Frenzy && Frenzy_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_FRENZY);
+ DoScriptText(EMOTE_GENERIC_FRENZY_KILL, m_creature);
+ Frenzy = true;
+ PoisonBolt_Timer = 3000;
+ Frenzy_Timer = urand(25000, 35000);
+ }else Frenzy_Timer -= diff;
+
+ // Wyvern Timer
+ if (Wyvern_Timer < diff)
+ {
+ if (Unit *target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0))
+ DoCastSpellIfCan(target,SPELL_WYVERNSTING);
+ Wyvern_Timer = urand(15000, 32000);
+ }else Wyvern_Timer -= diff;
+
+ //Spit Timer
+ if (Spit_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_ACIDSPIT);
+ Spit_Timer = urand(5000, 10000);
+ }else Spit_Timer -= diff;
+
+ //NoxiousPoison_Timer
+ if (NoxiousPoison_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_NOXIOUSPOISON);
+ NoxiousPoison_Timer = urand(12000, 24000);
+ }else NoxiousPoison_Timer -= diff;
+
+ //PoisonBolt only if frenzy or berserk
+ if (Frenzy || Berserk)
+ {
+ if (PoisonBolt_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_POISONBOLT);
+ PoisonBolt_Timer = 3000;
+ }else PoisonBolt_Timer -= diff;
+ }
+
+ //FrenzyBack_Timer
+ if (Frenzy && FrenzyBack_Timer < diff)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ Frenzy = false;
+ FrenzyBack_Timer = 15000;
+ }else FrenzyBack_Timer -= diff;
+
+ if (!Berserk && m_creature->GetHealthPercent() < 31.0f)
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoScriptText(EMOTE_GENERIC_BERSERK, m_creature);
+ DoCastSpellIfCan(m_creature, SPELL_BERSERK);
+ Berserk = true;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_boss_huhuran(Creature* pCreature)
+{
+ return new boss_huhuranAI(pCreature);
+}
+
+void AddSC_boss_huhuran()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_huhuran";
+ newscript->GetAI = &GetAI_boss_huhuran;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp
new file mode 100644
index 0000000..cc3a8f8
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp
@@ -0,0 +1,178 @@
+/* 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_Ouro
+SD%Complete: 50
+SDComment: script needs to be reworked
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+#include "temple_of_ahnqiraj.h"
+
+enum
+{
+ SPELL_SWEEP = 26103,
+ SPELL_SANDBLAST = 26102,
+ SPELL_GROUND_RUPTURE = 26100,
+ SPELL_BIRTH = 26262, //The Birth Animation
+ SPELL_BOULDER = 26616,
+ SPELL_BERSERK = 26615,
+
+ SPELL_SUMMON_SCARABS = 26060,
+ SPELL_SUMMON_OURO_MOUND = 26058,
+ SPELL_SUMMON_OURO = 26642,
+
+ SPELL_DIRTMOUND_PASSIVE = 26092,
+ SPELL_SUBMERGE_VISUAL = 26063,
+
+ NPC_OURO_SCARAB = 15718,
+ NPC_OURO_SPAWNER = 15957,
+ NPC_OURO_TRIGGER = 15717
+};
+
+struct MANGOS_DLL_DECL boss_ouroAI : public ScriptedAI
+{
+ boss_ouroAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 m_uiSweepTimer;
+ uint32 m_uiSandBlastTimer;
+ uint32 m_uiSubmergeTimer;
+ uint32 m_uiBackTimer;
+ uint32 m_uiChangeTargetTimer;
+ uint32 m_uiSpawnTimer;
+
+ bool m_bEnraged;
+ bool m_bSubmerged;
+
+ void Reset()
+ {
+ m_uiSweepTimer = urand(5000, 10000);
+ m_uiSandBlastTimer = urand(20000, 35000);
+ m_uiSubmergeTimer = urand(90000, 150000);
+ m_uiBackTimer = urand(30000, 45000);
+ m_uiChangeTargetTimer = urand(5000, 8000);
+ m_uiSpawnTimer = urand(10000, 20000);
+
+ m_bEnraged = false;
+ m_bSubmerged = false;
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BIRTH);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ // Return since we have no pTarget
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!m_bSubmerged)
+ {
+ // Sweep
+ if (m_uiSweepTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SWEEP);
+ m_uiSweepTimer = urand(15000, 30000);
+ }
+ else
+ m_uiSweepTimer -= uiDiff;
+
+ // Sand Blast
+ if (m_uiSandBlastTimer < uiDiff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_SANDBLAST);
+ m_uiSandBlastTimer = urand(20000, 35000);
+ }
+ else
+ m_uiSandBlastTimer -= uiDiff;
+
+ if (!m_bEnraged)
+ {
+ if (m_creature->GetHealthPercent() < 20.0f)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BERSERK);
+ m_bEnraged = true;
+ return;
+ }
+
+ // Submerge
+ if (m_uiSubmergeTimer < uiDiff)
+ {
+ //Cast
+ m_creature->HandleEmote(EMOTE_ONESHOT_SUBMERGE);
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->setFaction(35);
+ DoCastSpellIfCan(m_creature, SPELL_DIRTMOUND_PASSIVE);
+
+ m_bSubmerged = true;
+ m_uiBackTimer = urand(30000, 45000);
+ }
+ else
+ m_uiSubmergeTimer -= uiDiff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ else
+ {
+ // Change Target
+ if (m_uiChangeTargetTimer < uiDiff)
+ {
+ if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
+ {
+ m_creature->GetMap()->CreatureRelocation(m_creature, pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), 0.0f);
+ m_creature->SendMonsterMove(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), SPLINETYPE_NORMAL, SPLINEFLAG_WALKMODE, 1);
+ }
+
+ m_uiChangeTargetTimer = urand(10000, 20000);
+ }
+ else
+ m_uiChangeTargetTimer -= uiDiff;
+
+ // Back
+ if (m_uiBackTimer < uiDiff)
+ {
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->setFaction(14);
+
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_GROUND_RUPTURE);
+
+ m_bSubmerged = false;
+ m_uiSubmergeTimer = urand(60000, 120000);
+ }
+ else
+ m_uiBackTimer -= uiDiff;
+ }
+ }
+};
+
+CreatureAI* GetAI_boss_ouro(Creature* pCreature)
+{
+ return new boss_ouroAI(pCreature);
+}
+
+void AddSC_boss_ouro()
+{
+ Script* newscript;
+ newscript = new Script;
+ newscript->Name = "boss_ouro";
+ newscript->GetAI = &GetAI_boss_ouro;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp
new file mode 100644
index 0000000..ce86a0c
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp
@@ -0,0 +1,292 @@
+/* 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_Sartura
+SD%Complete: 95
+SDComment:
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SAY_AGGRO -1531008
+#define SAY_SLAY -1531009
+#define SAY_DEATH -1531010
+
+#define SPELL_WHIRLWIND 26083
+#define SPELL_ENRAGE 28747 //Not sure if right ID.
+#define SPELL_ENRAGEHARD 28798
+
+//Guard Spell
+#define SPELL_WHIRLWINDADD 26038
+#define SPELL_KNOCKBACK 26027
+
+struct MANGOS_DLL_DECL boss_sarturaAI : public ScriptedAI
+{
+ boss_sarturaAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 WhirlWind_Timer;
+ uint32 WhirlWindRandom_Timer;
+ uint32 WhirlWindEnd_Timer;
+ uint32 AggroReset_Timer;
+ uint32 AggroResetEnd_Timer;
+ uint32 EnrageHard_Timer;
+
+ bool Enraged;
+ bool EnragedHard;
+ bool WhirlWind;
+ bool AggroReset;
+
+ void Reset()
+ {
+ WhirlWind_Timer = 30000;
+ WhirlWindRandom_Timer = urand(3000, 7000);
+ WhirlWindEnd_Timer = 15000;
+ AggroReset_Timer = urand(45000, 55000);
+ AggroResetEnd_Timer = 5000;
+ EnrageHard_Timer = 10*60000;
+
+ WhirlWind = false;
+ AggroReset = false;
+ Enraged = false;
+ EnragedHard = false;
+
+ }
+
+ void Aggro(Unit *who)
+ {
+ DoScriptText(SAY_AGGRO, m_creature);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoScriptText(SAY_SLAY, m_creature);
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (WhirlWind)
+ {
+ if (WhirlWindRandom_Timer < diff)
+ {
+ //Attack random Gamers
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1);
+ if (target)
+ m_creature->AddThreat(target);
+ m_creature->TauntApply(target);
+ AttackStart(target);
+
+ WhirlWindRandom_Timer = urand(3000, 7000);
+ }else WhirlWindRandom_Timer -= diff;
+
+ if (WhirlWindEnd_Timer < diff)
+ {
+ WhirlWind = false;
+ WhirlWind_Timer = urand(25000, 40000);
+ }else WhirlWindEnd_Timer -= diff;
+ }
+
+ if (!WhirlWind)
+ {
+ if (WhirlWind_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_WHIRLWIND);
+ WhirlWind = true;
+ WhirlWindEnd_Timer = 15000;
+ }else WhirlWind_Timer -= diff;
+
+ if (AggroReset_Timer < diff)
+ {
+ //Attack random Gamers
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1);
+ if (target)
+ m_creature->AddThreat(target);
+ m_creature->TauntApply(target);
+ AttackStart(target);
+
+ AggroReset = true;
+ AggroReset_Timer = urand(2000, 5000);
+ }else AggroReset_Timer -= diff;
+
+ if (AggroReset)
+ {
+ if (AggroResetEnd_Timer GetHealthPercent() <= 20.0f && !m_creature->IsNonMeleeSpellCasted(false))
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
+ Enraged = true;
+ }
+ }
+
+ //After 10 minutes hard enrage
+ if (!EnragedHard)
+ {
+ if (EnrageHard_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_ENRAGEHARD);
+ EnragedHard = true;
+ } else EnrageHard_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+ }
+};
+
+struct MANGOS_DLL_DECL mob_sartura_royal_guardAI : public ScriptedAI
+{
+ mob_sartura_royal_guardAI(Creature* pCreature) : ScriptedAI(pCreature) {Reset();}
+
+ uint32 WhirlWind_Timer;
+ uint32 WhirlWindRandom_Timer;
+ uint32 WhirlWindEnd_Timer;
+ uint32 AggroReset_Timer;
+ uint32 AggroResetEnd_Timer;
+ uint32 KnockBack_Timer;
+
+ bool WhirlWind;
+ bool AggroReset;
+
+ void Reset()
+ {
+ WhirlWind_Timer = 30000;
+ WhirlWindRandom_Timer = urand(3000, 7000);
+ WhirlWindEnd_Timer = 15000;
+ AggroReset_Timer = urand(45000, 55000);
+ AggroResetEnd_Timer = 5000;
+ KnockBack_Timer = 10000;
+
+ WhirlWind = false;
+ AggroReset = false;
+
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!WhirlWind && WhirlWind_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_WHIRLWINDADD);
+ WhirlWind = true;
+ WhirlWind_Timer = urand(25000, 40000);
+ WhirlWindEnd_Timer = 15000;
+ }else WhirlWind_Timer -= diff;
+
+ if (WhirlWind)
+ {
+ if (WhirlWindRandom_Timer < diff)
+ {
+ //Attack random Gamers
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1);
+ if (target)
+ m_creature->AddThreat(target);
+ m_creature->TauntApply(target);
+ AttackStart(target);
+
+ WhirlWindRandom_Timer = urand(3000, 7000);
+ }else WhirlWindRandom_Timer -= diff;
+
+ if (WhirlWindEnd_Timer < diff)
+ {
+ WhirlWind = false;
+ }else WhirlWindEnd_Timer -= diff;
+ }
+
+ if (!WhirlWind)
+ {
+ if (AggroReset_Timer < diff)
+ {
+ //Attack random Gamers
+ Unit* target = NULL;
+ target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,1);
+ if (target)
+ m_creature->AddThreat(target);
+ m_creature->TauntApply(target);
+ AttackStart(target);
+
+ AggroReset = true;
+ AggroReset_Timer = urand(2000, 5000);
+ }else AggroReset_Timer -= diff;
+
+ if (KnockBack_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature, SPELL_WHIRLWINDADD);
+ KnockBack_Timer = urand(10000, 20000);
+ }else KnockBack_Timer -= diff;
+ }
+
+ if (AggroReset)
+ {
+ if (AggroResetEnd_Timer Name = "boss_sartura";
+ newscript->GetAI = &GetAI_boss_sartura;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "mob_sartura_royal_guard";
+ newscript->GetAI = &GetAI_mob_sartura_royal_guard;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp
new file mode 100644
index 0000000..c154ee5
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp
@@ -0,0 +1,306 @@
+/* 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_Skeram
+SD%Complete: 75
+SDComment: Mind Control buggy.
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+#include "temple_of_ahnqiraj.h"
+#include "Group.h"
+
+#define SAY_AGGRO1 -1531000
+#define SAY_AGGRO2 -1531001
+#define SAY_AGGRO3 -1531002
+#define SAY_SLAY1 -1531003
+#define SAY_SLAY2 -1531004
+#define SAY_SLAY3 -1531005
+#define SAY_SPLIT -1531006
+#define SAY_DEATH -1531007
+
+#define SPELL_ARCANE_EXPLOSION 25679
+#define SPELL_EARTH_SHOCK 26194
+#define SPELL_TRUE_FULFILLMENT4 26526
+#define SPELL_BLINK 28391
+
+class ov_mycoordinates
+{
+ public:
+ float x,y,z,r;
+ ov_mycoordinates(float cx, float cy, float cz, float cr)
+ {
+ x = cx; y = cy; z = cz; r = cr;
+ }
+};
+
+struct MANGOS_DLL_DECL boss_skeramAI : public ScriptedAI
+{
+ boss_skeramAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ IsImage = false;
+ Reset();
+ }
+
+ ScriptedInstance* m_pInstance;
+
+ uint32 ArcaneExplosion_Timer;
+ uint32 EarthShock_Timer;
+ uint32 FullFillment_Timer;
+ uint32 Blink_Timer;
+ uint32 Invisible_Timer;
+
+ Creature *Image1, *Image2;
+
+ bool Images75;
+ bool Images50;
+ bool Images25;
+ bool IsImage;
+ bool Invisible;
+
+ void Reset()
+ {
+ ArcaneExplosion_Timer = urand(6000, 12000);
+ EarthShock_Timer = 2000;
+ FullFillment_Timer = 15000;
+ Blink_Timer = urand(8000, 20000);
+ Invisible_Timer = 500;
+
+ Images75 = false;
+ Images50 = false;
+ Images25 = false;
+ Invisible = false;
+
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetVisibility(VISIBILITY_ON);
+
+ if (IsImage)
+ m_creature->SetDeathState(JUST_DIED);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_SLAY1, m_creature); break;
+ case 1: DoScriptText(SAY_SLAY2, m_creature); break;
+ case 2: DoScriptText(SAY_SLAY3, m_creature); break;
+ }
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (!IsImage)
+ DoScriptText(SAY_DEATH, m_creature);
+ }
+
+ void Aggro(Unit *who)
+ {
+ if (IsImage || Images75)
+ return;
+ switch(urand(0, 2))
+ {
+ case 0: DoScriptText(SAY_AGGRO1, m_creature); break;
+ case 1: DoScriptText(SAY_AGGRO2, m_creature); break;
+ case 2: DoScriptText(SAY_AGGRO3, m_creature); break;
+ }
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ //ArcaneExplosion_Timer
+ if (ArcaneExplosion_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(), SPELL_ARCANE_EXPLOSION);
+ ArcaneExplosion_Timer = urand(8000, 18000);
+ }else ArcaneExplosion_Timer -= diff;
+
+ //If we are within range melee the target
+ if (m_creature->IsWithinDistInMap(m_creature->getVictim(), ATTACK_DISTANCE))
+ {
+ //Make sure our attack is ready and we arn't currently casting
+ if (m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false))
+ {
+ m_creature->AttackerStateUpdate(m_creature->getVictim());
+ m_creature->resetAttackTimer();
+ }
+ }else
+ {
+ //EarthShock_Timer
+ if (EarthShock_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_EARTH_SHOCK);
+ EarthShock_Timer = 1000;
+ }else EarthShock_Timer -= diff;
+ }
+
+ //Blink_Timer
+ if (Blink_Timer < diff)
+ {
+ //DoCastSpellIfCan(m_creature, SPELL_BLINK);
+ switch(urand(0, 2))
+ {
+ case 0:
+ m_creature->GetMap()->CreatureRelocation(m_creature, -8340.782227f, 2083.814453f, 125.648788f, 0.0f);
+ DoResetThreat();
+ break;
+ case 1:
+ m_creature->GetMap()->CreatureRelocation(m_creature, -8341.546875f, 2118.504639f, 133.058151f, 0.0f);
+ DoResetThreat();
+ break;
+ case 2:
+ m_creature->GetMap()->CreatureRelocation(m_creature, -8318.822266f, 2058.231201f, 133.058151f, 0.0f);
+ DoResetThreat();
+ break;
+ }
+ DoStopAttack();
+
+ Blink_Timer = urand(20000, 40000);
+ }else Blink_Timer -= diff;
+
+ float procent = m_creature->GetHealthPercent();
+
+ //Summoning 2 Images and teleporting to a random position on 75% health
+ if (!Images75 && !IsImage && procent <= 75.0f && procent > 70.0f)
+ DoSplit(75);
+
+ //Summoning 2 Images and teleporting to a random position on 50% health
+ if (!Images50 && !IsImage && procent <= 50.0f && procent > 45.0f)
+ DoSplit(50);
+
+ //Summoning 2 Images and teleporting to a random position on 25% health
+ if (!Images25 && !IsImage && procent <= 25.0f && procent > 20.0f)
+ DoSplit(25);
+
+ //Invisible_Timer
+ if (Invisible)
+ {
+ if (Invisible_Timer < diff)
+ {
+ //Making Skeram visible after telporting
+ m_creature->SetVisibility(VISIBILITY_ON);
+ m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+
+ Invisible_Timer = 2500;
+ Invisible = false;
+ }else Invisible_Timer -= diff;
+ }
+
+ DoMeleeAttackIfReady();
+ }
+
+ void DoSplit(int atPercent /* 75 50 25 */)
+ {
+ DoScriptText(SAY_SPLIT, m_creature);
+
+ ov_mycoordinates *place1 = new ov_mycoordinates(-8340.782227f, 2083.814453f, 125.648788f, 0.0f);
+ ov_mycoordinates *place2 = new ov_mycoordinates(-8341.546875f, 2118.504639f, 133.058151f, 0.0f);
+ ov_mycoordinates *place3 = new ov_mycoordinates(-8318.822266f, 2058.231201f, 133.058151f, 0.0f);
+
+ ov_mycoordinates *bossc=place1, *i1=place2, *i2=place3;
+
+ switch(urand(0, 2))
+ {
+ case 0:
+ bossc = place1;
+ i1 = place2;
+ i2 = place3;
+ break;
+ case 1:
+ bossc = place2;
+ i1 = place1;
+ i2 = place3;
+ break;
+ case 2:
+ bossc = place3;
+ i1 = place1;
+ i2 = place2;
+ break;
+ }
+
+ m_creature->RemoveAllAuras();
+ m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ m_creature->SetVisibility(VISIBILITY_OFF);
+
+ m_creature->GetMap()->CreatureRelocation(m_creature, bossc->x, bossc->y, bossc->z, bossc->r);
+
+ Invisible = true;
+ DoResetThreat();
+ DoStopAttack();
+
+ switch (atPercent)
+ {
+ case 75: Images75 = true; break;
+ case 50: Images50 = true; break;
+ case 25: Images25 = true; break;
+ }
+
+ Unit* target = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM,0);
+
+ Image1 = m_creature->SummonCreature(15263, i1->x, i1->y, i1->z, i1->r, TEMPSUMMON_CORPSE_DESPAWN, 30000);
+ if (Image1)
+ {
+ Image1->SetMaxHealth(m_creature->GetMaxHealth() / 5);
+ Image1->SetHealth(m_creature->GetHealth() / 5);
+
+ if (target)
+ Image1->AI()->AttackStart(target);
+
+ if (boss_skeramAI* pImageAI = dynamic_cast(Image1->AI()))
+ pImageAI->IsImage = true;
+ }
+
+ Image2 = m_creature->SummonCreature(15263,i2->x, i2->y, i2->z, i2->r, TEMPSUMMON_CORPSE_DESPAWN, 30000);
+ if (Image2)
+ {
+ Image2->SetMaxHealth(m_creature->GetMaxHealth() / 5);
+ Image2->SetHealth(m_creature->GetHealth() / 5);
+
+ if (target)
+ Image2->AI()->AttackStart(target);
+
+ if (boss_skeramAI* pImageAI = dynamic_cast(Image2->AI()))
+ pImageAI->IsImage = true;
+ }
+
+
+ Invisible = true;
+ delete place1;
+ delete place2;
+ delete place3;
+ }
+};
+
+CreatureAI* GetAI_boss_skeram(Creature* pCreature)
+{
+ return new boss_skeramAI(pCreature);
+}
+
+void AddSC_boss_skeram()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "boss_skeram";
+ newscript->GetAI = &GetAI_boss_skeram;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp
new file mode 100644
index 0000000..829bb0c
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp
@@ -0,0 +1,653 @@
+/* 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_Twinemperors
+SD%Complete: 95
+SDComment:
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+#include "temple_of_ahnqiraj.h"
+#include "WorldPacket.h"
+
+#include "Item.h"
+#include "Spell.h"
+
+#define SPELL_HEAL_BROTHER 7393
+#define SPELL_TWIN_TELEPORT 800 // CTRA watches for this spell to start its teleport timer
+#define SPELL_TWIN_TELEPORT_VISUAL 26638 // visual
+
+#define SPELL_EXPLODEBUG 804
+#define SPELL_MUTATE_BUG 802
+
+#define SOUND_VN_DEATH 8660 //8660 - Death - Feel
+#define SOUND_VN_AGGRO 8661 //8661 - Aggro - Let none
+#define SOUND_VN_KILL 8662 //8661 - Kill - your fate
+
+#define SOUND_VL_AGGRO 8657 //8657 - Aggro - To Late
+#define SOUND_VL_KILL 8658 //8658 - Kill - You will not
+#define SOUND_VL_DEATH 8659 //8659 - Death
+
+#define PULL_RANGE 50
+#define ABUSE_BUG_RANGE 20
+#define SPELL_BERSERK 26662
+#define TELEPORTTIME 30000
+
+#define SPELL_UPPERCUT 26007
+#define SPELL_UNBALANCING_STRIKE 26613
+
+#define VEKLOR_DIST 20 // VL will not come to melee when attacking
+
+#define SPELL_SHADOWBOLT 26006
+#define SPELL_BLIZZARD 26607
+#define SPELL_ARCANEBURST 568
+
+struct MANGOS_DLL_DECL boss_twinemperorsAI : public ScriptedAI
+{
+ ScriptedInstance* m_pInstance;
+ uint32 Heal_Timer;
+ uint32 Teleport_Timer;
+ bool AfterTeleport;
+ uint32 AfterTeleportTimer;
+ bool DontYellWhenDead;
+ uint32 Abuse_Bug_Timer, BugsTimer;
+ bool tspellcasted;
+ uint32 EnrageTimer;
+
+ virtual bool IAmVeklor() = 0;
+ virtual void Reset() = 0;
+ virtual void CastSpellOnBug(Creature *target) = 0;
+
+ boss_twinemperorsAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
+ }
+
+ void TwinReset()
+ {
+ Heal_Timer = 0; // first heal immediately when they get close together
+ Teleport_Timer = TELEPORTTIME;
+ AfterTeleport = false;
+ tspellcasted = false;
+ AfterTeleportTimer = 0;
+ Abuse_Bug_Timer = urand(10000, 17000);
+ BugsTimer = 2000;
+ m_creature->clearUnitState(UNIT_STAT_STUNNED);
+ DontYellWhenDead = false;
+ EnrageTimer = 15*60000;
+ }
+
+ Creature *GetOtherBoss()
+ {
+ if (m_pInstance)
+ {
+ return m_creature->GetMap()->GetCreature(m_pInstance->GetData64(IAmVeklor() ? DATA_VEKNILASH : DATA_VEKLOR));
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ void DamageTaken(Unit *done_by, uint32 &damage)
+ {
+ Creature *pOtherBoss = GetOtherBoss();
+ if (pOtherBoss)
+ {
+ float dPercent = ((float)damage) / ((float)m_creature->GetMaxHealth());
+ int odmg = (int)(dPercent * ((float)pOtherBoss->GetMaxHealth()));
+ int ohealth = pOtherBoss->GetHealth()-odmg;
+ pOtherBoss->SetHealth(ohealth > 0 ? ohealth : 0);
+ if (ohealth <= 0)
+ {
+ pOtherBoss->SetDeathState(JUST_DIED);
+ pOtherBoss->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+ }
+ }
+ }
+
+ void JustDied(Unit* Killer)
+ {
+ if (Creature* pOtherBoss = GetOtherBoss())
+ {
+ pOtherBoss->SetHealth(0);
+ pOtherBoss->SetDeathState(JUST_DIED);
+ pOtherBoss->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
+
+ if (boss_twinemperorsAI* pOtherAI = dynamic_cast(pOtherBoss->AI()))
+ pOtherAI->DontYellWhenDead = true;
+ }
+
+ if (!DontYellWhenDead) // I hope AI is not threaded
+ DoPlaySoundToSet(m_creature, IAmVeklor() ? SOUND_VL_DEATH : SOUND_VN_DEATH);
+ }
+
+ void KilledUnit(Unit* victim)
+ {
+ DoPlaySoundToSet(m_creature, IAmVeklor() ? SOUND_VL_KILL : SOUND_VN_KILL);
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ m_creature->SetInCombatWithZone();
+
+ Creature *pOtherBoss = GetOtherBoss();
+ if (pOtherBoss)
+ {
+ // TODO: we should activate the other boss location so he can start attackning even if nobody
+ // is near I dont know how to do that
+ if (!pOtherBoss->isInCombat())
+ {
+ DoPlaySoundToSet(m_creature, IAmVeklor() ? SOUND_VL_AGGRO : SOUND_VN_AGGRO);
+ pOtherBoss->AI()->AttackStart(pWho);
+ }
+ }
+ }
+
+ void SpellHit(Unit *caster, const SpellEntry *entry)
+ {
+ if (caster == m_creature)
+ return;
+
+ Creature *pOtherBoss = GetOtherBoss();
+ if (entry->Id != SPELL_HEAL_BROTHER || !pOtherBoss)
+ return;
+
+ // add health so we keep same percentage for both brothers
+ uint32 mytotal = m_creature->GetMaxHealth(), histotal = pOtherBoss->GetMaxHealth();
+ float mult = ((float)mytotal) / ((float)histotal);
+ if (mult < 1)
+ mult = 1.0f/mult;
+ #define HEAL_BROTHER_AMOUNT 30000.0f
+ uint32 largerAmount = (uint32)((HEAL_BROTHER_AMOUNT * mult) - HEAL_BROTHER_AMOUNT);
+
+ uint32 myh = m_creature->GetHealth();
+ uint32 hish = pOtherBoss->GetHealth();
+ if (mytotal > histotal)
+ {
+ uint32 h = m_creature->GetHealth()+largerAmount;
+ m_creature->SetHealth(std::min(mytotal, h));
+ }
+ else
+ {
+ uint32 h = pOtherBoss->GetHealth()+largerAmount;
+ pOtherBoss->SetHealth(std::min(histotal, h));
+ }
+ }
+
+ void TryHealBrother(uint32 diff)
+ {
+ if (IAmVeklor()) // this spell heals caster and the other brother so let VN cast it
+ return;
+
+ if (Heal_Timer < diff)
+ {
+ Unit *pOtherBoss = GetOtherBoss();
+ if (pOtherBoss && pOtherBoss->IsWithinDist(m_creature, 60.0f))
+ {
+ DoCastSpellIfCan(pOtherBoss, SPELL_HEAL_BROTHER);
+ Heal_Timer = 1000;
+ }
+ } else Heal_Timer -= diff;
+ }
+
+ Unit *GetAnyoneCloseEnough(float dist, bool totallyRandom)
+ {
+ int cnt = 0;
+ std::list candidates;
+
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ if (m_creature->IsWithinDistInMap(pUnit, dist))
+ {
+ if (!totallyRandom)
+ return pUnit;
+ candidates.push_back((*i));
+ ++cnt;
+ }
+ }
+ if (!cnt)
+ return NULL;
+ for (int randomi = rand() % cnt; randomi > 0; randomi --)
+ candidates.pop_front();
+
+ Unit *ret = m_creature->GetMap()->GetUnit(candidates.front()->getUnitGuid());
+ candidates.clear();
+ return ret;
+ }
+
+ Unit *PickNearestPlayer()
+ {
+ Unit *nearp = NULL;
+ float neardist = 0.0f;
+ ThreatList const& tList = m_creature->getThreatManager().getThreatList();
+ for (ThreatList::const_iterator i = tList.begin();i != tList.end(); ++i)
+ {
+ Unit* pUnit = m_creature->GetMap()->GetUnit((*i)->getUnitGuid());
+
+ if (!pUnit)
+ continue;
+
+ float pudist = pUnit->GetDistance((const Creature *)m_creature);
+ if (!nearp || (neardist > pudist))
+ {
+ nearp = pUnit;
+ neardist = pudist;
+ }
+ }
+ return nearp;
+ }
+
+ void TeleportToMyBrother()
+ {
+ if (!m_pInstance)
+ return;
+
+ Teleport_Timer = TELEPORTTIME;
+
+ if (IAmVeklor())
+ return; // mechanics handled by veknilash so they teleport exactly at the same time and to correct coordinates
+
+ Creature *pOtherBoss = GetOtherBoss();
+ if (pOtherBoss)
+ {
+ //m_creature->MonsterYell("Teleporting ...", LANG_UNIVERSAL, 0);
+ float other_x = pOtherBoss->GetPositionX();
+ float other_y = pOtherBoss->GetPositionY();
+ float other_z = pOtherBoss->GetPositionZ();
+ float other_o = pOtherBoss->GetOrientation();
+
+ Map *thismap = m_creature->GetMap();
+ thismap->CreatureRelocation(pOtherBoss, m_creature->GetPositionX(),
+ m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation());
+ thismap->CreatureRelocation(m_creature, other_x, other_y, other_z, other_o);
+
+ SetAfterTeleport();
+
+ if (boss_twinemperorsAI* pOtherAI = dynamic_cast(pOtherBoss->AI()))
+ pOtherAI->SetAfterTeleport();
+ }
+ }
+
+ void SetAfterTeleport()
+ {
+ m_creature->InterruptNonMeleeSpells(false);
+ DoStopAttack();
+ DoResetThreat();
+ DoCastSpellIfCan(m_creature, SPELL_TWIN_TELEPORT_VISUAL);
+ m_creature->addUnitState(UNIT_STAT_STUNNED);
+ AfterTeleport = true;
+ AfterTeleportTimer = 2000;
+ tspellcasted = false;
+ }
+
+ bool TryActivateAfterTTelep(uint32 diff)
+ {
+ if (AfterTeleport)
+ {
+ if (!tspellcasted)
+ {
+ m_creature->clearUnitState(UNIT_STAT_STUNNED);
+ DoCastSpellIfCan(m_creature, SPELL_TWIN_TELEPORT);
+ m_creature->addUnitState(UNIT_STAT_STUNNED);
+ }
+
+ tspellcasted = true;
+
+ if (AfterTeleportTimer < diff)
+ {
+ AfterTeleport = false;
+ m_creature->clearUnitState(UNIT_STAT_STUNNED);
+ Unit *nearu = PickNearestPlayer();
+ //DoYell(nearu->GetName(), LANG_UNIVERSAL, 0);
+ AttackStart(nearu);
+ m_creature->getThreatManager().addThreat(nearu, 10000);
+ return true;
+ }
+ else
+ {
+ AfterTeleportTimer -= diff;
+ // update important timers which would otherwise get skipped
+ if (EnrageTimer > diff)
+ EnrageTimer -= diff;
+ else
+ EnrageTimer = 0;
+ if (Teleport_Timer > diff)
+ Teleport_Timer -= diff;
+ else
+ Teleport_Timer = 0;
+ return false;
+ }
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ void MoveInLineOfSight(Unit *who)
+ {
+ if (!who || m_creature->getVictim())
+ return;
+
+ if (who->isTargetableForAttack() && who->isInAccessablePlaceFor(m_creature) && m_creature->IsHostileTo(who))
+ {
+ float attackRadius = m_creature->GetAttackDistance(who);
+ if (attackRadius < PULL_RANGE)
+ attackRadius = PULL_RANGE;
+ if (m_creature->IsWithinDistInMap(who, attackRadius) && m_creature->GetDistanceZ(who) <= /*CREATURE_Z_ATTACK_RANGE*/7 /*there are stairs*/)
+ {
+ if (who->HasStealthAura())
+ who->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
+ AttackStart(who);
+ }
+ }
+ }
+
+ Creature *RespawnNearbyBugsAndGetOne()
+ {
+ std::list lUnitList;
+ GetCreatureListWithEntryInGrid(lUnitList,m_creature,15316,150.0f);
+ GetCreatureListWithEntryInGrid(lUnitList,m_creature,15317,150.0f);
+
+ if (lUnitList.empty())
+ return NULL;
+
+ Creature *nearb = NULL;
+
+ for(std::list::iterator iter = lUnitList.begin(); iter != lUnitList.end(); ++iter)
+ {
+ Creature *c = (Creature *)(*iter);
+ if (c->isDead())
+ {
+ c->Respawn();
+ c->setFaction(7);
+ c->RemoveAllAuras();
+ }
+ if (c->IsWithinDistInMap(m_creature, ABUSE_BUG_RANGE))
+ {
+ if (!nearb || !urand(0, 3))
+ nearb = c;
+ }
+ }
+ return nearb;
+ }
+
+ void HandleBugs(uint32 diff)
+ {
+ if (BugsTimer < diff || Abuse_Bug_Timer < diff)
+ {
+ Creature *c = RespawnNearbyBugsAndGetOne();
+ if (Abuse_Bug_Timer < diff)
+ {
+ if (c)
+ {
+ CastSpellOnBug(c);
+ Abuse_Bug_Timer = urand(10000, 17000);
+ }
+ else
+ {
+ Abuse_Bug_Timer = 1000;
+ }
+ }
+ else
+ {
+ Abuse_Bug_Timer -= diff;
+ }
+ BugsTimer = 2000;
+ }
+ else
+ {
+ BugsTimer -= diff;
+ Abuse_Bug_Timer -= diff;
+ }
+ }
+
+ void CheckEnrage(uint32 diff)
+ {
+ if (EnrageTimer < diff)
+ {
+ if (!m_creature->IsNonMeleeSpellCasted(true))
+ {
+ DoCastSpellIfCan(m_creature, SPELL_BERSERK);
+ EnrageTimer = 60*60000;
+ } else EnrageTimer = 0;
+ } else EnrageTimer-=diff;
+ }
+};
+
+struct MANGOS_DLL_DECL boss_veknilashAI : public boss_twinemperorsAI
+{
+ bool IAmVeklor() {return false;}
+ boss_veknilashAI(Creature* pCreature) : boss_twinemperorsAI(pCreature)
+ {
+ Reset();
+ }
+
+ uint32 UpperCut_Timer;
+ uint32 UnbalancingStrike_Timer;
+ uint32 Scarabs_Timer;
+ int Rand;
+ int RandX;
+ int RandY;
+
+ Creature* Summoned;
+
+ void Reset()
+ {
+ TwinReset();
+ UpperCut_Timer = urand(14000, 29000);
+ UnbalancingStrike_Timer = urand(8000, 18000);
+ Scarabs_Timer = urand(7000, 14000);
+
+ //Added. Can be removed if its included in DB.
+ m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true);
+ }
+
+ void CastSpellOnBug(Creature *target)
+ {
+ target->setFaction(14);
+
+ DoCastSpellIfCan(target, SPELL_MUTATE_BUG, CAST_TRIGGERED);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!TryActivateAfterTTelep(diff))
+ return;
+
+ //UnbalancingStrike_Timer
+ if (UnbalancingStrike_Timer < diff)
+ {
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_UNBALANCING_STRIKE);
+ UnbalancingStrike_Timer = urand(8000, 20000);
+ }else UnbalancingStrike_Timer -= diff;
+
+ if (UpperCut_Timer < diff)
+ {
+ Unit* randomMelee = GetAnyoneCloseEnough(ATTACK_DISTANCE, true);
+ if (randomMelee)
+ DoCastSpellIfCan(randomMelee,SPELL_UPPERCUT);
+ UpperCut_Timer = urand(15000, 30000);
+ }else UpperCut_Timer -= diff;
+
+ HandleBugs(diff);
+
+ //Heal brother when 60yrds close
+ TryHealBrother(diff);
+
+ //Teleporting to brother
+ if (Teleport_Timer < diff)
+ {
+ TeleportToMyBrother();
+ }else Teleport_Timer -= diff;
+
+ CheckEnrage(diff);
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+struct MANGOS_DLL_DECL boss_veklorAI : public boss_twinemperorsAI
+{
+ bool IAmVeklor() {return true;}
+ boss_veklorAI(Creature* pCreature) : boss_twinemperorsAI(pCreature)
+ {
+ Reset();
+ }
+
+ uint32 ShadowBolt_Timer;
+ uint32 Blizzard_Timer;
+ uint32 ArcaneBurst_Timer;
+ uint32 Scorpions_Timer;
+ int Rand;
+ int RandX;
+ int RandY;
+
+ Creature* Summoned;
+
+ void Reset()
+ {
+ TwinReset();
+ ShadowBolt_Timer = 0;
+ Blizzard_Timer = urand(15000, 20000);
+ ArcaneBurst_Timer = 1000;
+ Scorpions_Timer = urand(7000, 14000);
+
+ //Added. Can be removed if its included in DB.
+ m_creature->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true);
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MINDAMAGE, 0);
+ m_creature->SetBaseWeaponDamage(BASE_ATTACK, MAXDAMAGE, 0);
+ }
+
+ void CastSpellOnBug(Creature *target)
+ {
+ target->setFaction(14);
+
+ DoCastSpellIfCan(target, SPELL_EXPLODEBUG, CAST_TRIGGERED);
+ }
+
+ void UpdateAI(const uint32 diff)
+ {
+ //Return since we have no target
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ // reset arcane burst after teleport - we need to do this because
+ // when VL jumps to VN's location there will be a warrior who will get only 2s to run away
+ // which is almost impossible
+ if (AfterTeleport)
+ ArcaneBurst_Timer = 5000;
+ if (!TryActivateAfterTTelep(diff))
+ return;
+
+ //ShadowBolt_Timer
+ if (ShadowBolt_Timer < diff)
+ {
+ if (!m_creature->IsWithinDist(m_creature->getVictim(), 45.0f))
+ m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim(), VEKLOR_DIST, 0);
+ else
+ DoCastSpellIfCan(m_creature->getVictim(),SPELL_SHADOWBOLT);
+ ShadowBolt_Timer = 2000;
+ }else ShadowBolt_Timer -= diff;
+
+ //Blizzard_Timer
+ if (Blizzard_Timer < diff)
+ {
+ Unit* target = NULL;
+ target = GetAnyoneCloseEnough(45, true);
+ if (target)
+ DoCastSpellIfCan(target,SPELL_BLIZZARD);
+ Blizzard_Timer = urand(15000, 30000);
+ }else Blizzard_Timer -= diff;
+
+ if (ArcaneBurst_Timer < diff)
+ {
+ Unit *mvic;
+ if ((mvic=GetAnyoneCloseEnough(ATTACK_DISTANCE, false))!=NULL)
+ {
+ DoCastSpellIfCan(mvic,SPELL_ARCANEBURST);
+ ArcaneBurst_Timer = 5000;
+ }
+ }else ArcaneBurst_Timer -= diff;
+
+ HandleBugs(diff);
+
+ //Heal brother when 60yrds close
+ TryHealBrother(diff);
+
+ //Teleporting to brother
+ if (Teleport_Timer < diff)
+ {
+ TeleportToMyBrother();
+ }else Teleport_Timer -= diff;
+
+ CheckEnrage(diff);
+
+ //VL doesn't melee
+ //DoMeleeAttackIfReady();
+ }
+
+ void AttackStart(Unit* who)
+ {
+ if (!who)
+ return;
+
+ // VL doesn't melee
+ if (m_creature->Attack(who, false))
+ {
+ m_creature->AddThreat(who);
+ m_creature->SetInCombatWith(who);
+ who->SetInCombatWith(m_creature);
+
+ m_creature->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0);
+ }
+ }
+};
+
+CreatureAI* GetAI_boss_veknilash(Creature* pCreature)
+{
+ return new boss_veknilashAI(pCreature);
+}
+
+CreatureAI* GetAI_boss_veklor(Creature* pCreature)
+{
+ return new boss_veklorAI(pCreature);
+}
+
+void AddSC_boss_twinemperors()
+{
+ Script *newscript;
+
+ newscript = new Script;
+ newscript->Name = "boss_veknilash";
+ newscript->GetAI = &GetAI_boss_veknilash;
+ newscript->RegisterSelf();
+
+ newscript = new Script;
+ newscript->Name = "boss_veklor";
+ newscript->GetAI = &GetAI_boss_veklor;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp b/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp
new file mode 100644
index 0000000..e9ee3ab
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp
@@ -0,0 +1,29 @@
+/* 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_Viscidus
+SD%Complete: 0
+SDComment: place holder
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+#define SPELL_POISON_SHOCK 25993
+#define SPELL_POISONBOLT_VOLLEY 25991
+
+#define SPELL_TOXIN_CLOUD 25989
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp b/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp
new file mode 100644
index 0000000..393a7d3
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.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_Temple_of_Ahnqiraj
+SD%Complete: 80
+SDComment:
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+#include "temple_of_ahnqiraj.h"
+
+struct MANGOS_DLL_DECL instance_temple_of_ahnqiraj : public ScriptedInstance
+{
+ instance_temple_of_ahnqiraj(Map* pMap) : ScriptedInstance(pMap) {Initialize();};
+
+ uint32 m_auiEncounter[MAX_ENCOUNTER];
+
+ //Storing Skeram, Vem and Kri.
+ uint64 m_uiSkeramGUID;
+ uint64 m_uiVemGUID;
+ uint64 m_uiKriGUID;
+ uint64 m_uiVeklorGUID;
+ uint64 m_uiVeknilashGUID;
+
+ uint32 m_uiBugTrioDeathCount;
+
+ uint32 m_uiCthunPhase;
+
+ void Initialize()
+ {
+ memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
+
+ m_uiSkeramGUID = 0;
+ m_uiVemGUID = 0;
+ m_uiKriGUID = 0;
+ m_uiVeklorGUID = 0;
+ m_uiVeknilashGUID = 0;
+
+ m_uiBugTrioDeathCount = 0;
+
+ m_uiCthunPhase = 0;
+ }
+
+ void OnCreatureCreate (Creature* pCreature)
+ {
+ switch (pCreature->GetEntry())
+ {
+ case 15263: m_uiSkeramGUID = pCreature->GetGUID(); break;
+ case 15544: m_uiVemGUID = pCreature->GetGUID(); break;
+ case 15511: m_uiKriGUID = pCreature->GetGUID(); break;
+ case 15276: m_uiVeklorGUID = pCreature->GetGUID(); break;
+ case 15275: m_uiVeknilashGUID = pCreature->GetGUID(); break;
+ }
+ }
+
+ bool IsEncounterInProgress() const
+ {
+ //not active in AQ40
+ return false;
+ }
+
+ void SetData(uint32 uiType, uint32 uiData)
+ {
+ switch(uiType)
+ {
+ case TYPE_VEM:
+ m_auiEncounter[0] = uiData;
+ break;
+ case TYPE_VEKLOR:
+ m_auiEncounter[1] = uiData;
+ break;
+ case TYPE_VEKNILASH:
+ m_auiEncounter[2] = uiData;
+ break;
+
+ case DATA_BUG_TRIO_DEATH:
+ ++m_uiBugTrioDeathCount;
+ break;
+
+ case TYPE_CTHUN_PHASE:
+ m_uiCthunPhase = uiData;
+ break;
+ }
+ }
+
+ uint32 GetData(uint32 uiType)
+ {
+ switch(uiType)
+ {
+ case TYPE_VEM:
+ return m_auiEncounter[0];
+
+ case DATA_BUG_TRIO_DEATH:
+ return m_uiBugTrioDeathCount;
+
+ case TYPE_CTHUN_PHASE:
+ return m_uiCthunPhase;
+ }
+ return 0;
+ }
+
+ uint64 GetData64(uint32 uiData)
+ {
+ switch(uiData)
+ {
+ case DATA_SKERAM:
+ return m_uiSkeramGUID;
+ case DATA_VEM:
+ return m_uiVemGUID;
+ case DATA_KRI:
+ return m_uiKriGUID;
+ case DATA_VEKLOR:
+ return m_uiVeklorGUID;
+ case DATA_VEKNILASH:
+ return m_uiVeknilashGUID;
+ }
+ return 0;
+ }
+};
+
+InstanceData* GetInstanceData_instance_temple_of_ahnqiraj(Map* pMap)
+{
+ return new instance_temple_of_ahnqiraj(pMap);
+}
+
+void AddSC_instance_temple_of_ahnqiraj()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "instance_temple_of_ahnqiraj";
+ newscript->GetInstanceData = &GetInstanceData_instance_temple_of_ahnqiraj;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp b/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp
new file mode 100644
index 0000000..609097a
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp
@@ -0,0 +1,196 @@
+/* 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: mob_anubisath_sentinel
+SD%Complete: 75
+SDComment: Abilities selection needs further improvements. Shadow storm is not properly implemented in core it should only target ppl outside of melee range.
+SDCategory: Temple of Ahn'Qiraj
+EndScriptData */
+
+#include "precompiled.h"
+
+enum
+{
+ EMOTE_GENERIC_FRENZY = -1000002,
+
+ SPELL_PERIODIC_MANA_BURN = 812,
+ SPELL_MENDING = 2147,
+ SPELL_PERIODIC_SHADOW_STORM = 2148,
+ SPELL_PERIODIC_THUNDERCLAP = 2834,
+ SPELL_MORTAL_STRIKE = 9347,
+ SPELL_FIRE_ARCANE_REFLECT = 13022,
+ SPELL_SHADOW_FROST_REFLECT = 19595,
+ SPELL_PERIODIC_KNOCK_AWAY = 21737,
+ SPELL_THORNS = 25777,
+
+ SPELL_ENRAGE = 8599,
+
+ MAX_BUDDY = 4
+};
+
+struct MANGOS_DLL_DECL npc_anubisath_sentinelAI : public ScriptedAI
+{
+ npc_anubisath_sentinelAI(Creature* pCreature) : ScriptedAI(pCreature)
+ {
+ m_lAssistList.clear();
+ Reset();
+ }
+
+ uint32 m_uiMyAbility;
+ bool m_bEnraged;
+
+ std::list m_lAssistList;
+
+ void Reset()
+ {
+ m_uiMyAbility = 0;
+ m_bEnraged = false;
+ }
+
+ void JustReachedHome()
+ {
+ for(std::list::iterator itr = m_lAssistList.begin(); itr != m_lAssistList.end(); ++itr)
+ {
+ if (*itr == m_creature->GetGUID())
+ continue;
+
+ if (Creature* pBuddy = m_creature->GetMap()->GetCreature(*itr))
+ {
+ if (pBuddy->isDead())
+ pBuddy->Respawn();
+ }
+ }
+ }
+
+ void Aggro(Unit* pWho)
+ {
+ SetAbility();
+ InitSentinelsNear(pWho);
+ }
+
+ void JustDied(Unit* pKiller)
+ {
+ DoTransferAbility();
+ }
+
+ // this way will make it quite possible that sentinels get the same buff as others, need to fix that, it should be one unique each
+ void SetAbility()
+ {
+ switch(urand(0, 8))
+ {
+ case 0: m_uiMyAbility = SPELL_MENDING; break;
+ case 1: m_uiMyAbility = SPELL_PERIODIC_KNOCK_AWAY; break;
+ case 2: m_uiMyAbility = SPELL_PERIODIC_MANA_BURN; break;
+ case 3: m_uiMyAbility = SPELL_FIRE_ARCANE_REFLECT; break;
+ case 4: m_uiMyAbility = SPELL_SHADOW_FROST_REFLECT; break;
+ case 5: m_uiMyAbility = SPELL_THORNS; break;
+ case 6: m_uiMyAbility = SPELL_PERIODIC_THUNDERCLAP; break;
+ case 7: m_uiMyAbility = SPELL_MORTAL_STRIKE; break;
+ case 8: m_uiMyAbility = SPELL_PERIODIC_SHADOW_STORM; break;
+ }
+
+ DoCastSpellIfCan(m_creature, m_uiMyAbility, CAST_TRIGGERED);
+ }
+
+ void DoTransferAbility()
+ {
+ for(std::list::iterator itr = m_lAssistList.begin(); itr != m_lAssistList.end(); ++itr)
+ {
+ if (Creature* pBuddy = m_creature->GetMap()->GetCreature(*itr))
+ {
+ if (*itr == m_creature->GetGUID())
+ continue;
+
+ if (!pBuddy->isAlive())
+ continue;
+
+ pBuddy->SetHealth(pBuddy->GetMaxHealth());
+ DoCastSpellIfCan(pBuddy, m_uiMyAbility, CAST_TRIGGERED);
+ }
+ }
+ }
+
+ void InitSentinelsNear(Unit* pTarget)
+ {
+ if (!m_lAssistList.empty())
+ {
+ for(std::list::iterator itr = m_lAssistList.begin(); itr != m_lAssistList.end(); ++itr)
+ {
+ if (*itr == m_creature->GetGUID())
+ continue;
+
+ if (Creature* pBuddy = m_creature->GetMap()->GetCreature(*itr))
+ {
+ if (pBuddy->isAlive())
+ pBuddy->AI()->AttackStart(pTarget);
+ }
+ }
+
+ return;
+ }
+
+ std::list lAssistList;
+ GetCreatureListWithEntryInGrid(lAssistList, m_creature, m_creature->GetEntry(), 80.0f);
+
+ if (lAssistList.empty())
+ return;
+
+ for(std::list::iterator iter = lAssistList.begin(); iter != lAssistList.end(); ++iter)
+ {
+ m_lAssistList.push_back((*iter)->GetGUID());
+
+ if ((*iter)->GetGUID() == m_creature->GetGUID())
+ continue;
+
+ (*iter)->AI()->AttackStart(pTarget);
+ }
+
+ if (m_lAssistList.size() != MAX_BUDDY)
+ error_log("SD2: npc_anubisath_sentinel found too few/too many buddies, expected %u.", MAX_BUDDY);
+ }
+
+ void UpdateAI(const uint32 uiDiff)
+ {
+ if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
+ return;
+
+ if (!m_bEnraged && m_creature->GetHealthPercent() < 30.0f)
+ {
+ if (DoCastSpellIfCan(m_creature, SPELL_ENRAGE) == CAST_OK)
+ {
+ DoScriptText(EMOTE_GENERIC_FRENZY, m_creature);
+ m_bEnraged = true;
+ }
+ }
+
+ DoMeleeAttackIfReady();
+ }
+};
+
+CreatureAI* GetAI_npc_anubisath_sentinel(Creature* pCreature)
+{
+ return new npc_anubisath_sentinelAI(pCreature);
+}
+
+void AddSC_mob_anubisath_sentinel()
+{
+ Script *newscript;
+ newscript = new Script;
+ newscript->Name = "mob_anubisath_sentinel";
+ newscript->GetAI = &GetAI_npc_anubisath_sentinel;
+ newscript->RegisterSelf();
+}
diff --git a/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h b/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h
new file mode 100644
index 0000000..6f59313
--- /dev/null
+++ b/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h
@@ -0,0 +1,27 @@
+/* Copyright (C) 2006 - 2010 ScriptDev2