aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml8
-rw-r--r--CMakeLists.txt1
-rw-r--r--CONTRIBUTING.md2
-rw-r--r--cmake/compiler/clang/settings.cmake2
-rw-r--r--cmake/compiler/gcc/settings.cmake2
-rw-r--r--cmake/compiler/msvc/settings.cmake4
-rw-r--r--cmake/macros/ConfigureScripts.cmake104
-rw-r--r--cmake/options.cmake21
-rw-r--r--cmake/showoptions.cmake20
-rw-r--r--contrib/check_updates.sh5
-rw-r--r--dep/CMakeLists.txt2
-rw-r--r--dep/boost/CMakeLists.txt31
-rw-r--r--dep/efsw/CMakeLists.txt4
-rw-r--r--issue_template.md10
-rw-r--r--revision_data.h.in.cmake2
-rw-r--r--sql/base/auth_database.sql6
-rw-r--r--sql/base/characters_database.sql8
-rw-r--r--sql/base/dev/world_database.sql6
-rw-r--r--sql/old/3.3.5a/auth/60_2016_04_11/2015_11_07_00_auth.sql (renamed from sql/updates/auth/2015_11_07_00_auth.sql)0
-rw-r--r--sql/old/3.3.5a/auth/60_2016_04_11/2016_01_13_00_auth.sql (renamed from sql/updates/auth/2016_01_13_00_auth.sql)0
-rw-r--r--sql/old/3.3.5a/characters/60_2016_04_11/2015_11_07_00_characters.sql (renamed from sql/updates/characters/2015_11_07_00_characters.sql)0
-rw-r--r--sql/old/3.3.5a/characters/60_2016_04_11/2016_02_10_00_characters.sql (renamed from sql/updates/characters/2016_02_10_00_characters.sql)0
-rw-r--r--sql/old/3.3.5a/characters/60_2016_04_11/2016_03_13_2016_01_05_00_characters.sql (renamed from sql/updates/characters/2016_03_13_2016_01_05_00_characters.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_07_02_world.sql (renamed from sql/updates/world/2015_11_07_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_00_world.sql (renamed from sql/updates/world/2015_11_08_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_01_world.sql (renamed from sql/updates/world/2015_11_08_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_00_world.sql (renamed from sql/updates/world/2015_11_09_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_01_world.sql (renamed from sql/updates/world/2015_11_09_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_02_world_335.sql (renamed from sql/updates/world/2015_11_09_02_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_00_world.sql (renamed from sql/updates/world/2015_11_10_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_01_world.sql (renamed from sql/updates/world/2015_11_10_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_02_world.sql (renamed from sql/updates/world/2015_11_10_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_00_world.sql (renamed from sql/updates/world/2015_11_11_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_01_world.sql (renamed from sql/updates/world/2015_11_11_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_00_world.sql (renamed from sql/updates/world/2015_11_12_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_01_world.sql (renamed from sql/updates/world/2015_11_12_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_20_00_world.sql (renamed from sql/updates/world/2015_11_20_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_00_world.sql (renamed from sql/updates/world/2015_11_22_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_01_world.sql (renamed from sql/updates/world/2015_11_22_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_02_world.sql (renamed from sql/updates/world/2015_11_22_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_03_world_355.sql (renamed from sql/updates/world/2015_11_22_03_world_355.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_00_world_335.sql (renamed from sql/updates/world/2015_11_23_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_01_world_335.sql (renamed from sql/updates/world/2015_11_23_01_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_02_world_335.sql (renamed from sql/updates/world/2015_11_23_02_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_03_world_335.sql (renamed from sql/updates/world/2015_11_23_03_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_04_world_335.sql (renamed from sql/updates/world/2015_11_23_04_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_05_world.sql (renamed from sql/updates/world/2015_11_23_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_24_00_world_355.sql (renamed from sql/updates/world/2015_11_24_00_world_355.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_27_00_world.sql (renamed from sql/updates/world/2015_11_27_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_00_world.sql (renamed from sql/updates/world/2015_11_28_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_01_world_335.sql (renamed from sql/updates/world/2015_11_28_01_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_00_world.sql (renamed from sql/updates/world/2015_11_29_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_01_world.sql (renamed from sql/updates/world/2015_11_29_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_01_00_world.sql (renamed from sql/updates/world/2015_12_01_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_04_00_world.sql (renamed from sql/updates/world/2015_12_04_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_05_00_world.sql (renamed from sql/updates/world/2015_12_05_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_06_00_world.sql (renamed from sql/updates/world/2015_12_06_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_00_world_335.sql (renamed from sql/updates/world/2015_12_08_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_01_world.sql (renamed from sql/updates/world/2015_12_08_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_02_world.sql (renamed from sql/updates/world/2015_12_08_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_00_world.sql (renamed from sql/updates/world/2015_12_09_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_01_world.sql (renamed from sql/updates/world/2015_12_09_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_11_00_world.sql (renamed from sql/updates/world/2015_12_11_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_14_00_world.sql (renamed from sql/updates/world/2015_12_14_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_00_world.sql (renamed from sql/updates/world/2015_12_15_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_01_world.sql (renamed from sql/updates/world/2015_12_15_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_02_world.sql (renamed from sql/updates/world/2015_12_15_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_03_world.sql (renamed from sql/updates/world/2015_12_15_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_00_world.sql (renamed from sql/updates/world/2015_12_16_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_01_world.sql (renamed from sql/updates/world/2015_12_16_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_02_world_335.sql (renamed from sql/updates/world/2015_12_16_02_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_17_00_world.sql (renamed from sql/updates/world/2015_12_17_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_00_world_335.sql (renamed from sql/updates/world/2015_12_18_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_01_world.sql (renamed from sql/updates/world/2015_12_18_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_02_world.sql (renamed from sql/updates/world/2015_12_18_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_03_world_335.sql (renamed from sql/updates/world/2015_12_18_03_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_04_world.sql (renamed from sql/updates/world/2015_12_18_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_20_00_world.sql (renamed from sql/updates/world/2015_12_20_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_24_00_world.sql (renamed from sql/updates/world/2015_12_24_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_00_world.sql (renamed from sql/updates/world/2015_12_26_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_01_world.sql (renamed from sql/updates/world/2015_12_26_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_02_world.sql (renamed from sql/updates/world/2015_12_26_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_00_world.sql (renamed from sql/updates/world/2015_12_29_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_01_world.sql (renamed from sql/updates/world/2015_12_29_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_02_world.sql (renamed from sql/updates/world/2015_12_29_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_03_world.sql (renamed from sql/updates/world/2015_12_29_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_04_world.sql (renamed from sql/updates/world/2015_12_29_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_05_world.sql (renamed from sql/updates/world/2015_12_29_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_06_world.sql (renamed from sql/updates/world/2015_12_29_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_07_world.sql (renamed from sql/updates/world/2015_12_29_07_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_08_world.sql (renamed from sql/updates/world/2015_12_29_08_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_09_world.sql (renamed from sql/updates/world/2015_12_29_09_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_10_world.sql (renamed from sql/updates/world/2015_12_29_10_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_11_world.sql (renamed from sql/updates/world/2015_12_29_11_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_12_world.sql (renamed from sql/updates/world/2015_12_29_12_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_13_world.sql (renamed from sql/updates/world/2015_12_29_13_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_00_world.sql (renamed from sql/updates/world/2015_12_31_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_01_world.sql (renamed from sql/updates/world/2015_12_31_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_00_world.sql (renamed from sql/updates/world/2016_01_01_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_01_world.sql (renamed from sql/updates/world/2016_01_01_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_00_world_335.sql (renamed from sql/updates/world/2016_01_02_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_01_world.sql (renamed from sql/updates/world/2016_01_02_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_00_world_335.sql (renamed from sql/updates/world/2016_01_03_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_01_world.sql (renamed from sql/updates/world/2016_01_03_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_02_world.sql (renamed from sql/updates/world/2016_01_03_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_03_world.sql (renamed from sql/updates/world/2016_01_03_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_04_world.sql (renamed from sql/updates/world/2016_01_03_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_05_world.sql (renamed from sql/updates/world/2016_01_03_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_04_00_world.sql (renamed from sql/updates/world/2016_01_04_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_00_world.sql (renamed from sql/updates/world/2016_01_05_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_01_world.sql (renamed from sql/updates/world/2016_01_05_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_02_world.sql (renamed from sql/updates/world/2016_01_05_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_00_world.sql (renamed from sql/updates/world/2016_01_07_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_01_world.sql (renamed from sql/updates/world/2016_01_07_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_02_world.sql (renamed from sql/updates/world/2016_01_07_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_00_world.sql (renamed from sql/updates/world/2016_01_08_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_01_world.sql (renamed from sql/updates/world/2016_01_08_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_02_world.sql (renamed from sql/updates/world/2016_01_08_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_03_world.sql (renamed from sql/updates/world/2016_01_08_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_09_00_world.sql (renamed from sql/updates/world/2016_01_09_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_00_world.sql (renamed from sql/updates/world/2016_01_10_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_01_world.sql (renamed from sql/updates/world/2016_01_10_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_02_world.sql (renamed from sql/updates/world/2016_01_10_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_03_world.sql (renamed from sql/updates/world/2016_01_10_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_04_world.sql (renamed from sql/updates/world/2016_01_10_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_05_world_335.sql (renamed from sql/updates/world/2016_01_10_05_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_00_world.sql (renamed from sql/updates/world/2016_01_12_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_01_world_335.sql (renamed from sql/updates/world/2016_01_12_01_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_02_world_335.sql (renamed from sql/updates/world/2016_01_12_02_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_03_world.sql (renamed from sql/updates/world/2016_01_12_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_04_world.sql (renamed from sql/updates/world/2016_01_12_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_13_00_world.sql (renamed from sql/updates/world/2016_01_13_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_15_00_world.sql (renamed from sql/updates/world/2016_01_15_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_00_world_335.sql (renamed from sql/updates/world/2016_01_16_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_01_world.sql (renamed from sql/updates/world/2016_01_16_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_02_world.sql (renamed from sql/updates/world/2016_01_16_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_03_world.sql (renamed from sql/updates/world/2016_01_16_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_04_world.sql (renamed from sql/updates/world/2016_01_16_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_05_world.sql (renamed from sql/updates/world/2016_01_16_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_00_world_335.sql (renamed from sql/updates/world/2016_01_17_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_01_world.sql (renamed from sql/updates/world/2016_01_17_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_02_world.sql (renamed from sql/updates/world/2016_01_17_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_03_world.sql (renamed from sql/updates/world/2016_01_17_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_04_world.sql (renamed from sql/updates/world/2016_01_17_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_05_world.sql (renamed from sql/updates/world/2016_01_17_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_06_world.sql (renamed from sql/updates/world/2016_01_17_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_07_world.sql (renamed from sql/updates/world/2016_01_17_07_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_08_world.sql (renamed from sql/updates/world/2016_01_17_08_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_09_world.sql (renamed from sql/updates/world/2016_01_17_09_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_10_world.sql (renamed from sql/updates/world/2016_01_17_10_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_11_world.sql (renamed from sql/updates/world/2016_01_17_11_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_12_world.sql (renamed from sql/updates/world/2016_01_17_12_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_13_world.sql (renamed from sql/updates/world/2016_01_17_13_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_14_world.sql (renamed from sql/updates/world/2016_01_17_14_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_15_world.sql (renamed from sql/updates/world/2016_01_17_15_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_00_world.sql (renamed from sql/updates/world/2016_01_18_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_01_world.sql (renamed from sql/updates/world/2016_01_18_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_02_world.sql (renamed from sql/updates/world/2016_01_18_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_03_world.sql (renamed from sql/updates/world/2016_01_18_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_04_world.sql (renamed from sql/updates/world/2016_01_18_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_05_world.sql (renamed from sql/updates/world/2016_01_18_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_06_world.sql (renamed from sql/updates/world/2016_01_18_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_00_world.sql (renamed from sql/updates/world/2016_01_19_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_01_world.sql (renamed from sql/updates/world/2016_01_19_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_02_world.sql (renamed from sql/updates/world/2016_01_19_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_03_world.sql (renamed from sql/updates/world/2016_01_19_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_04_world.sql (renamed from sql/updates/world/2016_01_19_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_05_world.sql (renamed from sql/updates/world/2016_01_19_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_06_world.sql (renamed from sql/updates/world/2016_01_19_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_07_world.sql (renamed from sql/updates/world/2016_01_19_07_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_08_world.sql (renamed from sql/updates/world/2016_01_19_08_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_00_world.sql (renamed from sql/updates/world/2016_01_20_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_01_world.sql (renamed from sql/updates/world/2016_01_20_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_02_world.sql (renamed from sql/updates/world/2016_01_20_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_23_00_world.sql (renamed from sql/updates/world/2016_01_23_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_24_00_world.sql (renamed from sql/updates/world/2016_01_24_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_26_00_world.sql (renamed from sql/updates/world/2016_01_26_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_00_world_335.sql (renamed from sql/updates/world/2016_01_28_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_01_world.sql (renamed from sql/updates/world/2016_01_28_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_00_world_335.sql (renamed from sql/updates/world/2016_01_30_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_01_world.sql (renamed from sql/updates/world/2016_01_30_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_02_world.sql (renamed from sql/updates/world/2016_01_30_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_03_world.sql (renamed from sql/updates/world/2016_01_30_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_04_world.sql (renamed from sql/updates/world/2016_01_30_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_05_world.sql (renamed from sql/updates/world/2016_01_30_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_01_31_00_world.sql (renamed from sql/updates/world/2016_01_31_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_00_world.sql (renamed from sql/updates/world/2016_02_02_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_01_world.sql (renamed from sql/updates/world/2016_02_02_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_04_00_world.sql (renamed from sql/updates/world/2016_02_04_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_05_00_world.sql (renamed from sql/updates/world/2016_02_05_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_00_world.sql (renamed from sql/updates/world/2016_02_06_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_01_world.sql (renamed from sql/updates/world/2016_02_06_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_02_world.sql (renamed from sql/updates/world/2016_02_06_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_03_world.sql (renamed from sql/updates/world/2016_02_06_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_04_world.sql (renamed from sql/updates/world/2016_02_06_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_05_world.sql (renamed from sql/updates/world/2016_02_06_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_06_world.sql (renamed from sql/updates/world/2016_02_06_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_07_world.sql (renamed from sql/updates/world/2016_02_06_07_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_08_world.sql (renamed from sql/updates/world/2016_02_06_08_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_09_world.sql (renamed from sql/updates/world/2016_02_06_09_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_10_world.sql (renamed from sql/updates/world/2016_02_06_10_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_11_world.sql (renamed from sql/updates/world/2016_02_06_11_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_12_world.sql (renamed from sql/updates/world/2016_02_06_12_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_13_world_335.sql (renamed from sql/updates/world/2016_02_06_13_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_14_world.sql (renamed from sql/updates/world/2016_02_06_14_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_00_world.sql (renamed from sql/updates/world/2016_02_07_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_01_world_335.sql (renamed from sql/updates/world/2016_02_07_01_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_02_world_335.sql (renamed from sql/updates/world/2016_02_07_02_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_03_world_335.sql (renamed from sql/updates/world/2016_02_07_03_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_04_world.sql (renamed from sql/updates/world/2016_02_07_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_05_world_335.sql (renamed from sql/updates/world/2016_02_07_05_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_06_world.sql (renamed from sql/updates/world/2016_02_07_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_07_world_335.sql (renamed from sql/updates/world/2016_02_07_07_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_08_world_335.sql (renamed from sql/updates/world/2016_02_07_08_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_09_world.sql (renamed from sql/updates/world/2016_02_07_09_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_10_world.sql (renamed from sql/updates/world/2016_02_07_10_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_11_world.sql (renamed from sql/updates/world/2016_02_07_11_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_12_world.sql (renamed from sql/updates/world/2016_02_07_12_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_13_world.sql (renamed from sql/updates/world/2016_02_07_13_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_14_world.sql (renamed from sql/updates/world/2016_02_07_14_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_15_world.sql (renamed from sql/updates/world/2016_02_07_15_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_00_world_335.sql (renamed from sql/updates/world/2016_02_08_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_01_world.sql (renamed from sql/updates/world/2016_02_08_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_02_world.sql (renamed from sql/updates/world/2016_02_08_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_03_world.sql (renamed from sql/updates/world/2016_02_08_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_04_world.sql (renamed from sql/updates/world/2016_02_08_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_05_world.sql (renamed from sql/updates/world/2016_02_08_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_06_world.sql (renamed from sql/updates/world/2016_02_08_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_07_world.sql (renamed from sql/updates/world/2016_02_08_07_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_08_world.sql (renamed from sql/updates/world/2016_02_08_08_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_00_world.sql (renamed from sql/updates/world/2016_02_09_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_01_world.sql (renamed from sql/updates/world/2016_02_09_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world.sql (renamed from sql/updates/world/2016_02_09_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world_335.sql (renamed from sql/updates/world/2016_02_09_02_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_03_world.sql (renamed from sql/updates/world/2016_02_09_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_04_world.sql (renamed from sql/updates/world/2016_02_09_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_05_world.sql (renamed from sql/updates/world/2016_02_09_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_06_world.sql (renamed from sql/updates/world/2016_02_09_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_07_world.sql (renamed from sql/updates/world/2016_02_09_07_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_08_world.sql (renamed from sql/updates/world/2016_02_09_08_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_00_world.sql (renamed from sql/updates/world/2016_02_10_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_01_world.sql (renamed from sql/updates/world/2016_02_10_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_02_world.sql (renamed from sql/updates/world/2016_02_10_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_03_world.sql (renamed from sql/updates/world/2016_02_10_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_04_world.sql (renamed from sql/updates/world/2016_02_10_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_05_world.sql (renamed from sql/updates/world/2016_02_10_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_06_world.sql (renamed from sql/updates/world/2016_02_10_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_07_world.sql (renamed from sql/updates/world/2016_02_10_07_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_00_world.sql (renamed from sql/updates/world/2016_02_11_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_01_world.sql (renamed from sql/updates/world/2016_02_11_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_02_world.sql (renamed from sql/updates/world/2016_02_11_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_03_world.sql (renamed from sql/updates/world/2016_02_11_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_04_world.sql (renamed from sql/updates/world/2016_02_11_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_05_world.sql (renamed from sql/updates/world/2016_02_11_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_06_world.sql (renamed from sql/updates/world/2016_02_11_06_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_07_world.sql (renamed from sql/updates/world/2016_02_11_07_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_12_00_world.sql (renamed from sql/updates/world/2016_02_12_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_00_world.sql (renamed from sql/updates/world/2016_02_13_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_01_world.sql (renamed from sql/updates/world/2016_02_13_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_02_world.sql (renamed from sql/updates/world/2016_02_13_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_03_world.sql (renamed from sql/updates/world/2016_02_13_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_04_world.sql (renamed from sql/updates/world/2016_02_13_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_00_world.sql (renamed from sql/updates/world/2016_02_14_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_01_world.sql (renamed from sql/updates/world/2016_02_14_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_02_world.sql (renamed from sql/updates/world/2016_02_14_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_03_world.sql (renamed from sql/updates/world/2016_02_14_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_04_world.sql (renamed from sql/updates/world/2016_02_14_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_15_00_world.sql (renamed from sql/updates/world/2016_02_15_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_00_world.sql (renamed from sql/updates/world/2016_02_17_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_01_world.sql (renamed from sql/updates/world/2016_02_17_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_02_world.sql (renamed from sql/updates/world/2016_02_17_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_00_world.sql (renamed from sql/updates/world/2016_02_18_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_01_world.sql (renamed from sql/updates/world/2016_02_18_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_02_world.sql (renamed from sql/updates/world/2016_02_18_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_00_world.sql (renamed from sql/updates/world/2016_02_19_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_01_world_335.sql (renamed from sql/updates/world/2016_02_19_01_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_00_world.sql (renamed from sql/updates/world/2016_02_22_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_01_world.sql (renamed from sql/updates/world/2016_02_22_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_02_world.sql (renamed from sql/updates/world/2016_02_22_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_00_world.sql (renamed from sql/updates/world/2016_02_23_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_01_world.sql (renamed from sql/updates/world/2016_02_23_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_02_world.sql (renamed from sql/updates/world/2016_02_23_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_24_00_world.sql (renamed from sql/updates/world/2016_02_24_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_00_world.sql (renamed from sql/updates/world/2016_02_25_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_01_world_335.sql (renamed from sql/updates/world/2016_02_25_01_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_02_world.sql (renamed from sql/updates/world/2016_02_25_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_00_world.sql (renamed from sql/updates/world/2016_02_26_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_01_world.sql (renamed from sql/updates/world/2016_02_26_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_27_00_world.sql (renamed from sql/updates/world/2016_02_27_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_28_00_world.sql (renamed from sql/updates/world/2016_02_28_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_00_world.sql (renamed from sql/updates/world/2016_02_29_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_01_world.sql (renamed from sql/updates/world/2016_02_29_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_01_00_world_335.sql (renamed from sql/updates/world/2016_03_01_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_02_00_world_335.sql (renamed from sql/updates/world/2016_03_02_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_00_world.sql (renamed from sql/updates/world/2016_03_03_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_01_world.sql (renamed from sql/updates/world/2016_03_03_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_00_world.sql (renamed from sql/updates/world/2016_03_04_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_01_world.sql (renamed from sql/updates/world/2016_03_04_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_02_world_335.sql (renamed from sql/updates/world/2016_03_04_02_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_03_world.sql (renamed from sql/updates/world/2016_03_04_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_05_00_world.sql (renamed from sql/updates/world/2016_03_05_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_00_world.sql (renamed from sql/updates/world/2016_03_06_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_01_world.sql (renamed from sql/updates/world/2016_03_06_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_00_world.sql (renamed from sql/updates/world/2016_03_07_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_01_world.sql (renamed from sql/updates/world/2016_03_07_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_09_00_world.sql (renamed from sql/updates/world/2016_03_09_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_00_world.sql (renamed from sql/updates/world/2016_03_10_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_01_world.sql (renamed from sql/updates/world/2016_03_10_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_12_2015_11_14_00_world.sql (renamed from sql/updates/world/2016_03_12_2015_11_14_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_00_world.sql (renamed from sql/updates/world/2016_03_13_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_01_world.sql (renamed from sql/updates/world/2016_03_13_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_15_00_world.sql (renamed from sql/updates/world/2016_03_15_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_00_world.sql (renamed from sql/updates/world/2016_03_19_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_01_world.sql (renamed from sql/updates/world/2016_03_19_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_02_world.sql (renamed from sql/updates/world/2016_03_19_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_00_world.sql (renamed from sql/updates/world/2016_03_20_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_01_world.sql (renamed from sql/updates/world/2016_03_20_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_02_world.sql (renamed from sql/updates/world/2016_03_20_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_21_00_world.sql (renamed from sql/updates/world/2016_03_21_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_23_00_world.sql (renamed from sql/updates/world/2016_03_23_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_00_world_335.sql (renamed from sql/updates/world/2016_03_24_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_01_world_335.sql (renamed from sql/updates/world/2016_03_24_01_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_02_world.sql (renamed from sql/updates/world/2016_03_24_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_26_00_world.sql (renamed from sql/updates/world/2016_03_26_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_27_00_world.sql (renamed from sql/updates/world/2016_03_27_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_00_world.sql (renamed from sql/updates/world/2016_03_28_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_01_world.sql (renamed from sql/updates/world/2016_03_28_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_03_29_00_world_335.sql (renamed from sql/updates/world/2016_03_29_00_world_335.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_00_world.sql (renamed from sql/updates/world/2016_04_01_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_01_world.sql (renamed from sql/updates/world/2016_04_01_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_00_world.sql (renamed from sql/updates/world/2016_04_02_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_01_world.sql (renamed from sql/updates/world/2016_04_02_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_02_world.sql (renamed from sql/updates/world/2016_04_02_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_00_world.sql (renamed from sql/updates/world/2016_04_03_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_01_world.sql (renamed from sql/updates/world/2016_04_03_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_02_world.sql (renamed from sql/updates/world/2016_04_03_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_04_00_world.sql (renamed from sql/updates/world/2016_04_04_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_00_world.sql (renamed from sql/updates/world/2016_04_05_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_01_world.sql (renamed from sql/updates/world/2016_04_05_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_08_00_world.sql (renamed from sql/updates/world/2016_04_08_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_00_world_2016_03_28_00_world.sql (renamed from sql/updates/world/2016_04_09_00_world_2016_03_28_00_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_01_world.sql (renamed from sql/updates/world/2016_04_09_01_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_02_world.sql (renamed from sql/updates/world/2016_04_09_02_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_03_world.sql (renamed from sql/updates/world/2016_04_09_03_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_04_world.sql (renamed from sql/updates/world/2016_04_09_04_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_05_world.sql (renamed from sql/updates/world/2016_04_09_05_world.sql)0
-rw-r--r--sql/old/3.3.5a/world/60_2016_04_11/2016_04_10_00_world.sql20
-rw-r--r--sql/updates/auth/3.3.5/2016_04_11_00_auth.sql1
-rw-r--r--sql/updates/auth/3.3.5/dummy (renamed from sql/updates/auth/dummy)0
-rw-r--r--sql/updates/characters/3.3.5/2016_04_11_00_characters.sql1
-rw-r--r--sql/updates/characters/3.3.5/dummy (renamed from sql/updates/characters/dummy)0
-rw-r--r--sql/updates/world/3.3.5/2016_04_11_00_world.sql3
-rw-r--r--sql/updates/world/3.3.5/2016_04_11_01_world_335.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_04_11_02_world_335.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_04_15_03_world_335.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_04_16_00_world.sql3
-rw-r--r--sql/updates/world/3.3.5/2016_04_16_01_world.sql307
-rw-r--r--sql/updates/world/3.3.5/2016_04_16_02_world.sql39
-rw-r--r--sql/updates/world/3.3.5/2016_04_16_03_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_04_16_04_world.sql33
-rw-r--r--sql/updates/world/3.3.5/2016_04_17_00_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_04_17_01_world.sql3
-rw-r--r--sql/updates/world/3.3.5/2016_04_17_02_world.sql7
-rw-r--r--sql/updates/world/3.3.5/2016_04_17_03_world.sql6
-rw-r--r--sql/updates/world/3.3.5/2016_04_17_04_world.sql27
-rw-r--r--sql/updates/world/3.3.5/2016_04_20_00_world.sql7
-rw-r--r--sql/updates/world/3.3.5/2016_04_20_01_world.sql5
-rw-r--r--sql/updates/world/3.3.5/2016_04_20_02_world.sql89
-rw-r--r--sql/updates/world/3.3.5/2016_04_20_03_world.sql4
-rw-r--r--sql/updates/world/3.3.5/2016_04_22_00_world.sql20
-rw-r--r--sql/updates/world/3.3.5/2016_04_23_00_world.sql7
-rw-r--r--sql/updates/world/3.3.5/2016_04_23_01_world.sql4
-rw-r--r--sql/updates/world/3.3.5/2016_04_23_02_world.sql19
-rw-r--r--sql/updates/world/3.3.5/2016_04_24_00_world_335.sql3
-rw-r--r--sql/updates/world/3.3.5/2016_04_24_01_world.sql22
-rw-r--r--sql/updates/world/3.3.5/2016_04_25_00_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_04_25_01_world.sql42
-rw-r--r--sql/updates/world/3.3.5/2016_04_25_02_world.sql48
-rw-r--r--sql/updates/world/3.3.5/2016_04_25_03_world.sql47
-rw-r--r--sql/updates/world/3.3.5/2016_04_26_00_world.sql9
-rw-r--r--sql/updates/world/3.3.5/2016_04_26_01_world.sql57
-rw-r--r--sql/updates/world/3.3.5/2016_04_26_02_world.sql16
-rw-r--r--sql/updates/world/3.3.5/2016_04_26_03_world.sql99
-rw-r--r--sql/updates/world/3.3.5/2016_04_28_00_world.sql3
-rw-r--r--sql/updates/world/3.3.5/2016_04_29_00_world.sql55
-rw-r--r--sql/updates/world/3.3.5/2016_04_29_01_world.sql5
-rw-r--r--sql/updates/world/3.3.5/2016_05_01_00_world.sql1
-rw-r--r--sql/updates/world/3.3.5/2016_05_01_01_world.sql68
-rw-r--r--sql/updates/world/3.3.5/2016_05_02_00_world.sql14
-rw-r--r--sql/updates/world/3.3.5/2016_05_02_01_world.sql18
-rw-r--r--sql/updates/world/3.3.5/2016_05_04_00_world.sql1
-rw-r--r--sql/updates/world/3.3.5/2016_05_04_01_world.sql69
-rw-r--r--sql/updates/world/3.3.5/2016_05_04_02_world.sql2
-rw-r--r--sql/updates/world/3.3.5/2016_05_05_00_world.sql13
-rw-r--r--sql/updates/world/3.3.5/dummy0
-rw-r--r--src/common/CMakeLists.txt4
-rw-r--r--src/common/Common.h6
-rw-r--r--src/common/Configuration/Config.cpp6
-rw-r--r--src/common/Configuration/Config.h6
-rw-r--r--src/common/Cryptography/SHA1.cpp8
-rw-r--r--src/common/Cryptography/SHA1.h5
-rw-r--r--src/common/Utilities/Containers.h13
-rw-r--r--src/common/Utilities/StartProcess.cpp269
-rw-r--r--src/common/Utilities/StartProcess.h67
-rw-r--r--src/common/Utilities/Timer.h4
-rw-r--r--src/server/authserver/Main.cpp17
-rw-r--r--src/server/authserver/Server/AuthSession.cpp35
-rw-r--r--src/server/authserver/authserver.conf.dist8
-rw-r--r--src/server/database/CMakeLists.txt1
-rw-r--r--src/server/database/Database/DatabaseWorkerPool.h4
-rw-r--r--src/server/database/Updater/DBUpdater.cpp72
-rw-r--r--src/server/database/Updater/UpdateFetcher.cpp16
-rw-r--r--src/server/database/Updater/UpdateFetcher.h1
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.cpp6
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.h2
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp12
-rw-r--r--src/server/game/AI/CoreAI/PetAI.h2
-rw-r--r--src/server/game/AI/CreatureAI.cpp24
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.cpp2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp6
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp18
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp13
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp41
-rw-r--r--src/server/game/CMakeLists.txt27
-rw-r--r--src/server/game/Chat/Chat.cpp26
-rw-r--r--src/server/game/Chat/Chat.h4
-rw-r--r--src/server/game/DataStores/DBCStores.cpp247
-rw-r--r--src/server/game/DataStores/DBCStores.h5
-rw-r--r--src/server/game/DataStores/DBCStructure.h12
-rw-r--r--src/server/game/DataStores/DBCfmt.h3
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp4
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.cpp12
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.h3
-rw-r--r--src/server/game/DungeonFinding/LFGScripts.cpp6
-rw-r--r--src/server/game/DungeonFinding/LFGScripts.h2
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp44
-rw-r--r--src/server/game/Entities/Creature/Creature.h21
-rw-r--r--src/server/game/Entities/GameObject/GameObject.cpp8
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h4
-rw-r--r--src/server/game/Entities/Item/Item.cpp34
-rw-r--r--src/server/game/Entities/Item/ItemPrototype.cpp121
-rw-r--r--src/server/game/Entities/Item/ItemPrototype.h68
-rw-r--r--src/server/game/Entities/Object/Object.cpp23
-rw-r--r--src/server/game/Entities/Object/Object.h1
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp11
-rw-r--r--src/server/game/Entities/Player/Player.cpp393
-rw-r--r--src/server/game/Entities/Player/Player.h139
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp233
-rw-r--r--src/server/game/Entities/Unit/Unit.h48
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp100
-rw-r--r--src/server/game/Globals/ObjectMgr.h3
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp23
-rw-r--r--src/server/game/Handlers/GroupHandler.cpp19
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp24
-rw-r--r--src/server/game/Handlers/MovementHandler.cpp2
-rw-r--r--src/server/game/Handlers/SpellHandler.cpp10
-rw-r--r--src/server/game/Instances/InstanceScript.cpp14
-rw-r--r--src/server/game/Instances/InstanceScript.h8
-rw-r--r--src/server/game/Maps/Map.cpp20
-rw-r--r--src/server/game/Maps/MapManager.cpp2
-rw-r--r--src/server/game/Maps/MapManager.h8
-rw-r--r--src/server/game/Maps/MapScripts.cpp (renamed from src/server/game/Scripting/MapScripts.cpp)7
-rw-r--r--src/server/game/Miscellaneous/Language.h2
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Movement/MotionMaster.cpp21
-rw-r--r--src/server/game/Movement/MotionMaster.h6
-rw-r--r--src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp9
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h2
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp6
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp1126
-rw-r--r--src/server/game/Scripting/ScriptMgr.h72
-rw-r--r--src/server/game/Scripting/ScriptReloadMgr.cpp1609
-rw-r--r--src/server/game/Scripting/ScriptReloadMgr.h81
-rw-r--r--src/server/game/Server/Protocol/PacketLog.cpp4
-rw-r--r--src/server/game/Server/WorldSocket.cpp3
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp50
-rw-r--r--src/server/game/Spells/Spell.cpp29
-rw-r--r--src/server/game/Spells/SpellEffects.cpp49
-rw-r--r--src/server/game/Spells/SpellInfo.cpp5
-rw-r--r--src/server/game/Spells/SpellScript.cpp7
-rw-r--r--src/server/game/Spells/SpellScript.h11
-rw-r--r--src/server/game/World/World.cpp19
-rw-r--r--src/server/game/World/World.h8
-rw-r--r--src/server/scripts/CMakeLists.txt253
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp17
-rw-r--r--src/server/scripts/Commands/cs_misc.cpp2
-rw-r--r--src/server/scripts/Commands/cs_modify.cpp460
-rw-r--r--src/server/scripts/Commands/cs_reload.cpp10
-rw-r--r--src/server/scripts/Commands/cs_reset.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp34
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp8
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp32
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp14
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp4
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp10
-rw-r--r--src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp9
-rw-r--r--src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp2
-rw-r--r--src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp2
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp16
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp46
-rw-r--r--src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp52
-rw-r--r--src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp6
-rw-r--r--src/server/scripts/Kalimdor/kalimdor_script_loader.cpp2
-rw-r--r--src/server/scripts/Kalimdor/zone_azshara.cpp2
-rw-r--r--src/server/scripts/Kalimdor/zone_desolace.cpp2
-rw-r--r--src/server/scripts/Kalimdor/zone_durotar.cpp4
-rw-r--r--src/server/scripts/Kalimdor/zone_the_barrens.cpp43
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp6
-rw-r--r--src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp4
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp2
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp6
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp12
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp57
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp4
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp429
-rw-r--r--src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp7
-rw-r--r--src/server/scripts/Northrend/Naxxramas/naxxramas.h2
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp14
-rw-r--r--src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp6
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp6
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp2
-rw-r--r--src/server/scripts/Northrend/zone_icecrown.cpp2
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_illidan.cpp36
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp4
-rw-r--r--src/server/scripts/Outland/BlackTemple/boss_supremus.cpp4
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp4
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp2
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp1052
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp120
-rw-r--r--src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h38
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp2
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp19
-rw-r--r--src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp6
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp6
-rw-r--r--src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp151
-rw-r--r--src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp2
-rw-r--r--src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp2
-rw-r--r--src/server/scripts/Outland/outland_script_loader.cpp2
-rw-r--r--src/server/scripts/Outland/zone_hellfire_peninsula.cpp8
-rw-r--r--src/server/scripts/Outland/zone_shattrath_city.cpp201
-rw-r--r--src/server/scripts/Pet/pet_dk.cpp4
-rw-r--r--src/server/scripts/ScriptLoader.cpp51
-rw-r--r--src/server/scripts/ScriptLoader.cpp.in.cmake64
-rw-r--r--src/server/scripts/ScriptPCH.cpp (renamed from src/server/scripts/PrecompiledHeaders/ScriptPCH.cpp)0
-rw-r--r--src/server/scripts/ScriptPCH.h (renamed from src/server/scripts/PrecompiledHeaders/ScriptPCH.h)0
-rw-r--r--src/server/scripts/Spells/spell_item.cpp102
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp2
-rw-r--r--src/server/scripts/World/boss_emerald_dragons.cpp2
-rw-r--r--src/server/scripts/World/go_scripts.cpp2
-rw-r--r--src/server/scripts/World/item_scripts.cpp14
-rw-r--r--src/server/shared/DataStores/DBCStore.h115
-rw-r--r--src/server/worldserver/CMakeLists.txt6
-rw-r--r--src/server/worldserver/Main.cpp19
-rw-r--r--src/server/worldserver/worldserver.conf.dist85
-rw-r--r--src/tools/map_extractor/System.cpp74
568 files changed, 8746 insertions, 2051 deletions
diff --git a/.travis.yml b/.travis.yml
index a790d35fc17..cddb98492a2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -23,17 +23,17 @@ install:
- mysql -uroot -e 'create database test_mysql;'
- mkdir bin
- cd bin
- - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS=1 -DSERVERS=1 -DNOJEM=1 -DWITH_DYNAMIC_LINKING=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" -DCMAKE_INSTALL_PREFIX=check_install
+ - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS="dynamic" -DSERVERS=1 -DNOJEM=1 -DWITH_DYNAMIC_LINKING=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" -DCMAKE_INSTALL_PREFIX=check_install
- cd ..
- - sudo chmod +x contrib/check_updates.sh
+ - chmod +x contrib/check_updates.sh
script:
- $CXX --version
- mysql -uroot < sql/create/create_mysql.sql
- mysql -utrinity -ptrinity auth < sql/base/auth_database.sql
- - ./contrib/check_updates.sh auth auth
+ - ./contrib/check_updates.sh auth 3.3.5 auth
- mysql -utrinity -ptrinity characters < sql/base/characters_database.sql
- - ./contrib/check_updates.sh characters characters
+ - ./contrib/check_updates.sh characters 3.3.5 characters
- mysql -utrinity -ptrinity world < sql/base/dev/world_database.sql
- cat sql/updates/world/*.sql | mysql -utrinity -ptrinity world
- mysql -uroot < sql/create/drop_mysql.sql
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 01d785ca855..de08fe3181f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,6 +44,7 @@ endif()
include(CheckCXXSourceRuns)
include(CheckIncludeFiles)
+include(ConfigureScripts)
# set default buildoptions and print them
include(cmake/options.cmake)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4baa1197965..e7bd9263a70 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -8,7 +8,7 @@ Issues
======
Read [this](http://www.trinitycore.org/f/topic/37-the-trinitycore-issuetracker-and-you/) before creating a ticket.
-If you have problems with TrinityCore instalation, read [this](http://www.trinitycore.org/f/topic/1518-trouble-with-your-trinity-install-readme-1st-faqs/)
+If you have problems with TrinityCore installation, read [this](http://www.trinitycore.org/f/topic/1518-trouble-with-your-trinity-install-readme-1st-faqs/).
Mandatory things when creating a ticket:
========================================
diff --git a/cmake/compiler/clang/settings.cmake b/cmake/compiler/clang/settings.cmake
index 9a8cb85275e..1cd95bbf703 100644
--- a/cmake/compiler/clang/settings.cmake
+++ b/cmake/compiler/clang/settings.cmake
@@ -19,7 +19,7 @@ endif()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-narrowing -Wno-deprecated-register")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1")
-if (WITH_DYNAMIC_LINKING)
+if (BUILD_SHARED_LIBS)
# -fPIC is needed to allow static linking in shared libs.
# -fvisibility=hidden sets the default visibility to hidden to prevent exporting of all symbols.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden")
diff --git a/cmake/compiler/gcc/settings.cmake b/cmake/compiler/gcc/settings.cmake
index d9eda767b8e..c4f97f4ffd4 100644
--- a/cmake/compiler/gcc/settings.cmake
+++ b/cmake/compiler/gcc/settings.cmake
@@ -35,7 +35,7 @@ if( WITH_COREDEBUG )
message(STATUS "GCC: Debug-flags set (-g3)")
endif()
-if (WITH_DYNAMIC_LINKING)
+if (BUILD_SHARED_LIBS)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden -Wno-attributes")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden -Wno-attributes")
diff --git a/cmake/compiler/msvc/settings.cmake b/cmake/compiler/msvc/settings.cmake
index 336ed84c8ed..afde70b0f79 100644
--- a/cmake/compiler/msvc/settings.cmake
+++ b/cmake/compiler/msvc/settings.cmake
@@ -42,7 +42,7 @@ endif()
# multithreaded compiling on VS
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
-if((PLATFORM EQUAL 64) OR (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0) OR WITH_DYNAMIC_LINKING)
+if((PLATFORM EQUAL 64) OR (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0) OR BUILD_SHARED_LIBS)
# Enable extended object support
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
message(STATUS "MSVC: Enabled increased number of sections in object files")
@@ -80,7 +80,7 @@ if(NOT WITH_WARNINGS)
message(STATUS "MSVC: Disabled generic compiletime warnings")
endif()
-if (WITH_DYNAMIC_LINKING)
+if (BUILD_SHARED_LIBS)
# C4251: needs to have dll-interface to be used by clients of class '...'
# C4275: non dll-interface class ...' used as base for dll-interface class '...'
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251 /wd4275")
diff --git a/cmake/macros/ConfigureScripts.cmake b/cmake/macros/ConfigureScripts.cmake
new file mode 100644
index 00000000000..5260d3a1afe
--- /dev/null
+++ b/cmake/macros/ConfigureScripts.cmake
@@ -0,0 +1,104 @@
+# Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+#
+# This file is free software; as a special exception the author gives
+# unlimited permission to copy and/or distribute it, with or without
+# modifications, as long as this notice is preserved.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+# Returns the base path to the script directory in the source directory
+function(WarnAboutSpacesInBuildPath)
+ # Only check win32 since unix doesn't allow spaces in paths
+ if (WIN32)
+ string(FIND "${CMAKE_BINARY_DIR}" " " SPACE_INDEX_POS)
+
+ if (SPACE_INDEX_POS GREATER -1)
+ message("")
+ message(WARNING " *** WARNING!\n"
+ " *** Your selected build directory contains spaces!\n"
+ " *** Please note that this will cause issues!")
+ endif()
+ endif()
+endfunction()
+
+# Returns the base path to the script directory in the source directory
+function(GetScriptsBasePath variable)
+ set(${variable} "${CMAKE_SOURCE_DIR}/src/server/scripts" PARENT_SCOPE)
+endfunction()
+
+# Stores the absolut path of the given module in the variable
+function(GetPathToScriptModule module variable)
+ GetScriptsBasePath(SCRIPTS_BASE_PATH)
+ set(${variable} "${SCRIPTS_BASE_PATH}/${module}" PARENT_SCOPE)
+endfunction()
+
+# Stores the project name of the given module in the variable
+function(GetProjectNameOfScriptModule module variable)
+ string(TOLOWER "scripts_${SCRIPT_MODULE}" GENERATED_NAME)
+ set(${variable} "${GENERATED_NAME}" PARENT_SCOPE)
+endfunction()
+
+# Creates a list of all script modules
+# and stores it in the given variable.
+function(GetScriptModuleList variable)
+ GetScriptsBasePath(BASE_PATH)
+ file(GLOB LOCALE_SCRIPT_MODULE_LIST RELATIVE
+ ${BASE_PATH}
+ ${BASE_PATH}/*)
+
+ set(${variable})
+ foreach(SCRIPT_MODULE ${LOCALE_SCRIPT_MODULE_LIST})
+ GetPathToScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PATH)
+ if (IS_DIRECTORY ${SCRIPT_MODULE_PATH})
+ list(APPEND ${variable} ${SCRIPT_MODULE})
+ endif()
+ endforeach()
+ set(${variable} ${${variable}} PARENT_SCOPE)
+endfunction()
+
+# Converts the given script module name into it's
+# variable name which holds the linkage type.
+function(ScriptModuleNameToVariable module variable)
+ string(TOUPPER ${module} ${variable})
+ set(${variable} "SCRIPTS_${${variable}}")
+ set(${variable} ${${variable}} PARENT_SCOPE)
+endfunction()
+
+# Stores in the given variable whether dynamic linking is required
+function(IsDynamicLinkingRequired variable)
+ if(SCRIPTS MATCHES "dynamic")
+ set(IS_DEFAULT_VALUE_DYNAMIC ON)
+ endif()
+
+ GetScriptModuleList(SCRIPT_MODULE_LIST)
+ set(IS_REQUIRED OFF)
+ foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST})
+ ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE)
+ if ((${SCRIPT_MODULE_VARIABLE} STREQUAL "dynamic") OR
+ (${SCRIPT_MODULE_VARIABLE} STREQUAL "default" AND IS_DEFAULT_VALUE_DYNAMIC))
+ set(IS_REQUIRED ON)
+ break()
+ endif()
+ endforeach()
+ set(${variable} ${IS_REQUIRED} PARENT_SCOPE)
+endfunction()
+
+# Stores the native variable name
+function(GetNativeSharedLibraryName module variable)
+ if(WIN32)
+ set(${variable} "${module}.dll" PARENT_SCOPE)
+ else()
+ set(${variable} "lib${module}.so" PARENT_SCOPE)
+ endif()
+endfunction()
+
+# Stores the native install path in the variable
+function(GetInstallOffset variable)
+ if(WIN32)
+ set(${variable} "${CMAKE_INSTALL_PREFIX}/scripts" PARENT_SCOPE)
+ else()
+ set(${variable} "${CMAKE_INSTALL_PREFIX}/bin/scripts" PARENT_SCOPE)
+ endif()
+endfunction()
diff --git a/cmake/options.cmake b/cmake/options.cmake
index 62810b2d3f2..085a45fa03f 100644
--- a/cmake/options.cmake
+++ b/cmake/options.cmake
@@ -9,11 +9,30 @@
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
option(SERVERS "Build worldserver and authserver" 1)
-option(SCRIPTS "Build core with scripts included" 1)
+set(SCRIPTS "static" CACHE STRING "Build core with scripts")
+set_property(CACHE SCRIPTS PROPERTY STRINGS none static dynamic minimal-static minimal-dynamic)
+
+# Build a list of all script modules when -DSCRIPT="custom" is selected
+GetScriptModuleList(SCRIPT_MODULE_LIST)
+foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST})
+ ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE)
+ set(${SCRIPT_MODULE_VARIABLE} "default" CACHE STRING "Build type of the ${SCRIPT_MODULE} module.")
+ set_property(CACHE ${SCRIPT_MODULE_VARIABLE} PROPERTY STRINGS default disabled static dynamic)
+endforeach()
+
option(TOOLS "Build map/vmap/mmap extraction/assembler tools" 0)
option(USE_SCRIPTPCH "Use precompiled headers when compiling scripts" 1)
option(USE_COREPCH "Use precompiled headers when compiling servers" 1)
option(WITH_DYNAMIC_LINKING "Enable dynamic library linking." 0)
+IsDynamicLinkingRequired(WITH_DYNAMIC_LINKING_FORCED)
+if (WITH_DYNAMIC_LINKING AND WITH_DYNAMIC_LINKING_FORCED)
+ set(WITH_DYNAMIC_LINKING_FORCED OFF)
+endif()
+if (WITH_DYNAMIC_LINKING OR WITH_DYNAMIC_LINKING_FORCED)
+ set(BUILD_SHARED_LIBS ON)
+else()
+ set(BUILD_SHARED_LIBS OFF)
+endif()
option(WITH_WARNINGS "Show all warnings during compile" 0)
option(WITH_COREDEBUG "Include additional debug-code in core" 0)
set(WITH_SOURCE_TREE "hierarchical" CACHE STRING "Build the source tree for IDE's.")
diff --git a/cmake/showoptions.cmake b/cmake/showoptions.cmake
index e6d709207b3..9229590381a 100644
--- a/cmake/showoptions.cmake
+++ b/cmake/showoptions.cmake
@@ -23,9 +23,8 @@ else()
message("* Build world/authserver : No")
endif()
-if( SCRIPTS )
- message("* Build with scripts : Yes (default)")
- add_definitions(-DSCRIPTS)
+if(SCRIPTS AND (NOT SCRIPTS STREQUAL "none"))
+ message("* Build with scripts : Yes (${SCRIPTS})")
else()
message("* Build with scripts : No")
endif()
@@ -70,7 +69,7 @@ else()
endif()
if( NOT WITH_SOURCE_TREE STREQUAL "no" )
- message("* Show source tree : Yes - \"${WITH_SOURCE_TREE}\"")
+ message("* Show source tree : Yes (${WITH_SOURCE_TREE})")
else()
message("* Show source tree : No")
endif()
@@ -87,7 +86,7 @@ if ( WITHOUT_GIT )
message(" *** version of git for the revision-hash to work, and be allowede to ask for")
message(" *** support if needed.")
else()
- message("* Use GIT revision hash : Yes")
+ message("* Use GIT revision hash : Yes (default)")
endif()
if ( NOJEM )
@@ -113,15 +112,18 @@ if ( HELGRIND )
add_definitions(-DHELGRIND)
endif()
-if (WITH_DYNAMIC_LINKING)
+if (BUILD_SHARED_LIBS)
message("")
message(" *** WITH_DYNAMIC_LINKING - INFO!")
message(" *** Will link against shared libraries!")
message(" *** Please note that this is an experimental feature!")
+ if (WITH_DYNAMIC_LINKING_FORCED)
+ message("")
+ message(" *** Dynamic linking was enforced through a dynamic script module!")
+ endif()
add_definitions(-DTRINITY_API_USE_DYNAMIC_LINKING)
- set(BUILD_SHARED_LIBS ON)
-else()
- set(BUILD_SHARED_LIBS OFF)
+
+ WarnAboutSpacesInBuildPath()
endif()
message("")
diff --git a/contrib/check_updates.sh b/contrib/check_updates.sh
index 017542eb807..6c33d07ae8b 100644
--- a/contrib/check_updates.sh
+++ b/contrib/check_updates.sh
@@ -1,6 +1,7 @@
#!/bin/sh
name=$1
-database=$2
+branch=$2
+database=$3
echo "Database Updater check script:"
echo " Checking database '${name}' for missing filenames in tables..."
@@ -9,7 +10,7 @@ echo
# Select all entries which are in the updates table
entries=$(mysql -uroot ${database} -e "SELECT name FROM updates" | grep ".sql")
-cd sql/updates/${name}
+cd sql/updates/${name}/${branch}
error=0
updates=0
diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt
index 6c8fd09de28..48be56bc9ef 100644
--- a/dep/CMakeLists.txt
+++ b/dep/CMakeLists.txt
@@ -20,6 +20,7 @@ add_subdirectory(threads)
if(SERVERS OR TOOLS)
add_subdirectory(boost)
+ add_subdirectory(process)
add_subdirectory(zlib)
add_subdirectory(g3dlite)
add_subdirectory(recastnavigation)
@@ -35,7 +36,6 @@ if(SERVERS)
add_subdirectory(mysql)
add_subdirectory(readline)
add_subdirectory(gsoap)
- add_subdirectory(process)
add_subdirectory(efsw)
endif()
diff --git a/dep/boost/CMakeLists.txt b/dep/boost/CMakeLists.txt
index 118635c85bd..6cda5fbec4e 100644
--- a/dep/boost/CMakeLists.txt
+++ b/dep/boost/CMakeLists.txt
@@ -35,19 +35,14 @@ include (CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_INCLUDES ${Boost_INCLUDE_DIR})
set(CMAKE_REQUIRED_LIBRARIES ${Boost_SYSTEM_LIBRARY} ${Boost_FILESYSTEM_LIBRARY} ${Boost_IOSTREAMS_LIBRARY})
set(CMAKE_REQUIRED_FLAGS "-std=c++11")
-unset(boost_filesystem_copy_links_without_NO_SCOPED_ENUM CACHE)
check_cxx_source_compiles("
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
int main() { boost::filesystem::copy_file(boost::filesystem::path(), boost::filesystem::path()); }"
boost_filesystem_copy_links_without_NO_SCOPED_ENUM)
-unset(CMAKE_REQUIRED_INCLUDES CACHE)
-unset(CMAKE_REQUIRED_LIBRARIES CACHE)
-unset(CMAKE_REQUIRED_FLAGS CACHE)
-
-if (NOT boost_filesystem_copy_links_without_NO_SCOPED_ENUM)
- set(OPTIONAL_BOOST_NO_SCOPED_ENUMS -DBOOST_NO_CXX11_SCOPED_ENUMS)
-endif()
+unset(CMAKE_REQUIRED_INCLUDES)
+unset(CMAKE_REQUIRED_LIBRARIES)
+unset(CMAKE_REQUIRED_FLAGS)
add_library(boost INTERFACE)
@@ -59,9 +54,17 @@ target_include_directories(boost
INTERFACE
${Boost_INCLUDE_DIRS})
-target_compile_definitions(boost
- INTERFACE
- -DBOOST_DATE_TIME_NO_LIB
- -DBOOST_REGEX_NO_LIB
- -DBOOST_CHRONO_NO_LIB
- ${OPTIONAL_BOOST_NO_SCOPED_ENUMS})
+if (boost_filesystem_copy_links_without_NO_SCOPED_ENUM)
+ target_compile_definitions(boost
+ INTERFACE
+ -DBOOST_DATE_TIME_NO_LIB
+ -DBOOST_REGEX_NO_LIB
+ -DBOOST_CHRONO_NO_LIB)
+else()
+ target_compile_definitions(boost
+ INTERFACE
+ -DBOOST_DATE_TIME_NO_LIB
+ -DBOOST_REGEX_NO_LIB
+ -DBOOST_CHRONO_NO_LIB
+ -DBOOST_NO_CXX11_SCOPED_ENUMS)
+endif()
diff --git a/dep/efsw/CMakeLists.txt b/dep/efsw/CMakeLists.txt
index 81a1d20b204..eecc5531944 100644
--- a/dep/efsw/CMakeLists.txt
+++ b/dep/efsw/CMakeLists.txt
@@ -1,4 +1,4 @@
-if (WITH_DYNAMIC_LINKING)
+if (BUILD_SHARED_LIBS)
set(SRCS
src/efsw/DirectorySnapshot.cpp
src/efsw/DirectorySnapshotDiff.cpp
@@ -81,5 +81,5 @@ if (WITH_DYNAMIC_LINKING)
FOLDER
"dep")
else()
- add_library(efsw INTERFACE)
+ add_library(efsw INTERFACE IMPORTED GLOBAL)
endif()
diff --git a/issue_template.md b/issue_template.md
index fe090da2338..8653726f830 100644
--- a/issue_template.md
+++ b/issue_template.md
@@ -10,13 +10,15 @@
2.
3.
-**Branch(es)**: 335/6x
+**Branch(es)**: 335/6x
-**TC hash/commit**:
+**TC hash/commit**:
-**TDB version**:
+**TDB version**:
-**Operating system**:
+**Operating system**:
+
+**Linking model**: static/dynamic
[//]: # (This template is for problem reports, for other type of reports edit it accordingly)
diff --git a/revision_data.h.in.cmake b/revision_data.h.in.cmake
index 04c6e2008a1..14faa04a0bc 100644
--- a/revision_data.h.in.cmake
+++ b/revision_data.h.in.cmake
@@ -7,7 +7,7 @@
#define _SOURCE_DIRECTORY R"(@CMAKE_SOURCE_DIR@)"
#define _BUILD_DIRECTORY R"(@BUILDDIR@)"
#define _MYSQL_EXECUTABLE R"(@MYSQL_EXECUTABLE@)"
- #define _FULL_DATABASE "TDB_full_world_335.60_2015_11_07.sql"
+ #define _FULL_DATABASE "TDB_full_world_335.61_2016_04_11.sql"
#define VER_COMPANYNAME_STR "TrinityCore Developers"
#define VER_LEGALCOPYRIGHT_STR "(c)2008-2016 TrinityCore"
#define VER_FILEVERSION 0,0,0
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql
index 0ac0ffaf9d1..fd47a349f01 100644
--- a/sql/base/auth_database.sql
+++ b/sql/base/auth_database.sql
@@ -1,6 +1,6 @@
-- MySQL dump 10.13 Distrib 5.6.26, for Win64 (x86_64)
--
--- Host: localhost Database: auth335
+-- Host: localhost Database: auth
-- ------------------------------------------------------
-- Server version 5.6.26-log
@@ -486,7 +486,7 @@ CREATE TABLE `updates` (
LOCK TABLES `updates` WRITE;
/*!40000 ALTER TABLE `updates` DISABLE KEYS */;
-INSERT INTO `updates` VALUES ('2014_11_10_00_auth.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 21:44:12',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_21_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_00_auth.sql','E8C5B74BB45F0F35DEC182C72BACF435C7066FB0','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_01_auth.sql','862961815354DA2746F5F71FBC8155F57CBE75AB','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_02_auth.sql','33E4F94086590768EF5D4855DD43D7DE7C06ADA4','ARCHIVED','2015-03-21 21:44:51',0),('2015_08_21_00_auth.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-10-05 23:16:19',0),('2015_11_07_00_auth.sql','BAF9F6B8F97A30D04BDBBA8127A62A1720F9B904','RELEASED','2015-11-07 15:40:47',0),('2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','RELEASED','2016-01-13 00:00:00',0);
+INSERT INTO `updates` VALUES ('2014_11_10_00_auth.sql','0E3CB119442D09DD88E967015319BBC8DAFBBFE0','ARCHIVED','2015-03-21 21:44:12',0),('2014_11_10_01_auth.sql','327E77A1DA3546D5275AB249915DD57EDD6FDD3D','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_10_00_auth.sql','821703A96D80F9080074852B5A46E2909C9562EA','ARCHIVED','2015-03-21 21:44:12',0),('2014_12_21_00_auth.sql','CE2E5D2CD82E79C25294539ADED27A1429105B43','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_00_auth.sql','E8C5B74BB45F0F35DEC182C72BACF435C7066FB0','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_01_auth.sql','862961815354DA2746F5F71FBC8155F57CBE75AB','ARCHIVED','2015-03-21 21:44:12',0),('2015_03_20_02_auth.sql','33E4F94086590768EF5D4855DD43D7DE7C06ADA4','ARCHIVED','2015-03-21 21:44:51',0),('2015_08_21_00_auth.sql','C31A9E1D28E11B60BE8F8198637DD51F6D75123F','ARCHIVED','2015-10-05 23:16:19',0),('2015_11_07_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2016-04-11 00:42:36',92),('2016_01_13_00_auth.sql','24615CC69B3CD7BB4699874647C35BA86E8A93FD','ARCHIVED','2016-01-13 00:00:00',0),('2016_04_11_00_auth.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 03:18:17',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
@@ -549,4 +549,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2015-11-07 14:42:34
+-- Dump completed on 2016-04-11 2:32:16
diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql
index 94841144017..1f071db3781 100644
--- a/sql/base/characters_database.sql
+++ b/sql/base/characters_database.sql
@@ -1,6 +1,6 @@
-- MySQL dump 10.13 Distrib 5.6.26, for Win64 (x86_64)
--
--- Host: localhost Database: characters335
+-- Host: localhost Database: characters
-- ------------------------------------------------------
-- Server version 5.6.26-log
@@ -783,7 +783,7 @@ CREATE TABLE `character_instance` (
`guid` int(10) unsigned NOT NULL DEFAULT '0',
`instance` int(10) unsigned NOT NULL DEFAULT '0',
`permanent` tinyint(3) unsigned NOT NULL DEFAULT '0',
- `extendState` TINYINT(2) UNSIGNED NOT NULL DEFAULT '1',
+ `extendState` tinyint(2) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (`guid`,`instance`),
KEY `instance` (`instance`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@@ -2545,7 +2545,7 @@ CREATE TABLE `updates` (
LOCK TABLES `updates` WRITE;
/*!40000 ALTER TABLE `updates` DISABLE KEYS */;
-INSERT INTO `updates` VALUES ('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_01_characters.sql','894F08B70449A5481FFAF394EE5571D7FC4D8A3A','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_02_characters.sql','97D7BE0CAADC79F3F11B9FD296B8C6CD40FE593B','ARCHIVED','2015-03-21 21:44:51',0),('2015_06_26_00_characters_335.sql','C2CC6E50AFA1ACCBEBF77CC519AAEB09F3BBAEBC','ARCHIVED','2015-07-13 23:49:22',0),('2015_09_28_00_characters_335.sql','F8682A431D50E54BDC4AC0E7DBED21AE8AAB6AD4','ARCHIVED','2015-09-28 21:00:00',0),('2015_08_26_00_characters_335.sql','C7D6A3A00FECA3EBFF1E71744CA40D3076582374','ARCHIVED','2015-08-26 21:00:00',0),('2015_10_06_00_characters.sql','16842FDD7E8547F2260D3312F53EFF8761EFAB35','ARCHIVED','2015-10-06 16:06:38',0),('2015_10_07_00_characters.sql','E15AB463CEBE321001D7BFDEA4B662FF618728FD','ARCHIVED','2015-10-07 23:32:00',0),('2015_10_12_00_characters.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-10-12 15:35:47',0),('2015_10_28_00_characters.sql','622A9CA8FCE690429EBE23BA071A37C7A007BF8B','ARCHIVED','2015-10-19 14:32:22',0),('2015_10_29_00_characters_335.sql','4555A7F35C107E54C13D74D20F141039ED42943E','ARCHIVED','2015-10-29 17:05:43',0),('2015_11_03_00_characters.sql','CC045717B8FDD9733351E52A5302560CD08AAD57','ARCHIVED','2015-10-12 15:23:33',0),('2015_11_07_00_characters.sql','BAF9F6B8F97A30D04BDBBA8127A62A1720F9B904','RELEASED','2015-11-07 15:40:47',0),('2016_02_10_00_characters.sql','F1B4DA202819CABC7319A4470A2D224A34609E97','RELEASED','2016-02-10 00:00:00',0),('2016_03_13_2016_01_05_00_characters.sql','0EAD24977F40DE2476B4567DA2B477867CC0DA1A','RELEASED','2016-03-13 20:03:56',0);
+INSERT INTO `updates` VALUES ('2015_03_20_00_characters.sql','B761760804EA73BD297F296C5C1919687DF7191C','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_01_characters.sql','894F08B70449A5481FFAF394EE5571D7FC4D8A3A','ARCHIVED','2015-03-21 21:44:15',0),('2015_03_20_02_characters.sql','97D7BE0CAADC79F3F11B9FD296B8C6CD40FE593B','ARCHIVED','2015-03-21 21:44:51',0),('2015_06_26_00_characters_335.sql','C2CC6E50AFA1ACCBEBF77CC519AAEB09F3BBAEBC','ARCHIVED','2015-07-13 23:49:22',0),('2015_09_28_00_characters_335.sql','F8682A431D50E54BDC4AC0E7DBED21AE8AAB6AD4','ARCHIVED','2015-09-28 21:00:00',0),('2015_08_26_00_characters_335.sql','C7D6A3A00FECA3EBFF1E71744CA40D3076582374','ARCHIVED','2015-08-26 21:00:00',0),('2015_10_06_00_characters.sql','16842FDD7E8547F2260D3312F53EFF8761EFAB35','ARCHIVED','2015-10-06 16:06:38',0),('2015_10_07_00_characters.sql','E15AB463CEBE321001D7BFDEA4B662FF618728FD','ARCHIVED','2015-10-07 23:32:00',0),('2015_10_12_00_characters.sql','D6F9927BDED72AD0A81D6EC2C6500CBC34A39FA2','ARCHIVED','2015-10-12 15:35:47',0),('2015_10_28_00_characters.sql','622A9CA8FCE690429EBE23BA071A37C7A007BF8B','ARCHIVED','2015-10-19 14:32:22',0),('2015_10_29_00_characters_335.sql','4555A7F35C107E54C13D74D20F141039ED42943E','ARCHIVED','2015-10-29 17:05:43',0),('2015_11_03_00_characters.sql','CC045717B8FDD9733351E52A5302560CD08AAD57','ARCHIVED','2015-10-12 15:23:33',0),('2015_11_07_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','ARCHIVED','2016-04-11 00:42:36',94),('2016_02_10_00_characters.sql','F1B4DA202819CABC7319A4470A2D224A34609E97','ARCHIVED','2016-02-10 00:00:00',0),('2016_03_13_2016_01_05_00_characters.sql','0EAD24977F40DE2476B4567DA2B477867CC0DA1A','ARCHIVED','2016-03-13 20:03:56',0),('2016_04_11_00_characters.sql','0ACDD35EC9745231BCFA701B78056DEF94D0CC53','RELEASED','2016-04-11 03:18:17',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
@@ -2630,4 +2630,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2015-11-07 14:42:34
+-- Dump completed on 2016-04-11 2:32:17
diff --git a/sql/base/dev/world_database.sql b/sql/base/dev/world_database.sql
index 02318987448..85e7c2391da 100644
--- a/sql/base/dev/world_database.sql
+++ b/sql/base/dev/world_database.sql
@@ -1,6 +1,6 @@
-- MySQL dump 10.13 Distrib 5.6.26, for Win64 (x86_64)
--
--- Host: localhost Database: world335
+-- Host: localhost Database: world
-- ------------------------------------------------------
-- Server version 5.6.26-log
@@ -1022,7 +1022,7 @@ CREATE TABLE `game_tele` (
`map` smallint(5) unsigned NOT NULL DEFAULT '0',
`name` varchar(100) NOT NULL DEFAULT '',
PRIMARY KEY (`id`)
-) ENGINE=MyISAM AUTO_INCREMENT=1425 DEFAULT CHARSET=utf8 COMMENT='Tele Command';
+) ENGINE=MyISAM AUTO_INCREMENT=1429 DEFAULT CHARSET=utf8 COMMENT='Tele Command';
/*!40101 SET character_set_client = @saved_cs_client */;
--
@@ -3785,4 +3785,4 @@ CREATE TABLE `waypoints` (
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
--- Dump completed on 2015-11-07 14:42:45
+-- Dump completed on 2016-04-11 2:32:19
diff --git a/sql/updates/auth/2015_11_07_00_auth.sql b/sql/old/3.3.5a/auth/60_2016_04_11/2015_11_07_00_auth.sql
index be8a4d21b66..be8a4d21b66 100644
--- a/sql/updates/auth/2015_11_07_00_auth.sql
+++ b/sql/old/3.3.5a/auth/60_2016_04_11/2015_11_07_00_auth.sql
diff --git a/sql/updates/auth/2016_01_13_00_auth.sql b/sql/old/3.3.5a/auth/60_2016_04_11/2016_01_13_00_auth.sql
index c70d4c09468..c70d4c09468 100644
--- a/sql/updates/auth/2016_01_13_00_auth.sql
+++ b/sql/old/3.3.5a/auth/60_2016_04_11/2016_01_13_00_auth.sql
diff --git a/sql/updates/characters/2015_11_07_00_characters.sql b/sql/old/3.3.5a/characters/60_2016_04_11/2015_11_07_00_characters.sql
index be8a4d21b66..be8a4d21b66 100644
--- a/sql/updates/characters/2015_11_07_00_characters.sql
+++ b/sql/old/3.3.5a/characters/60_2016_04_11/2015_11_07_00_characters.sql
diff --git a/sql/updates/characters/2016_02_10_00_characters.sql b/sql/old/3.3.5a/characters/60_2016_04_11/2016_02_10_00_characters.sql
index d49ed155bc8..d49ed155bc8 100644
--- a/sql/updates/characters/2016_02_10_00_characters.sql
+++ b/sql/old/3.3.5a/characters/60_2016_04_11/2016_02_10_00_characters.sql
diff --git a/sql/updates/characters/2016_03_13_2016_01_05_00_characters.sql b/sql/old/3.3.5a/characters/60_2016_04_11/2016_03_13_2016_01_05_00_characters.sql
index 11850067be9..11850067be9 100644
--- a/sql/updates/characters/2016_03_13_2016_01_05_00_characters.sql
+++ b/sql/old/3.3.5a/characters/60_2016_04_11/2016_03_13_2016_01_05_00_characters.sql
diff --git a/sql/updates/world/2015_11_07_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_07_02_world.sql
index 3e23e0e629b..3e23e0e629b 100644
--- a/sql/updates/world/2015_11_07_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_07_02_world.sql
diff --git a/sql/updates/world/2015_11_08_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_00_world.sql
index fea6f43bc64..fea6f43bc64 100644
--- a/sql/updates/world/2015_11_08_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_00_world.sql
diff --git a/sql/updates/world/2015_11_08_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_01_world.sql
index f5642f73af4..f5642f73af4 100644
--- a/sql/updates/world/2015_11_08_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_08_01_world.sql
diff --git a/sql/updates/world/2015_11_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_00_world.sql
index 6fd5dec39b7..6fd5dec39b7 100644
--- a/sql/updates/world/2015_11_09_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_00_world.sql
diff --git a/sql/updates/world/2015_11_09_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_01_world.sql
index e9360cf8963..e9360cf8963 100644
--- a/sql/updates/world/2015_11_09_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_01_world.sql
diff --git a/sql/updates/world/2015_11_09_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_02_world_335.sql
index 84c0fd423ad..84c0fd423ad 100644
--- a/sql/updates/world/2015_11_09_02_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_09_02_world_335.sql
diff --git a/sql/updates/world/2015_11_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_00_world.sql
index 6e969f288f1..6e969f288f1 100644
--- a/sql/updates/world/2015_11_10_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_00_world.sql
diff --git a/sql/updates/world/2015_11_10_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_01_world.sql
index fe9c0b1b8e2..fe9c0b1b8e2 100644
--- a/sql/updates/world/2015_11_10_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_01_world.sql
diff --git a/sql/updates/world/2015_11_10_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_02_world.sql
index 8ff255defa4..8ff255defa4 100644
--- a/sql/updates/world/2015_11_10_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_10_02_world.sql
diff --git a/sql/updates/world/2015_11_11_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_00_world.sql
index 07393641f3f..07393641f3f 100644
--- a/sql/updates/world/2015_11_11_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_00_world.sql
diff --git a/sql/updates/world/2015_11_11_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_01_world.sql
index 3c1ce85ec17..3c1ce85ec17 100644
--- a/sql/updates/world/2015_11_11_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_11_01_world.sql
diff --git a/sql/updates/world/2015_11_12_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_00_world.sql
index 79c2461e5ff..79c2461e5ff 100644
--- a/sql/updates/world/2015_11_12_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_00_world.sql
diff --git a/sql/updates/world/2015_11_12_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_01_world.sql
index c08ebda2471..c08ebda2471 100644
--- a/sql/updates/world/2015_11_12_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_12_01_world.sql
diff --git a/sql/updates/world/2015_11_20_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_20_00_world.sql
index 7c5fe7ea426..7c5fe7ea426 100644
--- a/sql/updates/world/2015_11_20_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_20_00_world.sql
diff --git a/sql/updates/world/2015_11_22_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_00_world.sql
index 2b70a2c97b6..2b70a2c97b6 100644
--- a/sql/updates/world/2015_11_22_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_00_world.sql
diff --git a/sql/updates/world/2015_11_22_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_01_world.sql
index ba63c72ba16..ba63c72ba16 100644
--- a/sql/updates/world/2015_11_22_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_01_world.sql
diff --git a/sql/updates/world/2015_11_22_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_02_world.sql
index 7fcbc7ec9aa..7fcbc7ec9aa 100644
--- a/sql/updates/world/2015_11_22_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_02_world.sql
diff --git a/sql/updates/world/2015_11_22_03_world_355.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_03_world_355.sql
index 9bf71a146d0..9bf71a146d0 100644
--- a/sql/updates/world/2015_11_22_03_world_355.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_22_03_world_355.sql
diff --git a/sql/updates/world/2015_11_23_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_00_world_335.sql
index fffc4531e5e..fffc4531e5e 100644
--- a/sql/updates/world/2015_11_23_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_00_world_335.sql
diff --git a/sql/updates/world/2015_11_23_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_01_world_335.sql
index 8432c2d14fd..8432c2d14fd 100644
--- a/sql/updates/world/2015_11_23_01_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_01_world_335.sql
diff --git a/sql/updates/world/2015_11_23_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_02_world_335.sql
index ba569d1420f..ba569d1420f 100644
--- a/sql/updates/world/2015_11_23_02_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_02_world_335.sql
diff --git a/sql/updates/world/2015_11_23_03_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_03_world_335.sql
index 9ef011f551e..9ef011f551e 100644
--- a/sql/updates/world/2015_11_23_03_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_03_world_335.sql
diff --git a/sql/updates/world/2015_11_23_04_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_04_world_335.sql
index 845eefeb7ca..845eefeb7ca 100644
--- a/sql/updates/world/2015_11_23_04_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_04_world_335.sql
diff --git a/sql/updates/world/2015_11_23_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_05_world.sql
index 579af5a5ca1..579af5a5ca1 100644
--- a/sql/updates/world/2015_11_23_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_23_05_world.sql
diff --git a/sql/updates/world/2015_11_24_00_world_355.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_24_00_world_355.sql
index 0983d03e649..0983d03e649 100644
--- a/sql/updates/world/2015_11_24_00_world_355.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_24_00_world_355.sql
diff --git a/sql/updates/world/2015_11_27_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_27_00_world.sql
index 632dec537dd..632dec537dd 100644
--- a/sql/updates/world/2015_11_27_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_27_00_world.sql
diff --git a/sql/updates/world/2015_11_28_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_00_world.sql
index 0a1dd574fb4..0a1dd574fb4 100644
--- a/sql/updates/world/2015_11_28_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_00_world.sql
diff --git a/sql/updates/world/2015_11_28_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_01_world_335.sql
index 4bec178ecee..4bec178ecee 100644
--- a/sql/updates/world/2015_11_28_01_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_28_01_world_335.sql
diff --git a/sql/updates/world/2015_11_29_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_00_world.sql
index fd64b65bd02..fd64b65bd02 100644
--- a/sql/updates/world/2015_11_29_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_00_world.sql
diff --git a/sql/updates/world/2015_11_29_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_01_world.sql
index cd46800c5dd..cd46800c5dd 100644
--- a/sql/updates/world/2015_11_29_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_11_29_01_world.sql
diff --git a/sql/updates/world/2015_12_01_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_01_00_world.sql
index 1572245a517..1572245a517 100644
--- a/sql/updates/world/2015_12_01_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_01_00_world.sql
diff --git a/sql/updates/world/2015_12_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_04_00_world.sql
index ee721273bef..ee721273bef 100644
--- a/sql/updates/world/2015_12_04_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_04_00_world.sql
diff --git a/sql/updates/world/2015_12_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_05_00_world.sql
index c2c90164a4f..c2c90164a4f 100644
--- a/sql/updates/world/2015_12_05_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_05_00_world.sql
diff --git a/sql/updates/world/2015_12_06_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_06_00_world.sql
index b60d4d3e88c..b60d4d3e88c 100644
--- a/sql/updates/world/2015_12_06_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_06_00_world.sql
diff --git a/sql/updates/world/2015_12_08_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_00_world_335.sql
index e742130b1a4..e742130b1a4 100644
--- a/sql/updates/world/2015_12_08_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_00_world_335.sql
diff --git a/sql/updates/world/2015_12_08_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_01_world.sql
index 9e24acd91db..9e24acd91db 100644
--- a/sql/updates/world/2015_12_08_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_01_world.sql
diff --git a/sql/updates/world/2015_12_08_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_02_world.sql
index 375d0941adb..375d0941adb 100644
--- a/sql/updates/world/2015_12_08_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_08_02_world.sql
diff --git a/sql/updates/world/2015_12_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_00_world.sql
index 6ac4da31404..6ac4da31404 100644
--- a/sql/updates/world/2015_12_09_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_00_world.sql
diff --git a/sql/updates/world/2015_12_09_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_01_world.sql
index d27bc7ff49a..d27bc7ff49a 100644
--- a/sql/updates/world/2015_12_09_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_09_01_world.sql
diff --git a/sql/updates/world/2015_12_11_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_11_00_world.sql
index dc5fd8c40b6..dc5fd8c40b6 100644
--- a/sql/updates/world/2015_12_11_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_11_00_world.sql
diff --git a/sql/updates/world/2015_12_14_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_14_00_world.sql
index 85faf4448e2..85faf4448e2 100644
--- a/sql/updates/world/2015_12_14_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_14_00_world.sql
diff --git a/sql/updates/world/2015_12_15_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_00_world.sql
index f27bb448bbd..f27bb448bbd 100644
--- a/sql/updates/world/2015_12_15_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_00_world.sql
diff --git a/sql/updates/world/2015_12_15_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_01_world.sql
index 86fbec83c38..86fbec83c38 100644
--- a/sql/updates/world/2015_12_15_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_01_world.sql
diff --git a/sql/updates/world/2015_12_15_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_02_world.sql
index eda5c26550f..eda5c26550f 100644
--- a/sql/updates/world/2015_12_15_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_02_world.sql
diff --git a/sql/updates/world/2015_12_15_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_03_world.sql
index 99cc9e14646..99cc9e14646 100644
--- a/sql/updates/world/2015_12_15_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_15_03_world.sql
diff --git a/sql/updates/world/2015_12_16_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_00_world.sql
index 62d640117f7..62d640117f7 100644
--- a/sql/updates/world/2015_12_16_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_00_world.sql
diff --git a/sql/updates/world/2015_12_16_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_01_world.sql
index 73c9675e5be..73c9675e5be 100644
--- a/sql/updates/world/2015_12_16_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_01_world.sql
diff --git a/sql/updates/world/2015_12_16_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_02_world_335.sql
index 20c1ac94a39..20c1ac94a39 100644
--- a/sql/updates/world/2015_12_16_02_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_16_02_world_335.sql
diff --git a/sql/updates/world/2015_12_17_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_17_00_world.sql
index 8419473b203..8419473b203 100644
--- a/sql/updates/world/2015_12_17_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_17_00_world.sql
diff --git a/sql/updates/world/2015_12_18_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_00_world_335.sql
index 3fb3e5a6e1e..3fb3e5a6e1e 100644
--- a/sql/updates/world/2015_12_18_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_00_world_335.sql
diff --git a/sql/updates/world/2015_12_18_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_01_world.sql
index 2ccc93def23..2ccc93def23 100644
--- a/sql/updates/world/2015_12_18_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_01_world.sql
diff --git a/sql/updates/world/2015_12_18_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_02_world.sql
index f590d18a8ab..f590d18a8ab 100644
--- a/sql/updates/world/2015_12_18_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_02_world.sql
diff --git a/sql/updates/world/2015_12_18_03_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_03_world_335.sql
index de778343a0e..de778343a0e 100644
--- a/sql/updates/world/2015_12_18_03_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_03_world_335.sql
diff --git a/sql/updates/world/2015_12_18_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_04_world.sql
index c8c3352319c..c8c3352319c 100644
--- a/sql/updates/world/2015_12_18_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_18_04_world.sql
diff --git a/sql/updates/world/2015_12_20_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_20_00_world.sql
index 7c658877f13..7c658877f13 100644
--- a/sql/updates/world/2015_12_20_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_20_00_world.sql
diff --git a/sql/updates/world/2015_12_24_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_24_00_world.sql
index 52d83bb63c3..52d83bb63c3 100644
--- a/sql/updates/world/2015_12_24_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_24_00_world.sql
diff --git a/sql/updates/world/2015_12_26_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_00_world.sql
index 02c0acbedae..02c0acbedae 100644
--- a/sql/updates/world/2015_12_26_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_00_world.sql
diff --git a/sql/updates/world/2015_12_26_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_01_world.sql
index 92a9d21af25..92a9d21af25 100644
--- a/sql/updates/world/2015_12_26_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_01_world.sql
diff --git a/sql/updates/world/2015_12_26_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_02_world.sql
index 021dec0be80..021dec0be80 100644
--- a/sql/updates/world/2015_12_26_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_26_02_world.sql
diff --git a/sql/updates/world/2015_12_29_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_00_world.sql
index da6de123190..da6de123190 100644
--- a/sql/updates/world/2015_12_29_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_00_world.sql
diff --git a/sql/updates/world/2015_12_29_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_01_world.sql
index 24b201b4d06..24b201b4d06 100644
--- a/sql/updates/world/2015_12_29_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_01_world.sql
diff --git a/sql/updates/world/2015_12_29_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_02_world.sql
index 3bfd0ba2a25..3bfd0ba2a25 100644
--- a/sql/updates/world/2015_12_29_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_02_world.sql
diff --git a/sql/updates/world/2015_12_29_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_03_world.sql
index f928061c269..f928061c269 100644
--- a/sql/updates/world/2015_12_29_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_03_world.sql
diff --git a/sql/updates/world/2015_12_29_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_04_world.sql
index 22a1ee3edcf..22a1ee3edcf 100644
--- a/sql/updates/world/2015_12_29_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_04_world.sql
diff --git a/sql/updates/world/2015_12_29_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_05_world.sql
index 056ea4fe230..056ea4fe230 100644
--- a/sql/updates/world/2015_12_29_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_05_world.sql
diff --git a/sql/updates/world/2015_12_29_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_06_world.sql
index 167c4c23005..167c4c23005 100644
--- a/sql/updates/world/2015_12_29_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_06_world.sql
diff --git a/sql/updates/world/2015_12_29_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_07_world.sql
index ec71d28c787..ec71d28c787 100644
--- a/sql/updates/world/2015_12_29_07_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_07_world.sql
diff --git a/sql/updates/world/2015_12_29_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_08_world.sql
index ce874d7a8d2..ce874d7a8d2 100644
--- a/sql/updates/world/2015_12_29_08_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_08_world.sql
diff --git a/sql/updates/world/2015_12_29_09_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_09_world.sql
index d57785e8d88..d57785e8d88 100644
--- a/sql/updates/world/2015_12_29_09_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_09_world.sql
diff --git a/sql/updates/world/2015_12_29_10_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_10_world.sql
index 919309dd558..919309dd558 100644
--- a/sql/updates/world/2015_12_29_10_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_10_world.sql
diff --git a/sql/updates/world/2015_12_29_11_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_11_world.sql
index 930baf15f78..930baf15f78 100644
--- a/sql/updates/world/2015_12_29_11_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_11_world.sql
diff --git a/sql/updates/world/2015_12_29_12_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_12_world.sql
index c065e1d6a18..c065e1d6a18 100644
--- a/sql/updates/world/2015_12_29_12_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_12_world.sql
diff --git a/sql/updates/world/2015_12_29_13_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_13_world.sql
index fc182ae49fb..fc182ae49fb 100644
--- a/sql/updates/world/2015_12_29_13_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_29_13_world.sql
diff --git a/sql/updates/world/2015_12_31_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_00_world.sql
index b7c310323ed..b7c310323ed 100644
--- a/sql/updates/world/2015_12_31_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_00_world.sql
diff --git a/sql/updates/world/2015_12_31_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_01_world.sql
index 3bee62963ef..3bee62963ef 100644
--- a/sql/updates/world/2015_12_31_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2015_12_31_01_world.sql
diff --git a/sql/updates/world/2016_01_01_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_00_world.sql
index 38991837113..38991837113 100644
--- a/sql/updates/world/2016_01_01_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_00_world.sql
diff --git a/sql/updates/world/2016_01_01_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_01_world.sql
index 025f2c07f9c..025f2c07f9c 100644
--- a/sql/updates/world/2016_01_01_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_01_01_world.sql
diff --git a/sql/updates/world/2016_01_02_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_00_world_335.sql
index b46a41bc6e9..b46a41bc6e9 100644
--- a/sql/updates/world/2016_01_02_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_00_world_335.sql
diff --git a/sql/updates/world/2016_01_02_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_01_world.sql
index b862cc0e644..b862cc0e644 100644
--- a/sql/updates/world/2016_01_02_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_02_01_world.sql
diff --git a/sql/updates/world/2016_01_03_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_00_world_335.sql
index 658b180a41a..658b180a41a 100644
--- a/sql/updates/world/2016_01_03_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_00_world_335.sql
diff --git a/sql/updates/world/2016_01_03_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_01_world.sql
index 3ddb56a9c72..3ddb56a9c72 100644
--- a/sql/updates/world/2016_01_03_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_01_world.sql
diff --git a/sql/updates/world/2016_01_03_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_02_world.sql
index 79eba012e41..79eba012e41 100644
--- a/sql/updates/world/2016_01_03_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_02_world.sql
diff --git a/sql/updates/world/2016_01_03_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_03_world.sql
index 1b1766ee557..1b1766ee557 100644
--- a/sql/updates/world/2016_01_03_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_03_world.sql
diff --git a/sql/updates/world/2016_01_03_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_04_world.sql
index ffe8eb07fd5..ffe8eb07fd5 100644
--- a/sql/updates/world/2016_01_03_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_04_world.sql
diff --git a/sql/updates/world/2016_01_03_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_05_world.sql
index 4c2fe0817f0..4c2fe0817f0 100644
--- a/sql/updates/world/2016_01_03_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_03_05_world.sql
diff --git a/sql/updates/world/2016_01_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_04_00_world.sql
index 57236a6f66e..57236a6f66e 100644
--- a/sql/updates/world/2016_01_04_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_04_00_world.sql
diff --git a/sql/updates/world/2016_01_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_00_world.sql
index 3f7f01449fc..3f7f01449fc 100644
--- a/sql/updates/world/2016_01_05_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_00_world.sql
diff --git a/sql/updates/world/2016_01_05_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_01_world.sql
index dc1064a75b9..dc1064a75b9 100644
--- a/sql/updates/world/2016_01_05_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_01_world.sql
diff --git a/sql/updates/world/2016_01_05_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_02_world.sql
index 64909129e60..64909129e60 100644
--- a/sql/updates/world/2016_01_05_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_05_02_world.sql
diff --git a/sql/updates/world/2016_01_07_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_00_world.sql
index d36dda80e50..d36dda80e50 100644
--- a/sql/updates/world/2016_01_07_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_00_world.sql
diff --git a/sql/updates/world/2016_01_07_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_01_world.sql
index 4a15aa405ec..4a15aa405ec 100644
--- a/sql/updates/world/2016_01_07_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_01_world.sql
diff --git a/sql/updates/world/2016_01_07_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_02_world.sql
index 7724b42ac9d..7724b42ac9d 100644
--- a/sql/updates/world/2016_01_07_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_07_02_world.sql
diff --git a/sql/updates/world/2016_01_08_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_00_world.sql
index 55ed3ddf336..55ed3ddf336 100644
--- a/sql/updates/world/2016_01_08_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_00_world.sql
diff --git a/sql/updates/world/2016_01_08_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_01_world.sql
index ebf4560d326..ebf4560d326 100644
--- a/sql/updates/world/2016_01_08_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_01_world.sql
diff --git a/sql/updates/world/2016_01_08_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_02_world.sql
index 28e55dfba3b..28e55dfba3b 100644
--- a/sql/updates/world/2016_01_08_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_02_world.sql
diff --git a/sql/updates/world/2016_01_08_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_03_world.sql
index 2899c6e06eb..2899c6e06eb 100644
--- a/sql/updates/world/2016_01_08_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_08_03_world.sql
diff --git a/sql/updates/world/2016_01_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_09_00_world.sql
index 534e17ccb00..534e17ccb00 100644
--- a/sql/updates/world/2016_01_09_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_09_00_world.sql
diff --git a/sql/updates/world/2016_01_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_00_world.sql
index 83ed21c8489..83ed21c8489 100644
--- a/sql/updates/world/2016_01_10_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_00_world.sql
diff --git a/sql/updates/world/2016_01_10_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_01_world.sql
index c79c157a1a1..c79c157a1a1 100644
--- a/sql/updates/world/2016_01_10_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_01_world.sql
diff --git a/sql/updates/world/2016_01_10_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_02_world.sql
index eca8ef07849..eca8ef07849 100644
--- a/sql/updates/world/2016_01_10_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_02_world.sql
diff --git a/sql/updates/world/2016_01_10_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_03_world.sql
index 5ac352ffe10..5ac352ffe10 100644
--- a/sql/updates/world/2016_01_10_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_03_world.sql
diff --git a/sql/updates/world/2016_01_10_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_04_world.sql
index da6eed191ad..da6eed191ad 100644
--- a/sql/updates/world/2016_01_10_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_04_world.sql
diff --git a/sql/updates/world/2016_01_10_05_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_05_world_335.sql
index 7fb021cc9dd..7fb021cc9dd 100644
--- a/sql/updates/world/2016_01_10_05_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_10_05_world_335.sql
diff --git a/sql/updates/world/2016_01_12_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_00_world.sql
index 8ed4099450b..8ed4099450b 100644
--- a/sql/updates/world/2016_01_12_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_00_world.sql
diff --git a/sql/updates/world/2016_01_12_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_01_world_335.sql
index c3206e70ac4..c3206e70ac4 100644
--- a/sql/updates/world/2016_01_12_01_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_01_world_335.sql
diff --git a/sql/updates/world/2016_01_12_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_02_world_335.sql
index 354d0bc129d..354d0bc129d 100644
--- a/sql/updates/world/2016_01_12_02_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_02_world_335.sql
diff --git a/sql/updates/world/2016_01_12_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_03_world.sql
index 6ff3a769918..6ff3a769918 100644
--- a/sql/updates/world/2016_01_12_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_03_world.sql
diff --git a/sql/updates/world/2016_01_12_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_04_world.sql
index 7cee9220060..7cee9220060 100644
--- a/sql/updates/world/2016_01_12_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_12_04_world.sql
diff --git a/sql/updates/world/2016_01_13_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_13_00_world.sql
index cba5d3a18a1..cba5d3a18a1 100644
--- a/sql/updates/world/2016_01_13_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_13_00_world.sql
diff --git a/sql/updates/world/2016_01_15_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_15_00_world.sql
index b5f3da2dd99..b5f3da2dd99 100644
--- a/sql/updates/world/2016_01_15_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_15_00_world.sql
diff --git a/sql/updates/world/2016_01_16_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_00_world_335.sql
index 14362432555..14362432555 100644
--- a/sql/updates/world/2016_01_16_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_00_world_335.sql
diff --git a/sql/updates/world/2016_01_16_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_01_world.sql
index 235378a7a84..235378a7a84 100644
--- a/sql/updates/world/2016_01_16_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_01_world.sql
diff --git a/sql/updates/world/2016_01_16_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_02_world.sql
index b36d7d69ff6..b36d7d69ff6 100644
--- a/sql/updates/world/2016_01_16_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_02_world.sql
diff --git a/sql/updates/world/2016_01_16_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_03_world.sql
index 5a06cfaecca..5a06cfaecca 100644
--- a/sql/updates/world/2016_01_16_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_03_world.sql
diff --git a/sql/updates/world/2016_01_16_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_04_world.sql
index a6bb7ae185c..a6bb7ae185c 100644
--- a/sql/updates/world/2016_01_16_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_04_world.sql
diff --git a/sql/updates/world/2016_01_16_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_05_world.sql
index 46511cb0de8..46511cb0de8 100644
--- a/sql/updates/world/2016_01_16_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_16_05_world.sql
diff --git a/sql/updates/world/2016_01_17_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_00_world_335.sql
index abb3579fb07..abb3579fb07 100644
--- a/sql/updates/world/2016_01_17_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_00_world_335.sql
diff --git a/sql/updates/world/2016_01_17_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_01_world.sql
index 8e5bcd22a07..8e5bcd22a07 100644
--- a/sql/updates/world/2016_01_17_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_01_world.sql
diff --git a/sql/updates/world/2016_01_17_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_02_world.sql
index f019b927228..f019b927228 100644
--- a/sql/updates/world/2016_01_17_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_02_world.sql
diff --git a/sql/updates/world/2016_01_17_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_03_world.sql
index cf43c650888..cf43c650888 100644
--- a/sql/updates/world/2016_01_17_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_03_world.sql
diff --git a/sql/updates/world/2016_01_17_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_04_world.sql
index 6d72807e0b1..6d72807e0b1 100644
--- a/sql/updates/world/2016_01_17_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_04_world.sql
diff --git a/sql/updates/world/2016_01_17_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_05_world.sql
index 2d253bae713..2d253bae713 100644
--- a/sql/updates/world/2016_01_17_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_05_world.sql
diff --git a/sql/updates/world/2016_01_17_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_06_world.sql
index 659f146845a..659f146845a 100644
--- a/sql/updates/world/2016_01_17_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_06_world.sql
diff --git a/sql/updates/world/2016_01_17_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_07_world.sql
index df588168d38..df588168d38 100644
--- a/sql/updates/world/2016_01_17_07_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_07_world.sql
diff --git a/sql/updates/world/2016_01_17_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_08_world.sql
index 48cd420a242..48cd420a242 100644
--- a/sql/updates/world/2016_01_17_08_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_08_world.sql
diff --git a/sql/updates/world/2016_01_17_09_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_09_world.sql
index 85e6f535866..85e6f535866 100644
--- a/sql/updates/world/2016_01_17_09_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_09_world.sql
diff --git a/sql/updates/world/2016_01_17_10_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_10_world.sql
index 0fdc04eb60f..0fdc04eb60f 100644
--- a/sql/updates/world/2016_01_17_10_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_10_world.sql
diff --git a/sql/updates/world/2016_01_17_11_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_11_world.sql
index 9ab963a2ff2..9ab963a2ff2 100644
--- a/sql/updates/world/2016_01_17_11_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_11_world.sql
diff --git a/sql/updates/world/2016_01_17_12_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_12_world.sql
index e4e8ab5e9e2..e4e8ab5e9e2 100644
--- a/sql/updates/world/2016_01_17_12_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_12_world.sql
diff --git a/sql/updates/world/2016_01_17_13_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_13_world.sql
index 163aa3fb659..163aa3fb659 100644
--- a/sql/updates/world/2016_01_17_13_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_13_world.sql
diff --git a/sql/updates/world/2016_01_17_14_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_14_world.sql
index c8b9405abff..c8b9405abff 100644
--- a/sql/updates/world/2016_01_17_14_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_14_world.sql
diff --git a/sql/updates/world/2016_01_17_15_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_15_world.sql
index da949d7100d..da949d7100d 100644
--- a/sql/updates/world/2016_01_17_15_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_17_15_world.sql
diff --git a/sql/updates/world/2016_01_18_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_00_world.sql
index 85f41cfc0c5..85f41cfc0c5 100644
--- a/sql/updates/world/2016_01_18_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_00_world.sql
diff --git a/sql/updates/world/2016_01_18_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_01_world.sql
index 9768ecda6c0..9768ecda6c0 100644
--- a/sql/updates/world/2016_01_18_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_01_world.sql
diff --git a/sql/updates/world/2016_01_18_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_02_world.sql
index ec9a8748cc8..ec9a8748cc8 100644
--- a/sql/updates/world/2016_01_18_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_02_world.sql
diff --git a/sql/updates/world/2016_01_18_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_03_world.sql
index 4b8eb4ae0c9..4b8eb4ae0c9 100644
--- a/sql/updates/world/2016_01_18_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_03_world.sql
diff --git a/sql/updates/world/2016_01_18_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_04_world.sql
index 28ab2d96731..28ab2d96731 100644
--- a/sql/updates/world/2016_01_18_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_04_world.sql
diff --git a/sql/updates/world/2016_01_18_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_05_world.sql
index 0d28cd17642..0d28cd17642 100644
--- a/sql/updates/world/2016_01_18_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_05_world.sql
diff --git a/sql/updates/world/2016_01_18_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_06_world.sql
index f8b90c15f54..f8b90c15f54 100644
--- a/sql/updates/world/2016_01_18_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_18_06_world.sql
diff --git a/sql/updates/world/2016_01_19_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_00_world.sql
index f210b95c13a..f210b95c13a 100644
--- a/sql/updates/world/2016_01_19_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_00_world.sql
diff --git a/sql/updates/world/2016_01_19_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_01_world.sql
index a10bc7e278f..a10bc7e278f 100644
--- a/sql/updates/world/2016_01_19_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_01_world.sql
diff --git a/sql/updates/world/2016_01_19_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_02_world.sql
index 7c71156b248..7c71156b248 100644
--- a/sql/updates/world/2016_01_19_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_02_world.sql
diff --git a/sql/updates/world/2016_01_19_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_03_world.sql
index 0d559ace044..0d559ace044 100644
--- a/sql/updates/world/2016_01_19_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_03_world.sql
diff --git a/sql/updates/world/2016_01_19_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_04_world.sql
index f4fe95f5539..f4fe95f5539 100644
--- a/sql/updates/world/2016_01_19_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_04_world.sql
diff --git a/sql/updates/world/2016_01_19_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_05_world.sql
index 5afd9e2b8a5..5afd9e2b8a5 100644
--- a/sql/updates/world/2016_01_19_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_05_world.sql
diff --git a/sql/updates/world/2016_01_19_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_06_world.sql
index cece0c623bf..cece0c623bf 100644
--- a/sql/updates/world/2016_01_19_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_06_world.sql
diff --git a/sql/updates/world/2016_01_19_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_07_world.sql
index e1a72398a5f..e1a72398a5f 100644
--- a/sql/updates/world/2016_01_19_07_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_07_world.sql
diff --git a/sql/updates/world/2016_01_19_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_08_world.sql
index d078c059201..d078c059201 100644
--- a/sql/updates/world/2016_01_19_08_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_19_08_world.sql
diff --git a/sql/updates/world/2016_01_20_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_00_world.sql
index 26ce069edd8..26ce069edd8 100644
--- a/sql/updates/world/2016_01_20_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_00_world.sql
diff --git a/sql/updates/world/2016_01_20_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_01_world.sql
index b1c6e0de756..b1c6e0de756 100644
--- a/sql/updates/world/2016_01_20_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_01_world.sql
diff --git a/sql/updates/world/2016_01_20_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_02_world.sql
index d026c3cb478..d026c3cb478 100644
--- a/sql/updates/world/2016_01_20_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_20_02_world.sql
diff --git a/sql/updates/world/2016_01_23_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_23_00_world.sql
index 02eaa7c370d..02eaa7c370d 100644
--- a/sql/updates/world/2016_01_23_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_23_00_world.sql
diff --git a/sql/updates/world/2016_01_24_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_24_00_world.sql
index a28b3fa25b8..a28b3fa25b8 100644
--- a/sql/updates/world/2016_01_24_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_24_00_world.sql
diff --git a/sql/updates/world/2016_01_26_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_26_00_world.sql
index 71fe8dc21e3..71fe8dc21e3 100644
--- a/sql/updates/world/2016_01_26_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_26_00_world.sql
diff --git a/sql/updates/world/2016_01_28_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_00_world_335.sql
index 64b32cb2d89..64b32cb2d89 100644
--- a/sql/updates/world/2016_01_28_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_00_world_335.sql
diff --git a/sql/updates/world/2016_01_28_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_01_world.sql
index 3c4cadb310d..3c4cadb310d 100644
--- a/sql/updates/world/2016_01_28_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_28_01_world.sql
diff --git a/sql/updates/world/2016_01_30_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_00_world_335.sql
index 43025f581d7..43025f581d7 100644
--- a/sql/updates/world/2016_01_30_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_00_world_335.sql
diff --git a/sql/updates/world/2016_01_30_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_01_world.sql
index c9405c4ee61..c9405c4ee61 100644
--- a/sql/updates/world/2016_01_30_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_01_world.sql
diff --git a/sql/updates/world/2016_01_30_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_02_world.sql
index 25325dddd7a..25325dddd7a 100644
--- a/sql/updates/world/2016_01_30_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_02_world.sql
diff --git a/sql/updates/world/2016_01_30_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_03_world.sql
index 06c4b0826c0..06c4b0826c0 100644
--- a/sql/updates/world/2016_01_30_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_03_world.sql
diff --git a/sql/updates/world/2016_01_30_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_04_world.sql
index b90e7b95810..b90e7b95810 100644
--- a/sql/updates/world/2016_01_30_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_04_world.sql
diff --git a/sql/updates/world/2016_01_30_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_05_world.sql
index 1e341506dfc..1e341506dfc 100644
--- a/sql/updates/world/2016_01_30_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_30_05_world.sql
diff --git a/sql/updates/world/2016_01_31_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_31_00_world.sql
index f64d9182784..f64d9182784 100644
--- a/sql/updates/world/2016_01_31_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_01_31_00_world.sql
diff --git a/sql/updates/world/2016_02_02_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_00_world.sql
index ce561af3a61..ce561af3a61 100644
--- a/sql/updates/world/2016_02_02_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_00_world.sql
diff --git a/sql/updates/world/2016_02_02_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_01_world.sql
index f1b181a29e3..f1b181a29e3 100644
--- a/sql/updates/world/2016_02_02_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_02_01_world.sql
diff --git a/sql/updates/world/2016_02_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_04_00_world.sql
index 758286544af..758286544af 100644
--- a/sql/updates/world/2016_02_04_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_04_00_world.sql
diff --git a/sql/updates/world/2016_02_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_05_00_world.sql
index 46f2b488b9a..46f2b488b9a 100644
--- a/sql/updates/world/2016_02_05_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_05_00_world.sql
diff --git a/sql/updates/world/2016_02_06_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_00_world.sql
index d303a8b5b85..d303a8b5b85 100644
--- a/sql/updates/world/2016_02_06_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_00_world.sql
diff --git a/sql/updates/world/2016_02_06_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_01_world.sql
index 6812c4af52e..6812c4af52e 100644
--- a/sql/updates/world/2016_02_06_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_01_world.sql
diff --git a/sql/updates/world/2016_02_06_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_02_world.sql
index b9fd7cd9d63..b9fd7cd9d63 100644
--- a/sql/updates/world/2016_02_06_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_02_world.sql
diff --git a/sql/updates/world/2016_02_06_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_03_world.sql
index 85f8d3c6ae7..85f8d3c6ae7 100644
--- a/sql/updates/world/2016_02_06_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_03_world.sql
diff --git a/sql/updates/world/2016_02_06_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_04_world.sql
index 188b3b5f2a7..188b3b5f2a7 100644
--- a/sql/updates/world/2016_02_06_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_04_world.sql
diff --git a/sql/updates/world/2016_02_06_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_05_world.sql
index 823a8abaca6..823a8abaca6 100644
--- a/sql/updates/world/2016_02_06_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_05_world.sql
diff --git a/sql/updates/world/2016_02_06_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_06_world.sql
index 37df2ef0868..37df2ef0868 100644
--- a/sql/updates/world/2016_02_06_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_06_world.sql
diff --git a/sql/updates/world/2016_02_06_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_07_world.sql
index c5d6434321a..c5d6434321a 100644
--- a/sql/updates/world/2016_02_06_07_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_07_world.sql
diff --git a/sql/updates/world/2016_02_06_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_08_world.sql
index f0855ba348a..f0855ba348a 100644
--- a/sql/updates/world/2016_02_06_08_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_08_world.sql
diff --git a/sql/updates/world/2016_02_06_09_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_09_world.sql
index bf92b89e1c2..bf92b89e1c2 100644
--- a/sql/updates/world/2016_02_06_09_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_09_world.sql
diff --git a/sql/updates/world/2016_02_06_10_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_10_world.sql
index 291bd0bb333..291bd0bb333 100644
--- a/sql/updates/world/2016_02_06_10_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_10_world.sql
diff --git a/sql/updates/world/2016_02_06_11_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_11_world.sql
index cea352fec36..cea352fec36 100644
--- a/sql/updates/world/2016_02_06_11_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_11_world.sql
diff --git a/sql/updates/world/2016_02_06_12_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_12_world.sql
index df550156bc1..df550156bc1 100644
--- a/sql/updates/world/2016_02_06_12_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_12_world.sql
diff --git a/sql/updates/world/2016_02_06_13_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_13_world_335.sql
index 22bd5596d98..22bd5596d98 100644
--- a/sql/updates/world/2016_02_06_13_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_13_world_335.sql
diff --git a/sql/updates/world/2016_02_06_14_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_14_world.sql
index 7bf05b61c71..7bf05b61c71 100644
--- a/sql/updates/world/2016_02_06_14_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_06_14_world.sql
diff --git a/sql/updates/world/2016_02_07_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_00_world.sql
index 5a49f8fd310..5a49f8fd310 100644
--- a/sql/updates/world/2016_02_07_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_00_world.sql
diff --git a/sql/updates/world/2016_02_07_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_01_world_335.sql
index 5f1d5f4280e..5f1d5f4280e 100644
--- a/sql/updates/world/2016_02_07_01_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_01_world_335.sql
diff --git a/sql/updates/world/2016_02_07_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_02_world_335.sql
index ea4608f3a6b..ea4608f3a6b 100644
--- a/sql/updates/world/2016_02_07_02_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_02_world_335.sql
diff --git a/sql/updates/world/2016_02_07_03_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_03_world_335.sql
index 8322ff59c4c..8322ff59c4c 100644
--- a/sql/updates/world/2016_02_07_03_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_03_world_335.sql
diff --git a/sql/updates/world/2016_02_07_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_04_world.sql
index 3a3a7a393d7..3a3a7a393d7 100644
--- a/sql/updates/world/2016_02_07_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_04_world.sql
diff --git a/sql/updates/world/2016_02_07_05_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_05_world_335.sql
index 794b3d80411..794b3d80411 100644
--- a/sql/updates/world/2016_02_07_05_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_05_world_335.sql
diff --git a/sql/updates/world/2016_02_07_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_06_world.sql
index 31ecf826660..31ecf826660 100644
--- a/sql/updates/world/2016_02_07_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_06_world.sql
diff --git a/sql/updates/world/2016_02_07_07_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_07_world_335.sql
index af323a47bda..af323a47bda 100644
--- a/sql/updates/world/2016_02_07_07_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_07_world_335.sql
diff --git a/sql/updates/world/2016_02_07_08_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_08_world_335.sql
index 2b78a317f95..2b78a317f95 100644
--- a/sql/updates/world/2016_02_07_08_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_08_world_335.sql
diff --git a/sql/updates/world/2016_02_07_09_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_09_world.sql
index 8057534fbb8..8057534fbb8 100644
--- a/sql/updates/world/2016_02_07_09_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_09_world.sql
diff --git a/sql/updates/world/2016_02_07_10_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_10_world.sql
index c2e59c15d9c..c2e59c15d9c 100644
--- a/sql/updates/world/2016_02_07_10_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_10_world.sql
diff --git a/sql/updates/world/2016_02_07_11_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_11_world.sql
index c40b663c205..c40b663c205 100644
--- a/sql/updates/world/2016_02_07_11_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_11_world.sql
diff --git a/sql/updates/world/2016_02_07_12_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_12_world.sql
index c85265d857d..c85265d857d 100644
--- a/sql/updates/world/2016_02_07_12_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_12_world.sql
diff --git a/sql/updates/world/2016_02_07_13_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_13_world.sql
index 612fef2274d..612fef2274d 100644
--- a/sql/updates/world/2016_02_07_13_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_13_world.sql
diff --git a/sql/updates/world/2016_02_07_14_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_14_world.sql
index 6550e53f9c9..6550e53f9c9 100644
--- a/sql/updates/world/2016_02_07_14_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_14_world.sql
diff --git a/sql/updates/world/2016_02_07_15_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_15_world.sql
index ceec02f881b..ceec02f881b 100644
--- a/sql/updates/world/2016_02_07_15_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_07_15_world.sql
diff --git a/sql/updates/world/2016_02_08_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_00_world_335.sql
index 83091035e3c..83091035e3c 100644
--- a/sql/updates/world/2016_02_08_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_00_world_335.sql
diff --git a/sql/updates/world/2016_02_08_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_01_world.sql
index 9f8fa3dc4ed..9f8fa3dc4ed 100644
--- a/sql/updates/world/2016_02_08_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_01_world.sql
diff --git a/sql/updates/world/2016_02_08_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_02_world.sql
index 0f22abafe8e..0f22abafe8e 100644
--- a/sql/updates/world/2016_02_08_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_02_world.sql
diff --git a/sql/updates/world/2016_02_08_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_03_world.sql
index fe429cf42c8..fe429cf42c8 100644
--- a/sql/updates/world/2016_02_08_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_03_world.sql
diff --git a/sql/updates/world/2016_02_08_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_04_world.sql
index f8a9e2c776a..f8a9e2c776a 100644
--- a/sql/updates/world/2016_02_08_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_04_world.sql
diff --git a/sql/updates/world/2016_02_08_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_05_world.sql
index d2cc597a6ac..d2cc597a6ac 100644
--- a/sql/updates/world/2016_02_08_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_05_world.sql
diff --git a/sql/updates/world/2016_02_08_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_06_world.sql
index c9e93889790..c9e93889790 100644
--- a/sql/updates/world/2016_02_08_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_06_world.sql
diff --git a/sql/updates/world/2016_02_08_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_07_world.sql
index 1d90630d829..1d90630d829 100644
--- a/sql/updates/world/2016_02_08_07_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_07_world.sql
diff --git a/sql/updates/world/2016_02_08_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_08_world.sql
index ae4f454bc91..ae4f454bc91 100644
--- a/sql/updates/world/2016_02_08_08_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_08_08_world.sql
diff --git a/sql/updates/world/2016_02_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_00_world.sql
index c93a1d8fed1..c93a1d8fed1 100644
--- a/sql/updates/world/2016_02_09_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_00_world.sql
diff --git a/sql/updates/world/2016_02_09_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_01_world.sql
index 7878ea7faa2..7878ea7faa2 100644
--- a/sql/updates/world/2016_02_09_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_01_world.sql
diff --git a/sql/updates/world/2016_02_09_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world.sql
index 891c8c2ff4b..891c8c2ff4b 100644
--- a/sql/updates/world/2016_02_09_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world.sql
diff --git a/sql/updates/world/2016_02_09_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world_335.sql
index a8612c5d88d..a8612c5d88d 100644
--- a/sql/updates/world/2016_02_09_02_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_02_world_335.sql
diff --git a/sql/updates/world/2016_02_09_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_03_world.sql
index bd012f0d172..bd012f0d172 100644
--- a/sql/updates/world/2016_02_09_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_03_world.sql
diff --git a/sql/updates/world/2016_02_09_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_04_world.sql
index 015ab519557..015ab519557 100644
--- a/sql/updates/world/2016_02_09_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_04_world.sql
diff --git a/sql/updates/world/2016_02_09_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_05_world.sql
index 3612c270d02..3612c270d02 100644
--- a/sql/updates/world/2016_02_09_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_05_world.sql
diff --git a/sql/updates/world/2016_02_09_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_06_world.sql
index 03fe998cca5..03fe998cca5 100644
--- a/sql/updates/world/2016_02_09_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_06_world.sql
diff --git a/sql/updates/world/2016_02_09_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_07_world.sql
index 84d65e2eda5..84d65e2eda5 100644
--- a/sql/updates/world/2016_02_09_07_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_07_world.sql
diff --git a/sql/updates/world/2016_02_09_08_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_08_world.sql
index 307a9f9a0b3..307a9f9a0b3 100644
--- a/sql/updates/world/2016_02_09_08_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_09_08_world.sql
diff --git a/sql/updates/world/2016_02_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_00_world.sql
index 872861b08dc..872861b08dc 100644
--- a/sql/updates/world/2016_02_10_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_00_world.sql
diff --git a/sql/updates/world/2016_02_10_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_01_world.sql
index 9ffe2e81c1c..9ffe2e81c1c 100644
--- a/sql/updates/world/2016_02_10_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_01_world.sql
diff --git a/sql/updates/world/2016_02_10_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_02_world.sql
index 92ee165dd83..92ee165dd83 100644
--- a/sql/updates/world/2016_02_10_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_02_world.sql
diff --git a/sql/updates/world/2016_02_10_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_03_world.sql
index f52872c3431..f52872c3431 100644
--- a/sql/updates/world/2016_02_10_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_03_world.sql
diff --git a/sql/updates/world/2016_02_10_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_04_world.sql
index 1349b83f442..1349b83f442 100644
--- a/sql/updates/world/2016_02_10_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_04_world.sql
diff --git a/sql/updates/world/2016_02_10_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_05_world.sql
index c19dd8feb06..c19dd8feb06 100644
--- a/sql/updates/world/2016_02_10_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_05_world.sql
diff --git a/sql/updates/world/2016_02_10_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_06_world.sql
index 9e24ab31ce1..9e24ab31ce1 100644
--- a/sql/updates/world/2016_02_10_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_06_world.sql
diff --git a/sql/updates/world/2016_02_10_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_07_world.sql
index 5feb4f44163..5feb4f44163 100644
--- a/sql/updates/world/2016_02_10_07_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_10_07_world.sql
diff --git a/sql/updates/world/2016_02_11_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_00_world.sql
index b130133a2ca..b130133a2ca 100644
--- a/sql/updates/world/2016_02_11_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_00_world.sql
diff --git a/sql/updates/world/2016_02_11_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_01_world.sql
index ec1c98659e1..ec1c98659e1 100644
--- a/sql/updates/world/2016_02_11_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_01_world.sql
diff --git a/sql/updates/world/2016_02_11_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_02_world.sql
index 9228e2d99d7..9228e2d99d7 100644
--- a/sql/updates/world/2016_02_11_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_02_world.sql
diff --git a/sql/updates/world/2016_02_11_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_03_world.sql
index 4dfefb12281..4dfefb12281 100644
--- a/sql/updates/world/2016_02_11_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_03_world.sql
diff --git a/sql/updates/world/2016_02_11_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_04_world.sql
index 41f648b5f6e..41f648b5f6e 100644
--- a/sql/updates/world/2016_02_11_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_04_world.sql
diff --git a/sql/updates/world/2016_02_11_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_05_world.sql
index 76b59765d08..76b59765d08 100644
--- a/sql/updates/world/2016_02_11_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_05_world.sql
diff --git a/sql/updates/world/2016_02_11_06_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_06_world.sql
index bbf9880dca9..bbf9880dca9 100644
--- a/sql/updates/world/2016_02_11_06_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_06_world.sql
diff --git a/sql/updates/world/2016_02_11_07_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_07_world.sql
index e34106cb44c..e34106cb44c 100644
--- a/sql/updates/world/2016_02_11_07_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_11_07_world.sql
diff --git a/sql/updates/world/2016_02_12_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_12_00_world.sql
index af599148e04..af599148e04 100644
--- a/sql/updates/world/2016_02_12_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_12_00_world.sql
diff --git a/sql/updates/world/2016_02_13_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_00_world.sql
index 2341e33a8b5..2341e33a8b5 100644
--- a/sql/updates/world/2016_02_13_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_00_world.sql
diff --git a/sql/updates/world/2016_02_13_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_01_world.sql
index 29f94a9f41d..29f94a9f41d 100644
--- a/sql/updates/world/2016_02_13_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_01_world.sql
diff --git a/sql/updates/world/2016_02_13_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_02_world.sql
index 5a4633fee41..5a4633fee41 100644
--- a/sql/updates/world/2016_02_13_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_02_world.sql
diff --git a/sql/updates/world/2016_02_13_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_03_world.sql
index 136a068bd9e..136a068bd9e 100644
--- a/sql/updates/world/2016_02_13_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_03_world.sql
diff --git a/sql/updates/world/2016_02_13_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_04_world.sql
index 83d95745052..83d95745052 100644
--- a/sql/updates/world/2016_02_13_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_13_04_world.sql
diff --git a/sql/updates/world/2016_02_14_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_00_world.sql
index 961ecd74d4d..961ecd74d4d 100644
--- a/sql/updates/world/2016_02_14_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_00_world.sql
diff --git a/sql/updates/world/2016_02_14_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_01_world.sql
index 2ce06020621..2ce06020621 100644
--- a/sql/updates/world/2016_02_14_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_01_world.sql
diff --git a/sql/updates/world/2016_02_14_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_02_world.sql
index 1459b702cf0..1459b702cf0 100644
--- a/sql/updates/world/2016_02_14_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_02_world.sql
diff --git a/sql/updates/world/2016_02_14_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_03_world.sql
index 9a0237725c0..9a0237725c0 100644
--- a/sql/updates/world/2016_02_14_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_03_world.sql
diff --git a/sql/updates/world/2016_02_14_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_04_world.sql
index 58e0aaee311..58e0aaee311 100644
--- a/sql/updates/world/2016_02_14_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_14_04_world.sql
diff --git a/sql/updates/world/2016_02_15_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_15_00_world.sql
index 43c2ae69382..43c2ae69382 100644
--- a/sql/updates/world/2016_02_15_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_15_00_world.sql
diff --git a/sql/updates/world/2016_02_17_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_00_world.sql
index 8f22aaa3e4e..8f22aaa3e4e 100644
--- a/sql/updates/world/2016_02_17_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_00_world.sql
diff --git a/sql/updates/world/2016_02_17_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_01_world.sql
index 20f3605b197..20f3605b197 100644
--- a/sql/updates/world/2016_02_17_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_01_world.sql
diff --git a/sql/updates/world/2016_02_17_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_02_world.sql
index 6590396b7d9..6590396b7d9 100644
--- a/sql/updates/world/2016_02_17_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_17_02_world.sql
diff --git a/sql/updates/world/2016_02_18_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_00_world.sql
index c20196ddc80..c20196ddc80 100644
--- a/sql/updates/world/2016_02_18_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_00_world.sql
diff --git a/sql/updates/world/2016_02_18_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_01_world.sql
index c3ffdbb6344..c3ffdbb6344 100644
--- a/sql/updates/world/2016_02_18_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_01_world.sql
diff --git a/sql/updates/world/2016_02_18_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_02_world.sql
index 414c6fd9c3a..414c6fd9c3a 100644
--- a/sql/updates/world/2016_02_18_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_18_02_world.sql
diff --git a/sql/updates/world/2016_02_19_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_00_world.sql
index bee93f7bdd4..bee93f7bdd4 100644
--- a/sql/updates/world/2016_02_19_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_00_world.sql
diff --git a/sql/updates/world/2016_02_19_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_01_world_335.sql
index f7fee657170..f7fee657170 100644
--- a/sql/updates/world/2016_02_19_01_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_19_01_world_335.sql
diff --git a/sql/updates/world/2016_02_22_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_00_world.sql
index d92ea91681a..d92ea91681a 100644
--- a/sql/updates/world/2016_02_22_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_00_world.sql
diff --git a/sql/updates/world/2016_02_22_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_01_world.sql
index b1345bb1aab..b1345bb1aab 100644
--- a/sql/updates/world/2016_02_22_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_01_world.sql
diff --git a/sql/updates/world/2016_02_22_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_02_world.sql
index dd62e6dce29..dd62e6dce29 100644
--- a/sql/updates/world/2016_02_22_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_22_02_world.sql
diff --git a/sql/updates/world/2016_02_23_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_00_world.sql
index 871ce608f1c..871ce608f1c 100644
--- a/sql/updates/world/2016_02_23_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_00_world.sql
diff --git a/sql/updates/world/2016_02_23_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_01_world.sql
index 0773487dbc7..0773487dbc7 100644
--- a/sql/updates/world/2016_02_23_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_01_world.sql
diff --git a/sql/updates/world/2016_02_23_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_02_world.sql
index 9e2c550dd65..9e2c550dd65 100644
--- a/sql/updates/world/2016_02_23_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_23_02_world.sql
diff --git a/sql/updates/world/2016_02_24_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_24_00_world.sql
index 06c7c29bd72..06c7c29bd72 100644
--- a/sql/updates/world/2016_02_24_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_24_00_world.sql
diff --git a/sql/updates/world/2016_02_25_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_00_world.sql
index 346c77bee43..346c77bee43 100644
--- a/sql/updates/world/2016_02_25_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_00_world.sql
diff --git a/sql/updates/world/2016_02_25_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_01_world_335.sql
index 473cbd506ce..473cbd506ce 100644
--- a/sql/updates/world/2016_02_25_01_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_01_world_335.sql
diff --git a/sql/updates/world/2016_02_25_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_02_world.sql
index c5355b13c29..c5355b13c29 100644
--- a/sql/updates/world/2016_02_25_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_25_02_world.sql
diff --git a/sql/updates/world/2016_02_26_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_00_world.sql
index d08d5055089..d08d5055089 100644
--- a/sql/updates/world/2016_02_26_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_00_world.sql
diff --git a/sql/updates/world/2016_02_26_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_01_world.sql
index b30b3cba35f..b30b3cba35f 100644
--- a/sql/updates/world/2016_02_26_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_26_01_world.sql
diff --git a/sql/updates/world/2016_02_27_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_27_00_world.sql
index b9288b2ddfb..b9288b2ddfb 100644
--- a/sql/updates/world/2016_02_27_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_27_00_world.sql
diff --git a/sql/updates/world/2016_02_28_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_28_00_world.sql
index 5a5694e0320..5a5694e0320 100644
--- a/sql/updates/world/2016_02_28_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_28_00_world.sql
diff --git a/sql/updates/world/2016_02_29_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_00_world.sql
index 280f2f901ef..280f2f901ef 100644
--- a/sql/updates/world/2016_02_29_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_00_world.sql
diff --git a/sql/updates/world/2016_02_29_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_01_world.sql
index 40343440d9a..40343440d9a 100644
--- a/sql/updates/world/2016_02_29_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_02_29_01_world.sql
diff --git a/sql/updates/world/2016_03_01_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_01_00_world_335.sql
index 36c48379190..36c48379190 100644
--- a/sql/updates/world/2016_03_01_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_01_00_world_335.sql
diff --git a/sql/updates/world/2016_03_02_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_02_00_world_335.sql
index e7a9f60e790..e7a9f60e790 100644
--- a/sql/updates/world/2016_03_02_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_02_00_world_335.sql
diff --git a/sql/updates/world/2016_03_03_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_00_world.sql
index 473bac4708a..473bac4708a 100644
--- a/sql/updates/world/2016_03_03_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_00_world.sql
diff --git a/sql/updates/world/2016_03_03_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_01_world.sql
index a242d26efe1..a242d26efe1 100644
--- a/sql/updates/world/2016_03_03_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_03_01_world.sql
diff --git a/sql/updates/world/2016_03_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_00_world.sql
index f338d6d0043..f338d6d0043 100644
--- a/sql/updates/world/2016_03_04_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_00_world.sql
diff --git a/sql/updates/world/2016_03_04_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_01_world.sql
index b02c2eb4e79..b02c2eb4e79 100644
--- a/sql/updates/world/2016_03_04_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_01_world.sql
diff --git a/sql/updates/world/2016_03_04_02_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_02_world_335.sql
index db8ca3a9178..db8ca3a9178 100644
--- a/sql/updates/world/2016_03_04_02_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_02_world_335.sql
diff --git a/sql/updates/world/2016_03_04_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_03_world.sql
index 4d148adde55..4d148adde55 100644
--- a/sql/updates/world/2016_03_04_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_04_03_world.sql
diff --git a/sql/updates/world/2016_03_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_05_00_world.sql
index 8dde060140d..8dde060140d 100644
--- a/sql/updates/world/2016_03_05_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_05_00_world.sql
diff --git a/sql/updates/world/2016_03_06_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_00_world.sql
index e991023e514..e991023e514 100644
--- a/sql/updates/world/2016_03_06_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_00_world.sql
diff --git a/sql/updates/world/2016_03_06_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_01_world.sql
index 183121d6735..183121d6735 100644
--- a/sql/updates/world/2016_03_06_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_06_01_world.sql
diff --git a/sql/updates/world/2016_03_07_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_00_world.sql
index b9df4d07bb9..b9df4d07bb9 100644
--- a/sql/updates/world/2016_03_07_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_00_world.sql
diff --git a/sql/updates/world/2016_03_07_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_01_world.sql
index d74f4296903..d74f4296903 100644
--- a/sql/updates/world/2016_03_07_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_07_01_world.sql
diff --git a/sql/updates/world/2016_03_09_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_09_00_world.sql
index d3ebf1af0ff..d3ebf1af0ff 100644
--- a/sql/updates/world/2016_03_09_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_09_00_world.sql
diff --git a/sql/updates/world/2016_03_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_00_world.sql
index e3170b27499..e3170b27499 100644
--- a/sql/updates/world/2016_03_10_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_00_world.sql
diff --git a/sql/updates/world/2016_03_10_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_01_world.sql
index 80b23be82c2..80b23be82c2 100644
--- a/sql/updates/world/2016_03_10_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_10_01_world.sql
diff --git a/sql/updates/world/2016_03_12_2015_11_14_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_12_2015_11_14_00_world.sql
index b3e49eb1114..b3e49eb1114 100644
--- a/sql/updates/world/2016_03_12_2015_11_14_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_12_2015_11_14_00_world.sql
diff --git a/sql/updates/world/2016_03_13_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_00_world.sql
index 0c45636d945..0c45636d945 100644
--- a/sql/updates/world/2016_03_13_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_00_world.sql
diff --git a/sql/updates/world/2016_03_13_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_01_world.sql
index 12bc205f125..12bc205f125 100644
--- a/sql/updates/world/2016_03_13_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_13_01_world.sql
diff --git a/sql/updates/world/2016_03_15_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_15_00_world.sql
index 69e2e3a873b..69e2e3a873b 100644
--- a/sql/updates/world/2016_03_15_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_15_00_world.sql
diff --git a/sql/updates/world/2016_03_19_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_00_world.sql
index ce96286d585..ce96286d585 100644
--- a/sql/updates/world/2016_03_19_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_00_world.sql
diff --git a/sql/updates/world/2016_03_19_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_01_world.sql
index 79452fdf43c..79452fdf43c 100644
--- a/sql/updates/world/2016_03_19_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_01_world.sql
diff --git a/sql/updates/world/2016_03_19_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_02_world.sql
index a0a6ff3619c..a0a6ff3619c 100644
--- a/sql/updates/world/2016_03_19_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_19_02_world.sql
diff --git a/sql/updates/world/2016_03_20_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_00_world.sql
index 8120f1be86f..8120f1be86f 100644
--- a/sql/updates/world/2016_03_20_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_00_world.sql
diff --git a/sql/updates/world/2016_03_20_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_01_world.sql
index f59710f1e32..f59710f1e32 100644
--- a/sql/updates/world/2016_03_20_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_01_world.sql
diff --git a/sql/updates/world/2016_03_20_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_02_world.sql
index 9b03a9cdea3..9b03a9cdea3 100644
--- a/sql/updates/world/2016_03_20_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_20_02_world.sql
diff --git a/sql/updates/world/2016_03_21_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_21_00_world.sql
index 55f6cceaed8..55f6cceaed8 100644
--- a/sql/updates/world/2016_03_21_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_21_00_world.sql
diff --git a/sql/updates/world/2016_03_23_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_23_00_world.sql
index 9195b652288..9195b652288 100644
--- a/sql/updates/world/2016_03_23_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_23_00_world.sql
diff --git a/sql/updates/world/2016_03_24_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_00_world_335.sql
index 4d69d8fd3f2..4d69d8fd3f2 100644
--- a/sql/updates/world/2016_03_24_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_00_world_335.sql
diff --git a/sql/updates/world/2016_03_24_01_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_01_world_335.sql
index 01d7857519e..01d7857519e 100644
--- a/sql/updates/world/2016_03_24_01_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_01_world_335.sql
diff --git a/sql/updates/world/2016_03_24_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_02_world.sql
index 199582eb4a0..199582eb4a0 100644
--- a/sql/updates/world/2016_03_24_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_24_02_world.sql
diff --git a/sql/updates/world/2016_03_26_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_26_00_world.sql
index 58a42dc214d..58a42dc214d 100644
--- a/sql/updates/world/2016_03_26_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_26_00_world.sql
diff --git a/sql/updates/world/2016_03_27_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_27_00_world.sql
index 9421881c88a..9421881c88a 100644
--- a/sql/updates/world/2016_03_27_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_27_00_world.sql
diff --git a/sql/updates/world/2016_03_28_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_00_world.sql
index b4a7e2d5a36..b4a7e2d5a36 100644
--- a/sql/updates/world/2016_03_28_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_00_world.sql
diff --git a/sql/updates/world/2016_03_28_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_01_world.sql
index b4a24b011b3..b4a24b011b3 100644
--- a/sql/updates/world/2016_03_28_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_28_01_world.sql
diff --git a/sql/updates/world/2016_03_29_00_world_335.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_29_00_world_335.sql
index e3851e59c8e..e3851e59c8e 100644
--- a/sql/updates/world/2016_03_29_00_world_335.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_03_29_00_world_335.sql
diff --git a/sql/updates/world/2016_04_01_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_00_world.sql
index 024bbb6fa5a..024bbb6fa5a 100644
--- a/sql/updates/world/2016_04_01_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_00_world.sql
diff --git a/sql/updates/world/2016_04_01_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_01_world.sql
index 38a13f0ea84..38a13f0ea84 100644
--- a/sql/updates/world/2016_04_01_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_01_01_world.sql
diff --git a/sql/updates/world/2016_04_02_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_00_world.sql
index dc8f4375da0..dc8f4375da0 100644
--- a/sql/updates/world/2016_04_02_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_00_world.sql
diff --git a/sql/updates/world/2016_04_02_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_01_world.sql
index 4bcca1d6250..4bcca1d6250 100644
--- a/sql/updates/world/2016_04_02_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_01_world.sql
diff --git a/sql/updates/world/2016_04_02_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_02_world.sql
index 89b8032be10..89b8032be10 100644
--- a/sql/updates/world/2016_04_02_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_02_02_world.sql
diff --git a/sql/updates/world/2016_04_03_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_00_world.sql
index 8344df664f2..8344df664f2 100644
--- a/sql/updates/world/2016_04_03_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_00_world.sql
diff --git a/sql/updates/world/2016_04_03_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_01_world.sql
index a150fe2d69e..a150fe2d69e 100644
--- a/sql/updates/world/2016_04_03_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_01_world.sql
diff --git a/sql/updates/world/2016_04_03_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_02_world.sql
index 1a408d3ec6a..1a408d3ec6a 100644
--- a/sql/updates/world/2016_04_03_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_03_02_world.sql
diff --git a/sql/updates/world/2016_04_04_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_04_00_world.sql
index 69da8a7d699..69da8a7d699 100644
--- a/sql/updates/world/2016_04_04_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_04_00_world.sql
diff --git a/sql/updates/world/2016_04_05_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_00_world.sql
index f59e70ddb34..f59e70ddb34 100644
--- a/sql/updates/world/2016_04_05_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_00_world.sql
diff --git a/sql/updates/world/2016_04_05_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_01_world.sql
index eb2609af74d..eb2609af74d 100644
--- a/sql/updates/world/2016_04_05_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_05_01_world.sql
diff --git a/sql/updates/world/2016_04_08_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_08_00_world.sql
index 930e599396f..930e599396f 100644
--- a/sql/updates/world/2016_04_08_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_08_00_world.sql
diff --git a/sql/updates/world/2016_04_09_00_world_2016_03_28_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_00_world_2016_03_28_00_world.sql
index 0fc505965a3..0fc505965a3 100644
--- a/sql/updates/world/2016_04_09_00_world_2016_03_28_00_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_00_world_2016_03_28_00_world.sql
diff --git a/sql/updates/world/2016_04_09_01_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_01_world.sql
index 0c01492d746..0c01492d746 100644
--- a/sql/updates/world/2016_04_09_01_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_01_world.sql
diff --git a/sql/updates/world/2016_04_09_02_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_02_world.sql
index 60ae64d1715..60ae64d1715 100644
--- a/sql/updates/world/2016_04_09_02_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_02_world.sql
diff --git a/sql/updates/world/2016_04_09_03_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_03_world.sql
index 732e3d83ee5..732e3d83ee5 100644
--- a/sql/updates/world/2016_04_09_03_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_03_world.sql
diff --git a/sql/updates/world/2016_04_09_04_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_04_world.sql
index 01154d2070a..01154d2070a 100644
--- a/sql/updates/world/2016_04_09_04_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_04_world.sql
diff --git a/sql/updates/world/2016_04_09_05_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_05_world.sql
index 815540ecef1..815540ecef1 100644
--- a/sql/updates/world/2016_04_09_05_world.sql
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_09_05_world.sql
diff --git a/sql/old/3.3.5a/world/60_2016_04_11/2016_04_10_00_world.sql b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_10_00_world.sql
new file mode 100644
index 00000000000..d5c24c4a65d
--- /dev/null
+++ b/sql/old/3.3.5a/world/60_2016_04_11/2016_04_10_00_world.sql
@@ -0,0 +1,20 @@
+UPDATE `creature` SET `unit_flags`=33587968 WHERE `guid`IN(53208,53209,53210,53617,53586,53229,53711,53230,53710);
+
+DELETE FROM `creature_addon` WHERE `guid` IN(53208,53209,53210,53210,53617,53586,53229,53711,53230,53710);
+INSERT INTO `creature_addon` (`guid`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES
+(53208, 0, 0x7, 0x1, ''), -- 23232 - 41290 - 41290
+(53209, 0, 0x7, 0x1, ''), -- 23232 - 41290 - 41290
+(53210, 0, 0x7, 0x1, ''), -- 23232 - 41290 - 41290
+(53617, 0, 0x7, 0x1, ''), -- 23236
+(53586, 0, 0x7, 0x1, ''), -- 23236
+(53229, 0, 0x7, 0x1, ''), -- 23235
+(53711, 0, 0x7, 0x1, ''), -- 23237
+(53230, 0, 0x7, 0x1, ''), -- 23235
+(53710, 0, 0x7, 0x1, ''); -- 23237
+
+UPDATE `creature_template` SET `ainame`='SmartAI', `scriptname`='' WHERE `entry` IN(23232);
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN(23232) AND `source_type`=0;
+
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(23232, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 11, 41290, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mutant War Hound - On Reset - Cast Disease Cloud'),
+(23232, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 11, 41193, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Mutant War Hound - On Death - Cast Cloud of Disease');
diff --git a/sql/updates/auth/3.3.5/2016_04_11_00_auth.sql b/sql/updates/auth/3.3.5/2016_04_11_00_auth.sql
new file mode 100644
index 00000000000..be8a4d21b66
--- /dev/null
+++ b/sql/updates/auth/3.3.5/2016_04_11_00_auth.sql
@@ -0,0 +1 @@
+UPDATE `updates` SET `state`='ARCHIVED';
diff --git a/sql/updates/auth/dummy b/sql/updates/auth/3.3.5/dummy
index e69de29bb2d..e69de29bb2d 100644
--- a/sql/updates/auth/dummy
+++ b/sql/updates/auth/3.3.5/dummy
diff --git a/sql/updates/characters/3.3.5/2016_04_11_00_characters.sql b/sql/updates/characters/3.3.5/2016_04_11_00_characters.sql
new file mode 100644
index 00000000000..be8a4d21b66
--- /dev/null
+++ b/sql/updates/characters/3.3.5/2016_04_11_00_characters.sql
@@ -0,0 +1 @@
+UPDATE `updates` SET `state`='ARCHIVED';
diff --git a/sql/updates/characters/dummy b/sql/updates/characters/3.3.5/dummy
index e69de29bb2d..e69de29bb2d 100644
--- a/sql/updates/characters/dummy
+++ b/sql/updates/characters/3.3.5/dummy
diff --git a/sql/updates/world/3.3.5/2016_04_11_00_world.sql b/sql/updates/world/3.3.5/2016_04_11_00_world.sql
new file mode 100644
index 00000000000..2f8d539fe43
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_11_00_world.sql
@@ -0,0 +1,3 @@
+UPDATE `version` SET `db_version`='TDB 335.61', `cache_id`=61 LIMIT 1;
+
+UPDATE `updates` SET `state`='ARCHIVED';
diff --git a/sql/updates/world/3.3.5/2016_04_11_01_world_335.sql b/sql/updates/world/3.3.5/2016_04_11_01_world_335.sql
new file mode 100644
index 00000000000..a432307d0b1
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_11_01_world_335.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `gameobject` SET `spawntimesecs` = 5 WHERE `guid` IN (45719, 45720, 45721);
diff --git a/sql/updates/world/3.3.5/2016_04_11_02_world_335.sql b/sql/updates/world/3.3.5/2016_04_11_02_world_335.sql
new file mode 100644
index 00000000000..93b6000554c
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_11_02_world_335.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `spell_group` SET `spell_id`=56112 WHERE `id`=1061 and`spell_id`=46910;
diff --git a/sql/updates/world/3.3.5/2016_04_15_03_world_335.sql b/sql/updates/world/3.3.5/2016_04_15_03_world_335.sql
new file mode 100644
index 00000000000..afbe3b3ab63
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_15_03_world_335.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `smart_scripts` SET `action_type`=51, `action_param1`=0 WHERE `entryorguid`=193100 AND `source_type`=9 AND `id`=7;
diff --git a/sql/updates/world/3.3.5/2016_04_16_00_world.sql b/sql/updates/world/3.3.5/2016_04_16_00_world.sql
new file mode 100644
index 00000000000..9219a4ef316
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_16_00_world.sql
@@ -0,0 +1,3 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName`='spell_baron_geddon_inferno';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(19695, 'spell_baron_geddon_inferno');
diff --git a/sql/updates/world/3.3.5/2016_04_16_01_world.sql b/sql/updates/world/3.3.5/2016_04_16_01_world.sql
new file mode 100644
index 00000000000..95a8f0934ad
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_16_01_world.sql
@@ -0,0 +1,307 @@
+SET @OGUID := 78735; -- 20 free guids required
+SET @CGUID := 84148; -- 9 free guids required
+
+SET @NPC := @CGUID+1;
+SET @PATH := @NPC * 10;
+
+UPDATE `creature_template` SET `difficulty_entry_1`=0 WHERE `entry` IN (25740,25755,25756,25865);
+UPDATE `creature_template` SET `minlevel`=82,`maxlevel`=82, `mechanic_immune_mask`=617299839, `ScriptName`='boss_ahune' WHERE `entry`=25740; -- Ahune
+UPDATE `creature_template` SET `minlevel`=80,`maxlevel`=80, `AIName`='SmartAI' WHERE `entry`=25755; -- Ahunite Hailstone
+UPDATE `creature_template` SET `minlevel`=80,`maxlevel`=80, `AIName`='SmartAI' WHERE `entry`=25756; -- Ahunite Coldwave
+UPDATE `creature_template` SET `minlevel`=80,`maxlevel`=80, `AIName`='SmartAI' WHERE `entry`=25757; -- Ahunite Frostwind
+UPDATE `creature_template` SET `minlevel`=80,`maxlevel`=80, `flags_extra`=`flags_extra`|0x40000000, `mechanic_immune_mask`=617299839, `ScriptName`='npc_frozen_core' WHERE `entry`=25865; -- Frozen Core
+UPDATE `creature_template` SET `ScriptName`='npc_ahune_bunny' WHERE `entry`=25745;
+UPDATE `creature_template` SET `ScriptName`='npc_earthen_ring_flamecaller' WHERE `entry`=25754;
+UPDATE `creature_template` SET `unit_flags`=33554432, `MovementType`=2 WHERE `entry` IN (25964,25965,25966); -- Shaman beam bunny
+UPDATE `creature_template` SET `unit_flags`=33554432 WHERE `entry`=26239; -- Ghost of Ahune
+UPDATE `creature_template` SET `flags_extra`=128 WHERE `entry`=25985; -- Ahune Ice Spear Bunny
+UPDATE `gameobject_template` SET `ScriptName`='go_ahune_ice_stone' WHERE `entry`=187882;
+UPDATE `creature` SET `orientation`=2.408554 WHERE `guid`=202734; -- Luma
+UPDATE `creature` SET `orientation`=3.804818 WHERE `guid`=202737; -- Flamecaller
+UPDATE `creature_template` SET `HealthModifier`=94.5, `unit_flags`=33554688 WHERE `entry`=25865;
+UPDATE `creature_template` SET `HealthModifier`=18.8 WHERE `entry`=25755;
+UPDATE `creature_template` SET `HealthModifier`=3.538 WHERE `entry`=25756;
+UPDATE `creature_template` SET `HealthModifier`=1.5 WHERE `entry`=25757;
+UPDATE `creature_template` SET `HealthModifier`=4 WHERE `entry`=40446;
+UPDATE `creature_template` SET `InhabitType`=7 WHERE `entry` IN (25964,25965,25966,26190);
+
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN
+('spell_ahune_synch_health',
+'spell_ice_spear_control_aura',
+'spell_slippery_floor_periodic',
+'spell_summon_ice_spear_delayer',
+'spell_summoning_rhyme_aura',
+'spell_ahune_spanky_hands',
+'spell_ahune_minion_despawner',
+'spell_ice_spear_target_picker',
+'spell_ice_bombardment_dest_picker');
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(46430, 'spell_ahune_synch_health'),
+(46371, 'spell_ice_spear_control_aura'),
+(46320, 'spell_slippery_floor_periodic'),
+(46878, 'spell_summon_ice_spear_delayer'),
+(45926, 'spell_summoning_rhyme_aura'),
+(46146, 'spell_ahune_spanky_hands'),
+(46843, 'spell_ahune_minion_despawner'),
+(46372, 'spell_ice_spear_target_picker'),
+(46398, 'spell_ice_bombardment_dest_picker');
+
+DELETE FROM `creature_text` WHERE `entry` IN (25745,25754,25697,40446);
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(25745,0,0,'The Earthen Ring\'s Assault Begins.',41,0,100,0,0,0,24930,1,'Ahune Bunny- EMOTE_EARTHEN_ASSAULT'),
+(25754,0,0,'Ahune Retreats. His defenses diminish.',41,0,100,0,0,0,24931,1,'Earthen Ring Flamecaller - EMOTE_RETREAT'),
+(25754,1,0,'Ahune will soon resurface.',41,0,100,0,0,0,24932,1,'Earthen Ring Flamecaller - EMOTE_RESURFACE'),
+(40446,0,0,'How DARE you! You will not stop the coming of Lord Ahune!',14,0,100,0,0,0,40437,0,'Skar\'this the Summoner'),
+(25697,0,0,'The Ice Stone has melted!',14,0,100,0,0,0,24895,0,'Luma Skymother - SAY_PLAYER_1'),
+(25697,1,0,'Ahune, your strength grows no more!',14,0,100,0,0,0,24893,0,'Luma Skymother - SAY_PLAYER_2'),
+(25697,2,0,'Your frozen reign will not come to pass!',14,0,100,0,0,0,24894,0,'Luma Skymother - SAY_PLAYER_3');
+
+DELETE FROM `gossip_menu` WHERE `entry`=11389;
+INSERT INTO `gossip_menu` VALUES
+(11389,15864);
+
+DELETE FROM `gossip_menu_option` WHERE `menu_id`=11389;
+INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`OptionBroadcastTextID`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`,`BoxBroadcastTextID`) VALUES
+(11389,1,0,'Disturb the stone and summon Lord Ahune.',40443,1,1,0,0,0,0,NULL,0);
+
+DELETE FROM `creature_template_addon` WHERE `entry` IN (25740,25755,25865,25985,25952);
+INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `auras`) VALUES
+(25740, 0, 0, 9, 1, 61976),
+(25755, 0, 0, 0, 0, 46542),
+(25865, 0, 0, 0, 0, '46810 61976'),
+(25985, 0, 0, 0, 0, '75498 46878'),
+(25952, 0, 0, 0, 0, 46314);
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry` IN (46603,46593,46735,45930,45941,46809,46843,46396,46398,46236);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13,1,46603,0,0,31,0,3,26121,0,0,0,0,'',"Spell 'Force Wisp Flight Missile' can hit 'Wisp Source Bunny'"),
+(13,1,46593,0,0,31,0,3,26120,0,0,0,0,'',"Spell 'Wisp Flight Missile and Beam' can hit 'Wisp Dest Bunny'"),
+(13,1,46735,0,0,31,0,3,26190,0,0,0,0,'',"Spell 'Spank - Force Bunny To Knock You To' can hit '[PH] Spank Target Bunny'"),
+(13,1,45930,0,1,31,0,3,25971,0,0,0,0,'',"Spell 'Ahune - Summoning Rhyme Spell, make bonfire' can hit 'Shaman Bonfire Bunny 000'"),
+(13,1,45930,0,2,31,0,3,25972,0,0,0,0,'',"Spell 'Ahune - Summoning Rhyme Spell, make bonfire' can hit 'Shaman Bonfire Bunny 001'"),
+(13,1,45930,0,3,31,0,3,25973,0,0,0,0,'',"Spell 'Ahune - Summoning Rhyme Spell, make bonfire' can hit 'Shaman Bonfire Bunny 002'"),
+(13,1,45941,0,0,31,0,3,25746,0,0,0,0,'',"Spell 'Summon Ahune's Loot Missile' can hit '[PH] Ahune Loot Loc Bunny'"),
+(13,1,46809,0,0,31,0,3,26239,0,0,0,0,'',"Spell 'Make Ahune's Ghost Burst' can hit 'Ghost of Ahune"),
+(13,1,46843,0,1,31,0,3,25756,0,0,0,0,'',"Spell 'Minion Despawner' can hit 'Ahunite Coldwave'"),
+(13,1,46843,0,2,31,0,3,25757,0,0,0,0,'',"Spell 'Minion Despawner' can hit 'Ahunite Frostwind'"),
+(13,1,46843,0,3,31,0,3,25755,0,0,0,0,'',"Spell 'Minion Despawner' can hit 'Ahunite Hailstone'"),
+(13,1,46398,0,0,31,0,3,25972,0,0,0,0,'',"Spell 'Ice Bombardment Dest Picker' can hit 'Shaman Bonfire Bunny'"),
+(13,1,46396,0,0,31,0,3,25972,0,0,0,0,'',"Spell 'Ice Bombardment' can hit 'Shaman Bonfire Bunny'"),
+(13,1,46236,0,1,31,0,3,25971,0,0,0,0,'',"Spell 'Close opening Visual' can hit 'Shaman Bonfire Bunny 000'"),
+(13,1,46236,0,2,31,0,3,25972,0,0,0,0,'',"Spell 'Close opening Visual' can hit 'Shaman Bonfire Bunny 001'"),
+(13,1,46236,0,3,31,0,3,25973,0,0,0,0,'',"Spell 'Close opening Visual' can hit 'Shaman Bonfire Bunny 002'");
+
+DELETE FROM `disables` WHERE `sourceType`=0 AND `entry` IN (46314,46603,46593,46422);
+INSERT INTO `disables` (`sourceType`, `entry`, `flags`, `params_0`, `params_1`, `comment`) VALUES
+(0,46314,64,0,0,'Disable LOS for spell Ahune - Slippery Floor Ambient'),
+(0,46603,64,0,0,'Disable LOS for spell Force Whisp to Flight'),
+(0,46593,64,0,0,'Disable LOS for spell Whisp Flight Missile and Beam'),
+(0,46422,64,0,0,'Disable LOS for spell Shamans Look for Opening');
+
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger` IN (45947,-45964,45964);
+INSERT INTO `spell_linked_spell` (`spell_trigger`,`spell_effect`,`type`,`comment`) VALUES
+(45947,45946,2,''),
+(-45964,-46333,0,''),
+(45964,46333,0,'');
+
+-- Skar'this the Summoner
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=40446;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=40446 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(40446,0,0,0,1,0,100,1,0,0,0,0,11,75427,0,0,0,0,0,1,0,0,0,0,0,0,0,'Skar\'this the Summoner - OOC - Cast \'Frost Channelling\''),
+(40446,0,1,0,4,0,100,1,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Skar\'this the Summoner - On agro - say'),
+(40446,0,2,0,0,0,100,0,5000,5000,15000,15000,11,55909,1,0,0,0,0,2,0,0,0,0,0,0,0,'Skar\'this the Summoner - IC - Cast Crashing Wave'),
+(40446,0,3,0,0,0,100,0,10000,10000,20000,20000,11,11831,1,0,0,0,0,2,0,0,0,0,0,0,0,'Skar\'this the Summoner - IC - Cast Frost Nova'),
+(40446,0,4,0,0,0,100,0,7000,7000,9000,9000,11,15043,0,0,0,0,0,2,0,0,0,0,0,0,0,'Skar\'this the Summoner - IC - Cast Frostbolt');
+
+-- Summon Loot Bunny SAI
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25746;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=25746 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(25746,0,0,0,8,0,100,0,45941,0,0,0,11,46891,0,0,0,0,0,1,0,0,0,0,0,0,0,'[PH] Ahune Loot Loc Bunny - On SpellHit - Cast \'Summon Loot\'');
+
+-- [PH] Spank Target Bunny SAI
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=26190;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=26190 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(26190,0,0,0,8,0,100,0,46735,0,0,0,11,46734,0,0,0,0,0,7,0,0,0,0,0,0,0,'[PH] Spank Target Bunny - On SpellHit \'Spank - Force Bunny To Knock You To\' - Cast \'Knock To\'');
+
+-- Ghost of Ahune
+UPDATE `creature_template` SET `AIName`='SmartAI', `flags_extra`='2' WHERE `entry`=26239;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=26239 AND `source_type`=0;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=2623900 AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(26239,0,0,0,25,0,100,0,0,0,0,0,3,0,11686,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - On Reset - Morph to Model 11686'),
+(26239,0,1,0,8,0,100,0,46809,0,4000,4000,80,2623900,2,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - On SpellHit \'Make Ahune\'s Ghost Burst\' - Call Timed ActionList'),
+(2623900,9,0,0,0,0,100,0,0,0,0,0,3,0,23707,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Morph to Model 23707'),
+(2623900,9,1,0,0,0,100,0,0,0,0,0,11,46786,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Cast \'Ahune\'s Ghost Disguise\''),
+(2623900,9,2,0,0,0,100,0,2400,2400,0,0,47,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Set Visibility Off'),
+(2623900,9,3,0,0,0,100,0,500,500,0,0,3,0,11686,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Morph to Model 11686'),
+(2623900,9,4,0,0,0,100,0,0,0,0,0,47,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ghost of Ahune - Timed ActionList - Set Visibility On');
+
+-- Wisp Source Bunny SAI
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=26121;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=26121 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(26121,0,0,1,8,0,100,0,46603,0,0,0,11,46593,0,0,0,0,0,11,26120,100,0,0,0,0,0,'Wisp Source Bunny - On SpellHit \'Force Wisp Flight Missile\' - Cast \'Wisp Flight Missile and Beam\''),
+(26121,0,1,0,61,0,100,0,0,0,0,0,41,9000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Wisp Source Bunny - On SpellHit \'Force Wisp Flight Missile\' - Despawn in 9s');
+
+-- Wisp Dest Bunny SAI
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=26120;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=26120 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(26120,0,0,0,8,0,100,0,46593,0,0,0,41,9000,0,0,0,0,0,1,0,0,0,0,0,0,0,'Wisp Dest Bunny - On SpellHit \'Wisp Flight Missile and Beam\' - Despawn in 9s');
+
+-- Shaman Beam Bunny SAI
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (25971,25972,25973);
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (25971,25972,25973) AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(25971,0,0,0,8,0,100,0,45930,0,0,0,11,46339,0,0,0,0,0,1,0,0,0,0,0,0,0,'Shaman Beam Bunny 000 - On SpellHit - Cast \'Bonfire Disguise\''),
+(25972,0,0,0,8,0,100,0,45930,0,0,0,11,46339,0,0,0,0,0,1,0,0,0,0,0,0,0,'Shaman Beam Bunny 001 - On SpellHit - Cast \'Bonfire Disguise\''),
+(25973,0,0,0,8,0,100,0,45930,0,0,0,11,46339,0,0,0,0,0,1,0,0,0,0,0,0,0,'Shaman Beam Bunny 002 - On SpellHit - Cast \'Bonfire Disguise\'');
+
+-- Ahunite Hailstone SAI
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25755;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=25755 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(25755,0,0,0,0,0,100,0,6000,8000,6000,8000,11,2676,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ahunite Hailstone - In Combat - Cast \'Pulverize\'');
+
+-- Ahunite Coldwave SAI
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25756;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=25756 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(25756,0,0,0,0,0,100,0,5000,7000,6000,8000,11,46406,0,0,0,0,0,2,0,0,0,0,0,0,0,'Ahunite Coldwave - In Combat - Cast \'Bitter Blast\'');
+
+-- Ahunite Frostwind SAI
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25757;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=25757 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(25757,0,0,0,54,0,100,0,0,0,0,0,11,12550,0,0,0,0,0,1,0,0,0,0,0,0,0,'Ahunite Frostwind - On Just Summoned - Cast \'Lightning Shield\''),
+(25757,0,1,0,0,0,100,0,2000,2000,5000,7000,11,46568,0,0,0,0,0,18,120,0,0,0,0,0,0,'Ahunite Frostwind - In Combat - Cast \'Wind Buffet\'');
+
+DELETE FROM `item_loot_template` WHERE `entry`=35512;
+INSERT INTO `item_loot_template` (`Entry`,`Item`,`Reference`,`Chance`,`QuestRequired`,`LootMode`,`GroupId`,`MinCount`,`MaxCount`,`Comment`) VALUES
+(35512,17202,0,100,0,1,0,2,5,NULL);
+
+DELETE FROM `item_loot_template` WHERE `Entry`=54536;
+INSERT INTO `item_loot_template` (`Entry`, `Item`, `Reference`, `Chance`, `QuestRequired`, `LootMode`, `GroupId`, `MinCount`, `MaxCount`) VALUES
+(54536, 54806, 0, 3, 0, 1, 0, 1, 1),
+(54536, 23247, 0, 100, 0, 1, 1, 5, 10),
+(54536, 53641, 0, 3, 0, 1, 0, 1, 1);
+
+DELETE FROM `creature` WHERE `guid` BETWEEN @CGUID AND @CGUID+8;
+INSERT INTO `creature` (`guid`,`id`,`map`,`spawnMask`,`phaseMask`,`modelid`,`equipment_id`,`position_x`,`position_y`,`position_z`,`orientation`,`spawntimesecs`,`spawndist`,`currentwaypoint`,`curhealth`,`curmana`,`MovementType`,`npcflag`,`unit_flags`,`dynamicflags`) VALUES
+(@CGUID,25745,547,1,1,0,0,-96.64146,-230.8864,4.780959,1.413717,300,0,0,1,1,0,0,0,0), -- [PH] Ahune Summon Loc Bunny
+(@CGUID+1,25964,547,1,1,0,0,-90.00211,-224.9285,-1.378754,2.956095,300,0,0,1,1,2,0,0,0), -- Shaman Beam Bunny 000
+(@CGUID+2,25965,547,1,1,0,0,-97.39627,-223.761,-1.494899,0.9130945,300,0,0,1,1,2,0,0,0), -- Shaman Beam Bunny 001
+(@CGUID+3,25966,547,1,1,0,0,-103.3054,-224.0149,0.5259815,5.676991,300,0,0,1,1,2,0,0,0), -- Shaman Beam Bunny 002
+(@CGUID+4,26190,547,1,1,0,0,-95.33572,-207.4834,16.28742,4.904375,300,0,0,1,1,0,0,0,0), -- [PH] Spank Target Bunny
+(@CGUID+5,25952,547,1,1,0,0,-96.64146,-230.8864,4.780959,1.413717,300,0,0,1,1,0,0,0,0), -- Slippery Floor Bunny
+(@CGUID+6,25952,547,1,1,0,0,-69.83901,-162.474,-2.303646,2.513274,300,0,0,1,1,0,0,0,0), -- Slippery Floor Bunny
+(@CGUID+7,26239,547,1,1,0,0,-99.10214,-233.1872,-1.22297,1.466077,300,0,0,1,1,0,0,0,0), -- Ghost of Ahune
+(@CGUID+8,25746,547,1,1,0,0,-96.8723,-212.8425,-1.149142,4.153883,300,0,0,1,1,0,0,0,0); -- [PH] Ahune Loot Loc Bunny
+
+DELETE FROM `gameobject` WHERE `guid` BETWEEN @OGUID AND @OGUID+19;
+INSERT INTO `gameobject` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `position_x`, `position_y`, `position_z`, `orientation`, `rotation0`, `rotation1`, `rotation2`, `rotation3`, `spawntimesecs`, `animprogress`, `state`, `VerifiedBuild`) VALUES
+(@OGUID+0, 187882, 547, 0, 0, 1, 1, -69.90455, -162.2449, -2.366563, 2.426008, 0, 0, 0.9366722, 0.3502074, 120, 255, 1,0), -- Icestone
+(@OGUID+1, 188067, 547, 0, 0, 1, 1,-79.397, -219.7025, -4.042892, -2.199115, 0, 0, -0.8910065, 0.4539906, 120, 255, 1, 0), -- Ice Block
+(@OGUID+2, 188067, 547, 0, 0, 1, 1, -115.5985, -162.7724, -1.924025, -0.5585039, 0, 0, -0.2756367, 0.9612619, 120, 255, 1, 0), -- Ice Block
+(@OGUID+3, 188067, 547, 0, 0, 1, 1, -71.89625, -145.4974, -1.551813, -1.954766, 0, 0, -0.8290367, 0.5591941, 120, 255, 1, 0), -- Ice Block
+(@OGUID+4, 188067, 547, 0, 0, 1, 1, -49.27251, -168.9859, -1.898811, 2.007128, 0, 0, 0.8433914, 0.5372996, 120, 255, 1, 0), -- Ice Block
+(@OGUID+5, 188067, 547, 0, 0, 1, 1, -75.95139, -182.771, -4.882017, -1.151916, 0, 0, -0.5446386, 0.8386708, 120, 255, 1, 0), -- Ice Block
+(@OGUID+6, 188067, 547, 0, 0, 1, 1, -83.52528, -172.1806, -3.816522, 0.01745246, 0, 0, 0.00872612, 0.9999619, 120, 255, 1, 0), -- Ice Block
+(@OGUID+7, 188067, 547, 0, 0, 1, 1, -83.52528, -217.3293, -3.0728, -0.4886912, 0, 0, -0.2419214, 0.9702958, 120, 255, 1, 0), -- Ice Block
+(@OGUID+8, 188072, 547, 0, 0, 1, 1, -71.48915, -160.7316, -4.18569, -0.4188786, 0, 0, -0.2079115, 0.9781476, 120, 255, 1, 0), -- Ice Stone Mount
+(@OGUID+9, 188072, 547, 0, 0, 1, 1, -69.21773, -163.491, -2.044773, 2.967041, 0, 0, 0.9961939, 0.08716504, 120, 255, 1, 0), -- Ice Stone Mount
+(@OGUID+10, 188072, 547, 0, 0, 1, 1, -71.82486, -164.475, -3.962982, -0.9250239, 0, 0, -0.4461975, 0.8949345, 120, 255, 1, 0), -- Ice Stone Mount
+(@OGUID+11, 188072, 547, 0, 0, 1, 1, -69.20837, -160.345, -4.25643, 1.850049, 0, 0, 0.7986355, 0.601815, 120, 255, 1, 0), -- Ice Stone Mount
+(@OGUID+12, 188073, 547, 0, 0, 1, 1, -89.75205, -113.5002, -2.709442, 0.453785, 0, 0, 0.2249508, 0.9743701, 120, 255, 1, 0), -- Ahune Bonfire
+(@OGUID+13, 188073, 547, 0, 0, 1, 1,-114.9574, -117.3017, -2.71, 2.007128, 0, 0, 0.8433914, 0.5372996, 120, 255, 1, 0), -- Ahune Bonfire
+(@OGUID+14, 188142, 547, 0, 0, 1, 1, -74.65959, -243.8125, -2.735999, 2.216565, 0, 0, 0.8949337, 0.4461992, 120, 255, 1, 0), -- Ice Block, Big
+(@OGUID+15, 188142, 547, 0, 0, 1, 1, -72.75314, -185.1547, -4.930593, 0.157079, 0, 0, 0.07845879, 0.9969174, 120, 255, 1, 0), -- Ice Block, Big
+(@OGUID+16, 188142, 547, 0, 0, 1, 1, -103.7134, -245.5041, -1.377881, -1.291542, 0, 0, -0.6018143, 0.7986361, 120, 255, 1, 0), -- Ice Block, Big
+(@OGUID+17, 188142, 547, 0, 0, 1, 1, -118.9196, -204.8023, -1.504161, 1.919862, 0, 0, 0.8191519, 0.5735767, 120, 255, 1, 0), -- Ice Block, Big
+(@OGUID+18, 188142, 547, 0, 0, 1, 1, -117.3857, -165.9649, -2.018646, 0.5585039, 0, 0, 0.2756367, 0.9612619, 120, 255, 1, 0), -- Ice Block, Big
+(@OGUID+19, 188142, 547, 0, 0, 1, 1, -75.42784, -221.16, -2.882941, 0.4886912, 0, 0, 0.2419214, 0.9702958, 120, 255, 1, 0); -- Ice Block, Big
+
+DELETE FROM `creature_addon` WHERE `guid` IN (@NPC,@NPC+1,@NPC+2);
+INSERT INTO `creature_addon` (`guid`,`path_id`) VALUES
+(@NPC,@PATH),
+(@NPC+1,@PATH+10),
+(@NPC+2,@PATH+20);
+
+DELETE FROM `waypoint_data` WHERE `id` IN (@PATH,@PATH+10,@PATH+20);
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-107.1537,-233.7247,27.1834,0,0,0,100,0),
+(@PATH,2,-109.4618,-232.0907,25.12787,0,0,0,100,0),
+(@PATH,3,-109.4792,-229.4328,20.98899,0,0,0,100,0),
+(@PATH,4,-105.9522,-226.8887,17.26674,0,0,0,100,0),
+(@PATH,5,-101.0044,-224.8914,16.04452,0,0,0,100,0),
+(@PATH,6,-96.82773,-225.9608,15.73896,0,0,0,100,0),
+(@PATH,7,-92.59879,-227.0505,15.54452,0,0,0,100,0),
+(@PATH,8,-90.07465,-229.0938,16.58224,0,0,0,100,0),
+(@PATH,9,-88.24558,-231.7715,22.47455,0,0,0,100,0),
+(@PATH,10,-91.0969,-232.6422,24.65563,0,0,0,100,0),
+(@PATH,11,-97.20647,-234.4709,28.46118,0,0,0,100,0),
+(@PATH,12,-101.5825,-234.9054,29.35008,0,0,0,100,0),
+
+(@PATH+10,1,-109.4618,-232.0907,25.12787,0,0,0,100,0),
+(@PATH+10,2,-109.4792,-229.4328,20.98899,0,0,0,100,0),
+(@PATH+10,3,-105.9522,-226.8887,17.26674,0,0,0,100,0),
+(@PATH+10,4,-101.0044,-224.8914,16.04452,0,0,0,100,0),
+(@PATH+10,5,-96.82773,-225.9608,15.73896,0,0,0,100,0),
+(@PATH+10,6,-92.59879,-227.0505,15.54452,0,0,0,100,0),
+(@PATH+10,7,-90.07465,-229.0938,16.58224,0,0,0,100,0),
+(@PATH+10,8,-88.24558,-231.7715,22.47455,0,0,0,100,0),
+(@PATH+10,9,-91.0969,-232.6422,24.65563,0,0,0,100,0),
+(@PATH+10,10,-97.20647,-234.4709,28.46118,0,0,0,100,0),
+(@PATH+10,11,-101.5825,-234.9054,29.35008,0,0,0,100,0),
+(@PATH+10,12,-107.1537,-233.7247,27.1834,0,0,0,100,0),
+
+(@PATH+20,1,-97.20647,-234.4709,28.46118,0,0,0,100,0),
+(@PATH+20,2,-101.5825,-234.9054,29.35008,0,0,0,100,0),
+(@PATH+20,3,-107.1537,-233.7247,27.1834,0,0,0,100,0),
+(@PATH+20,4,-109.4618,-232.0907,25.12787,0,0,0,100,0),
+(@PATH+20,5,-109.4792,-229.4328,20.98899,0,0,0,100,0),
+(@PATH+20,6,-105.9522,-226.8887,17.26674,0,0,0,100,0),
+(@PATH+20,7,-101.0044,-224.8914,16.04452,0,0,0,100,0),
+(@PATH+20,8,-96.82773,-225.9608,15.73896,0,0,0,100,0),
+(@PATH+20,9,-92.59879,-227.0505,15.54452,0,0,0,100,0),
+(@PATH+20,10,-90.07465,-229.0938,16.58224,0,0,0,100,0),
+(@PATH+20,11,-88.24558,-231.7715,22.47455,0,0,0,100,0),
+(@PATH+20,12,-91.0969,-232.6422,24.65563,0,0,0,100,0);
+
+DELETE FROM `game_event_creature` WHERE `guid` BETWEEN @CGUID AND @CGUID+8 AND `eventEntry`=1;
+INSERT INTO `game_event_creature` (`eventEntry`,`guid`) VALUES
+(1,@CGUID),
+(1,@CGUID+1),
+(1,@CGUID+2),
+(1,@CGUID+3),
+(1,@CGUID+4),
+(1,@CGUID+5),
+(1,@CGUID+6),
+(1,@CGUID+7),
+(1,@CGUID+8);
+
+DELETE FROM `game_event_gameobject` WHERE `guid` BETWEEN @OGUID AND @OGUID+19 AND `eventEntry`=1;
+INSERT INTO `game_event_gameobject` (`eventEntry`,`guid`) VALUES
+(1,@OGUID),
+(1,@OGUID+1),
+(1,@OGUID+2),
+(1,@OGUID+3),
+(1,@OGUID+4),
+(1,@OGUID+5),
+(1,@OGUID+6),
+(1,@OGUID+7),
+(1,@OGUID+8),
+(1,@OGUID+9),
+(1,@OGUID+10),
+(1,@OGUID+11),
+(1,@OGUID+12),
+(1,@OGUID+13),
+(1,@OGUID+14),
+(1,@OGUID+15),
+(1,@OGUID+16),
+(1,@OGUID+17),
+(1,@OGUID+18),
+(1,@OGUID+19);
diff --git a/sql/updates/world/3.3.5/2016_04_16_02_world.sql b/sql/updates/world/3.3.5/2016_04_16_02_world.sql
new file mode 100644
index 00000000000..82982753067
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_16_02_world.sql
@@ -0,0 +1,39 @@
+-- The column `spell1` was misused for this NPC. This NPC is undead. He cannot be MCed. The spell 29307 should be cast using SmartAI or by Script.
+-- Also, link the zombies chows to the custom ScriptedAI defined in boss_gluth.cpp.
+UPDATE `creature_template` SET `spell1`=0, `ScriptName`='npc_zombie_chow' WHERE `entry`=16360;
+UPDATE `creature_template` SET `spell1`=0 WHERE `entry`=30303;
+
+-- connect the decimate spell (effect 0) used by Gluth (in both 10 man & 25) to the spell script defined in boss_gluth.cpp.
+-- and connect the 2 zombie chow's search spells to a unique spell script used by both.
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_gluth_decimate', 'spell_gluth_zombiechow_search');
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(28374, 'spell_gluth_decimate'),
+(54426, 'spell_gluth_decimate'),
+(28239, 'spell_gluth_zombiechow_search'),
+(28404, 'spell_gluth_zombiechow_search');
+
+-- add the condition to the multi-target insta-kill spell 28404 which is that only zombies are eligible targets to the spell.
+-- add a condition to the decimate spell (28374/54426). It's damage component should only affect players and zombies.
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`= 13 AND `SourceEntry` IN (28374, 28404, 54426);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 28404, 0, 0, 31, 0, 3, 16360, 0, 0, 0, 0, '', 'Zombie Chow Search targets zombies only'),
+(13, 1, 28374, 0, 0, 31, 0, 3, 16360, 0, 0, 0, 0, '', 'Decimate damage should only hit zombie or player'),
+(13, 1, 28374, 0, 1, 31, 0, 4, 0, 0, 0, 0, 0, '', 'Decimate damage should only hit zombie or player'),
+(13, 1, 54426, 0, 0, 31, 0, 3, 16360, 0, 0, 0, 0, '', 'Decimate damage should only hit zombie or player'),
+(13, 1, 54426, 0, 1, 31, 0, 4, 0, 0, 0, 0, 0, '', 'Decimate damage should only hit zombie or player');
+
+-- adds Gluth's 5 emotes into the DB.
+DELETE FROM `creature_text` WHERE `entry`=15932 AND `groupid` IN(0,1,2,3,4) AND `id`=0;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(15932, 0, 0, '%s spots a zombie to devour!', 16, 0, 100, 0, 0, 0, 12242, 2/3, 'Gluth - spots one'),
+(15932, 1, 0, '%s decimates all nearby flesh!', 41, 0, 100, 0, 0, 0, 32321, 2/3, 'Gluth - decimate'),
+(15932, 2, 0, '%s becomes enraged!', 41, 0, 100, 0, 0, 0, 24144, 2/3, 'Gluth - enrage'),
+(15932, 3, 0, '%s devours all nearby zombies!', 16, 0, 100, 0, 0, 0, 12348, 2/3, 'Gluth - devours all'),
+(15932, 4, 0, '%s goes into a berserker rage!', 41, 0, 100, 0, 0, 0, 34057, 2/3, 'Gluth - berserker');
+
+-- move zombie chows to summon groups (gets rid of hardcoded spawn coords)
+DELETE FROM `creature_summon_groups` WHERE `summonerId`=15932;
+INSERT INTO `creature_summon_groups` (`summonerId`,`summonerType`,`groupId`,`entry`,`position_x`,`position_y`,`position_z`,`orientation`,`summonType`,`summonTime`) VALUES
+(15932,0,1,16360,3270.132,-3169.948,297.5891,5.88176,6,10000),
+(15932,0,2,16360,3307.298,-3183.449,297.5891,5.74213,6,10000),
+(15932,0,2,16360,3255.708,-3135.677,297.5891,1.86750,6,10000);
diff --git a/sql/updates/world/3.3.5/2016_04_16_03_world.sql b/sql/updates/world/3.3.5/2016_04_16_03_world.sql
new file mode 100644
index 00000000000..c6a6e1b07de
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_16_03_world.sql
@@ -0,0 +1,2 @@
+UPDATE `npc_spellclick_spells` SET `spell_id`=46598 WHERE `npc_entry`=31583 and`spell_id`=59319;
+UPDATE `smart_scripts` SET `action_param2`=2 WHERE `entryorguid`=31578 and`source_type`=0 and`id`=3;
diff --git a/sql/updates/world/3.3.5/2016_04_16_04_world.sql b/sql/updates/world/3.3.5/2016_04_16_04_world.sql
new file mode 100644
index 00000000000..75d241b62f4
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_16_04_world.sql
@@ -0,0 +1,33 @@
+-- new gossip_menu_option and creature text entries for:
+-- NPC ID 18538 Ishanah, High Priestess of the Aldor
+-- NPC ID 18584 Sal'salabim, quest giver
+-- NPC ID 18585 Raliq the Drunk, target
+-- NPC ID 25967 Zephyr, portal provider
+
+DELETE FROM `gossip_menu_option` WHERE `menu_id` IN (7725,7729,7735,9205);
+INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`OptionBroadcastTextID`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`,`BoxBroadcastTextID`) VALUES
+(7725,0,0,'Altruis sent me. He said that you could help me.', 15552,1,1, 0,0,0,0,'',0),
+(7729,0,0,"I have been sent by Sal'salabim to collect a debt that you owe. Pay up or I'm going to have to hurt you.",15560,1,1,0,0,0,0,'',0),
+(7735,0,0,"Who are the Sha'tar?", 15642,1,1,7736,0,0,0,'',0),
+(7735,1,0,"Isn't Shattrath a draenei city? Why do you allow others here?",15644,1,1,7737,0,0,0,'',0),
+(9205,0,0,'Take me to the Caverns of Time.', 25111,1,1, 0,0,0,0,'',0);
+
+-- conditions for the gossip menu options as a preparation for future SAI scripts
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`= 15 AND `SourceGroup` IN (7725,7729);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
+(15, 7725,0, 0,0, 9,0, 10004,0,0,0,0,0,'', 'Show gossip menu option 7725 only if Quest 10004 is taken (active)'),
+(15, 7729,0, 0,0, 9,0, 10009,0,0,0,0,0,'', 'Show gossip menu option 7729 only if Quest 10009 is taken (active)');
+
+-- insert missing creature text (say lines) for Sal'salabim and Raliq the Drunk
+DELETE FROM `creature_text` WHERE `entry` IN (18584,18585) AND `groupid`= 0;
+INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(18584,0,0,'[Demonic] Ka kalix!', 12,0,100,0,0,0,15551,0,"Sal'salabim SAY_DEMONIC_AGGRO"),
+(18585,0,0,'Raliq teach you lesson now!',12,0,100,0,0,0,15567,0,'Raliq the Drunk SAY_RALIQ_ATTACK');
+
+-- insert missing quest Progress gossip, quest 10004
+DELETE FROM `quest_request_items` WHERE `ID` = 10004;
+INSERT INTO `quest_request_items` (`ID`,`EmoteOnComplete`,`EmoteOnIncomplete`,`CompletionText`,`VerifiedBuild`) VALUES
+(10004,0,0,"<Sal'salabim rubs his head.>$B$B[Demonic] Ik il romath sardon.",0);
+
+-- remove core script for Ishanah, High Priestess of the Aldor
+UPDATE `creature_template` SET `ScriptName`= '' WHERE `entry`= 18538;
diff --git a/sql/updates/world/3.3.5/2016_04_17_00_world.sql b/sql/updates/world/3.3.5/2016_04_17_00_world.sql
new file mode 100644
index 00000000000..ebfbdb1d008
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_17_00_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `creature_template` SET `exp`=0 WHERE `entry` IN (33432, 34106);
diff --git a/sql/updates/world/3.3.5/2016_04_17_01_world.sql b/sql/updates/world/3.3.5/2016_04_17_01_world.sql
new file mode 100644
index 00000000000..f57f73c925d
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_17_01_world.sql
@@ -0,0 +1,3 @@
+--
+UPDATE `gameobject` SET `spawntimesecs` = 10 WHERE `id` IN (148499, 178084, 178085, 176785);
+UPDATE `gameobject` SET `spawntimesecs` = 2 WHERE `id` IN (190447, 759);
diff --git a/sql/updates/world/3.3.5/2016_04_17_02_world.sql b/sql/updates/world/3.3.5/2016_04_17_02_world.sql
new file mode 100644
index 00000000000..e63928925df
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_17_02_world.sql
@@ -0,0 +1,7 @@
+--
+-- Rework Scourge Deathspeaker SAI
+DELETE FROM `smart_scripts` WHERE `entryorguid`=27615 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(27615, 0, 0, 0, 1, 0, 100, 0, 1000, 1000, 0, 0, 11, 49119, 2, 0, 0, 0, 0, 10, 101497, 27452, 0, 0, 0, 0, 0, 'Scourge Deathspeaker - Out of Combat - Cast \'Fire Beam\' (Triggered)'),
+(27615, 0, 1, 0, 4, 0, 100, 0, 0, 0, 0, 0, 11, 52281, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Scourge Deathspeaker - On Aggro - Cast \'Flame of the Seer\' (No Repeat)'),
+(27615, 0, 2, 0, 0, 0, 100, 0, 1000, 2000, 5000, 6000, 11, 52282, 1, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Scourge Deathspeaker - In Combat - Cast \'Fireball\'');
diff --git a/sql/updates/world/3.3.5/2016_04_17_03_world.sql b/sql/updates/world/3.3.5/2016_04_17_03_world.sql
new file mode 100644
index 00000000000..3dc63f55637
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_17_03_world.sql
@@ -0,0 +1,6 @@
+--
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=27547;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=27547 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(27547, 0, 0, 1, 2, 0, 100, 0, 0, 40, 9000, 9000, 11, 32714, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vladek - In HPCT - Cast \'Enrage\''),
+(27547, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 11, 47457, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Vladek - In HPCT - Cast Worgen Transform - Male');
diff --git a/sql/updates/world/3.3.5/2016_04_17_04_world.sql b/sql/updates/world/3.3.5/2016_04_17_04_world.sql
new file mode 100644
index 00000000000..c03969b14b3
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_17_04_world.sql
@@ -0,0 +1,27 @@
+--
+-- Quest Bring 'Em Back Alive
+UPDATE `creature_template_addon` SET `auras`=45771 WHERE `entry`=25596;
+UPDATE `creature_template` SET `spell1`=45876, `spell2`=45877 WHERE `entry`=25596;
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=25607;
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (25596, 25607) AND `source_type`=0;
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (22560700) AND `source_type`=9;
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(25596, 0, 0, 0, 0, 0, 100, 0, 10000, 12000, 20000, 22000, 11, 45876, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Infected Kodo Beast - In Combat - Cast \'Stampede\''),
+(25596, 0, 1, 0, 4, 0, 100, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Infected Kodo Beast - On Aggro - Remove Flag Standstate Dead'),
+(25596, 0, 2, 3, 27, 0, 100, 0, 0, 0, 0, 0, 91, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Infected Kodo Beast - On Passenger Boarded - Remove Flag Standstate Dead'),
+(25596, 0, 3, 4, 61, 0, 100, 1, 0, 0, 0, 0, 28, 45771, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Infected Kodo Beast - On Link - Remove Aura \'Scourge Infection\' (No Repeat)'),
+(25596, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Infected Kodo Beast - On Link - Remove Aura \'Scourge Infection\' (No Repeat)'),
+(25596, 0, 5, 6, 31, 0, 100, 0, 45877, 0, 0, 0, 11, 50630, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Infected Kodo Beast - On Target Spell Hit \'Deliver Kodo\' - Eject passenger'),
+(25596, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 45, 0, 1, 0, 0, 0, 0, 19, 25607, 20, 0, 0, 0, 0, 0, 'Infected Kodo Beast - On Target Spell Hit \'Deliver Kodo\' - Set data'),
+(25596, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Infected Kodo Beast - On Target Spell Hit \'Deliver Kodo\' - Despawn Instant'),
+(25607, 0, 0, 0, 38, 0, 100, 0, 0, 1, 3000, 3000, 80, 2560700, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Farmer Torp - In Data set - Action list'),
+(2560700, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 84, 0, 0, 0, 0, 0, 0, 21, 20, 0, 0, 0, 0, 0, 0, 'Farmer Torp - Action list - Player talk'),
+(2560700, 9, 1, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Farmer Torp - Action list - Say text');
+
+DELETE FROM `creature_text` WHERE `entry` IN (25607, 25596);
+INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`probability`,`BroadcastTextId`,`TextRange`,`comment`) VALUES
+(25607,0,0,"Here's your kodo, Torp!",12,100,24881,0,"Farmer Torp"),
+(25607,0,1,"Door-to-door kodo delivery!",12,100,24882,0,"Farmer Torp"),
+(25607,1,0,"YES! It worked!",12,100,24883,0,"Farmer Torp"),
+(25607,1,1,"Great job!",12,100,24884,0,"Farmer Torp"),
+(25596,0,0,"%s is cured!",16,100,24885,0,"Infected Kodo Beast");
diff --git a/sql/updates/world/3.3.5/2016_04_20_00_world.sql b/sql/updates/world/3.3.5/2016_04_20_00_world.sql
new file mode 100644
index 00000000000..776254b8fb9
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_20_00_world.sql
@@ -0,0 +1,7 @@
+--
+-- Add missing Gnomeregan Conjuror/Silvermoon Magister SAI (Cosmetic)
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry` IN (19006, 19007);
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (19006, 19007) AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(19006, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 11, 32783, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Silvermoon Magister - On Reset - Cast \'Arcane Channeling\''),
+(19007, 0, 0, 0, 25, 0, 100, 0, 0, 0, 0, 0, 11, 32783, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gnomeregan Conjuror - On Reset - Cast \'Arcane Channeling\'');
diff --git a/sql/updates/world/3.3.5/2016_04_20_01_world.sql b/sql/updates/world/3.3.5/2016_04_20_01_world.sql
new file mode 100644
index 00000000000..19bd02a91f5
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_20_01_world.sql
@@ -0,0 +1,5 @@
+--
+-- Hairy Herring Heads, Withered Batwings, Wasp's Wings, Muddy Mire Maggots, Knotroot, Spekled Guano, Seasoned Slider Cider, Pickled Eagle Egg, Prismatic Mojo, Raptor Claw
+-- Pulverized Gargoyle Teeth, Icerown Bottled Water, Putrid Pirate Perspiration, Spiky Spider Eggs, Abomination Guts, Amberseed, Shrunken Dragom's Claw, Crystallized Hogsnot
+-- Ancient Ectoplasm, Chrushed Basilisk Crystals, Blight Crystal, Frozen Spider Ichor, Trollbane, Ghoul Drool,
+UPDATE `gameobject` SET `spawntimesecs` = 0 WHERE `id` IN (190459,190461,190462,190463,190464,190465,190466,190467,190468,190469,190470,190471,190472,190473,190474,190476,190477,190478,190479,190480,190481,190482,191180,191181,191182);
diff --git a/sql/updates/world/3.3.5/2016_04_20_02_world.sql b/sql/updates/world/3.3.5/2016_04_20_02_world.sql
new file mode 100644
index 00000000000..743f1fdab50
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_20_02_world.sql
@@ -0,0 +1,89 @@
+--
+DELETE FROM `creature_addon` WHERE `guid` IN (202936, 202878, 202950, 202931, 202875, 202884, 202914, 202925, 202934, 202944, 202879, 202945, 202898, 202910, 202912, 202909, 202870, 202949, 202903, 202920, 202922, 202924, 202926, 202939, 202888, 202940, 202882, 202947, 202897, 202937, 202915, 202929, 202935, 202872, 202887, 202942, 202948, 202896, 202900, 202916, 202886, 202923, 202894, 202927, 202913, 202906, 202876, 202941, 202881, 202890, 202907, 202904, 202874, 202880, 202877, 202905, 202873, 202908, 202946, 202917, 202928, 202932, 202943, 202883, 202895, 202951, 202901, 202911, 202885, 202899, 202933, 202868, 202938, 202919, 202921, 202918, 202893, 202891, 202889, 202866, 202871, 202892, 202930, 202902, 202869, 202867);
+INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES
+(202936, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202878, 0, 0, 0, 1, 0, '66321 55944 66370'), -- Tauren Coliseum Spectator
+(202950, 0, 0, 0, 1, 0, '66321 55944 66361'), -- Argent Crusade Spectator, 66361 - Argent Crusade Pennant
+(202931, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Draenei
+(202875, 0, 0, 0, 1, 0, '66321 55944'), -- Troll Coliseum Spectator
+(202884, 0, 0, 0, 1, 0, '66321 55944 66369'), -- Orcish Coliseum Spectator
+(202914, 0, 0, 0, 1, 0, '66321 55944'), -- Human Coliseum Spectator
+(202925, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Orc
+(202934, 0, 0, 0, 1, 0, '66321 55944 66361'), -- Argent Crusade Spectator
+(202944, 0, 0, 0, 1, 0, '66321 55944 66361'), -- Argent Crusade Spectator
+(202879, 0, 0, 0, 1, 0, '66321 55944 66370'), -- Tauren Coliseum Spectator
+(202945, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202898, 0, 0, 0, 1, 0, '66321 55944'), -- Blood Elf Coliseum Spectator
+(202910, 0, 0, 0, 1, 0, '66321 55944 66366'), -- Gnomish Coliseum Spectator
+(202912, 0, 0, 0, 1, 0, '66321 55944'), -- Human Coliseum Spectator
+(202909, 0, 0, 0, 1, 0, '66321 55944'), -- Gnomish Coliseum Spectator
+(202870, 0, 0, 0, 1, 0, '66321 55944'), -- Dwarven Coliseum Spectator
+(202949, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202903, 0, 0, 0, 1, 0, '66321 55944 66362'), -- Draenei Coliseum Spectator
+(202920, 0, 0, 0, 1, 0, '66321 55944'), -- Night Elf Coliseum Spectator
+(202922, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Horde
+(202924, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Human
+(202926, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Troll
+(202939, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202888, 0, 0, 0, 1, 0, '66321 55944'), -- Orcish Coliseum Spectator
+(202940, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202882, 0, 0, 0, 1, 0, '66321 55944'), -- Tauren Coliseum Spectator
+(202947, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202897, 0, 0, 0, 1, 0, '66321 55944 66360'), -- Blood Elf Coliseum Spectator, 66360 - Silvermoon Pennant
+(202937, 0, 0, 0, 1, 0, '66321 55944 66361'), -- Argent Crusade Spectator
+(202915, 0, 0, 0, 1, 0, '66321 55944 66367'), -- Human Coliseum Spectator
+(202929, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Undead
+(202935, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202872, 0, 0, 0, 1, 0, '66321 55944 66371'), -- Troll Coliseum Spectator
+(202887, 0, 0, 0, 1, 0, '66321 55944'), -- Orcish Coliseum Spectator
+(202942, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202948, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202896, 0, 0, 0, 1, 0, '66321 55944'), -- Blood Elf Coliseum Spectator
+(202900, 0, 0, 0, 1, 0, '66321 55944'), -- Draenei Coliseum Spectator
+(202916, 0, 0, 0, 1, 0, '66321 55944 66367'), -- Human Coliseum Spectator
+(202886, 0, 0, 0, 1, 0, '66321 55944'), -- Orcish Coliseum Spectator
+(202923, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Alliance
+(202894, 0, 0, 0, 1, 0, '66321 55944 66360'), -- Blood Elf Coliseum Spectator
+(202927, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Tauren
+(202913, 0, 0, 0, 1, 0, '66321 55944'), -- Human Coliseum Spectator
+(202906, 0, 0, 0, 1, 0, '66321 55944'), -- Gnomish Coliseum Spectator
+(202876, 0, 0, 0, 1, 0, '66321 55944'), -- Troll Coliseum Spectator
+(202941, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202881, 0, 0, 0, 1, 0, '66321 55944'), -- Tauren Coliseum Spectator
+(202890, 0, 0, 0, 1, 0, '66321 55944 66365'), -- Forsaken Coliseum Spectator
+(202907, 0, 0, 0, 1, 0, '66321 55944 66366'), -- Gnomish Coliseum Spectator
+(202904, 0, 0, 0, 1, 0, '66321 55944 66362'), -- Draenei Coliseum Spectator
+(202874, 0, 0, 0, 1, 0, '66321 55944'), -- Troll Coliseum Spectator
+(202880, 0, 0, 0, 1, 0, '66321 55944'), -- Tauren Coliseum Spectator
+(202877, 0, 0, 0, 1, 0, '66321 55944 66371'), -- Troll Coliseum Spectator, 66371 - Sen'jin Pennant
+(202905, 0, 0, 0, 1, 0, '66321 55944'), -- Gnomish Coliseum Spectator
+(202873, 0, 0, 0, 1, 0, '66321 55944 66371'), -- Troll Coliseum Spectator
+(202908, 0, 0, 0, 1, 0, '66321 55944 66366'), -- Gnomish Coliseum Spectator
+(202946, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202917, 0, 0, 0, 1, 0, '66321 55944'), -- Night Elf Coliseum Spectator
+(202928, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Blood Elf
+(202932, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Night Elf
+(202943, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202883, 0, 0, 0, 1, 0, '66321 55944 66369'), -- Orcish Coliseum Spectator
+(202895, 0, 0, 0, 1, 0, '66321 55944 66360'), -- Blood Elf Coliseum Spectator
+(202951, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202901, 0, 0, 0, 1, 0, '66321 55944 66362'), -- Draenei Coliseum Spectator
+(202911, 0, 0, 0, 1, 0, '66321 55944'), -- Human Coliseum Spectator
+(202885, 0, 0, 0, 1, 0, '66321 55944'), -- Orcish Coliseum Spectator
+(202899, 0, 0, 0, 1, 0, '66321 55944'), -- Blood Elf Coliseum Spectator
+(202933, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Gnome
+(202868, 0, 0, 0, 1, 0, '66321 55944 66363'), -- Dwarven Coliseum Spectator, 66363 - Ironforge Pennant
+(202938, 0, 0, 0, 1, 0, '66321 55944'), -- Argent Crusade Spectator
+(202919, 0, 0, 0, 1, 0, '66321 55944 66368'), -- Night Elf Coliseum Spectator, 66368 - Darnassus Pennant
+(202921, 0, 0, 0, 1, 0, '66321 55944 66368'), -- Night Elf Coliseum Spectator
+(202918, 0, 0, 0, 1, 0, '66321 55944'), -- Night Elf Coliseum Spectator
+(202893, 0, 0, 0, 1, 0, '66321 55944'), -- Forsaken Coliseum Spectator
+(202891, 0, 0, 0, 1, 0, '66321 55944'), -- Forsaken Coliseum Spectator
+(202889, 0, 0, 0, 1, 0, '66321 55944 66365'), -- Forsaken Coliseum Spectator
+(202866, 0, 0, 0, 1, 0, '66321 55944 66363'), -- Dwarven Coliseum Spectator, 66363 - Ironforge Pennant
+(202871, 0, 0, 0, 1, 0, '66321 55944 66363'), -- Dwarven Coliseum Spectator
+(202892, 0, 0, 0, 1, 0, '66321 55944 66365'), -- Forsaken Coliseum Spectator, 66365 - Undercity Pennant
+(202930, 0, 0, 0, 1, 0, '66321 55944'), -- [ph] Argent Raid Spectator - FX - Dwarf
+(202902, 0, 0, 0, 1, 0, '66321 55944'), -- Draenei Coliseum Spectator
+(202869, 0, 0, 0, 1, 0, '66321 55944'), -- Dwarven Coliseum Spectator
+(202867, 0, 0, 0, 1, 0, '66321 55944'); -- Dwarven Coliseum Spectator
diff --git a/sql/updates/world/3.3.5/2016_04_20_03_world.sql b/sql/updates/world/3.3.5/2016_04_20_03_world.sql
new file mode 100644
index 00000000000..11fc8de7329
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_20_03_world.sql
@@ -0,0 +1,4 @@
+--
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (27435) AND `source_type`=0 AND `id`=2;
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(27435, 0, 2, 0, 63, 0, 100, 0, 0, 0, 0, 0, 18, 512, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Wintergarde Mine Bomb - Just created - Set immune to NPC');
diff --git a/sql/updates/world/3.3.5/2016_04_22_00_world.sql b/sql/updates/world/3.3.5/2016_04_22_00_world.sql
new file mode 100644
index 00000000000..e98ef9cf7e6
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_22_00_world.sql
@@ -0,0 +1,20 @@
+DELETE FROM `smart_scripts` WHERE `entryorguid`=2964700 AND `source_type`=9;
+DELETE FROM `smart_scripts` WHERE `entryorguid`IN(29647,29884) AND `source_type`=0;
+
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(29647, 0, 0, 1, 62, 0, 100, 0, 9852, 2, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Gossip Option 2 Selected - Close Gossip'), -- 21:50:33.764
+(29647, 0, 1, 2, 61, 0, 100, 0, 0, 0, 0, 0, 11, 55568, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Gossip Option 2 Selected - Cast Summon Gymer (Force)'), -- 21:50:33.967
+(29647, 0, 4, 0, 1, 0, 100, 0, 10000, 20000, 30000, 40000, 1, 1, 5000, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - Out of Combat - Say Line 1'),
+(29647, 0, 5, 0, 20, 0, 100, 0, 12916, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Quest reward - Say Line 7'),
+(29884, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 86, 55430, 2, 7, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Just Summoned - Cast Gymers Buddy'), -- 21:50:35.090
+(29884, 0, 1, 0, 61, 0, 100, 1, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Just Summoned - Set Passive'),
+(29884, 0, 2, 3, 27, 0, 100, 1, 0, 0, 0, 0, 44, 256, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Boarded - Set Phase 256'),
+(29884, 0, 3, 0, 61, 0, 100, 1, 0, 0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Boarded - Say Line 8 (No Repeat)'),
+(29884, 0, 4, 0, 61, 0, 100, 1, 0, 0, 0, 0, 11, 55461, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Boarded - Cast Storms Fury'),
+(29884, 0, 5, 6, 28, 0, 100, 1, 0, 0, 0, 0, 44, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Removed - Set Phase 1'),
+(29884, 0, 6, 7, 61, 0, 100, 0, 0, 0, 0, 0, 1, 10, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Removed - Say Line 10'),
+(29884, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 41, 5000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gymer - On Passenger Removed - Despawn after 5 seconds');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry`=29884;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(22, 6, 29884, 0, 0, 31, 0, 4, 0, 0, 0, 0, 0, '', 'Gymer only despawns if player leaves vehicle (not if mob thrown)');
diff --git a/sql/updates/world/3.3.5/2016_04_23_00_world.sql b/sql/updates/world/3.3.5/2016_04_23_00_world.sql
new file mode 100644
index 00000000000..fe5d5c7ccb6
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_23_00_world.sql
@@ -0,0 +1,7 @@
+--
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=19 AND (`SourceEntry`=11586 OR `SourceEntry`=11585);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceEntry`,`ConditionTypeOrReference`,`ConditionValue1`,`Comment`) VALUES
+(19, 11585, 14, 10172, "Accept quest 11585 - Quest 10172 needs to be incomplete"),
+(19, 11586, 8, 10172, "Accept quest 11586 - Quest 10172 needs to be rewarded");
+
+UPDATE `quest_template_addon` SET `ExclusiveGroup`=11585 WHERE `ID`IN(11585,11586);
diff --git a/sql/updates/world/3.3.5/2016_04_23_01_world.sql b/sql/updates/world/3.3.5/2016_04_23_01_world.sql
new file mode 100644
index 00000000000..d1be7adacfc
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_23_01_world.sql
@@ -0,0 +1,4 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_item_decahedral_dwarven_dice', 'spell_item_worn_troll_dice');
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(47770, 'spell_item_decahedral_dwarven_dice'),
+(47776, 'spell_item_worn_troll_dice');
diff --git a/sql/updates/world/3.3.5/2016_04_23_02_world.sql b/sql/updates/world/3.3.5/2016_04_23_02_world.sql
new file mode 100644
index 00000000000..e3806947c9c
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_23_02_world.sql
@@ -0,0 +1,19 @@
+--
+UPDATE `creature_template` SET `npcflag`=4096 WHERE `entry`=2404;
+UPDATE `creature_template` SET `npcflag`=2 WHERE `entry`=2910;
+UPDATE `creature_template` SET `npcflag`=81 WHERE `entry`=7231;
+UPDATE `creature_template` SET `npcflag`=128 WHERE `entry`=8121;
+UPDATE `creature_template` SET `npcflag`=2 WHERE `entry`=15309;
+
+DELETE FROM `npc_vendor` WHERE `entry`=8121;
+INSERT INTO `npc_vendor` (`entry`, `slot`, `item`) VALUES
+(8121, 0, 5740),
+(8121, 0, 8624),
+(8121, 0, 8625),
+(8121, 0, 8626),
+(8121, 0, 9312),
+(8121, 0, 9313),
+(8121, 0, 9314),
+(8121, 0, 9315),
+(8121, 0, 9317),
+(8121, 0, 9318);
diff --git a/sql/updates/world/3.3.5/2016_04_24_00_world_335.sql b/sql/updates/world/3.3.5/2016_04_24_00_world_335.sql
new file mode 100644
index 00000000000..065c31601cd
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_24_00_world_335.sql
@@ -0,0 +1,3 @@
+--
+-- spell aura effect 53055 from Hand of Salvation should not break invisibility
+INSERT INTO `spell_custom_attr` (`entry`,`attributes`) VALUES (53055, 64);
diff --git a/sql/updates/world/3.3.5/2016_04_24_01_world.sql b/sql/updates/world/3.3.5/2016_04_24_01_world.sql
new file mode 100644
index 00000000000..0d9f3aa6bd7
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_24_01_world.sql
@@ -0,0 +1,22 @@
+--
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN (17998,17999,18000,18002) AND `id`=1;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(17998,0,1,0,8,0,100,0,31736,0,0,0,12,18340,4,30000,0,0,0,8,0,0,0,-752.349, 5940.811, 18.261, 4.444397,"Umbrafen Steam Pump Credit Marker - On Spellhit 'Ironvine Seeds' - Summon Creature 'Steam Pump Overseer'"),
+(17999,0,1,0,8,0,100,0,31736,0,0,0,12,18340,4,30000,0,0,0,8,0,0,0,-227.935, 6307.861, 21.967, 5.719622,"Lagoon Steam Pump Credit Marker - On Spellhit 'Ironvine Seeds' - Summon Creature 'Steam Pump Overseer'"),
+(18000,0,1,0,8,0,100,0,31736,0,0,0,12,18340,4,30000,0,0,0,8,0,0,0,579.913, 6342.902, 23.849, 2.159061,"Serpent Steam Pump Credit Marker - On Spellhit 'Ironvine Seeds' - Summon Creature 'Steam Pump Overseer'"),
+(18002,0,1,0,8,0,100,0,31736,0,0,0,12,18340,4,30000,0,0,0,8,0,0,0,477.12, 8189.803, 21.985, 0.486592,"Marshlight Steam Pump Credit Marker - On Spellhit 'Ironvine Seeds' - Summon Creature 'Steam Pump Overseer'");
+
+SET @ENTRY := 18340;
+
+UPDATE `creature_template_addon` SET `auras`="6961 33962" WHERE `entry`=@ENTRY;
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=@ENTRY;
+DELETE FROM `smart_scripts` WHERE `source_type`=0 AND `entryorguid`=@ENTRY;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,1,54,0,100,0,0,0,0,0,1,0,0,0,0,0,0,21,40,0,0,0,0,0,0,'Steam Pump Overseer - Just summoned - Say text'),
+(@ENTRY,0,1,0,61,0,100,0,0,0,0,0,49,0,0,0,0,0,0,21,40,0,0,0,0,0,0,'Steam Pump Overseer - Just summoned - Start attack');
+
+DELETE FROM `creature_text` WHERE `entry`=@ENTRY;
+INSERT INTO `creature_text` (`entry`,`groupid`,`id`,`text`,`type`,`language`,`probability`,`emote`,`duration`,`sound`,`comment`, `BroadcastTextId`) VALUES
+(@ENTRY,0,0, 'I will show you not to cross us again!',12,0,100,0,0,0, 'Steam Pump Overseer', 15202),
+(@ENTRY,0,1, 'Warlord Kalithresh will hear of this insolence!',12,0,100,0,0,0, 'Steam Pump Overseer', 15201),
+(@ENTRY,0,2, 'I''ll make you pay for that!',12,0,100,0,0,0, 'Steam Pump Overseer', 15199);
diff --git a/sql/updates/world/3.3.5/2016_04_25_00_world.sql b/sql/updates/world/3.3.5/2016_04_25_00_world.sql
new file mode 100644
index 00000000000..2c603dc5d64
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_25_00_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `creature` SET `modelid`=11686 WHERE `id`=39010;
diff --git a/sql/updates/world/3.3.5/2016_04_25_01_world.sql b/sql/updates/world/3.3.5/2016_04_25_01_world.sql
new file mode 100644
index 00000000000..f83b99f1710
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_25_01_world.sql
@@ -0,0 +1,42 @@
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN(24161) AND `source_type`=0 AND `id`>4;
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN(24162,24016) AND `source_type`=0 AND `id`>3;
+DELETE FROM `smart_scripts` WHERE `entryorguid` IN(24015) AND `source_type`=0 AND `id`>2;
+
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(24161, 0, 5, 6, 11, 0, 100, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Spawn - Set Immune to combat'),
+(24161, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Spawn - Set Invisible'),
+(24161, 0, 7, 8, 38, 0, 100, 1, 1, 1, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Data Set - Enable combat Immune to combat'),
+(24161, 0, 8, 9, 61, 0, 100, 1, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Data Set - Set visible'),
+(24161, 0, 9, 0, 61, 0, 100, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Oric the Baleful - On Data Set - Say'),
+(24162, 0, 4, 5, 11, 0, 100, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Spawn - Set Immune to combat'),
+(24162, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Spawn - Set Invisible'),
+(24162, 0, 6, 7, 38, 0, 100, 1, 1, 1, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Data Set - Enable combat Immune to combat'),
+(24162, 0, 7, 8, 61, 0, 100, 1, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Data Set - Set visible'),
+(24162, 0, 8, 0, 61, 0, 100, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Gunnar Thorvardsson - On Data Set - Say'),
+(24016, 0, 4, 5, 11, 0, 100, 0, 0, 0, 0, 0, 18, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Spawn - Set Immune to combat'),
+(24016, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Spawn - Set Invisible'),
+(24016, 0, 6, 7, 38, 0, 100, 1, 1, 1, 0, 0, 47, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Data Set - Enable combat Immune to combat'),
+(24016, 0, 7, 8, 61, 0, 100, 1, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Data Set - Set visible'),
+(24016, 0, 8, 0, 61, 0, 100, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Ulf the Bloodletter - On Data Set - Say'),
+(24015, 0, 3, 0, 6, 0, 15, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 24161, 0, 0, 0, 0, 0, 0, 'Winterskorn Defender - On Death - Set Data on Oric the Baleful'),
+(24015, 0, 4, 0, 6, 0, 15, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 24162, 0, 0, 0, 0, 0, 0, 'Winterskorn Defender - On Death - Set Data on Gunnar Thorvardsson'),
+(24015, 0, 5, 0, 6, 0, 15, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, 24016, 0, 0, 0, 0, 0, 0, 'Winterskorn Defender - On Death - Set Data on Ulf the Bloodletter');
+
+DELETE FROM `creature_text` WHERE `entry` IN(24161,24162,24016);
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(24161, 0, 0, 'Enemies of the Winterskorn, you will be torn limb from limb!', 14, 0, 100, 0, 0, 0, 22867, 0, 'Oric the Baleful'),
+(24016, 0, 0, 'Drive this scum from the Vrykul homeland!', 14, 0, 100, 0, 0, 0, 22868, 0, 'Ulf the Bloodletter'),
+(24162, 0, 0, 'Gunnar, son of Thorvard, has arrived! Prepare to meet your demise!', 14, 0, 100, 0, 0, 0, 22863, 0, 'Gunnar Thorvardsson');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=22 AND `SourceEntry` IN(24161,24162,24016,24015);
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(22, 6, 24161, 0, 0, 36, 1, 0, 0, 0, 0, 0, 0, '', 'Only execute SAI if Oric the Baleful alive'),
+(22, 5, 24016, 0, 0, 36, 1, 0, 0, 0, 0, 0, 0, '', 'Only execute SAI if Ulf the Bloodletter alive'),
+(22, 5, 24162, 0, 0, 36, 1, 0, 0, 0, 0, 0, 0, '', 'Only execute SAI if Gunnar Thorvardsson alive'),
+(22, 4, 24015, 0, 0, 9, 0, 11282, 0, 0, 0, 0, 0, '', 'Only execute SAI if player has A Lesson in Fear taken'),
+(22, 5, 24015, 0, 0, 9, 0, 11282, 0, 0, 0, 0, 0, '', 'Only execute SAI if player has A Lesson in Fear taken'),
+(22, 6, 24015, 0, 0, 9, 0, 11282, 0, 0, 0, 0, 0, '', 'Only execute SAI if player has A Lesson in Fear taken');
+
+UPDATE `smart_scripts` SET `link`=0 WHERE `entryorguid`=29647 AND `source_type`=0 AND `id`=1 AND `link`=2;
+UPDATE `smart_scripts` SET `link`=4 WHERE `entryorguid`=29884 AND `source_type`=0 AND `id`=3 AND `link`=0;
+
diff --git a/sql/updates/world/3.3.5/2016_04_25_02_world.sql b/sql/updates/world/3.3.5/2016_04_25_02_world.sql
new file mode 100644
index 00000000000..31d98dd616c
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_25_02_world.sql
@@ -0,0 +1,48 @@
+--
+SET @Aura1:=44880;
+SET @Flare:=24916;
+SET @Grow:=44944;
+SET @Visual:=44877;
+SET @MiniExplosion:=44943;
+SET @Unstable:=24958;
+SET @Aura2:=46196;
+SET @Explosion:=46225;
+SET @credit:=44947;
+SET @Flame:=22323;
+
+UPDATE `creature_template` SET `unit_flags`=776, `faction`=1629, `InhabitType`=4, `AIName`='SmartAI' WHERE `entry`in (@Flare, @Unstable);
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`in (@Flame);
+
+DELETE FROM `creature_template_addon` WHERE `entry`=@Flare;
+INSERT INTO `creature_template_addon` (`entry`,`bytes2`,`auras`) VALUES (@Flare,1,@Aura1);
+
+DELETE FROM `smart_scripts` WHERE `entryorguid` = @Flame AND `source_type` = 0;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = @Flare AND `source_type` = 0;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = @Flare*100 AND `source_type` = 9;
+DELETE FROM `smart_scripts` WHERE `entryorguid` = @Flare*100+1 AND `source_type` = 9;
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(@Flare, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Just summoned - React passif'),
+(@Flare, 0, 1, 0, 23, 0, 100, 1, @Grow, 8, 0, 0, 80, @Flare*100, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - has aura x 8 - Action list'),
+(@Flare*100, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, @MiniExplosion, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - cast'),
+(@Flare*100, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 3, @Unstable, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - morph'),
+(@Flare*100, 9, 2, 0, 0, 0, 100, 0, 0, 0, 0, 0, 28, @Aura1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - Remove aura'),
+(@Flare*100, 9, 3, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, @Aura2, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - Add aura'),
+(@Flare*100, 9, 4, 0, 0, 0, 100, 0, 1000, 1000, 0, 0, 53, 1, @Flare, 0, 0, 500, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - Start way point'),
+(@Flare, 0, 2, 0, 58, 0, 100, 0, 0, 0, 0, 0, 80, @Flare*100+1, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Unstable - On way point Ended - Action list'),
+(@Flare*100+1, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, @Explosion, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - Cast'),
+(@Flare*100+1, 9, 1, 0, 0, 0, 100, 0, 0, 0, 0, 0, 11, @credit, 0, 0, 0, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 'Unstable - Action list - Cast'),
+(@Flare*100+1, 9, 2, 0, 0, 0, 100, 0, 500, 500, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - Action list - despawn'),
+(@Flare, 0, 3, 0, 38, 0, 100, 0, 1, 1, 0, 0, 11, @Visual, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flare - On data set- cast'),
+(@Flame, 0, 0, 0, 0, 0, 100, 0, 3000, 3000, 5000, 5000, 11, 36247, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 'Flare - IC - Cast'),
+(@Flame, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 45, 1, 1, 0, 0, 0, 0, 19, @Flare, 40, 0, 0, 0, 0, 0, 'Flare - On death - Set Data');
+
+DELETE FROM `waypoints` WHERE `entry`=@Flare;
+INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES
+(@Flare,1, 828.737000, 2509.100098, 300.700012,'Flare');
+
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger` = @Visual;
+INSERT INTO `spell_linked_spell` VALUES (@Visual, @Grow, 0, 'Flare Aura');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=@Visual;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
+(13,1,@Visual,0,0,31,0,3,@Flare,0,0,0,0,'','Only the Flare is a target for the spell.');
diff --git a/sql/updates/world/3.3.5/2016_04_25_03_world.sql b/sql/updates/world/3.3.5/2016_04_25_03_world.sql
new file mode 100644
index 00000000000..7bbd279e943
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_25_03_world.sql
@@ -0,0 +1,47 @@
+SET @CGUID := 145119;
+
+DELETE FROM `creature` WHERE `id`=21788;
+INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES
+(@CGUID+0, 21788, 530, 0, 0, 1, 1, 0, 0, -3090.62, 2402.483, 63.14528, 4.310963, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+1, 21788, 530, 0, 0, 1, 1, 0, 0, -3115.362, 2440.234, 64.67137, 1.902409, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+2, 21788, 530, 0, 0, 1, 1, 0, 0, -3138.009, 2452.761, 63.82878, 4.153883, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+3, 21788, 530, 0, 0, 1, 1, 0, 0, -3068.807, 2447.557, 64.62611, 1.380292, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+4, 21788, 530, 0, 0, 1, 1, 0, 0, -3125.387, 2489.521, 62.06233, 5.113815, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+5, 21788, 530, 0, 0, 1, 1, 0, 0, -3061.514, 2459.645, 65.18143, 4.520403, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+6, 21788, 530, 0, 0, 1, 1, 0, 0, -3122.754, 2501.015, 62.70392, 5.51524, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+7, 21788, 530, 0, 0, 1, 1, 0, 0, -3034.208, 2499.923, 63.14324, 1.48353, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+8, 21788, 530, 0, 0, 1, 1, 0, 0, -3079.527, 2527.942, 62.65857, 0.1570796, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+9, 21788, 530, 0, 0, 1, 1, 0, 0, -3067.415, 2495.909, 64.73977, 1.570796, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 0) (Auras: 37509 - 37509)
+(@CGUID+10, 21788, 530, 0, 0, 1, 1, 0, 0, -3130.252, 2537.187, 61.81245, 0.9250245, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+11, 21788, 530, 0, 0, 1, 1, 0, 0, -3036.085, 2528.19, 63.41149, 5.166174, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+12, 21788, 530, 0, 0, 1, 1, 0, 0, -3001.511, 2507.445, 61.33947, 1.553343, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+13, 21788, 530, 0, 0, 1, 1, 0, 0, -3020.436, 2502.759, 62.7676, 0.296706, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+14, 21788, 530, 0, 0, 1, 1, 0, 0, -3061.437, 2541.203, 62.35847, 4.361612, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+15, 21788, 530, 0, 0, 1, 1, 0, 0, -3022.704, 2512.111, 68.65653, 0.3839724, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+16, 21788, 530, 0, 0, 1, 1, 0, 0, -3016.363, 2549.719, 79.11957, 1.291544, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+17, 21788, 530, 0, 0, 1, 1, 0, 0, -3104.333, 2552.007, 61.75181, 5.380099, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+18, 21788, 530, 0, 0, 1, 1, 0, 0, -3115.356, 2556.791, 61.91945, 0.3141593, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+19, 21788, 530, 0, 0, 1, 1, 0, 0, -3133.627, 2548.74, 62.05401, 6.195919, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+20, 21788, 530, 0, 0, 1, 1, 0, 0, -2985.531, 2556.819, 76.62669, 3.961897, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+21, 21788, 530, 0, 0, 1, 1, 0, 0, -2987.325, 2568.416, 76.62669, 5.846853, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+22, 21788, 530, 0, 0, 1, 1, 0, 0, -3116.468, 2572.71, 61.88921, 0.1047198, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+23, 21788, 530, 0, 0, 1, 1, 0, 0, -3090.439, 2579.877, 61.85312, 4.817109, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+24, 21788, 530, 0, 0, 1, 1, 0, 0, -3147.669, 2577.585, 62.38097, 1.867502, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+25, 21788, 530, 0, 0, 1, 1, 0, 0, -3133.15, 2585.913, 61.80721, 2.86234, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+26, 21788, 530, 0, 0, 1, 1, 0, 0, -3073.789, 2609.983, 61.81239, 1.117011, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+27, 21788, 530, 0, 0, 1, 1, 0, 0, -3163.902, 2579.588, 62.70355, 0.4886922, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+28, 21788, 530, 0, 0, 1, 1, 0, 0, -3144.146, 2617.151, 61.85558, 3.752458, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+29, 21788, 530, 0, 0, 1, 1, 0, 0, -2963.017, 2518.091, 78.19579, 0.1047198, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+30, 21788, 530, 0, 0, 1, 1, 0, 0, -2965.681, 2540.958, 76.62669, 4.45059, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+31, 21788, 530, 0, 0, 1, 1, 0, 0, -2977.325, 2574.976, 76.62669, 1.413717, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+32, 21788, 530, 0, 0, 1, 1, 0, 0, -2999.423, 2619.978, 76.7438, 1.658063, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+33, 21788, 530, 0, 0, 1, 1, 0, 0, -3046.553, 2641.27, 76.62669, 5.916666, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+34, 21788, 530, 0, 0, 1, 1, 0, 0, -3028.977, 2656.449, 77.04675, 4.206244, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+35, 21788, 530, 0, 0, 1, 1, 0, 0, -2945.421, 2632.53, 91.97811, 3.910418, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+36, 21788, 530, 0, 0, 1, 1, 0, 0, -2907.585, 2603.013, 93.76357, 2.426008, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+37, 21788, 530, 0, 0, 1, 1, 0, 0, -2903.634, 2615.304, 93.76357, 3.071779, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+38, 21788, 530, 0, 0, 1, 1, 0, 0, -2926.175, 2646.125, 93.73645, 3.682645, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+39, 21788, 530, 0, 0, 1, 1, 0, 0, -2932.268, 2652.535, 93.76186, 3.961897, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+(@CGUID+40, 21788, 530, 0, 0, 1, 1, 0, 0, -2939.042, 2675.208, 93.76357, 4.433136, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463); -- 21788 (Area: 3744) (Auras: 37509 - 37509)
+
+UPDATE `creature_template_addon` SET `bytes1`=65536, `bytes2`=1 WHERE `entry`=21788;
diff --git a/sql/updates/world/3.3.5/2016_04_26_00_world.sql b/sql/updates/world/3.3.5/2016_04_26_00_world.sql
new file mode 100644
index 00000000000..72201221944
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_26_00_world.sql
@@ -0,0 +1,9 @@
+--
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|128 WHERE `entry` IN (33395,14031,22586,22585,14030,22584,14027,22583,14028,14029,22581,14026,33402,31878,33691,33942,34189,31462,37634,34153,39011,39012,39013,20654,31461,31670,33907,33906,33353,33352,34228,31875,30757,21584,34131,26337);
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|2 WHERE `entry`=30777;
+
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|130 WHERE `entry` IN (21625,31874);
+
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`|256 WHERE `entry` IN (20596,20745);
+
+UPDATE `creature_template` SET `flags_extra`=`flags_extra`&~1 WHERE `entry` IN (27309,27308,27307,27303);
diff --git a/sql/updates/world/3.3.5/2016_04_26_01_world.sql b/sql/updates/world/3.3.5/2016_04_26_01_world.sql
new file mode 100644
index 00000000000..2021a40a9e7
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_26_01_world.sql
@@ -0,0 +1,57 @@
+SET @CGUID := 145160;
+
+DELETE FROM `creature` WHERE `id`=21795;
+INSERT INTO `creature` (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES
+(@CGUID+0, 21795, 530, 0, 0, 1, 1, 0, 0, -3942.646, 2125.487, 96.96626, 5.357957, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+1, 21795, 530, 0, 0, 1, 1, 0, 0, -3943.109, 2193.898, 102.1291, 3.368572, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+2, 21795, 530, 0, 0, 1, 1, 0, 0, -4037.24, 2260.579, 113.4364, 3.5118, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+3, 21795, 530, 0, 0, 1, 1, 0, 0, -4023.835, 2206.558, 109.6129, 4.895111, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+4, 21795, 530, 0, 0, 1, 1, 0, 0, -4030.965, 2168.763, 107.4985, 2.480213, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+5, 21795, 530, 0, 0, 1, 1, 0, 0, -3951.485, 2265.172, 99.24145, 2.606144, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+6, 21795, 530, 0, 0, 1, 1, 0, 0, -4042.551, 2183.728, 109.3237, 3.009561, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+7, 21795, 530, 0, 0, 1, 1, 0, 0, -3984.742, 2197.148, 102.0214, 4.5442, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+8, 21795, 530, 0, 0, 1, 1, 0, 0, -3956.684, 2233.825, 101.9551, 1.479018, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+9, 21795, 530, 0, 0, 1, 1, 0, 0, -4019.452, 2140.292, 104.274, 0.1288698, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+10, 21795, 530, 0, 0, 1, 1, 0, 0, -4006.475, 2120.42, 115.6417, 1.27439, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+11, 21795, 530, 0, 0, 1, 1, 0, 0, -3940.616, 2152.896, 100.4848, 2.463561, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+12, 21795, 530, 0, 0, 1, 1, 0, 0, -4053.673, 2245.217, 112.0474, 0.036458, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+13, 21795, 530, 0, 0, 1, 1, 0, 0, -3939.613, 2223.242, 101.9156, 3.891035, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+14, 21795, 530, 0, 0, 1, 1, 0, 0, -3973.463, 2119.737, 103.7858, 2.866639, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+15, 21795, 530, 0, 0, 1, 1, 0, 0, -3988.523, 2153.718, 104.368, 6.001884, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+16, 21795, 530, 0, 0, 1, 1, 0, 0, -4070.058, 2227.373, 113.4363, 3.759574, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+17, 21795, 530, 0, 0, 1, 1, 0, 0, -4075.326, 2180.252, 107.5067, 3.183229, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+18, 21795, 530, 0, 0, 1, 1, 0, 0, -4054.947, 2124.536, 137.2578, 2.750937, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+19, 21795, 530, 0, 0, 1, 1, 0, 0, -4087.524, 2167.491, 111.391, 5.241858, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+20, 21795, 530, 0, 0, 1, 1, 0, 0, -4089.124, 2203.606, 97.22453, 5.805306, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+21, 21795, 530, 0, 0, 1, 1, 0, 0, -4080.437, 2179.819, 100.2801, 5.450742, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+22, 21795, 530, 0, 0, 1, 1, 0, 0, -4092.307, 2185.567, 100.2807, 0.1027414, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+23, 21795, 530, 0, 0, 1, 1, 0, 0, -4092.907, 2184.13, 106.9471, 5.606272, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+24, 21795, 530, 0, 0, 1, 1, 0, 0, -3918.483, 2046.919, 95.28484, 6.051655, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+25, 21795, 530, 0, 0, 1, 1, 0, 0, -3913.848, 2107.107, 96.72884, 4.46708, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+26, 21795, 530, 0, 0, 1, 1, 0, 0, -3947.833, 2040.741, 95.10477, 1.199215, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+27, 21795, 530, 0, 0, 1, 1, 0, 0, -3915.87, 2102.719, 96.12863, 1.258105, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+28, 21795, 530, 0, 0, 1, 1, 0, 0, -3839.461, 2121.8, 94.53188, 4.859396, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+29, 21795, 530, 0, 0, 1, 1, 0, 0, -3862.718, 2217.159, 95.1391, 3.999115, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+30, 21795, 530, 0, 0, 1, 1, 0, 0, -3849.665, 2175.306, 95.58624, 3.913765, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+31, 21795, 530, 0, 0, 1, 1, 0, 0, -4053.544, 2279.983, 112.0487, 4.612492, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+32, 21795, 530, 0, 0, 1, 1, 0, 0, -4066.031, 2258.548, 94.8257, 1.571143, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+33, 21795, 530, 0, 0, 1, 1, 0, 0, -4054.627, 2277.048, 121.7723, 4.634171, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+34, 21795, 530, 0, 0, 1, 1, 0, 0, -4070.104, 2263.355, 112.0474, 5.739568, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+35, 21795, 530, 0, 0, 1, 1, 0, 0, -4084.999, 2245.3, 121.7718, 5.480127, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+36, 21795, 530, 0, 0, 1, 1, 0, 0, -4087.486, 2244.981, 112.0474, 2.109367, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+37, 21795, 530, 0, 0, 1, 1, 0, 0, -4073.188, 2267.943, 94.82581, 1.50432, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+38, 21795, 530, 0, 0, 1, 1, 0, 0, -4071.124, 2294.895, 110.6591, 0.204018, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+39, 21795, 530, 0, 0, 1, 1, 0, 0, -4101.815, 2259.789, 110.659, 4.624498, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+40, 21795, 530, 0, 0, 1, 1, 0, 0, -4075.109, 2296.344, 121.7728, 2.60921, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+41, 21795, 530, 0, 0, 1, 1, 0, 0, -4094.75, 2260.984, 103.9927, 0.0229529, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+42, 21795, 530, 0, 0, 1, 1, 0, 0, -4088.135, 2265.592, 103.9921, 3.303511, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+43, 21795, 530, 0, 0, 1, 1, 0, 0, -4087.79, 2283.696, 103.9927, 1.226644, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+44, 21795, 530, 0, 0, 1, 1, 0, 0, -4094.398, 2277.201, 112.0475, 1.09602, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+45, 21795, 530, 0, 0, 1, 1, 0, 0, -4071.222, 2290.098, 103.9934, 0.974121, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+46, 21795, 530, 0, 0, 1, 1, 0, 0, -3823.303, 2124.582, 93.3121, 5.473604, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+47, 21795, 530, 0, 0, 1, 1, 0, 0, -3982.052, 1996.922, 95.26698, 6.067729, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+48, 21795, 530, 0, 0, 1, 1, 0, 0, -3830.084, 2177.76, 93.64696, 5.581445, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+49, 21795, 530, 0, 0, 1, 1, 0, 0, -3821.952, 2218.491, 92.7454, 2.951487, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463), -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+(@CGUID+50, 21795, 530, 0, 0, 1, 1, 0, 0, -3856.967, 2241.917, 97.24121, 0.3141558, 120, 5, 0, 0, 0, 1, 0, 0, 0, 21463); -- 21795 (Area: 3745) (Auras: 37509 - 37509)
+
+UPDATE `creature_template_addon` SET `bytes1`=65536, `bytes2`=1 WHERE `entry`=21795;
diff --git a/sql/updates/world/3.3.5/2016_04_26_02_world.sql b/sql/updates/world/3.3.5/2016_04_26_02_world.sql
new file mode 100644
index 00000000000..4df837e0d8f
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_26_02_world.sql
@@ -0,0 +1,16 @@
+--
+SET @ENTRY := 8035;
+-- Apply taunt sound effect instead of the Avatar of Hakkar's aggro sound
+UPDATE `creature_text` SET `sound`=3216 WHERE `entry` = @ENTRY AND `groupid` = 1 AND `id` = 0;
+-- Apply UNIT_FLAG_DISABLE_MOVE, UNIT_FLAG_PACIFIED, and UNIT_FLAG_DISARMED
+-- Extra OR's are for at-a-glance convenience
+UPDATE `creature_template` SET `unit_flags`= `unit_flags` | 4 | 131072 | 2097152 WHERE `Entry`= @ENTRY;
+-- Inserting an SAI event to make Dark Iron Land Mines not detonate prematurely.
+DELETE FROM `smart_scripts` WHERE `entryorguid` = @ENTRY AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(@ENTRY,0,0,0,1,0,100,3,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Out of Combat - Say Line 0'),
+(@ENTRY,0,1,0,1,0,100,3,5000,5000,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Out of Combat - Say Line 1'),
+(@ENTRY,0,2,0,1,0,100,3,10000,10000,0,0,1,2,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Out of Combat - Say Line 2'),
+(@ENTRY,0,3,0,1,0,100,3,10000,10000,0,0,19,131072,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Out of Combat - Remove Pacified Flag after 10s'),
+(@ENTRY,0,4,0,9,0,100,3,0,8,0,0,11,4043,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Within 0-8 Range - Cast \'Detonation\''),
+(@ENTRY,0,5,0,9,0,100,3,0,8,0,0,41,0,0,0,0,0,0,1,0,0,0,0,0,0,0,'Dark Iron Land Mine - Within 0-8 Range - Despawn Instant');
diff --git a/sql/updates/world/3.3.5/2016_04_26_03_world.sql b/sql/updates/world/3.3.5/2016_04_26_03_world.sql
new file mode 100644
index 00000000000..659006afcef
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_26_03_world.sql
@@ -0,0 +1,99 @@
+
+DELETE FROM creature WHERE `id` IN(24277,24516,24517);
+INSERT INTO creature (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES
+(45211, 24277, 571, 0, 0, 1, 1, 0, 0, 2578.047, -3028.564, 115.3411, 0, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 24277 (Area: 4054) (Auras: )
+(114439, 24516, 571, 0, 0, 1, 1, 0, 0, 2245.904, -3021.815, 135.1308, 1.318242, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 24516 (Area: 0)
+(114637, 24517, 571, 0, 0, 1, 1, 0, 0, 1886.899, -3555.015, 147.7859, 2.676408, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463); -- 24517 (Area: 3999) (Auras: 52071 - 52071)
+
+DELETE FROM `waypoint_data` WHERE `id` IN(452110,1144390,1146370);
+
+INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
+(452110, 1, 2603.876, -3028.025, 117.0937, 0, 0, 0, 0, 100, 0),
+(452110, 2, 2643.243, -3014.203, 104.8926, 0, 0, 0, 0, 100, 0),
+(452110, 3, 2667.486, -3001.944, 99.91364, 0, 0, 0, 0, 100, 0),
+(452110, 4, 2686.615, -2995.257, 94.60037, 0, 0, 0, 0, 100, 0),
+(452110, 5, 2708.851, -2996.379, 92.56187, 0, 0, 0, 0, 100, 0),
+(452110, 6, 2731.851, -2997.098, 91.55309, 0, 0, 0, 0, 100, 0),
+(452110, 7, 2751.252, -3001.074, 89.84369, 0, 0, 0, 0, 100, 0),
+(452110, 8, 2779.356, -3012.149, 91.26218, 0, 0, 0, 0, 100, 0),
+(452110, 9, 2790.117, -3024.486, 94.64268, 0, 0, 0, 0, 100, 0),
+(452110, 10, 2793.189, -3046.271, 97.1767, 0, 0, 0, 0, 100, 0),
+(452110, 11, 2787.66, -3063.327, 99.79316, 0, 0, 0, 0, 100, 0),
+(452110, 12, 2768.723, -3078.092, 104.6359, 0, 0, 0, 0, 100, 0),
+(452110, 13, 2744.823, -3091.001, 111.5423, 0, 0, 0, 0, 100, 0),
+(452110, 14, 2725.268, -3106.576, 111.8766, 0, 0, 0, 0, 100, 0),
+(452110, 15, 2697.289, -3117.357, 110.0175, 0, 0, 0, 0, 100, 0),
+(452110, 16, 2671.67, -3121.725, 118.3925, 0, 0, 0, 0, 100, 0),
+(452110, 17, 2647.262, -3119.072, 123.8932, 0, 0, 0, 0, 100, 0),
+(452110, 18, 2621.482, -3114.164, 127.1552, 0, 0, 0, 0, 100, 0),
+(452110, 19, 2597.5, -3107.631, 127.1276, 0, 0, 0, 0, 100, 0),
+(452110, 20, 2562.354, -3115.057, 123.5328, 0, 0, 0, 0, 100, 0),
+(452110, 21, 2547.443, -3131.256, 128.2941, 0, 0, 0, 0, 100, 0),
+(452110, 22, 2537.48, -3152.528, 130.5185, 0, 0, 0, 0, 100, 0),
+(452110, 23, 2523.183, -3170.009, 137.3546, 0, 0, 0, 0, 100, 0),
+(452110, 24, 2499.98, -3176.15, 146.2999, 0, 0, 0, 0, 100, 0),
+(452110, 25, 2477.218, -3173.943, 146.8427, 0, 0, 0, 0, 100, 0),
+(452110, 26, 2466.798, -3181.938, 148.4451, 0, 0, 0, 0, 100, 0),
+(452110, 27, 2449.986, -3186.217, 148.8962, 0, 0, 0, 0, 100, 0),
+(452110, 28, 2435.967, -3212.301, 150.5083, 0, 0, 0, 0, 100, 0),
+(452110, 29, 2430.812, -3224.802, 150.1544, 0, 0, 0, 0, 100, 0),
+(452110, 30, 2427.15, -3236.885, 149.6805, 0, 0, 0, 0, 100, 0),
+(452110, 31, 2420.321, -3249.048, 148.5472, 0, 0, 0, 0, 100, 0),
+(452110, 32, 2403.638, -3257.211, 150.8997, 0, 0, 0, 0, 100, 0),
+(452110, 33, 2386.398, -3251.84, 150.9332, 0, 0, 0, 0, 100, 0),
+(452110, 34, 2376.512, -3235.288, 151.3786, 0, 0, 0, 0, 100, 0),
+(452110, 35, 2375.435, -3213.906, 154.4518, 0, 0, 0, 0, 100, 0),
+(452110, 36, 2368.87, -3195.879, 154.6864, 0, 0, 0, 0, 100, 0),
+(452110, 37, 2383.123, -3178.886, 155.935, 0, 0, 0, 0, 100, 0),
+(452110, 38, 2398.307, -3176.602, 155.8448, 0, 0, 0, 0, 100, 0),
+(452110, 39, 2412.706, -3183.355, 153.6713, 0, 0, 0, 0, 100, 0),
+(452110, 40, 2436.154, -3172.414, 148.4366, 0, 0, 0, 0, 100, 0),
+(452110, 41, 2439.1, -3152.812, 145.9067, 0, 0, 0, 0, 100, 0),
+(452110, 42, 2423.416, -3137.387, 147.4658, 0, 0, 0, 0, 100, 0),
+(452110, 43, 2420.221, -3122.801, 146.8984, 0, 0, 0, 0, 100, 0),
+(452110, 44, 2432.173, -3109.894, 147.6966, 0, 0, 0, 0, 100, 0),
+(452110, 45, 2443.513, -3098.615, 147.4875, 0, 0, 0, 0, 100, 0),
+(452110, 46, 2458.256, -3078.243, 142.1544, 0, 0, 0, 0, 100, 0),
+(452110, 47, 2475.883, -3064.164, 139.0425, 0, 0, 0, 0, 100, 0),
+(452110, 48, 2507.794, -3040.304, 124.8166, 0, 0, 0, 0, 100, 0),
+(452110, 49, 2531.649, -3026.078, 119.3878, 0, 0, 0, 0, 100, 0),
+(452110, 50, 2560.749, -3028.565, 114.5343, 0, 0, 0, 0, 100, 0),
+(452110, 51, 2582.748, -3028.564, 115.9288, 0, 0, 0, 0, 100, 0),
+(1144390, 1, 2261.844 , -2975.589 , 137.7219, 0, 0, 0, 0, 100, 0),
+(1144390, 2, 2288.57 , -2967.957 , 134.1304, 0, 0, 0, 0, 100, 0),
+(1144390, 3, 2312.078 , -2973.851 , 131.6859, 0, 0, 0, 0, 100, 0),
+(1144390, 4, 2327.24 , -2996.011 , 135.0435, 0, 0, 0, 0, 100, 0),
+(1144390, 5, 2319.611 , -3020.818 , 136.6337, 0, 0, 0, 0, 100, 0),
+(1144390, 6, 2293.551 , -3033.061 , 136.8072, 0, 0, 0, 0, 100, 0),
+(1144390, 7, 2270.958 , -3049.189 , 136.8092, 0, 0, 0, 0, 100, 0),
+(1144390, 8, 2261.982 , -3069.591 , 137.1458, 0, 0, 0, 0, 100, 0),
+(1144390, 9, 2244.48 , -3111.4 , 136.8513, 0, 0, 0, 0, 100, 0),
+(1144390, 10, 2234.337 , -3129.741 , 138.2859, 0, 0, 0, 0, 100, 0),
+(1144390, 11, 2205.15 , -3149.454 , 140.4617, 0, 0, 0, 0, 100, 0),
+(1144390, 12, 2178.708 , -3143.635 , 139.101, 0, 0, 0, 0, 100, 0),
+(1144390, 13, 2159.131 , -3118.843 , 139.0326, 0, 0, 0, 0, 100, 0),
+(1144390, 14, 2157.424 , -3090.945 , 138.6674, 0, 0, 0, 0, 100, 0),
+(1144390, 15, 2184.693 , -3076.778 , 137.7539, 0, 0, 0, 0, 100, 0),
+(1144390, 16, 2205.282 , -3067.448 , 138.6362, 0, 0, 0, 0, 100, 0),
+(1144390, 17, 2241.108 , -3040.399 , 136.0237, 0, 0, 0, 0, 100, 0),
+(1144390, 18, 2251.254 , -3001.044 , 135.3165, 0, 0, 0, 0, 100, 0),
+(1146370, 1, 1851.814 , -3531.93 , 143.9488, 0, 0, 0, 0, 100, 0),
+(1146370, 2, 1845.242 , -3513.312 , 143.5822, 0, 0, 0, 0, 100, 0),
+(1146370, 3, 1850.21 , -3485.009 , 141.7585, 0, 0, 0, 0, 100, 0),
+(1146370, 4, 1876.234 , -3453.859 , 139.5074, 0, 0, 0, 0, 100, 0),
+(1146370, 5, 1914.745 , -3432.741 , 140.1635, 0, 0, 0, 0, 100, 0),
+(1146370, 6, 1944.544 , -3444.092 , 139.0286, 0, 0, 0, 0, 100, 0),
+(1146370, 7, 1957.72 , -3473.06 , 139.4977, 0, 0, 0, 0, 100, 0),
+(1146370, 8, 1961.842 , -3512.568 , 142.8533, 0, 0, 0, 0, 100, 0),
+(1146370, 9, 1954.096 , -3543.72 , 147.4886, 0, 0, 0, 0, 100, 0),
+(1146370, 10, 1939.206 , -3558.753 , 147.6136, 0, 0, 0, 0, 100, 0),
+(1146370, 11, 1923.051 , -3563.351 , 147.5182, 0, 0, 0, 0, 100, 0),
+(1146370, 12, 1899.894 , -3561.537 , 147.5989, 0, 0, 0, 0, 100, 0),
+(1146370, 13, 1876.972 , -3550.032 , 147.9288, 0, 0, 0, 0, 100, 0);
+
+DELETE FROM `creature_template_addon` WHERE `entry` IN(24516,24517);
+INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES
+(24516, 1144390, 0, 0, 4097, 0, NULL),
+(24517, 1146370, 0, 0, 4097, 0, NULL);
+
+
diff --git a/sql/updates/world/3.3.5/2016_04_28_00_world.sql b/sql/updates/world/3.3.5/2016_04_28_00_world.sql
new file mode 100644
index 00000000000..377f019f899
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_28_00_world.sql
@@ -0,0 +1,3 @@
+--
+UPDATE `creature_template` SET `ScriptName`="" WHERE `entry`=28033;
+UPDATE `creature_template` SET `ScriptName`="npc_the_etymidian" WHERE `entry`=28092;
diff --git a/sql/updates/world/3.3.5/2016_04_29_00_world.sql b/sql/updates/world/3.3.5/2016_04_29_00_world.sql
new file mode 100644
index 00000000000..14c700c0795
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_29_00_world.sql
@@ -0,0 +1,55 @@
+--
+UPDATE `creature_template` SET `AIName`='SmartAI' WHERE `entry`=29796;
+DELETE FROM `smart_scripts` WHERE `entryorguid`=29796 AND `source_type` = 0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(29796,0,0,0,19,0,100,0,12886,0,0,0,85,55253,0,0,0,0,0,7,0,0,0,0,0,0,0,'Gretta the Arbiter - On quest accept - cast Spell');
+
+DELETE FROM `smart_scripts` WHERE `entryorguid`=29694 AND `source_type` = 0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(29694, 0, 0, 0, 0, 0, 100, 0, 2000, 5000, 10000, 15000, 11, 32736, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, "Hyldsmeet Drakerider - In Combat - Cast 'Mortal Strike'"),
+(29694, 0, 1, 0, 6, 0, 100, 0, 0, 0, 0, 0, 33, 29800, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, "Hyldsmeet Drakerider - On Death - Kill credit Spell");
+
+UPDATE `creature_template` SET `AIName`='SmartAI', `InhabitType`=4, `speed_run`=3.2 WHERE `entry` IN (29679);
+DELETE FROM `smart_scripts` WHERE `entryorguid`=29679 AND `source_type` = 0;
+INSERT INTO `smart_scripts` (`entryorguid`,`source_type`,`id`,`link`,`event_type`,`event_phase_mask`,`event_chance`,`event_flags`,`event_param1`,`event_param2`,`event_param3`,`event_param4`,`action_type`,`action_param1`,`action_param2`,`action_param3`,`action_param4`,`action_param5`,`action_param6`,`target_type`,`target_param1`,`target_param2`,`target_param3`,`target_x`,`target_y`,`target_z`,`target_o`,`comment`) VALUES
+(29679, 0, 0, 0, 27, 0, 100, 0, 0, 0, 0, 0, 53, 1, 29679, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Hyldsmeet Proto-Drake - ON PASSENGER_BOARDED - Start waypoint');
+
+DELETE FROM `creature_template_addon` WHERE `entry`=29679;
+INSERT INTO `creature_template_addon` (`entry`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES
+(29679, 0, 0, 33554432, 0, 0, '55971');
+
+DELETE FROM `waypoints` WHERE `entry`=29679;
+INSERT INTO `waypoints` (`entry`,`pointid`,`position_x`,`position_y`,`position_z`,`point_comment`) VALUES
+(29679,1,6985.165039, -1662.842163, 868.941956, 'Hyldsmeet Proto-Drake'),
+(29679,2,6935.585449, -1516.853760, 968.493896, 'Hyldsmeet Proto-Drake'),
+(29679,3,6926.762207, -1282.424927, 1127.864380, 'Hyldsmeet Proto-Drake'),
+(29679,4,7365.684082, -644.429688, 1928.750610, 'Hyldsmeet Proto-Drake'),
+(29679,5,7388.145508, -652.783569, 1909.863647, 'Hyldsmeet Proto-Drake'),
+(29679,6,7439.698730, -661.380981, 1887.756714, 'Hyldsmeet Proto-Drake'),
+(29679,7,7494.946777, -650.403015, 1883.039795, 'Hyldsmeet Proto-Drake'),
+(29679,8,7548.416992, -601.006348, 1882.505737, 'Hyldsmeet Proto-Drake'),
+(29679,9,7575.110352, -541.134949, 1881.668701, 'Hyldsmeet Proto-Drake'),
+(29679,10,7550.558594, -458.574036, 1877.870972, 'Hyldsmeet Proto-Drake'),
+(29679,11,7482.576172, -404.054077, 1878.095581, 'Hyldsmeet Proto-Drake'),
+(29679,12,7390.999023, -404.312683, 1882.240234, 'Hyldsmeet Proto-Drake'),
+(29679,13,7324.988770, -455.605713, 1874.051270, 'Hyldsmeet Proto-Drake'),
+(29679,14,7289.477051, -552.180786, 1879.989258, 'Hyldsmeet Proto-Drake'),
+(29679,15,7332.199707, -623.493713, 1887.427734, 'Hyldsmeet Proto-Drake'),
+(29679,16,7367.857910, -647.534546, 1895.689453, 'Hyldsmeet Proto-Drake'),
+(29679,17,7388.145508, -652.783569, 1909.863647, 'Hyldsmeet Proto-Drake'),
+(29679,18,7439.698730, -661.380981, 1887.756714, 'Hyldsmeet Proto-Drake'),
+(29679,19,7494.946777, -650.403015, 1883.039795, 'Hyldsmeet Proto-Drake'),
+(29679,20,7548.416992, -601.006348, 1882.505737, 'Hyldsmeet Proto-Drake'),
+(29679,21,7575.110352, -541.134949, 1881.668701, 'Hyldsmeet Proto-Drake'),
+(29679,22,7550.558594, -458.574036, 1877.870972, 'Hyldsmeet Proto-Drake'),
+(29679,23,7482.576172, -404.054077, 1878.095581, 'Hyldsmeet Proto-Drake'),
+(29679,24,7390.999023, -404.312683, 1882.240234, 'Hyldsmeet Proto-Drake'),
+(29679,25,7324.988770, -455.605713, 1874.051270, 'Hyldsmeet Proto-Drake'),
+(29679,26,7289.477051, -552.180786, 1879.989258, 'Hyldsmeet Proto-Drake'),
+(29679,27,7332.199707, -623.493713, 1887.427734, 'Hyldsmeet Proto-Drake'),
+(29679,28,6926.762207, -1282.424927, 1127.864380, 'Hyldsmeet Proto-Drake'),
+(29679,29,6935.585449, -1516.853760, 968.493896, 'Hyldsmeet Proto-Drake'),
+(29679,30,6985.165039, -1662.842163, 868.941956, 'Hyldsmeet Proto-Drake'),
+(29679,31,6998.042969, -1664.234253, 867.953247, 'Hyldsmeet Proto-Drake'),
+(29679,32,7037.400879, -1725.409302, 838.695618, 'Hyldsmeet Proto-Drake'),
+(29679,33,7076.637695, -1770.263184, 825.775391, 'Hyldsmeet Proto-Drake');
diff --git a/sql/updates/world/3.3.5/2016_04_29_01_world.sql b/sql/updates/world/3.3.5/2016_04_29_01_world.sql
new file mode 100644
index 00000000000..c5b0311e1bc
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_04_29_01_world.sql
@@ -0,0 +1,5 @@
+DELETE FROM `vehicle_template_accessory` WHERE `entry`=29460;
+INSERT INTO `vehicle_template_accessory` (`entry`, `accessory_entry`, `seat_id`, `minion`, `description`, `summontype`, `summontimer`) VALUES
+(29460, 29458, 0, 1, "Brunnhildar Drakerider", 8, 0);
+
+UPDATE `npc_spellclick_spells` SET `spell_id`=46598 WHERE `npc_entry`=29460;
diff --git a/sql/updates/world/3.3.5/2016_05_01_00_world.sql b/sql/updates/world/3.3.5/2016_05_01_00_world.sql
new file mode 100644
index 00000000000..5a4d6c3197e
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_05_01_00_world.sql
@@ -0,0 +1 @@
+DELETE FROM `trinity_string` WHERE `entry`=5007;
diff --git a/sql/updates/world/3.3.5/2016_05_01_01_world.sql b/sql/updates/world/3.3.5/2016_05_01_01_world.sql
new file mode 100644
index 00000000000..30096e55335
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_05_01_01_world.sql
@@ -0,0 +1,68 @@
+DELETE FROM `waypoints` WHERE `entry`=28308;
+INSERT INTO `waypoints` (`entry`, `pointid`, `position_x`, `position_y`, `position_z`, `point_comment`) VALUES
+(28308, 1, 5268.226 ,4425.439 ,-95.55899, 'Captive Crocolisk'),
+(28308, 2, 5249.557 ,4405.892 ,-96.04365, 'Captive Crocolisk'),
+(28308, 3, 5266.678 ,4365.464 ,-98.19455, 'Captive Crocolisk'),
+(28308, 4, 5289.138 ,4366.553 ,-102.234, 'Captive Crocolisk'),
+(28308, 5, 5330.018 ,4363.27 ,-121.0311, 'Captive Crocolisk'),
+(28308, 6, 5349.229 ,4341.059 ,-134.0126, 'Captive Crocolisk'),
+(28308, 7, 5365.038 ,4333.716 ,-141.5817, 'Captive Crocolisk'),
+(28308, 8, 5405.443 ,4307.841 ,-142.03, 'Captive Crocolisk'),
+(28308, 9, 5434.999 ,4305.659 ,-136.4706, 'Captive Crocolisk'),
+(28308, 10, 5464.708 ,4302.066 ,-133.1981, 'Captive Crocolisk'),
+(28308, 11, 5490.555 ,4294.395 ,-127.5203, 'Captive Crocolisk'),
+(28308, 12, 5503.808 ,4269.717 ,-110.3168, 'Captive Crocolisk'),
+(28308, 13, 5518.324 ,4255.308 ,-103.0638, 'Captive Crocolisk'),
+(28308, 14, 5540.53 ,4259.77 ,-102.3979, 'Captive Crocolisk'),
+(28308, 15, 5564.194 ,4263.45 ,-102.7574, 'Captive Crocolisk'),
+(28308, 16, 5585.45 ,4261.137 ,-99.54807, 'Captive Crocolisk'),
+(28308, 17, 5609.614 ,4259.657 ,-98.87333, 'Captive Crocolisk'),
+(28308, 18, 5633.434 ,4259.228 ,-98.53442, 'Captive Crocolisk'),
+(28308, 19, 5660.568 ,4260.985 ,-98.63537, 'Captive Crocolisk'),
+(28308, 20, 5681.639 ,4266.31 ,-99.26748, 'Captive Crocolisk'),
+(28308, 21, 5708.126 ,4273.348 ,-102.9183, 'Captive Crocolisk'),
+(28308, 22, 5748.732 ,4284.135 ,-112.0557, 'Captive Crocolisk'),
+(28308, 23, 5839.82 ,4368.61 ,-112.0805, 'Captive Crocolisk'),
+(28308, 24, 5897.276 ,4408.44 ,-95.25065, 'Captive Crocolisk'),
+(28308, 25, 5925.311 ,4440.624 ,-94.77592, 'Captive Crocolisk'),
+(28308, 26, 5953.005 ,4476.29 ,-94.3763, 'Captive Crocolisk'),
+(28308, 27, 5964.229 ,4503.729 ,-92.81553, 'Captive Crocolisk'),
+(28308, 28, 5960.583 ,4546.558 ,-95.65462, 'Captive Crocolisk'),
+(28308, 29, 5965.167 ,4579.141 ,-97.39779, 'Captive Crocolisk'),
+(28308, 30, 5969.295 ,4613.739 ,-98.05751, 'Captive Crocolisk'),
+(28308, 31, 5975.809 ,4659.289 ,-99.27143, 'Captive Crocolisk'),
+(28308, 32, 5992.961 ,4699.554 ,-99.30317, 'Captive Crocolisk'),
+(28308, 33, 6015.139 ,4743.752 ,-97.52377, 'Captive Crocolisk'),
+(28308, 34, 6035.183 ,4788.787 ,-94.66938, 'Captive Crocolisk'),
+(28308, 35, 6064.951 ,4827.502 ,-94.54885, 'Captive Crocolisk'),
+(28308, 36, 6065.57 ,4870.553 ,-94.47726, 'Captive Crocolisk'),
+(28308, 37, 6096.612 ,4885.741 ,-94.44479, 'Captive Crocolisk'),
+(28308, 38, 6120.387 ,4902.048 ,-95.06882, 'Captive Crocolisk'),
+(28308, 39, 6139.616 ,4913.349 ,-94.8635, 'Captive Crocolisk'),
+(28308, 40, 6141.208, 4914.293, -92.7175, 'Captive Crocolisk');
+
+UPDATE `creature_template` SET `AIName`='SmartAI', `InhabitType`=4 WHERE `entry`=28307;
+UPDATE `smart_scripts` SET `link`=1 WHERE `entryorguid`=28298 AND `source_type`=0 AND `id`=0 AND `link`=0;
+
+DELETE FROM `smart_scripts` WHERE `entryorguid`IN(28307,28308) AND `source_type`=0;
+DELETE FROM `smart_scripts` WHERE `entryorguid`IN(28216) AND `source_type`=0 AND `id`>17;
+DELETE FROM `smart_scripts` WHERE `entryorguid`IN(28298) AND `source_type`=0 AND `id`=1;
+
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(28216, 0, 18, 19, 38, 0, 100, 0, 1, 3, 0, 0, 1, 6, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Zepik the Gorloc Hunter - On Data Set 1 3 - Say Line 6'),
+(28216, 0, 19, 0, 61, 0, 100, 0, 0, 0, 0, 0, 41, 3000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Zepik the Gorloc Hunter - On Data Set 1 3 - Despawn'),
+(28298, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 45, 1, 3, 0, 0, 0, 0, 19, 28216, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On Gossip Option 0 Selected - Set Data on Zepik'),
+(28307, 0, 0, 0, 1, 0, 100, 0, 0, 0, 3000, 3000, 11, 51256, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Croclisk Chain Bunny - OOC - Cast Captive Crocolisk Chains'),
+(28308, 0, 0, 0, 54, 0, 100, 0, 0, 0, 0, 0, 80, 2830800, 0, 2, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On Just Summoned - Run Script (Phase 1) (No Repeat)'),
+(28308, 0, 1, 2, 40, 0, 100, 0, 39, 0, 0, 0, 11, 50630, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On reached WP42 - Cast Eject All Passengers'),
+(28308, 0, 2, 3, 61, 0, 100, 0, 0, 0, 0, 0, 15, 12536, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On reached WP42 - Quest Credit \'A Rough Ride\''),
+(28308, 0, 3, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 52545, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On reached WP42 - Cast Forceitem Zepik'),
+(28308, 0, 4, 0, 40, 0, 100, 0, 40, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Captive Crocolisk - On reached WP43 - Despawn');
+
+DELETE FROM `creature_text` WHERE `entry`=28216 AND `groupid`=6;
+INSERT INTO `creature_text` (`entry`, `groupid`, `id`, `text`, `type`, `language`, `probability`, `emote`, `duration`, `sound`, `BroadcastTextId`, `TextRange`, `comment`) VALUES
+(28216, 6, 0, 'Enjoy ride! Call me when you get there.', 12, 0, 100, 0, 0, 0, 28881, 0, 'Zepik');
+
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`=13 AND `SourceEntry`=51256;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`, `SourceGroup`, `SourceEntry`, `SourceId`, `ElseGroup`, `ConditionTypeOrReference`, `ConditionTarget`, `ConditionValue1`, `ConditionValue2`, `ConditionValue3`, `NegativeCondition`, `ErrorType`, `ErrorTextId`, `ScriptName`, `Comment`) VALUES
+(13, 1, 51256, 0, 0, 31, 0, 3, 28298, 0, 0, 0, 0, '', 'Captive Crocolisk Chains targets captive crocolisk');
diff --git a/sql/updates/world/3.3.5/2016_05_02_00_world.sql b/sql/updates/world/3.3.5/2016_05_02_00_world.sql
new file mode 100644
index 00000000000..2063baf1ad7
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_05_02_00_world.sql
@@ -0,0 +1,14 @@
+UPDATE `smart_scripts` SET `link`=5 WHERE `entryorguid`=28082 AND `source_type`=0 AND `id` IN(0,1) AND `link`=0;
+UPDATE `smart_scripts` SET `link`=6 WHERE `entryorguid`=28082 AND `source_type`=0 AND `id` IN(2,3) AND `link`=0;
+UPDATE `smart_scripts` SET `link`=7 WHERE `entryorguid`=28082 AND `source_type`=0 AND `id` IN(4) AND `link`=0;
+
+DELETE FROM `smart_scripts` WHERE `entryorguid`=28082 AND `source_type`=0 AND `id` IN(5,6,7);
+DELETE FROM `smart_scripts` WHERE `entryorguid`=28027 AND `source_type`=0 AND `id` IN(9,10,11);
+
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(28082, 0, 5, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 51186, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - Link - Cast Summon Goregek the Bristlepine Hunter'),
+(28082, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 51188, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - Link - Cast Summon Dajik the Wasp Hunter'),
+(28082, 0, 7, 0, 61, 0, 100, 0, 0, 0, 0, 0, 85, 51189, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Shaman Rakjak - Link - Cast Summon Zepik the Gorloc Hunter'),
+(28027, 0, 9, 0, 19, 0, 100, 0, 12571, 0, 0, 0, 85, 51190, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Accept - Cast Summon Lafoo'),
+(28027, 0, 10, 0, 19, 0, 100, 0, 12574, 0, 0, 0, 85, 51191, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Accept - Cast Summon Jaloot'),
+(28027, 0, 11, 0, 19, 0, 100, 0, 12578, 0, 0, 0, 85, 51192, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'High-Oracle Soo-say - On Quest Accept - Cast Summon Moodle');
diff --git a/sql/updates/world/3.3.5/2016_05_02_01_world.sql b/sql/updates/world/3.3.5/2016_05_02_01_world.sql
new file mode 100644
index 00000000000..1671abee38f
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_05_02_01_world.sql
@@ -0,0 +1,18 @@
+-- Beaten Corpse (Mankrik's wife) in quest 4921 "Lost in Battle":
+UPDATE `creature_template` SET `gossip_menu_id`= 2871 WHERE `entry`= 10668;
+
+-- new gossip_menu.entry for creature 10668 (Beaten Corpse):
+DELETE FROM `gossip_menu` WHERE `entry` IN (2871,2872) AND `text_id` IN (3557,3558);
+INSERT INTO `gossip_menu` (`entry`,`text_id`) VALUES
+(2871, 3557),
+(2872, 3558);
+
+-- new gossip_menu_option for creature 10668 (Beaten Corpse):
+DELETE FROM `gossip_menu_option` WHERE `menu_id`= 2871 AND `OptionBroadcastTextID`= 5964;
+INSERT INTO `gossip_menu_option` (`menu_id`,`id`,`option_icon`,`option_text`,`OptionBroadcastTextID`,`option_id`,`npc_option_npcflag`,`action_menu_id`,`action_poi_id`,`box_coded`,`box_money`,`box_text`,`BoxBroadcastTextID`) VALUES
+(2871, 0, 0, 'I inspect the body further.', 5964, 1, 1, 2872, 0, 0, 0, '', 0);
+
+-- condition for gossip_menu_option 2871 in Quest ID 4921 "Lost in Battle":
+DELETE FROM `conditions` WHERE `SourceTypeOrReferenceId`= 15 AND `SourceGroup`= 2871;
+INSERT INTO `conditions` (`SourceTypeOrReferenceId`,`SourceGroup`,`SourceEntry`,`SourceId`,`ElseGroup`,`ConditionTypeOrReference`,`ConditionTarget`,`ConditionValue1`,`ConditionValue2`,`ConditionValue3`,`NegativeCondition`,`ErrorType`,`ErrorTextId`,`ScriptName`,`Comment`) VALUES
+(15, 2871,0, 0,0, 9,0, 4921, 0,0,0,0,0, '', 'Show gossip menu option 2871 only if Quest 4921 is taken (active)');
diff --git a/sql/updates/world/3.3.5/2016_05_04_00_world.sql b/sql/updates/world/3.3.5/2016_05_04_00_world.sql
new file mode 100644
index 00000000000..e4043768774
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_05_04_00_world.sql
@@ -0,0 +1 @@
+DELETE FROM `spell_linked_spell` WHERE `spell_trigger`=70157 AND `spell_effect`=69700 AND `type`=2;
diff --git a/sql/updates/world/3.3.5/2016_05_04_01_world.sql b/sql/updates/world/3.3.5/2016_05_04_01_world.sql
new file mode 100644
index 00000000000..8a40bd66b2a
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_05_04_01_world.sql
@@ -0,0 +1,69 @@
+SET @CGUID := 84723;
+
+UPDATE `creature_template` SET `InhabitType`=4 WHERE `entry`in(29066);
+
+DELETE FROM creature WHERE `id` IN(28069,28840);
+INSERT INTO creature (`guid`, `id`, `map`, `zoneId`, `areaId`, `spawnMask`, `phaseMask`, `modelid`, `equipment_id`, `position_x`, `position_y`, `position_z`, `orientation`, `spawntimesecs`, `spawndist`, `currentwaypoint`, `curhealth`, `curmana`, `MovementType`, `npcflag`, `unit_flags`, `dynamicflags`, `VerifiedBuild`) VALUES
+(@CGUID+0, 28069, 571, 0, 0, 1, 1, 0, 0, 5734.697, 3308.838, 299.8264, 1.867502, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 0)
+(@CGUID+1, 28069, 571, 0, 0, 1, 1, 0, 0, 5728.474, 3438.191, 300.8422, 0.1060605, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 28069 (Area: 0)
+(@CGUID+2, 28069, 571, 0, 0, 1, 1, 0, 0, 5717.042, 3428.265, 300.9259, 1.797689, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 0)
+(@CGUID+3, 28069, 571, 0, 0, 1, 1, 0, 0, 5697.737, 3426.803, 300.9259, 1.570796, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 0)
+(@CGUID+4, 28069, 571, 0, 0, 1, 1, 0, 0, 5738.866, 3156.665, 293.8326, 4.814398, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 28069 (Area: -1) (Auras: )
+(@CGUID+5, 28069, 571, 0, 0, 1, 1, 0, 0, 5706.989, 3306.817, 299.718, 1.518436, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412)
+(@CGUID+6, 28840, 571, 0, 0, 1, 1, 0, 0, 5737.756, 3273.594, 299.117, 2.794445, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463), -- 28840 (Area: 4412) (Auras: 55030 - 55030)
+(@CGUID+7, 28069, 571, 0, 0, 1, 1, 0, 0, 5752.529, 3141.505, 294.1674, 3.351032, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412)
+(@CGUID+8, 28069, 571, 0, 0, 1, 1, 0, 0, 5728.323, 3137.707, 294.1627, 0.715585, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412)
+(@CGUID+9, 28069, 571, 0, 0, 1, 1, 0, 0, 5737.385, 3051.348, 288.0696, 1.239184, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: -1)
+(@CGUID+10, 28069, 571, 0, 0, 1, 1, 0, 0, 5781.281, 3081.078, 288.0696, 3.089233, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412)
+(@CGUID+11, 28069, 571, 0, 0, 1, 1, 0, 0, 5717.863, 3074.304, 288.0696, 0.4014257, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412)
+(@CGUID+12, 28069, 571, 0, 0, 1, 1, 0, 0, 5767.666, 3052.907, 288.0696, 2.181662, 120, 0, 0, 0, 0, 0, 0, 0, 0, 21463), -- 28069 (Area: 4412)
+(@CGUID+13, 28069, 571, 0, 0, 1, 1, 0, 0, 5704.075, 3429.402, 300.8421, 1.239184, 120, 0, 0, 0, 0, 2, 0, 0, 0, 21463); -- 28069 (Area: 4412)
+
+DELETE FROM `waypoint_data` WHERE `id` =(@CGUID*10)+1;
+DELETE FROM `waypoint_data` WHERE `id` =(@CGUID*10)+4;
+DELETE FROM `waypoint_data` WHERE `id` =(@CGUID*10)+6;
+DELETE FROM `waypoint_data` WHERE `id` =(@CGUID*10)+13;
+
+
+INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
+((@CGUID*10)+6, 1, 5712.777, 3273.745, 299.1278, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 2, 5705.582, 3264.395, 299.1169, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 3, 5704.035, 3252.411, 299.1169, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 4, 5711.498, 3241.038, 299.117, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 5, 5725.473, 3233.009, 299.1144, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 6, 5738.392, 3238.95, 299.1152, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 7, 5744.125, 3248.184, 299.1169, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 8, 5747.937, 3262.18, 299.1169, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 9, 5737.756, 3273.594, 299.117, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+6, 10, 5723.768, 3278.654, 299.138, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 1, 5737.638, 3168.66, 293.8326, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 2, 5734.833, 3190.47, 294.0836, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 3, 5733.381, 3205.572, 295.6976, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 4, 5734.833, 3190.47, 294.0836, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 5, 5737.638, 3168.66, 293.8326, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 6, 5739.323, 3152.199, 293.8326, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 7, 5742.777, 3128.636, 294.0135, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 8, 5744.988, 3100.412, 287.9503, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 9, 5746.909, 3085.88, 287.758, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 10, 5744.988, 3100.412, 287.9503, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 11, 5742.777, 3128.636, 294.0135, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+4, 12, 5739.323, 3152.199, 293.8326, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+1, 1, 5754.452, 3440.957, 300.8421, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+1, 2, 5721.435, 3437.441, 300.8421, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+1, 3, 5690.508, 3433.794, 300.8422, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+1, 4, 5655.392, 3430.241, 300.8421, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+1, 5, 5690.508, 3433.794, 300.8422, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+1, 6, 5721.435, 3437.441, 300.8421, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+13, 1, 5709.812, 3394.623, 300.8422, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+13, 2, 5713.209, 3367.164, 300.2528, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+13, 3, 5715.425, 3346.877, 300.0398, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+13, 4, 5718.081, 3324.582, 299.8054, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+13, 5, 5715.425, 3346.877, 300.0398, 0, 0, 0, 0, 100, 0),
+((@CGUID*10)+13, 6, 5713.209, 3367.164, 300.2528, 0, 0, 0, 0, 100, 0);
+
+DELETE FROM `creature_addon` WHERE `guid` IN(@CGUID+1,@CGUID+4,@CGUID+6,@CGUID+13);
+INSERT INTO `creature_addon` (`guid`, `path_id`, `mount`, `bytes1`, `bytes2`, `emote`, `auras`) VALUES
+(@CGUID+1, (@CGUID*10)+1, 0, 0, 4097, 0, NULL),
+(@CGUID+4, (@CGUID*10)+4, 0, 0, 4097, 0, NULL),
+(@CGUID+6, (@CGUID*10)+6, 0, 0, 4097, 0, NULL),
+(@CGUID+13, (@CGUID*10)+13, 0, 0, 4097, 0, NULL);
diff --git a/sql/updates/world/3.3.5/2016_05_04_02_world.sql b/sql/updates/world/3.3.5/2016_05_04_02_world.sql
new file mode 100644
index 00000000000..4bb7870a4ea
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_05_04_02_world.sql
@@ -0,0 +1,2 @@
+UPDATE `quest_template_addon` SET `RewardMailTemplateID`=184, `RewardMailDelay`=900 WHERE `ID`=10966;
+UPDATE `quest_template_addon` SET `RewardMailTemplateID`=185, `RewardMailDelay`=900 WHERE `ID`=10967;
diff --git a/sql/updates/world/3.3.5/2016_05_05_00_world.sql b/sql/updates/world/3.3.5/2016_05_05_00_world.sql
new file mode 100644
index 00000000000..ba99f5df1a6
--- /dev/null
+++ b/sql/updates/world/3.3.5/2016_05_05_00_world.sql
@@ -0,0 +1,13 @@
+DELETE FROM `smart_scripts` WHERE `entryorguid`=27292 AND `source_type`=0;
+INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
+(27292, 0, 0, 1, 62, 0, 100, 0, 9512, 0, 0, 0, 11, 48606, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On gossip select - Cast Summon Flamebringer Cue'),
+(27292, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On gossip select - Close gossip'),
+(27292, 0, 2, 3, 54, 0, 100, 0, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On summon - Remove npcflag'),
+(27292, 0, 3, 4, 61, 0, 100, 0, 0, 0, 0, 0, 11, 48598, 2, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On Just Summoned -Cast Ride Flamebringer Cue'),
+(27292, 0, 4, 0, 61, 0, 100, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - Linked with previous Event -Set Passive'),
+(27292, 0, 5, 6, 27, 0, 100, 0, 0, 0, 0, 0, 11, 48602, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On passenger Boarded - Cast Flight'),
+(27292, 0, 6, 0, 61, 0, 100, 0, 0, 0, 0, 0, 19, 768, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On passenger Boarded - Enable Combat'),
+(27292, 0, 7, 8, 28, 0, 100, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On passenger removed - Evade'),
+(27292, 0, 8, 0, 61, 0, 100, 0, 0, 0, 0, 0, 41, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 'Flamebringer - On passenger removed - Despawn');
+
+UPDATE `creature_template_addon` SET `auras`='' WHERE `entry`=27292;
diff --git a/sql/updates/world/3.3.5/dummy b/sql/updates/world/3.3.5/dummy
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/sql/updates/world/3.3.5/dummy
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 436620e2900..0428738f2dd 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -71,7 +71,9 @@ target_link_libraries(common
openssl
valgrind
threads
- jemalloc)
+ jemalloc
+ PRIVATE
+ process)
add_dependencies(common revision_data.h)
diff --git a/src/common/Common.h b/src/common/Common.h
index 8216c519746..aa04abacd30 100644
--- a/src/common/Common.h
+++ b/src/common/Common.h
@@ -44,6 +44,8 @@
#include <cerrno>
#include <csignal>
+#include <boost/optional.hpp>
+#include <boost/utility/in_place_factory.hpp>
#include <boost/functional/hash.hpp>
#include "Debugging/Errors.h"
@@ -152,6 +154,10 @@ typedef std::vector<std::string> StringVector;
#define MAX_QUERY_LEN 32*1024
+//! Optional helper class to wrap optional values within.
+template <typename T>
+using Optional = boost::optional<T>;
+
namespace Trinity
{
//! std::make_unique implementation (TODO: remove this once C++14 is supported)
diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp
index ddaab7dee61..888aa6ecef3 100644
--- a/src/common/Configuration/Config.cpp
+++ b/src/common/Configuration/Config.cpp
@@ -25,11 +25,13 @@
using namespace boost::property_tree;
-bool ConfigMgr::LoadInitial(std::string const& file, std::string& error)
+bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> args,
+ std::string& error)
{
std::lock_guard<std::mutex> lock(_configLock);
_filename = file;
+ _args = args;
try
{
@@ -65,7 +67,7 @@ ConfigMgr* ConfigMgr::instance()
bool ConfigMgr::Reload(std::string& error)
{
- return LoadInitial(_filename, error);
+ return LoadInitial(_filename, std::move(_args), error);
}
template<class T>
diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h
index 10113cd88d3..573bc7b4a15 100644
--- a/src/common/Configuration/Config.h
+++ b/src/common/Configuration/Config.h
@@ -23,6 +23,7 @@
#include <string>
#include <list>
+#include <vector>
#include <mutex>
#include <boost/property_tree/ptree.hpp>
@@ -35,7 +36,8 @@ class TC_COMMON_API ConfigMgr
public:
/// Method used only for loading main configuration files (authserver.conf and worldserver.conf)
- bool LoadInitial(std::string const& file, std::string& error);
+ bool LoadInitial(std::string const& file, std::vector<std::string> args,
+ std::string& error);
static ConfigMgr* instance();
@@ -47,10 +49,12 @@ public:
float GetFloatDefault(std::string const& name, float def) const;
std::string const& GetFilename();
+ std::vector<std::string> const& GetArguments() const { return _args; }
std::list<std::string> GetKeysByString(std::string const& name);
private:
std::string _filename;
+ std::vector<std::string> _args;
boost::property_tree::ptree _config;
std::mutex _configLock;
diff --git a/src/common/Cryptography/SHA1.cpp b/src/common/Cryptography/SHA1.cpp
index a01bd7844ee..aed4a069827 100644
--- a/src/common/Cryptography/SHA1.cpp
+++ b/src/common/Cryptography/SHA1.cpp
@@ -18,6 +18,7 @@
#include "SHA1.h"
#include "BigNumber.h"
+#include "Util.h"
#include <cstring>
#include <stdarg.h>
@@ -67,3 +68,10 @@ void SHA1Hash::Finalize(void)
SHA1_Final(mDigest, &mC);
}
+std::string CalculateSHA1Hash(std::string const& content)
+{
+ unsigned char digest[SHA_DIGEST_LENGTH];
+ SHA1((unsigned char*)content.c_str(), content.length(), (unsigned char*)&digest);
+
+ return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH);
+}
diff --git a/src/common/Cryptography/SHA1.h b/src/common/Cryptography/SHA1.h
index 970ab5c0cb9..37ac2cc0166 100644
--- a/src/common/Cryptography/SHA1.h
+++ b/src/common/Cryptography/SHA1.h
@@ -46,5 +46,8 @@ class TC_COMMON_API SHA1Hash
SHA_CTX mC;
uint8 mDigest[SHA_DIGEST_LENGTH];
};
-#endif
+/// Returns the SHA1 hash of the given content as hex string.
+TC_COMMON_API std::string CalculateSHA1Hash(std::string const& content);
+
+#endif
diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h
index 7c889068011..0f83b52f9d0 100644
--- a/src/common/Utilities/Containers.h
+++ b/src/common/Utilities/Containers.h
@@ -118,6 +118,19 @@ namespace Trinity
}
/**
+ * @fn void Trinity::Containers::RandomShuffle(C& container)
+ *
+ * @brief Reorder the elements of the container randomly.
+ *
+ * @param container Container to reorder
+ */
+ template <class C>
+ void RandomShuffle(C& container)
+ {
+ std::shuffle(container.begin(), container.end(), SFMTEngine::Instance());
+ }
+
+ /**
* @fn bool Trinity::Containers::Intersects(Iterator first1, Iterator last1, Iterator first2, Iterator last2)
*
* @brief Checks if two SORTED containers have a common element
diff --git a/src/common/Utilities/StartProcess.cpp b/src/common/Utilities/StartProcess.cpp
new file mode 100644
index 00000000000..1e27b14f18a
--- /dev/null
+++ b/src/common/Utilities/StartProcess.cpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "StartProcess.h"
+
+#include <atomic>
+#include <thread>
+#include <functional>
+
+#include <boost/algorithm/string/join.hpp>
+#include <boost/iostreams/stream.hpp>
+#include <boost/iostreams/copy.hpp>
+#include <boost/iostreams/concepts.hpp>
+#include <boost/iostreams/device/file_descriptor.hpp>
+#include <boost/process.hpp>
+#include <boost/system/system_error.hpp>
+
+#include "Common.h"
+#include "Log.h"
+
+using namespace boost::process;
+using namespace boost::process::initializers;
+using namespace boost::iostreams;
+
+namespace Trinity {
+
+template<typename T>
+class TCLogSink
+{
+ T callback_;
+
+public:
+ typedef char char_type;
+ typedef sink_tag category;
+
+ // Requires a callback type which has a void(std::string) signature
+ TCLogSink(T callback)
+ : callback_(std::move(callback)) { }
+
+ std::streamsize write(const char* str, std::streamsize size)
+ {
+ callback_(std::string(str, size));
+ return size;
+ }
+};
+
+template<typename T>
+auto MakeTCLogSink(T&& callback)
+ -> TCLogSink<typename std::decay<T>::type>
+{
+ return { std::forward<T>(callback) };
+}
+
+template<typename T>
+static int CreateChildProcess(T waiter, std::string const& executable,
+ std::vector<std::string> const& args,
+ std::string const& logger, std::string const& input,
+ bool secure)
+{
+ auto outPipe = create_pipe();
+ auto errPipe = create_pipe();
+
+ Optional<file_descriptor_source> inputSource;
+
+ if (!secure)
+ {
+ TC_LOG_TRACE(logger, "Starting process \"%s\" with arguments: \"%s\".",
+ executable.c_str(), boost::algorithm::join(args, " ").c_str());
+ }
+
+ // Start the child process
+ child c = [&]
+ {
+ if (!input.empty())
+ {
+ inputSource = file_descriptor_source(input);
+
+ // With binding stdin
+ return execute(run_exe(boost::filesystem::absolute(executable)),
+ set_args(args),
+ inherit_env(),
+ bind_stdin(*inputSource),
+ bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)),
+ bind_stderr(file_descriptor_sink(errPipe.sink, close_handle)));
+ }
+ else
+ {
+ // Without binding stdin
+ return execute(run_exe(boost::filesystem::absolute(executable)),
+ set_args(args),
+ inherit_env(),
+ bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)),
+ bind_stderr(file_descriptor_sink(errPipe.sink, close_handle)));
+ }
+ }();
+
+ file_descriptor_source outFd(outPipe.source, close_handle);
+ file_descriptor_source errFd(errPipe.source, close_handle);
+
+ auto outInfo = MakeTCLogSink([&](std::string msg)
+ {
+ TC_LOG_INFO(logger, "%s", msg.c_str());
+ });
+
+ auto outError = MakeTCLogSink([&](std::string msg)
+ {
+ TC_LOG_ERROR(logger, "%s", msg.c_str());
+ });
+
+ copy(outFd, outInfo);
+ copy(errFd, outError);
+
+ // Call the waiter in the current scope to prevent
+ // the streams from closing too early on leaving the scope.
+ int const result = waiter(c);
+
+ if (!secure)
+ {
+ TC_LOG_TRACE(logger, ">> Process \"%s\" finished with return value %i.",
+ executable.c_str(), result);
+ }
+
+ if (inputSource)
+ inputSource->close();
+
+ return result;
+}
+
+int StartProcess(std::string const& executable, std::vector<std::string> const& args,
+ std::string const& logger, std::string input_file, bool secure)
+{
+ return CreateChildProcess([](child& c) -> int
+ {
+ try
+ {
+ return wait_for_exit(c);
+ }
+ catch (...)
+ {
+ return EXIT_FAILURE;
+ }
+ }, executable, args, logger, input_file, secure);
+}
+
+class AsyncProcessResultImplementation
+ : public AsyncProcessResult
+{
+ std::string const executable;
+ std::vector<std::string> const args;
+ std::string const logger;
+ std::string const input_file;
+ bool const is_secure;
+
+ std::atomic<bool> was_terminated;
+
+ // Workaround for missing move support in boost < 1.57
+ Optional<std::shared_ptr<std::future<int>>> result;
+ Optional<std::reference_wrapper<child>> my_child;
+
+public:
+ explicit AsyncProcessResultImplementation(std::string executable_, std::vector<std::string> args_,
+ std::string logger_, std::string input_file_,
+ bool secure)
+ : executable(std::move(executable_)), args(std::move(args_)),
+ logger(std::move(logger_)), input_file(input_file_),
+ is_secure(secure), was_terminated(false) { }
+
+ AsyncProcessResultImplementation(AsyncProcessResultImplementation const&) = delete;
+ AsyncProcessResultImplementation& operator= (AsyncProcessResultImplementation const&) = delete;
+ AsyncProcessResultImplementation(AsyncProcessResultImplementation&&) = delete;
+ AsyncProcessResultImplementation& operator= (AsyncProcessResultImplementation&&) = delete;
+
+ int StartProcess()
+ {
+ ASSERT(!my_child, "Process started already!");
+
+ return CreateChildProcess([&](child& c) -> int
+ {
+ int result;
+ my_child = std::reference_wrapper<child>(c);
+
+ try
+ {
+ result = wait_for_exit(c);
+ }
+ catch (...)
+ {
+ result = EXIT_FAILURE;
+ }
+
+ my_child.reset();
+ return was_terminated ? EXIT_FAILURE : result;
+
+ }, executable, args, logger, input_file, is_secure);
+ }
+
+ void SetFuture(std::future<int> result_)
+ {
+ result = std::make_shared<std::future<int>>(std::move(result_));
+ }
+
+ /// Returns the future which contains the result of the process
+ /// as soon it is finished.
+ std::future<int>& GetFutureResult() override
+ {
+ ASSERT(*result, "The process wasn't started!");
+ return **result;
+ }
+
+ /// Tries to terminate the process
+ void Terminate() override
+ {
+ if (!my_child)
+ {
+ was_terminated = true;
+ try
+ {
+ terminate(my_child->get());
+ }
+ catch(...)
+ {
+ // Do nothing
+ }
+ }
+ }
+};
+
+TC_COMMON_API std::shared_ptr<AsyncProcessResult>
+ StartAsyncProcess(std::string executable, std::vector<std::string> args,
+ std::string logger, std::string input_file, bool secure)
+{
+ auto handle = std::make_shared<AsyncProcessResultImplementation>(
+ std::move(executable), std::move(args), std::move(logger), std::move(input_file), secure);
+
+ handle->SetFuture(std::async(std::launch::async, [handle] { return handle->StartProcess(); }));
+ return handle;
+}
+
+Optional<std::string> SearchExecutableInPath(std::string const& filename)
+{
+ try
+ {
+ auto result = search_path(filename);
+ if (result.empty())
+ return boost::none;
+ else
+ return result;
+ }
+ catch (...)
+ {
+ return boost::none;
+ }
+}
+
+} // namespace Trinity
diff --git a/src/common/Utilities/StartProcess.h b/src/common/Utilities/StartProcess.h
new file mode 100644
index 00000000000..3b380bd4f4e
--- /dev/null
+++ b/src/common/Utilities/StartProcess.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef Process_h__
+#define Process_h__
+
+#include <future>
+#include <memory>
+#include "Common.h"
+
+namespace Trinity {
+
+/// Starts a process with the given arguments and parameters and will block
+/// until the process is finished.
+/// When an input path is given, the file will be routed to the processes stdin.
+/// When the process is marked as secure no arguments are leaked to logs.
+/// Note that most executables expect it's name as the first argument.
+TC_COMMON_API int StartProcess(std::string const& executable, std::vector<std::string> const& args,
+ std::string const& logger, std::string input_file = "",
+ bool secure = false);
+
+/// Platform and library independent representation
+/// of asynchronous process results
+class AsyncProcessResult
+{
+public:
+ virtual ~AsyncProcessResult() { }
+
+ /// Returns the future which contains the result of the process
+ /// as soon it is finished.
+ virtual std::future<int>& GetFutureResult() = 0;
+
+ /// Tries to terminate the process
+ virtual void Terminate() = 0;
+};
+
+/// Starts a process asynchronously with the given arguments and parameters and
+/// returns an AsyncProcessResult immediately which is set, when the process exits.
+/// When an input path is given, the file will be routed to the processes stdin.
+/// When the process is marked as secure no arguments are leaked to logs.
+/// Note that most executables expect it's name as the first argument.
+TC_COMMON_API std::shared_ptr<AsyncProcessResult>
+ StartAsyncProcess(std::string executable, std::vector<std::string> args,
+ std::string logger, std::string input_file = "",
+ bool secure = false);
+
+/// Searches for the given executable in the PATH variable
+/// and returns a present optional when it was found.
+TC_COMMON_API Optional<std::string> SearchExecutableInPath(std::string const& filename);
+
+} // namespace Trinity
+
+#endif // Process_h__
diff --git a/src/common/Utilities/Timer.h b/src/common/Utilities/Timer.h
index cdce08caaf0..f66bb90c98e 100644
--- a/src/common/Utilities/Timer.h
+++ b/src/common/Utilities/Timer.h
@@ -25,9 +25,9 @@ inline uint32 getMSTime()
{
using namespace std::chrono;
- static const system_clock::time_point ApplicationStartTime = system_clock::now();
+ static const steady_clock::time_point ApplicationStartTime = steady_clock::now();
- return uint32(duration_cast<milliseconds>(system_clock::now() - ApplicationStartTime).count());
+ return uint32(duration_cast<milliseconds>(steady_clock::now() - ApplicationStartTime).count());
}
inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp
index a53187ad737..1392900fb9a 100644
--- a/src/server/authserver/Main.cpp
+++ b/src/server/authserver/Main.cpp
@@ -36,12 +36,14 @@
#include "GitRevision.h"
#include "Util.h"
#include <iostream>
+#include <boost/filesystem/path.hpp>
#include <boost/program_options.hpp>
#include <openssl/opensslv.h>
#include <openssl/crypto.h>
using boost::asio::ip::tcp;
using namespace boost::program_options;
+namespace fs = boost::filesystem;
#ifndef _TRINITY_REALM_CONFIG
# define _TRINITY_REALM_CONFIG "authserver.conf"
@@ -69,7 +71,7 @@ void StopDB();
void SignalHandler(const boost::system::error_code& error, int signalNumber);
void KeepDatabaseAliveHandler(const boost::system::error_code& error);
void BanExpiryHandler(boost::system::error_code const& error);
-variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService);
+variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService);
boost::asio::io_service* _ioService;
boost::asio::deadline_timer* _dbPingTimer;
@@ -81,7 +83,7 @@ int main(int argc, char** argv)
{
signal(SIGABRT, &Trinity::AbortHandler);
- std::string configFile = _TRINITY_REALM_CONFIG;
+ auto configFile = fs::absolute(_TRINITY_REALM_CONFIG);
std::string configService;
auto vm = GetConsoleArguments(argc, argv, configFile, configService);
// exit if help or version is enabled
@@ -98,7 +100,9 @@ int main(int argc, char** argv)
#endif
std::string configError;
- if (!sConfigMgr->LoadInitial(configFile, configError))
+ if (!sConfigMgr->LoadInitial(configFile.generic_string(),
+ std::vector<std::string>(argv, argv + argc),
+ configError))
{
printf("Error in config file: %s\n", configError.c_str());
return 1;
@@ -109,7 +113,7 @@ int main(int argc, char** argv)
TC_LOG_INFO("server.authserver", "%s (authserver)", GitRevision::GetFullVersion());
TC_LOG_INFO("server.authserver", "<Ctrl-C> to stop.\n");
- TC_LOG_INFO("server.authserver", "Using configuration file %s.", configFile.c_str());
+ TC_LOG_INFO("server.authserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str());
TC_LOG_INFO("server.authserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
TC_LOG_INFO("server.authserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
@@ -286,13 +290,14 @@ void ServiceStatusWatcher(boost::system::error_code const& error)
}
#endif
-variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService)
+variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService)
{
options_description all("Allowed options");
all.add_options()
("help,h", "print usage message")
("version,v", "print version build info")
- ("config,c", value<std::string>(&configFile)->default_value(_TRINITY_REALM_CONFIG), "use <arg> as configuration file")
+ ("config,c", value<fs::path>(&configFile)->default_value(fs::absolute(_TRINITY_REALM_CONFIG)),
+ "use <arg> as configuration file")
;
#if PLATFORM == PLATFORM_WINDOWS
options_description win("Windows platform specific options");
diff --git a/src/server/authserver/Server/AuthSession.cpp b/src/server/authserver/Server/AuthSession.cpp
index f044e0cea94..43c327ffda1 100644
--- a/src/server/authserver/Server/AuthSession.cpp
+++ b/src/server/authserver/Server/AuthSession.cpp
@@ -820,41 +820,6 @@ bool AuthSession::HandleReconnectProof()
}
}
-tcp::endpoint const GetAddressForClient(Realm const& realm, ip::address const& clientAddr)
-{
- ip::address realmIp;
-
- // Attempt to send best address for client
- if (clientAddr.is_loopback())
- {
- // Try guessing if realm is also connected locally
- if (realm.LocalAddress.is_loopback() || realm.ExternalAddress.is_loopback())
- realmIp = clientAddr;
- else
- {
- // Assume that user connecting from the machine that authserver is located on
- // has all realms available in his local network
- realmIp = realm.LocalAddress;
- }
- }
- else
- {
- if (clientAddr.is_v4() &&
- (clientAddr.to_v4().to_ulong() & realm.LocalSubnetMask.to_v4().to_ulong()) ==
- (realm.LocalAddress.to_v4().to_ulong() & realm.LocalSubnetMask.to_v4().to_ulong()))
- {
- realmIp = realm.LocalAddress;
- }
- else
- realmIp = realm.ExternalAddress;
- }
-
- tcp::endpoint endpoint(realmIp, realm.Port);
-
- // Return external IP
- return endpoint;
-}
-
bool AuthSession::HandleRealmList()
{
TC_LOG_DEBUG("server.authserver", "Entering _HandleRealmList");
diff --git a/src/server/authserver/authserver.conf.dist b/src/server/authserver/authserver.conf.dist
index a97d75b3f57..1d3b48839a8 100644
--- a/src/server/authserver/authserver.conf.dist
+++ b/src/server/authserver/authserver.conf.dist
@@ -179,11 +179,19 @@ LoginDatabaseInfo = "127.0.0.1;3306;trinity;trinity;auth"
# LoginDatabase.WorkerThreads
# Description: The amount of worker threads spawned to handle asynchronous (delayed) MySQL
# statements. Each worker thread is mirrored with its own connection to the
+# MySQL server and their own thread on the MySQL server.
# Default: 1
LoginDatabase.WorkerThreads = 1
#
+# LoginDatabase.SynchThreads
+# Description: The amount of MySQL connections spawned to handle.
+# Default: 1 - (LoginDatabase.WorkerThreads)
+
+LoginDatabase.SynchThreads = 1
+
+#
###################################################################################################
###################################################################################################
diff --git a/src/server/database/CMakeLists.txt b/src/server/database/CMakeLists.txt
index 236586075ee..bd2fa280ad6 100644
--- a/src/server/database/CMakeLists.txt
+++ b/src/server/database/CMakeLists.txt
@@ -52,7 +52,6 @@ add_definitions(-DTRINITY_API_EXPORT_DATABASE)
target_link_libraries(database
PUBLIC
common
- process
mysql)
set_target_properties(database
diff --git a/src/server/database/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h
index d883366237f..59a42096c8e 100644
--- a/src/server/database/Database/DatabaseWorkerPool.h
+++ b/src/server/database/Database/DatabaseWorkerPool.h
@@ -120,7 +120,7 @@ class DatabaseWorkerPool
//! This method should only be used for queries that are only executed once, e.g during startup.
void DirectExecute(const char* sql)
{
- if (!sql)
+ if (Trinity::IsFormatEmptyOrNull(sql))
return;
T* connection = GetFreeConnection();
@@ -175,7 +175,7 @@ class DatabaseWorkerPool
template<typename Format, typename... Args>
QueryResult PQuery(Format&& sql, Args&&... args)
{
- if (!sql)
+ if (Trinity::IsFormatEmptyOrNull(sql))
return QueryResult(nullptr);
return Query(Trinity::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp
index 5f5b519d2b3..0d51f8ed060 100644
--- a/src/server/database/Updater/DBUpdater.cpp
+++ b/src/server/database/Updater/DBUpdater.cpp
@@ -22,19 +22,11 @@
#include "DatabaseLoader.h"
#include "Config.h"
#include "BuiltInConfig.h"
+#include "StartProcess.h"
#include <fstream>
#include <iostream>
#include <unordered_map>
-#include <boost/process.hpp>
-#include <boost/iostreams/stream.hpp>
-#include <boost/iostreams/copy.hpp>
-#include <boost/iostreams/device/file_descriptor.hpp>
-#include <boost/system/system_error.hpp>
-
-using namespace boost::process;
-using namespace boost::process::initializers;
-using namespace boost::iostreams;
std::string DBUpdaterUtil::GetCorrectedMySQLExecutable()
{
@@ -51,22 +43,19 @@ bool DBUpdaterUtil::CheckExecutable()
{
exe.clear();
- try
- {
- exe = search_path("mysql");
- }
- catch (std::runtime_error&)
+ if (auto path = Trinity::SearchExecutableInPath("mysql"))
{
- }
+ exe = std::move(*path);
- if (!exe.empty() && exists(exe))
- {
- // Correct the path to the cli
- corrected_path() = absolute(exe).generic_string();
- return true;
+ if (!exe.empty() && exists(exe))
+ {
+ // Correct the path to the cli
+ corrected_path() = absolute(exe).generic_string();
+ return true;
+ }
}
- TC_LOG_FATAL("sql.updates", "Didn't find executeable mysql binary at \'%s\' or in path, correct the path in the *.conf (\"Updates.MySqlCLIPath\").",
+ TC_LOG_FATAL("sql.updates", "Didn't find executeable mysql binary at \'%s\' or in path, correct the path in the *.conf (\"MySQLExecutable\").",
absolute(exe).generic_string().c_str());
return false;
@@ -387,44 +376,9 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
if (!database.empty())
args.push_back(database);
- // ToDo: use the existing query in memory as virtual file if possible
- file_descriptor_source source(path);
-
- uint32 ret;
- try
- {
- boost::process::pipe outPipe = create_pipe();
- boost::process::pipe errPipe = create_pipe();
-
- child c = execute(run_exe(
- boost::filesystem::absolute(DBUpdaterUtil::GetCorrectedMySQLExecutable()).generic_string()),
- set_args(args), bind_stdin(source), throw_on_error(),
- bind_stdout(file_descriptor_sink(outPipe.sink, close_handle)),
- bind_stderr(file_descriptor_sink(errPipe.sink, close_handle)));
-
- file_descriptor_source mysqlOutfd(outPipe.source, close_handle);
- file_descriptor_source mysqlErrfd(errPipe.source, close_handle);
-
- stream<file_descriptor_source> mysqlOutStream(mysqlOutfd);
- stream<file_descriptor_source> mysqlErrStream(mysqlErrfd);
-
- std::stringstream out;
- std::stringstream err;
-
- copy(mysqlOutStream, out);
- copy(mysqlErrStream, err);
-
- TC_LOG_INFO("sql.updates", "%s", out.str().c_str());
- TC_LOG_ERROR("sql.updates", "%s", err.str().c_str());
-
- ret = wait_for_exit(c);
- }
- catch (boost::system::system_error&)
- {
- ret = EXIT_FAILURE;
- }
-
- source.close();
+ // Invokes a mysql process which doesn't leak credentials to logs
+ int const ret = Trinity::StartProcess(DBUpdaterUtil::GetCorrectedMySQLExecutable(), args,
+ "sql.updates", path.generic_string(), true);
if (ret != EXIT_SUCCESS)
{
diff --git a/src/server/database/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp
index 6f67867c52b..7dc0a307ca2 100644
--- a/src/server/database/Updater/UpdateFetcher.cpp
+++ b/src/server/database/Updater/UpdateFetcher.cpp
@@ -18,6 +18,7 @@
#include "UpdateFetcher.h"
#include "Log.h"
#include "Util.h"
+#include "SHA1.h"
#include <fstream>
#include <chrono>
@@ -25,7 +26,6 @@
#include <sstream>
#include <exception>
#include <unordered_map>
-#include <openssl/sha.h>
using namespace boost::filesystem;
@@ -209,9 +209,8 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks,
}
}
- // Calculate hash
- std::string const hash =
- CalculateHash(ReadSQLUpdate(availableQuery.first));
+ // Calculate a Sha1 hash based on query content.
+ std::string const hash = CalculateSHA1Hash(ReadSQLUpdate(availableQuery.first));
UpdateMode mode = MODE_APPLY;
@@ -334,15 +333,6 @@ UpdateResult UpdateFetcher::Update(bool const redundancyChecks,
return UpdateResult(importedUpdates, countRecentUpdates, countArchivedUpdates);
}
-std::string UpdateFetcher::CalculateHash(std::string const& query) const
-{
- // Calculate a Sha1 hash based on query content.
- unsigned char digest[SHA_DIGEST_LENGTH];
- SHA1((unsigned char*)query.c_str(), query.length(), (unsigned char*)&digest);
-
- return ByteArrayToHexStr(digest, SHA_DIGEST_LENGTH);
-}
-
uint32 UpdateFetcher::Apply(Path const& path) const
{
using Time = std::chrono::high_resolution_clock;
diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h
index a17658818ce..cabc3c2fce3 100644
--- a/src/server/database/Updater/UpdateFetcher.h
+++ b/src/server/database/Updater/UpdateFetcher.h
@@ -112,7 +112,6 @@ private:
AppliedFileStorage ReceiveAppliedFiles() const;
std::string ReadSQLUpdate(Path const& file) const;
- std::string CalculateHash(std::string const& query) const;
uint32 Apply(Path const& path) const;
diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp
index aafde3c1d9a..3ed2f927645 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.cpp
+++ b/src/server/game/AI/CoreAI/PassiveAI.cpp
@@ -58,6 +58,12 @@ void PossessedAI::KilledUnit(Unit* victim)
victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
}
+void PossessedAI::OnCharmed(bool /*apply*/)
+{
+ me->NeedChangeAI = true;
+ me->IsAIEnabled = false;
+}
+
void CritterAI::DamageTaken(Unit* /*done_by*/, uint32&)
{
if (!me->HasUnitState(UNIT_STATE_FLEEING))
diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h
index 5a6dba7046d..9ca9e75bd9f 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.h
+++ b/src/server/game/AI/CoreAI/PassiveAI.h
@@ -46,6 +46,8 @@ class TC_GAME_API PossessedAI : public CreatureAI
void JustDied(Unit*) override;
void KilledUnit(Unit* victim) override;
+ void OnCharmed(bool /*apply*/) override;
+
static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
};
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index bbf4f4e02ce..2abe20f0ae6 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -245,9 +245,9 @@ void PetAI::UpdateAI(uint32 diff)
}
// Update speed as needed to prevent dropping too far behind and despawning
- me->UpdateSpeed(MOVE_RUN, true);
- me->UpdateSpeed(MOVE_WALK, true);
- me->UpdateSpeed(MOVE_FLIGHT, true);
+ me->UpdateSpeed(MOVE_RUN);
+ me->UpdateSpeed(MOVE_WALK);
+ me->UpdateSpeed(MOVE_FLIGHT);
}
@@ -588,6 +588,12 @@ void PetAI::ReceiveEmote(Player* player, uint32 emote)
}
}
+void PetAI::OnCharmed(bool /*apply*/)
+{
+ me->NeedChangeAI = true;
+ me->IsAIEnabled = false;
+}
+
void PetAI::ClearCharmInfoFlags()
{
// Quick access to set all flags to FALSE
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index 3ad34047b01..93ee6c41ece 100644
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -49,6 +49,8 @@ class TC_GAME_API PetAI : public CreatureAI
void MoveInLineOfSight_Safe(Unit* /*who*/) { } // CreatureAI interferes with returning pets
void EnterEvadeMode(EvadeReason /*why*/) override { } // For fleeing, pets don't use this type of Evade mechanic
+ void OnCharmed(bool /*apply*/) override;
+
private:
bool _isVisible(Unit*) const;
bool _needToStop(void);
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index 9a3ce3ffe43..d52306b8a2e 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -29,11 +29,13 @@
#include "Language.h"
//Disable CreatureAI when charmed
-void CreatureAI::OnCharmed(bool /*apply*/)
+void CreatureAI::OnCharmed(bool apply)
{
- //me->IsAIEnabled = !apply;*/
- me->NeedChangeAI = true;
- me->IsAIEnabled = false;
+ if (apply)
+ {
+ me->NeedChangeAI = true;
+ me->IsAIEnabled = false;
+ }
}
AISpellInfoType* UnitAI::AISpellInfo;
@@ -257,9 +259,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
if (!me->IsAlive())
return false;
- // don't remove vehicle auras, passengers aren't supposed to drop off the vehicle
- // don't remove clone caster on evade (to be verified)
- me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER);
+ me->RemoveAurasOnEvade();
// sometimes bosses stuck in combat?
me->DeleteThreatList();
@@ -276,11 +276,11 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/)
return true;
}
-const uint32 BOUNDARY_VISUALIZE_CREATURE = 15425;
-const float BOUNDARY_VISUALIZE_CREATURE_SCALE = 0.25f;
-const int8 BOUNDARY_VISUALIZE_STEP_SIZE = 1;
-const int32 BOUNDARY_VISUALIZE_FAILSAFE_LIMIT = 750;
-const float BOUNDARY_VISUALIZE_SPAWN_HEIGHT = 5.0f;
+static const uint32 BOUNDARY_VISUALIZE_CREATURE = 15425;
+static const float BOUNDARY_VISUALIZE_CREATURE_SCALE = 0.25f;
+static const int8 BOUNDARY_VISUALIZE_STEP_SIZE = 1;
+static const int32 BOUNDARY_VISUALIZE_FAILSAFE_LIMIT = 750;
+static const float BOUNDARY_VISUALIZE_SPAWN_HEIGHT = 5.0f;
int32 CreatureAI::VisualizeBoundary(uint32 duration, Unit* owner, bool fill) const
{
typedef std::pair<int32, int32> coordinate;
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp
index 680ecfb9414..12bfb86251b 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.cpp
+++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp
@@ -177,7 +177,7 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 /*diff*/)
for (Player::AuraEffectList::const_iterator iter = auras.begin(); iter != auras.end(); ++iter)
if ((*iter)->GetCasterGUID() == charmer->GetGUID() && (*iter)->GetBase()->IsPermanent())
{
- me->Kill(me);
+ me->KillSelf();
return;
}
}
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 95d52a45681..60df4fe6d5a 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -413,7 +413,7 @@ void SmartAI::EnterEvadeMode(EvadeReason /*why*/)
if (!me->IsAlive() || me->IsInEvadeMode())
return;
- me->RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER);
+ me->RemoveAurasOnEvade();
me->AddUnitState(UNIT_STATE_EVADE);
_EnterEvadeMode();
@@ -648,8 +648,8 @@ void SmartAI::OnCharmed(bool apply)
{
GetScript()->ProcessEventsFor(SMART_EVENT_CHARMED, NULL, 0, 0, apply);
- if (!apply && !me->IsInEvadeMode() && me->GetCharmerGUID())
- if (Unit* charmer = ObjectAccessor::GetUnit(*me, me->GetCharmerGUID()))
+ if (!apply && !me->IsInEvadeMode())
+ if (Unit* charmer = me->GetCharmer())
AttackStart(charmer);
}
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index 9db36c76bb4..a18f0a6574b 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -3239,29 +3239,28 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (!me)
return;
- WorldObject* creature = NULL;
+ Creature* creature = nullptr;
if (e.event.distance.guid != 0)
{
creature = FindCreatureNear(me, e.event.distance.guid);
-
if (!creature)
return;
- if (!me->IsInRange(creature, 0, (float)e.event.distance.dist))
+ if (!me->IsInRange(creature, 0, static_cast<float>(e.event.distance.dist)))
return;
}
else if (e.event.distance.entry != 0)
{
std::list<Creature*> list;
- me->GetCreatureListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
+ me->GetCreatureListWithEntryInGrid(list, e.event.distance.entry, static_cast<float>(e.event.distance.dist));
if (!list.empty())
creature = list.front();
}
if (creature)
- ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat);
+ ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat, creature);
break;
}
@@ -3270,29 +3269,28 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui
if (!me)
return;
- WorldObject* gameobject = NULL;
+ GameObject* gameobject = nullptr;
if (e.event.distance.guid != 0)
{
gameobject = FindGameObjectNear(me, e.event.distance.guid);
-
if (!gameobject)
return;
- if (!me->IsInRange(gameobject, 0, (float)e.event.distance.dist))
+ if (!me->IsInRange(gameobject, 0, static_cast<float>(e.event.distance.dist)))
return;
}
else if (e.event.distance.entry != 0)
{
std::list<GameObject*> list;
- me->GetGameObjectListWithEntryInGrid(list, e.event.distance.entry, (float)e.event.distance.dist);
+ me->GetGameObjectListWithEntryInGrid(list, e.event.distance.entry, static_cast<float>(e.event.distance.dist));
if (!list.empty())
gameobject = list.front();
}
if (gameobject)
- ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat);
+ ProcessTimedAction(e, e.event.distance.repeat, e.event.distance.repeat, nullptr, 0, 0, false, nullptr, gameobject);
break;
}
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index ebc814405bf..11c2635da33 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -646,13 +646,20 @@ void AchievementMgr::SendAchievementEarned(AchievementEntry const* achievement)
if (achievement->flags & (ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH))
{
+ uint32 team = GetPlayer()->GetTeam();
+
// broadcast realm first reached
WorldPacket data(SMSG_SERVER_FIRST_ACHIEVEMENT, GetPlayer()->GetName().size() + 1 + 8 + 4 + 4);
data << GetPlayer()->GetName();
data << uint64(GetPlayer()->GetGUID());
data << uint32(achievement->ID);
- data << uint32(0); // 1=link supplied string as player name, 0=display plain string
- sWorld->SendGlobalMessage(&data);
+
+ std::size_t linkTypePos = data.wpos();
+ data << uint32(1); // display name as clickable link in chat
+ sWorld->SendGlobalMessage(&data, nullptr, team);
+
+ data.put<uint32>(linkTypePos, 0); // display name as plain string in chat
+ sWorld->SendGlobalMessage(&data, nullptr, team == ALLIANCE ? HORDE : ALLIANCE);
}
// if player is in world he can tell his friends about new achievement
else if (GetPlayer()->IsInWorld())
@@ -1533,7 +1540,7 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
//! Since no common attributes were found, (not even in titleRewardFlags field)
//! we explicitly check by ID. Maybe in the future we could move the achievement_reward
//! condition fields to the condition system.
- if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->GetByteValue(PLAYER_BYTES_3, 0) : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)])
+ if (uint32 titleId = reward->titleId[achievement->ID == 1793 ? GetPlayer()->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER) : (GetPlayer()->GetTeam() == ALLIANCE ? 0 : 1)])
if (CharTitlesEntry const* titleEntry = sCharTitlesStore.LookupEntry(titleId))
GetPlayer()->SetTitle(titleEntry);
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
index 5acb56b5173..17b104eb388 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.cpp
@@ -582,13 +582,13 @@ void AuctionBotSeller::LoadSellerValues(SellerConfiguration& config)
break;
}
- config.SetPriceRatioPerQuality(AUCTION_QUALITY_GRAY, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO) / 100);
- config.SetPriceRatioPerQuality(AUCTION_QUALITY_WHITE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO) / 100);
- config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREEN, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO) / 100);
- config.SetPriceRatioPerQuality(AUCTION_QUALITY_BLUE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO) / 100);
- config.SetPriceRatioPerQuality(AUCTION_QUALITY_PURPLE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO) / 100);
- config.SetPriceRatioPerQuality(AUCTION_QUALITY_ORANGE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO) / 100);
- config.SetPriceRatioPerQuality(AUCTION_QUALITY_YELLOW, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO) / 100);
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_GRAY, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GRAY_PRICE_RATIO));
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_WHITE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_WHITE_PRICE_RATIO));
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_GREEN, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_GREEN_PRICE_RATIO));
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_BLUE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_BLUE_PRICE_RATIO));
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_PURPLE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_PURPLE_PRICE_RATIO));
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_ORANGE, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_ORANGE_PRICE_RATIO));
+ config.SetPriceRatioPerQuality(AUCTION_QUALITY_YELLOW, PriceRatio * sAuctionBotConfig->GetConfig(CONFIG_AHBOT_ITEM_YELLOW_PRICE_RATIO));
config.SetPriceRatioPerClass(ITEM_CLASS_CONSUMABLE, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONSUMABLE_PRICE_RATIO));
config.SetPriceRatioPerClass(ITEM_CLASS_CONTAINER, sAuctionBotConfig->GetConfig(CONFIG_AHBOT_CLASS_CONTAINER_PRICE_RATIO));
@@ -701,10 +701,10 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf
{
uint32 classRatio = config.GetPriceRatioPerClass(ItemClass(itemProto->Class));
uint32 qualityRatio = config.GetPriceRatioPerQuality(AuctionQuality(itemProto->Quality));
- uint32 priceRatio = (classRatio * qualityRatio) / 100;
+ float priceRatio = (classRatio * qualityRatio) / 10000.0f;
- uint32 buyPrice = itemProto->BuyPrice;
- uint32 sellPrice = itemProto->SellPrice;
+ float buyPrice = itemProto->BuyPrice;
+ float sellPrice = itemProto->SellPrice;
if (buyPrice == 0)
{
@@ -712,11 +712,11 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf
buyPrice = sellPrice * GetSellModifier(itemProto);
else
{
- uint32 divisor = ((itemProto->Class == 2 || itemProto->Class == 4) ? 284 : 80);
- uint32 tempLevel = (itemProto->ItemLevel == 0 ? 1 : itemProto->ItemLevel);
- uint32 tempQuality = (itemProto->Quality == 0 ? 1 : itemProto->Quality);
+ float divisor = ((itemProto->Class == ITEM_CLASS_WEAPON || itemProto->Class == ITEM_CLASS_ARMOR) ? 284.0f : 80.0f);
+ float tempLevel = (itemProto->ItemLevel == 0 ? 1.0f : itemProto->ItemLevel);
+ float tempQuality = (itemProto->Quality == 0 ? 1.0f : itemProto->Quality);
- buyPrice = tempLevel * tempQuality * GetBuyModifier(itemProto)* tempLevel / divisor;
+ buyPrice = tempLevel * tempQuality * static_cast<float>(GetBuyModifier(itemProto))* tempLevel / divisor;
}
}
@@ -726,14 +726,15 @@ void AuctionBotSeller::SetPricesOfItem(ItemTemplate const* itemProto, SellerConf
if (sAuctionBotConfig->GetConfig(CONFIG_AHBOT_BUYPRICE_SELLER))
buyPrice = sellPrice;
- uint32 basePrice = (buyPrice * stackCount * priceRatio) / (itemProto->Class == 6 ? 200 : itemProto->BuyCount) / 100;
- uint32 range = basePrice * 0.04;
+ float basePriceFloat = (buyPrice * stackCount * priceRatio) / (itemProto->Class == 6 ? 200.0f : static_cast<float>(itemProto->BuyCount)) / 100.0f;
+ float range = basePriceFloat * 0.04f;
- buyp = urand(basePrice - range, basePrice + range) + 1;
-
- basePrice = buyp * .5;
+ buyp = static_cast<uint32>(frand(basePriceFloat - range, basePriceFloat + range) + 0.5f);
+ if (buyp == 0)
+ buyp = 1;
+ uint32 basePrice = buyp * .5;
range = buyp * .4;
- bidp = urand(basePrice - range, basePrice + range) + 1;
+ bidp = urand(static_cast<uint32>(basePrice - range + 0.5f), static_cast<uint32>(basePrice + range + 0.5f)) + 1;
}
// Determines the stack size to use for the item
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index 60e86093f89..239e59d6dbb 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -23,27 +23,36 @@ GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
add_definitions(-DTRINITY_API_EXPORT_GAME)
-add_library(game
- ${PRIVATE_PCH_SOURCE}
- ${PRIVATE_SOURCES}
-)
-
CollectIncludeDirectories(
${CMAKE_CURRENT_SOURCE_DIR}
PUBLIC_INCLUDES
# Exclude
${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders)
+# Provide an interface target for the game project to allow
+# dependent projects to build meanwhile.
+add_library(game-interface INTERFACE)
+
+target_include_directories(game-interface
+ INTERFACE
+ ${PUBLIC_INCLUDES})
+
+target_link_libraries(game-interface
+ INTERFACE
+ shared
+ Detour)
+
+add_library(game
+ ${PRIVATE_PCH_SOURCE}
+ ${PRIVATE_SOURCES})
+
target_include_directories(game
- PUBLIC
- ${PUBLIC_INCLUDES}
PRIVATE
${CMAKE_CURRENT_BINARY_DIR})
target_link_libraries(game
PUBLIC
- shared
- Detour
+ game-interface
PRIVATE
efsw)
diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp
index f0e98ee8c1f..ec90a5f7efb 100644
--- a/src/server/game/Chat/Chat.cpp
+++ b/src/server/game/Chat/Chat.cpp
@@ -32,18 +32,19 @@
#include "ScriptMgr.h"
#include "ChatLink.h"
-bool ChatHandler::load_command_table = true;
+// Lazy loading of the command table cache from commands and the
+// ScriptMgr should be thread safe since the player commands,
+// cli commands and ScriptMgr updates are all dispatched one after
+// one inside the world update loop.
+static Optional<std::vector<ChatCommand>> commandTableCache;
std::vector<ChatCommand> const& ChatHandler::getCommandTable()
{
- static std::vector<ChatCommand> commandTableCache;
-
- if (LoadCommandTable())
+ if (!commandTableCache)
{
- SetLoadCommandTable(false);
-
- std::vector<ChatCommand> cmds = sScriptMgr->GetChatCommands();
- commandTableCache.swap(cmds);
+ // We need to initialize this at top since SetDataForCommandInTable
+ // calls getCommandTable() recursively.
+ commandTableCache = sScriptMgr->GetChatCommands();
PreparedStatement* stmt = WorldDatabase.GetPreparedStatement(WORLD_SEL_COMMANDS);
PreparedQueryResult result = WorldDatabase.Query(stmt);
@@ -54,13 +55,18 @@ std::vector<ChatCommand> const& ChatHandler::getCommandTable()
Field* fields = result->Fetch();
std::string name = fields[0].GetString();
- SetDataForCommandInTable(commandTableCache, name.c_str(), fields[1].GetUInt16(), fields[2].GetString(), name);
+ SetDataForCommandInTable(*commandTableCache, name.c_str(), fields[1].GetUInt16(), fields[2].GetString(), name);
}
while (result->NextRow());
}
}
- return commandTableCache;
+ return *commandTableCache;
+}
+
+void ChatHandler::invalidateCommandTable()
+{
+ commandTableCache.reset();
}
char const* ChatHandler::GetTrinityString(uint32 entry) const
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index a061ff63b00..1c9368275ad 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -96,6 +96,7 @@ class TC_GAME_API ChatHandler
bool ParseCommands(const char* text);
static std::vector<ChatCommand> const& getCommandTable();
+ static void invalidateCommandTable();
bool isValidChatMessage(const char* msg);
void SendGlobalSysMessage(const char *str);
@@ -143,8 +144,6 @@ class TC_GAME_API ChatHandler
GameObject* GetObjectGlobalyWithGuidOrNearWithDbGuid(ObjectGuid::LowType lowguid, uint32 entry);
bool HasSentErrorMessage() const { return sentErrorMessage; }
void SetSentErrorMessage(bool val){ sentErrorMessage = val; }
- static bool LoadCommandTable() { return load_command_table; }
- static void SetLoadCommandTable(bool val) { load_command_table = val; }
bool ShowHelpForCommand(std::vector<ChatCommand> const& table, const char* cmd);
protected:
@@ -157,7 +156,6 @@ class TC_GAME_API ChatHandler
WorldSession* m_session; // != NULL for chat command call and NULL for CLI command
// common global flag
- static bool load_command_table;
bool sentErrorMessage;
};
diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp
index 0e9b50d64c5..5ede70da2a3 100644
--- a/src/server/game/DataStores/DBCStores.cpp
+++ b/src/server/game/DataStores/DBCStores.cpp
@@ -27,6 +27,9 @@
#include <boost/regex.hpp>
#include <map>
+#include <fstream>
+#include <iostream>
+#include <iomanip>
typedef std::map<uint16, uint32> AreaFlagByAreaID;
typedef std::map<uint32, uint32> AreaFlagByMapID;
@@ -73,6 +76,7 @@ DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt);
+DBCStorage <CinematicCameraEntry> sCinematicCameraStore(CinematicCameraEntryfmt);
DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore(CinematicSequencesEntryfmt);
DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore(CreatureDisplayInfoExtrafmt);
@@ -217,6 +221,8 @@ DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt);
DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore(WorldMapOverlayEntryfmt);
DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt);
+std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore;
+
typedef std::list<std::string> StoreProblemList;
uint32 DBCFileCount = 0;
@@ -311,6 +317,7 @@ void LoadDBCStores(const std::string& dataPath)
LoadDBC(availableDbcLocales, bad_dbc_files, sChatChannelsStore, dbcPath, "ChatChannels.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sChrClassesStore, dbcPath, "ChrClasses.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sChrRacesStore, dbcPath, "ChrRaces.dbc");
+ LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicCameraStore, dbcPath, "CinematicCamera.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sCinematicSequencesStore, dbcPath, "CinematicSequences.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoStore, dbcPath, "CreatureDisplayInfo.dbc");
LoadDBC(availableDbcLocales, bad_dbc_files, sCreatureDisplayInfoExtraStore, dbcPath, "CreatureDisplayInfoExtra.dbc");
@@ -717,10 +724,250 @@ void LoadDBCStores(const std::string& dataPath)
exit(1);
}
+ LoadM2Cameras(dataPath);
+
TC_LOG_INFO("server.loading", ">> Initialized %d data stores in %u ms", DBCFileCount, GetMSTimeDiffToNow(oldMSTime));
}
+// Convert the geomoetry from a spline value, to an actual WoW XYZ
+G3D::Vector3 TranslateLocation(G3D::Vector4 const* DBCPosition, G3D::Vector3 const* basePosition, G3D::Vector3 const* splineVector)
+{
+ G3D::Vector3 work;
+ float x = basePosition->x + splineVector->x;
+ float y = basePosition->y + splineVector->y;
+ float z = basePosition->z + splineVector->z;
+ float const distance = sqrt((x * x) + (y * y));
+ float angle = std::atan2(x, y) - DBCPosition->w;
+
+ if (angle < 0)
+ angle += 2 * float(M_PI);
+
+ work.x = DBCPosition->x + (distance * sin(angle));
+ work.y = DBCPosition->y + (distance * cos(angle));
+ work.z = DBCPosition->z + z;
+ return work;
+}
+
+// Number of cameras not used. Multiple cameras never used in 3.3.5
+bool readCamera(M2Camera const* cam, uint32 buffSize, M2Header const* header, CinematicCameraEntry const* dbcentry)
+{
+ char const* buffer = reinterpret_cast<char const*>(header);
+
+ FlyByCameraCollection cameras;
+ FlyByCameraCollection targetcam;
+
+ G3D::Vector4 DBCData;
+ DBCData.x = dbcentry->base_x;
+ DBCData.y = dbcentry->base_y;
+ DBCData.z = dbcentry->base_z;
+ DBCData.w = dbcentry->base_o;
+
+ // Read target locations, only so that we can calculate orientation
+ for (uint32 k = 0; k < cam->target_positions.timestamps.number; ++k)
+ {
+ // Extract Target positions
+ if (cam->target_positions.timestamps.offset_elements + sizeof(M2Array) > buffSize)
+ return false;
+ M2Array const* targTsArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.timestamps.offset_elements);
+ if (targTsArray->offset_elements + sizeof(uint32) > buffSize || cam->target_positions.values.offset_elements + sizeof(M2Array) > buffSize)
+ return false;
+ uint32 const* targTimestamps = reinterpret_cast<uint32 const*>(buffer + targTsArray->offset_elements);
+ M2Array const* targArray = reinterpret_cast<M2Array const*>(buffer + cam->target_positions.values.offset_elements);
+
+ if (targArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
+ return false;
+ M2SplineKey<G3D::Vector3> const* targPositions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + targArray->offset_elements);
+
+ // Read the data for this set
+ uint32 currPos = targArray->offset_elements;
+ for (uint32 i = 0; i < targTsArray->number; ++i)
+ {
+ if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
+ return false;
+ // Translate co-ordinates
+ G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->target_position_base, &targPositions->p0);
+
+ // Add to vector
+ FlyByCamera thisCam;
+ thisCam.timeStamp = targTimestamps[i];
+ thisCam.locations.x = newPos.x;
+ thisCam.locations.y = newPos.y;
+ thisCam.locations.z = newPos.z;
+ thisCam.locations.w = 0.0f;
+ targetcam.push_back(thisCam);
+ targPositions++;
+ currPos += sizeof(M2SplineKey<G3D::Vector3>);
+ }
+ }
+
+ // Read camera positions and timestamps (translating first position of 3 only, we don't need to translate the whole spline)
+ for (uint32 k = 0; k < cam->positions.timestamps.number; ++k)
+ {
+ // Extract Camera positions for this set
+ if (cam->positions.timestamps.offset_elements + sizeof(M2Array) > buffSize)
+ return false;
+ M2Array const* posTsArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.timestamps.offset_elements);
+ if (posTsArray->offset_elements + sizeof(uint32) > buffSize || cam->positions.values.offset_elements + sizeof(M2Array) > buffSize)
+ return false;
+ uint32 const* posTimestamps = reinterpret_cast<uint32 const*>(buffer + posTsArray->offset_elements);
+ M2Array const* posArray = reinterpret_cast<M2Array const*>(buffer + cam->positions.values.offset_elements);
+ if (posArray->offset_elements + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
+ return false;
+ M2SplineKey<G3D::Vector3> const* positions = reinterpret_cast<M2SplineKey<G3D::Vector3> const*>(buffer + posArray->offset_elements);
+
+ // Read the data for this set
+ uint32 currPos = posArray->offset_elements;
+ for (uint32 i = 0; i < posTsArray->number; ++i)
+ {
+ if (currPos + sizeof(M2SplineKey<G3D::Vector3>) > buffSize)
+ return false;
+ // Translate co-ordinates
+ G3D::Vector3 newPos = TranslateLocation(&DBCData, &cam->position_base, &positions->p0);
+
+ // Add to vector
+ FlyByCamera thisCam;
+ thisCam.timeStamp = posTimestamps[i];
+ thisCam.locations.x = newPos.x;
+ thisCam.locations.y = newPos.y;
+ thisCam.locations.z = newPos.z;
+
+ if (targetcam.size() > 0)
+ {
+ // Find the target camera before and after this camera
+ FlyByCamera lastTarget;
+ FlyByCamera nextTarget;
+
+ // Pre-load first item
+ lastTarget = targetcam[0];
+ nextTarget = targetcam[0];
+ for (uint32 j = 0; j < targetcam.size(); ++j)
+ {
+ nextTarget = targetcam[j];
+ if (targetcam[j].timeStamp > posTimestamps[i])
+ break;
+
+ lastTarget = targetcam[j];
+ }
+
+ float x = lastTarget.locations.x;
+ float y = lastTarget.locations.y;
+ float z = lastTarget.locations.z;
+
+ // Now, the timestamps for target cam and position can be different. So, if they differ we interpolate
+ if (lastTarget.timeStamp != posTimestamps[i])
+ {
+ uint32 timeDiffTarget = nextTarget.timeStamp - lastTarget.timeStamp;
+ uint32 timeDiffThis = posTimestamps[i] - lastTarget.timeStamp;
+ float xDiff = nextTarget.locations.x - lastTarget.locations.x;
+ float yDiff = nextTarget.locations.y - lastTarget.locations.y;
+ float zDiff = nextTarget.locations.z - lastTarget.locations.z;
+ x = lastTarget.locations.x + (xDiff * (float(timeDiffThis) / float(timeDiffTarget)));
+ y = lastTarget.locations.y + (yDiff * (float(timeDiffThis) / float(timeDiffTarget)));
+ z = lastTarget.locations.z + (zDiff * (float(timeDiffThis) / float(timeDiffTarget)));
+ }
+ float xDiff = x - thisCam.locations.x;
+ float yDiff = y - thisCam.locations.y;
+ thisCam.locations.w = std::atan2(yDiff, xDiff);
+
+ if (thisCam.locations.w < 0)
+ thisCam.locations.w += 2 * float(M_PI);
+ }
+
+ cameras.push_back(thisCam);
+ positions++;
+ currPos += sizeof(M2SplineKey<G3D::Vector3>);
+ }
+ }
+
+ sFlyByCameraStore[dbcentry->id] = cameras;
+ return true;
+}
+
+void LoadM2Cameras(const std::string& dataPath)
+{
+ sFlyByCameraStore.clear();
+ TC_LOG_INFO("server.loading", ">> Loading Cinematic Camera files");
+
+ uint32 oldMSTime = getMSTime();
+ for (uint32 i = 0; i < sCinematicCameraStore.GetNumRows(); ++i)
+ {
+ if (CinematicCameraEntry const* dbcentry = sCinematicCameraStore.LookupEntry(i))
+ {
+ std::string filename = dataPath.c_str();
+ filename.append(dbcentry->filename);
+
+ // Replace slashes
+ size_t loc = filename.find("\\");
+ while (loc != std::string::npos)
+ {
+ filename.replace(loc, 1, "/");
+ loc = filename.find("\\");
+ }
+
+ // Replace mdx to .m2
+ loc = filename.find(".mdx");
+ if (loc != std::string::npos)
+ filename.replace(loc, 4, ".m2");
+
+ std::ifstream m2file(filename.c_str(), std::ios::in | std::ios::binary);
+ if (!m2file.is_open())
+ continue;
+
+ // Get file size
+ m2file.seekg(0, std::ios::end);
+ std::streamoff const fileSize = m2file.tellg();
+
+ // Reject if not at least the size of the header
+ if (static_cast<uint32 const>(fileSize) < sizeof(M2Header))
+ {
+ TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File is smaller than header size", filename.c_str());
+ m2file.close();
+ continue;
+ }
+
+ // Read 4 bytes (signature)
+ m2file.seekg(0, std::ios::beg);
+ char fileCheck[5];
+ m2file.read(fileCheck, 4);
+ fileCheck[4] = 0;
+
+ // Check file has correct magic (MD20)
+ if (strcmp(fileCheck, "MD20"))
+ {
+ TC_LOG_ERROR("server.loading", "Camera file %s is damaged. File identifier not found", filename.c_str());
+ m2file.close();
+ continue;
+ }
+
+ // Now we have a good file, read it all into a vector of char's, then close the file.
+ std::vector<char> buffer(fileSize);
+ m2file.seekg(0, std::ios::beg);
+ if (!m2file.read(buffer.data(), fileSize))
+ {
+ m2file.close();
+ continue;
+ }
+ m2file.close();
+
+ // Read header
+ M2Header const* header = reinterpret_cast<M2Header const*>(buffer.data());
+
+ if (header->ofsCameras + sizeof(M2Camera) > static_cast<uint32 const>(fileSize))
+ {
+ TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.c_str());
+ continue;
+ }
+
+ // Get camera(s) - Main header, then dump them.
+ M2Camera const* cam = reinterpret_cast<M2Camera const*>(buffer.data() + header->ofsCameras);
+ if (!readCamera(cam, fileSize, header, dbcentry))
+ TC_LOG_ERROR("server.loading", "Camera file %s is damaged. Camera references position beyond file end", filename.c_str());
+ }
+ }
+ TC_LOG_INFO("server.loading", ">> Loaded %u cinematic waypoint sets in %u ms", (uint32)sFlyByCameraStore.size(), GetMSTimeDiffToNow(oldMSTime));
+}
+
SimpleFactionsList const* GetFactionTeamList(uint32 faction)
{
FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction);
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index beb0bb514cc..6cad13fdf9a 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -27,6 +27,8 @@
#include <list>
typedef std::list<uint32> SimpleFactionsList;
+typedef std::vector<FlyByCamera> FlyByCameraCollection;
+
TC_GAME_API SimpleFactionsList const* GetFactionTeamList(uint32 faction);
TC_GAME_API char* GetPetName(uint32 petfamily, uint32 dbclang);
@@ -96,6 +98,7 @@ TC_GAME_API extern DBCStorage <CharSectionsEntry> sCharSectionsStore;
TC_GAME_API extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
TC_GAME_API extern DBCStorage <ChrClassesEntry> sChrClassesStore;
TC_GAME_API extern DBCStorage <ChrRacesEntry> sChrRacesStore;
+TC_GAME_API extern DBCStorage <CinematicCameraEntry> sCinematicCameraStore;
TC_GAME_API extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore;
TC_GAME_API extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
TC_GAME_API extern DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore;
@@ -193,7 +196,9 @@ TC_GAME_API extern DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore;
//TC_GAME_API extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates
TC_GAME_API extern DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore;
TC_GAME_API extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore;
+TC_GAME_API extern std::unordered_map<uint32, FlyByCameraCollection> sFlyByCameraStore;
TC_GAME_API void LoadDBCStores(const std::string& dataPath);
+TC_GAME_API void LoadM2Cameras(const std::string& dataPath);
#endif
diff --git a/src/server/game/DataStores/DBCStructure.h b/src/server/game/DataStores/DBCStructure.h
index b5dc4489148..51b3dcbd38b 100644
--- a/src/server/game/DataStores/DBCStructure.h
+++ b/src/server/game/DataStores/DBCStructure.h
@@ -725,24 +725,22 @@ struct ChrRacesEntry
uint32 expansion; // 68 (0 - original race, 1 - tbc addon, ...)
};
-/* not used
struct CinematicCameraEntry
{
uint32 id; // 0 index
char* filename; // 1
uint32 soundid; // 2 in SoundEntries.dbc or 0
- float start_x; // 3
- float start_y; // 4
- float start_z; // 5
- float unk6; // 6 speed?
+ float base_x; // 3
+ float base_y; // 4
+ float base_z; // 5
+ float base_o; // 6
};
-*/
struct CinematicSequencesEntry
{
uint32 Id; // 0 index
//uint32 unk1; // 1 always 0
- //uint32 cinematicCamera; // 2 id in CinematicCamera.dbc
+ uint32 cinematicCamera; // 2 id in CinematicCamera.dbc
// 3-9 always 0
};
diff --git a/src/server/game/DataStores/DBCfmt.h b/src/server/game/DataStores/DBCfmt.h
index c61ec997bc2..1accc81714b 100644
--- a/src/server/game/DataStores/DBCfmt.h
+++ b/src/server/game/DataStores/DBCfmt.h
@@ -38,7 +38,8 @@ char const CharTitlesEntryfmt[] = "nxssssssssssssssssxssssssssssssssssxi";
char const ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
char const ChrClassesEntryfmt[] = "nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
char const ChrRacesEntryfmt[] = "niixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
-char const CinematicSequencesEntryfmt[] = "nxxxxxxxxx";
+char const CinematicCameraEntryfmt[] = "nsiffff";
+char const CinematicSequencesEntryfmt[] = "nxixxxxxxx";
char const CreatureDisplayInfofmt[] = "nixifxxxxxxxxxxx";
char const CreatureDisplayInfoExtrafmt[] = "diixxxxxxxxxxxxxxxxxx";
char const CreatureFamilyfmt[] = "nfifiiiiixssssssssssssssssxx";
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index fe997bc0343..e72859c23e7 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -40,8 +40,6 @@ namespace lfg
LFGMgr::LFGMgr(): m_QueueTimer(0), m_lfgProposalId(1),
m_options(sWorld->getIntConfig(CONFIG_LFG_OPTIONSMASK))
{
- new LFGPlayerScript();
- new LFGGroupScript();
}
LFGMgr::~LFGMgr()
@@ -1148,7 +1146,7 @@ void LFGMgr::RemoveProposal(LfgProposalContainer::iterator itProposal, LfgUpdate
for (GuidList::const_iterator it = proposal.queues.begin(); it != proposal.queues.end(); ++it)
{
ObjectGuid guid = *it;
- queue.AddToQueue(guid);
+ queue.AddToQueue(guid, true);
}
ProposalsStore.erase(itProposal);
diff --git a/src/server/game/DungeonFinding/LFGQueue.cpp b/src/server/game/DungeonFinding/LFGQueue.cpp
index 314803d1602..d156158dee6 100644
--- a/src/server/game/DungeonFinding/LFGQueue.cpp
+++ b/src/server/game/DungeonFinding/LFGQueue.cpp
@@ -117,7 +117,7 @@ std::string LFGQueue::GetDetailedMatchRoles(GuidList const& check) const
return o.str();
}
-void LFGQueue::AddToQueue(ObjectGuid guid)
+void LFGQueue::AddToQueue(ObjectGuid guid, bool reAdd)
{
LfgQueueDataContainer::iterator itQueue = QueueDataStore.find(guid);
if (itQueue == QueueDataStore.end())
@@ -126,7 +126,10 @@ void LFGQueue::AddToQueue(ObjectGuid guid)
return;
}
- AddToNewQueue(guid);
+ if (reAdd)
+ AddToFrontCurrentQueue(guid);
+ else
+ AddToNewQueue(guid);
}
void LFGQueue::RemoveFromQueue(ObjectGuid guid)
@@ -171,6 +174,11 @@ void LFGQueue::AddToCurrentQueue(ObjectGuid guid)
currentQueueStore.push_back(guid);
}
+void LFGQueue::AddToFrontCurrentQueue(ObjectGuid guid)
+{
+ currentQueueStore.push_front(guid);
+}
+
void LFGQueue::RemoveFromCurrentQueue(ObjectGuid guid)
{
currentQueueStore.remove(guid);
diff --git a/src/server/game/DungeonFinding/LFGQueue.h b/src/server/game/DungeonFinding/LFGQueue.h
index 7c35c4d04e3..32711e81468 100644
--- a/src/server/game/DungeonFinding/LFGQueue.h
+++ b/src/server/game/DungeonFinding/LFGQueue.h
@@ -89,7 +89,7 @@ class TC_GAME_API LFGQueue
// Add/Remove from queue
std::string GetDetailedMatchRoles(GuidList const& check) const;
- void AddToQueue(ObjectGuid guid);
+ void AddToQueue(ObjectGuid guid, bool reAdd = false);
void RemoveFromQueue(ObjectGuid guid);
void AddQueueData(ObjectGuid guid, time_t joinTime, LfgDungeonSet const& dungeons, LfgRolesMap const& rolesMap);
void RemoveQueueData(ObjectGuid guid);
@@ -116,6 +116,7 @@ class TC_GAME_API LFGQueue
void AddToNewQueue(ObjectGuid guid);
void AddToCurrentQueue(ObjectGuid guid);
+ void AddToFrontCurrentQueue(ObjectGuid guid);
void RemoveFromNewQueue(ObjectGuid guid);
void RemoveFromCurrentQueue(ObjectGuid guid);
diff --git a/src/server/game/DungeonFinding/LFGScripts.cpp b/src/server/game/DungeonFinding/LFGScripts.cpp
index 79d36055870..1d2b963b254 100644
--- a/src/server/game/DungeonFinding/LFGScripts.cpp
+++ b/src/server/game/DungeonFinding/LFGScripts.cpp
@@ -241,4 +241,10 @@ void LFGGroupScript::OnInviteMember(Group* group, ObjectGuid guid)
sLFGMgr->LeaveLfg(leader);
}
+void AddSC_LFGScripts()
+{
+ new LFGPlayerScript();
+ new LFGGroupScript();
+}
+
} // namespace lfg
diff --git a/src/server/game/DungeonFinding/LFGScripts.h b/src/server/game/DungeonFinding/LFGScripts.h
index ec64604a282..9f52668ea61 100644
--- a/src/server/game/DungeonFinding/LFGScripts.h
+++ b/src/server/game/DungeonFinding/LFGScripts.h
@@ -53,4 +53,6 @@ class TC_GAME_API LFGGroupScript : public GroupScript
void OnInviteMember(Group* group, ObjectGuid guid) override;
};
+/*keep private*/ void AddSC_LFGScripts();
+
} // namespace lfg
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index eefd24e203b..450cf2396a8 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -342,10 +342,10 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
m_creatureInfo = cinfo; // map mode related always
// equal to player Race field, but creature does not have race
- SetByteValue(UNIT_FIELD_BYTES_0, 0, 0);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_RACE, 0);
// known valid are: CLASS_WARRIOR, CLASS_PALADIN, CLASS_ROGUE, CLASS_MAGE
- SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class));
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, uint8(cinfo->unit_class));
// Cancel load if no model defined
if (!(cinfo->GetFirstValidModelId()))
@@ -364,7 +364,7 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
SetDisplayId(displayID);
SetNativeDisplayId(displayID);
- SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender);
// Load creature equipment
if (data && data->equipmentId != 0)
@@ -379,10 +379,10 @@ bool Creature::InitEntry(uint32 entry, CreatureData const* data /*= nullptr*/)
SetFloatValue(UNIT_MOD_CAST_SPEED, 1.0f);
- SetSpeed(MOVE_WALK, cinfo->speed_walk);
- SetSpeed(MOVE_RUN, cinfo->speed_run);
- SetSpeed(MOVE_SWIM, 1.0f); // using 1.0 rate
- SetSpeed(MOVE_FLIGHT, 1.0f); // using 1.0 rate
+ SetSpeedRate(MOVE_WALK, cinfo->speed_walk);
+ SetSpeedRate(MOVE_RUN, cinfo->speed_run);
+ SetSpeedRate(MOVE_SWIM, 1.0f); // using 1.0 rate
+ SetSpeedRate(MOVE_FLIGHT, 1.0f); // using 1.0 rate
// Will set UNIT_FIELD_BOUNDINGRADIUS and UNIT_FIELD_COMBATREACH
SetObjectScale(cinfo->scale);
@@ -779,7 +779,7 @@ void Creature::DoFleeToGetAssistance()
cell.Visit(p, grid_creature_searcher, *GetMap(), *this, radius);
SetNoSearchAssistance(true);
- UpdateSpeed(MOVE_RUN, false);
+ UpdateSpeed(MOVE_RUN);
if (!creature)
//SetFeared(true, EnsureVictim()->GetGUID(), 0, sWorld->getIntConfig(CONFIG_CREATURE_FAMILY_FLEE_DELAY));
@@ -790,6 +790,24 @@ void Creature::DoFleeToGetAssistance()
}
}
+bool Creature::AIM_Destroy()
+{
+ if (m_AI_locked)
+ {
+ TC_LOG_DEBUG("scripts", "AIM_Destroy: failed to destroy, locked.");
+ return false;
+ }
+
+ ASSERT(!i_disabledAI,
+ "The disabled AI wasn't cleared!");
+
+ delete i_AI;
+ i_AI = nullptr;
+
+ IsAIEnabled = false;
+ return true;
+}
+
bool Creature::AIM_Initialize(CreatureAI* ai)
{
// make sure nothing can change the AI during AI update
@@ -799,12 +817,12 @@ bool Creature::AIM_Initialize(CreatureAI* ai)
return false;
}
- UnitAI* oldAI = i_AI;
+ AIM_Destroy();
Motion_Initialize();
i_AI = ai ? ai : FactorySelector::selectAI(this);
- delete oldAI;
+
IsAIEnabled = true;
i_AI->InitializeAI();
// Initialize vehicle
@@ -888,7 +906,7 @@ bool Creature::Create(ObjectGuid::LowType guidlow, Map* map, uint32 phaseMask, u
{
SetDisplayId(displayID);
SetNativeDisplayId(displayID);
- SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender);
}
LastUsedScriptID = GetCreatureTemplate()->ScriptID;
@@ -1617,7 +1635,7 @@ void Creature::setDeathState(DeathState s)
if (HasSearchedAssistance())
{
SetNoSearchAssistance(false);
- UpdateSpeed(MOVE_RUN, false);
+ UpdateSpeed(MOVE_RUN);
}
//Dismiss group if is leader
@@ -1704,7 +1722,7 @@ void Creature::Respawn(bool force)
{
SetDisplayId(displayID);
SetNativeDisplayId(displayID);
- SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender);
}
GetMotionMaster()->InitDefault();
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 71b1d118485..bb43bcb5ff1 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -67,13 +67,13 @@ enum CreatureFlagsExtra
CREATURE_FLAG_EXTRA_NO_SKILLGAIN | CREATURE_FLAG_EXTRA_TAUNT_DIMINISH | CREATURE_FLAG_EXTRA_ALL_DIMINISH | \
CREATURE_FLAG_EXTRA_GUARD | CREATURE_FLAG_EXTRA_IGNORE_PATHFINDING | CREATURE_FLAG_EXTRA_NO_PLAYER_DAMAGE_REQ | CREATURE_FLAG_EXTRA_IMMUNITY_KNOCKBACK)
-const uint32 CREATURE_REGEN_INTERVAL = 2 * IN_MILLISECONDS;
-const uint32 CREATURE_NOPATH_EVADE_TIME = 5 * IN_MILLISECONDS;
+static const uint32 CREATURE_REGEN_INTERVAL = 2 * IN_MILLISECONDS;
+static const uint32 CREATURE_NOPATH_EVADE_TIME = 5 * IN_MILLISECONDS;
-const uint8 MAX_KILL_CREDIT = 2;
-const uint32 MAX_CREATURE_MODELS = 4;
-const uint32 MAX_CREATURE_QUEST_ITEMS = 6;
-const uint32 MAX_CREATURE_SPELLS = 8;
+static const uint8 MAX_KILL_CREDIT = 2;
+static const uint32 MAX_CREATURE_MODELS = 4;
+static const uint32 MAX_CREATURE_QUEST_ITEMS = 6;
+static const uint32 MAX_CREATURE_SPELLS = 8;
// from `creature_template` table
struct TC_GAME_API CreatureTemplate
@@ -478,6 +478,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool IsInEvadeMode() const { return HasUnitState(UNIT_STATE_EVADE); }
bool IsEvadingAttacks() const { return IsInEvadeMode() || CanNotReachTarget(); }
+ bool AIM_Destroy();
bool AIM_Initialize(CreatureAI* ai = NULL);
void Motion_Initialize();
@@ -633,7 +634,13 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
virtual uint8 GetPetAutoSpellSize() const { return MAX_SPELL_CHARM; }
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const;
- void SetCannotReachTarget(bool cannotReach) { if (cannotReach == m_cannotReachTarget) return; m_cannotReachTarget = cannotReach; m_cannotReachTimer = 0; }
+ void SetCannotReachTarget(bool cannotReach)
+ {
+ if (cannotReach == m_cannotReachTarget)
+ return;
+ m_cannotReachTarget = cannotReach;
+ m_cannotReachTimer = 0;
+ }
bool CanNotReachTarget() const { return m_cannotReachTarget; }
void SetPosition(float x, float y, float z, float o);
diff --git a/src/server/game/Entities/GameObject/GameObject.cpp b/src/server/game/Entities/GameObject/GameObject.cpp
index 3fcd249c9be..7f922f89572 100644
--- a/src/server/game/Entities/GameObject/GameObject.cpp
+++ b/src/server/game/Entities/GameObject/GameObject.cpp
@@ -71,9 +71,15 @@ GameObject::~GameObject()
// CleanupsBeforeDelete();
}
-bool GameObject::AIM_Initialize()
+void GameObject::AIM_Destroy()
{
delete m_AI;
+ m_AI = nullptr;
+}
+
+bool GameObject::AIM_Initialize()
+{
+ AIM_Destroy();
m_AI = FactorySelector::SelectGameObjectAI(this);
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 49f94013ac2..2b092427178 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -849,8 +849,10 @@ class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>
void UpdateModelPosition();
- protected:
+ void AIM_Destroy();
bool AIM_Initialize();
+
+ protected:
GameObjectModel* CreateModel();
void UpdateModel(); // updates model in case displayId were changed
uint32 m_spellId;
diff --git a/src/server/game/Entities/Item/Item.cpp b/src/server/game/Entities/Item/Item.cpp
index 773d5a05772..a8dad0b2fbc 100644
--- a/src/server/game/Entities/Item/Item.cpp
+++ b/src/server/game/Entities/Item/Item.cpp
@@ -519,41 +519,11 @@ Player* Item::GetOwner()const
return ObjectAccessor::FindPlayer(GetOwnerGUID());
}
+// Just a "legacy shortcut" for proto->GetSkill()
uint32 Item::GetSkill()
{
- const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] =
- {
- SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES,
- SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0,
- SKILL_STAVES, 0, 0, SKILL_FIST_WEAPONS, 0,
- SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS,
- SKILL_FISHING
- };
-
- const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] =
- {
- 0, SKILL_CLOTH, SKILL_LEATHER, SKILL_MAIL, SKILL_PLATE_MAIL, 0, SKILL_SHIELD, 0, 0, 0, 0
- };
-
ItemTemplate const* proto = GetTemplate();
-
- switch (proto->Class)
- {
- case ITEM_CLASS_WEAPON:
- if (proto->SubClass >= MAX_ITEM_SUBCLASS_WEAPON)
- return 0;
- else
- return item_weapon_skills[proto->SubClass];
-
- case ITEM_CLASS_ARMOR:
- if (proto->SubClass >= MAX_ITEM_SUBCLASS_ARMOR)
- return 0;
- else
- return item_armor_skills[proto->SubClass];
-
- default:
- return 0;
- }
+ return proto->GetSkill();
}
uint32 Item::GetSpell()
diff --git a/src/server/game/Entities/Item/ItemPrototype.cpp b/src/server/game/Entities/Item/ItemPrototype.cpp
new file mode 100644
index 00000000000..3bb7b128b08
--- /dev/null
+++ b/src/server/game/Entities/Item/ItemPrototype.cpp
@@ -0,0 +1,121 @@
+/*
+* Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+*
+* This program is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License as published by the
+* Free Software Foundation; either version 2 of the License, or (at your
+* option) any later version.
+*
+* This program is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+* more details.
+*
+* You should have received a copy of the GNU General Public License along
+* with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "ItemPrototype.h"
+
+bool ItemTemplate::CanChangeEquipStateInCombat() const
+{
+ switch (InventoryType)
+ {
+ case INVTYPE_RELIC:
+ case INVTYPE_SHIELD:
+ case INVTYPE_HOLDABLE:
+ return true;
+ }
+
+ switch (Class)
+ {
+ case ITEM_CLASS_WEAPON:
+ case ITEM_CLASS_PROJECTILE:
+ return true;
+ }
+
+ return false;
+}
+
+
+float ItemTemplate::getDPS() const
+{
+ if (Delay == 0)
+ return 0;
+ float temp = 0;
+ for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
+ temp += Damage[i].DamageMin + Damage[i].DamageMax;
+ return temp * 500 / Delay;
+}
+
+
+int32 ItemTemplate::getFeralBonus(int32 extraDPS /*= 0*/) const
+{
+ // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
+ if (Class == ITEM_CLASS_WEAPON && (1 << SubClass) & 0x02A5F3)
+ {
+ int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767;
+ if (bonus < 0)
+ return 0;
+ return bonus;
+ }
+ return 0;
+}
+
+float ItemTemplate::GetItemLevelIncludingQuality() const
+{
+ float itemLevel = (float)ItemLevel;
+ switch (Quality)
+ {
+ case ITEM_QUALITY_POOR:
+ case ITEM_QUALITY_NORMAL:
+ case ITEM_QUALITY_UNCOMMON:
+ case ITEM_QUALITY_ARTIFACT:
+ case ITEM_QUALITY_HEIRLOOM:
+ itemLevel -= 13; // leaving this as a separate statement since we do not know the real behavior in this case
+ break;
+ case ITEM_QUALITY_RARE:
+ itemLevel -= 13;
+ break;
+ case ITEM_QUALITY_EPIC:
+ case ITEM_QUALITY_LEGENDARY:
+ default:
+ break;
+ }
+ return std::max<float>(0.f, itemLevel);
+}
+
+uint32 ItemTemplate::GetSkill() const
+{
+ const static uint32 item_weapon_skills[MAX_ITEM_SUBCLASS_WEAPON] =
+ {
+ SKILL_AXES, SKILL_2H_AXES, SKILL_BOWS, SKILL_GUNS, SKILL_MACES,
+ SKILL_2H_MACES, SKILL_POLEARMS, SKILL_SWORDS, SKILL_2H_SWORDS, 0,
+ SKILL_STAVES, 0, 0, SKILL_FIST_WEAPONS, 0,
+ SKILL_DAGGERS, SKILL_THROWN, SKILL_ASSASSINATION, SKILL_CROSSBOWS, SKILL_WANDS,
+ SKILL_FISHING
+ };
+
+ const static uint32 item_armor_skills[MAX_ITEM_SUBCLASS_ARMOR] =
+ {
+ 0, SKILL_CLOTH, SKILL_LEATHER, SKILL_MAIL, SKILL_PLATE_MAIL, 0, SKILL_SHIELD, 0, 0, 0, 0
+ };
+
+ switch (Class)
+ {
+ case ITEM_CLASS_WEAPON:
+ if (SubClass >= MAX_ITEM_SUBCLASS_WEAPON)
+ return 0;
+ else
+ return item_weapon_skills[SubClass];
+
+ case ITEM_CLASS_ARMOR:
+ if (SubClass >= MAX_ITEM_SUBCLASS_ARMOR)
+ return 0;
+ else
+ return item_armor_skills[SubClass];
+
+ default:
+ return 0;
+ }
+}
diff --git a/src/server/game/Entities/Item/ItemPrototype.h b/src/server/game/Entities/Item/ItemPrototype.h
index 48ef9e81016..9b0f4628364 100644
--- a/src/server/game/Entities/Item/ItemPrototype.h
+++ b/src/server/game/Entities/Item/ItemPrototype.h
@@ -664,25 +664,7 @@ struct ItemTemplate
uint32 FlagsCu;
// helpers
- bool CanChangeEquipStateInCombat() const
- {
- switch (InventoryType)
- {
- case INVTYPE_RELIC:
- case INVTYPE_SHIELD:
- case INVTYPE_HOLDABLE:
- return true;
- }
-
- switch (Class)
- {
- case ITEM_CLASS_WEAPON:
- case ITEM_CLASS_PROJECTILE:
- return true;
- }
-
- return false;
- }
+ bool CanChangeEquipStateInCombat() const;
bool IsCurrencyToken() const { return (BagFamily & BAG_FAMILY_MASK_CURRENCY_TOKENS) != 0; }
@@ -691,51 +673,13 @@ struct ItemTemplate
return (Stackable == 2147483647 || Stackable <= 0) ? uint32(0x7FFFFFFF-1) : uint32(Stackable);
}
- float getDPS() const
- {
- if (Delay == 0)
- return 0;
- float temp = 0;
- for (int i = 0; i < MAX_ITEM_PROTO_DAMAGES; ++i)
- temp+=Damage[i].DamageMin + Damage[i].DamageMax;
- return temp*500/Delay;
- }
+ float getDPS() const;
- int32 getFeralBonus(int32 extraDPS = 0) const
- {
- // 0x02A5F3 - is mask for Melee weapon from ItemSubClassMask.dbc
- if (Class == ITEM_CLASS_WEAPON && (1<<SubClass)&0x02A5F3)
- {
- int32 bonus = int32((extraDPS + getDPS())*14.0f) - 767;
- if (bonus < 0)
- return 0;
- return bonus;
- }
- return 0;
- }
+ int32 getFeralBonus(int32 extraDPS = 0) const;
- float GetItemLevelIncludingQuality() const
- {
- float itemLevel = (float)ItemLevel;
- switch (Quality)
- {
- case ITEM_QUALITY_POOR:
- case ITEM_QUALITY_NORMAL:
- case ITEM_QUALITY_UNCOMMON:
- case ITEM_QUALITY_ARTIFACT:
- case ITEM_QUALITY_HEIRLOOM:
- itemLevel -= 13; // leaving this as a separate statement since we do not know the real behavior in this case
- break;
- case ITEM_QUALITY_RARE:
- itemLevel -= 13;
- break;
- case ITEM_QUALITY_EPIC:
- case ITEM_QUALITY_LEGENDARY:
- default:
- break;
- }
- return std::max<float>(0.f, itemLevel);
- }
+ float GetItemLevelIncludingQuality() const;
+
+ uint32 GetSkill() const;
bool IsPotion() const { return Class == ITEM_CLASS_CONSUMABLE && SubClass == ITEM_SUBCLASS_POTION; }
bool IsWeaponVellum() const { return Class == ITEM_CLASS_TRADE_GOODS && SubClass == ITEM_SUBCLASS_WEAPON_ENCHANTMENT; }
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 824f42ad671..45952ba51ac 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -928,6 +928,11 @@ bool Object::HasByteFlag(uint16 index, uint8 offset, uint8 flag) const
return (((uint8*)&m_uint32Values[index])[offset] & flag) != 0;
}
+void Object::ApplyModByteFlag(uint16 index, uint8 offset, uint8 flag, bool apply)
+{
+ if (apply) SetByteFlag(index, offset, flag); else RemoveByteFlag(index, offset, flag);
+}
+
void Object::SetFlag64(uint16 index, uint64 newFlag)
{
uint64 oldval = GetUInt64Value(index);
@@ -1465,9 +1470,20 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
float WorldObject::GetGridActivationRange() const
{
if (ToPlayer())
+ {
+ if (ToPlayer()->IsOnCinematic())
+ return DEFAULT_VISIBILITY_INSTANCE;
return GetMap()->GetVisibilityRange();
+ }
else if (ToCreature())
return ToCreature()->m_SightDistance;
+ else if (ToDynObject())
+ {
+ if (isActiveObject())
+ return GetMap()->GetVisibilityRange();
+ else
+ return 0.0f;
+ }
else
return 0.0f;
}
@@ -1488,6 +1504,8 @@ float WorldObject::GetSightRange(const WorldObject* target) const
{
if (target && target->isActiveObject() && !target->ToPlayer())
return MAX_VISIBILITY_DISTANCE;
+ else if (ToPlayer()->IsOnCinematic())
+ return DEFAULT_VISIBILITY_INSTANCE;
else
return GetMap()->GetVisibilityRange();
}
@@ -1497,6 +1515,11 @@ float WorldObject::GetSightRange(const WorldObject* target) const
return SIGHT_RANGE_UNIT;
}
+ if (ToDynObject() && isActiveObject())
+ {
+ return GetMap()->GetVisibilityRange();
+ }
+
return 0.0f;
}
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 029a8c08fd7..d4c8fc35451 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -160,6 +160,7 @@ class TC_GAME_API Object
void RemoveByteFlag(uint16 index, uint8 offset, uint8 newFlag);
void ToggleByteFlag(uint16 index, uint8 offset, uint8 flag);
bool HasByteFlag(uint16 index, uint8 offset, uint8 flag) const;
+ void ApplyModByteFlag(uint16 index, uint8 offset, uint8 flag, bool apply);
void SetFlag64(uint16 index, uint64 newFlag);
void RemoveFlag64(uint16 index, uint64 oldFlag);
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index 0da63c5e500..37fb23b38f5 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -213,12 +213,14 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
case SUMMON_PET:
petlevel = owner->getLevel();
- SetUInt32Value(UNIT_FIELD_BYTES_0, 0x800); // class = mage
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, uint8(CLASS_MAGE));
SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
// this enables popup window (pet dismiss, cancel)
break;
case HUNTER_PET:
- SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100); // class = warrior, gender = none, power = focus
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_WARRIOR);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, GENDER_NONE);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, POWER_FOCUS);
SetSheath(SHEATH_STATE_MELEE);
SetByteFlag(UNIT_FIELD_BYTES_2, 2, fields[9].GetBool() ? UNIT_CAN_BE_ABANDONED : UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED);
@@ -226,7 +228,6 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
// this enables popup window (pet abandon, cancel)
SetMaxPower(POWER_HAPPINESS, GetCreatePowers(POWER_HAPPINESS));
SetPower(POWER_HAPPINESS, fields[12].GetUInt32());
- setPowerType(POWER_FOCUS);
break;
default:
if (!IsPetGhoul())
@@ -822,7 +823,9 @@ bool Pet::CreateBaseAtTamed(CreatureTemplate const* cinfo, Map* map, uint32 phas
if (cinfo->type == CREATURE_TYPE_BEAST)
{
- SetUInt32Value(UNIT_FIELD_BYTES_0, 0x02020100);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_WARRIOR);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, GENDER_NONE);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, POWER_FOCUS);
SetSheath(SHEATH_STATE_MELEE);
SetByteFlag(UNIT_FIELD_BYTES_2, 2, UNIT_CAN_BE_RENAMED | UNIT_CAN_BE_ABANDONED);
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 4a21a6d0fd7..281427a18f4 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -96,6 +96,9 @@
#define SKILL_PERM_BONUS(x) int16(PAIR32_HIPART(x))
#define MAKE_SKILL_BONUS(t, p) MAKE_PAIR32(t, p)
+#define CINEMATIC_LOOKAHEAD (2 * IN_MILLISECONDS)
+#define CINEMATIC_UPDATEDIFF 500
+
enum CharacterFlags
{
CHARACTER_FLAG_NONE = 0x00000000,
@@ -474,21 +477,11 @@ Player::Player(WorldSession* session): Unit(true)
// Player summoning
m_summon_expire = 0;
- m_summon_mapid = 0;
- m_summon_x = 0.0f;
- m_summon_y = 0.0f;
- m_summon_z = 0.0f;
m_mover = this;
m_movedPlayer = this;
m_seer = this;
- m_recallMap = 0;
- m_recallX = 0;
- m_recallY = 0;
- m_recallZ = 0;
- m_recallO = 0;
-
m_homebindMapId = 0;
m_homebindAreaId = 0;
m_homebindX = 0;
@@ -535,6 +528,14 @@ Player::Player(WorldSession* session): Unit(true)
_activeCheats = CHEAT_NONE;
healthBeforeDuel = 0;
manaBeforeDuel = 0;
+
+ m_cinematicDiff = 0;
+ m_lastCinematicCheck = 0;
+ m_activeCinematicCameraId = 0;
+ m_cinematicCamera = nullptr;
+ m_remoteSightPosition = Position(0.0f, 0.0f, 0.0f);
+ m_CinematicObject = nullptr;
+
m_achievementMgr = new AchievementMgr(this);
m_reputationMgr = new ReputationMgr(this);
}
@@ -643,9 +644,10 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
return false;
}
- uint32 RaceClassGender = (createInfo->Race) | (createInfo->Class << 8) | (createInfo->Gender << 16);
-
- SetUInt32Value(UNIT_FIELD_BYTES_0, (RaceClassGender | (powertype << 24)));
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_RACE, createInfo->Race);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, createInfo->Class);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, createInfo->Gender);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, powertype);
InitDisplayIds();
if (sWorld->getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_PVP || sWorld->getIntConfig(CONFIG_GAME_TYPE) == REALM_TYPE_RPPVP)
{
@@ -658,13 +660,14 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
SetInt32Value(PLAYER_FIELD_WATCHED_FACTION_INDEX, uint32(-1)); // -1 is default value
- SetUInt32Value(PLAYER_BYTES, (createInfo->Skin | (createInfo->Face << 8) | (createInfo->HairStyle << 16) | (createInfo->HairColor << 24)));
- SetUInt32Value(PLAYER_BYTES_2, (createInfo->FacialHair |
- (0x00 << 8) |
- (0x00 << 16) |
- (((GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0) ? REST_STATE_RAF_LINKED : REST_STATE_NOT_RAF_LINKED) << 24)));
- SetByteValue(PLAYER_BYTES_3, 0, createInfo->Gender);
- SetByteValue(PLAYER_BYTES_3, 3, 0); // BattlefieldArenaFaction (0 or 1)
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID, createInfo->Skin);
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID, createInfo->Face);
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID, createInfo->HairStyle);
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID, createInfo->HairColor);
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE, createInfo->FacialHair);
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, (GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0) ? REST_STATE_RAF_LINKED : REST_STATE_NOT_RAF_LINKED);
+ SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER, createInfo->Gender);
+ SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_ARENA_FACTION, 0);
SetUInt32Value(PLAYER_GUILDID, 0);
SetUInt32Value(PLAYER_GUILDRANK, 0);
@@ -1179,7 +1182,7 @@ void Player::SetDrunkValue(uint8 newDrunkValue, uint32 itemId /*= 0*/)
m_invisibilityDetect.DelFlag(INVISIBILITY_DRUNK);
uint32 newDrunkenState = Player::GetDrunkenstateByValue(newDrunkValue);
- SetByteValue(PLAYER_BYTES_3, 1, newDrunkValue);
+ SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION, newDrunkValue);
UpdateObjectVisibility();
if (!isSobering)
@@ -1222,7 +1225,15 @@ void Player::Update(uint32 p_time)
m_spellModTakingSpell = nullptr;
}
- //used to implement delayed far teleport
+ // Update cinematic location, if 500ms have passed and we're doing a cinematic now.
+ m_cinematicDiff += p_time;
+ if (m_cinematicCamera && m_activeCinematicCameraId && GetMSTimeDiffToNow(m_lastCinematicCheck) > CINEMATIC_UPDATEDIFF)
+ {
+ m_lastCinematicCheck = getMSTime();
+ UpdateCinematicLocation(p_time);
+ }
+
+ //used to implement delayed far teleports
SetCanDelayTeleport(true);
Unit::Update(p_time);
SetCanDelayTeleport(false);
@@ -2822,8 +2833,8 @@ void Player::GiveLevel(uint8 level)
{
++m_grantableLevels;
- if (!HasByteFlag(PLAYER_FIELD_BYTES, 1, 0x01))
- SetByteFlag(PLAYER_FIELD_BYTES, 1, 0x01);
+ if (!HasByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL, 0x01))
+ SetByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL, 0x01);
}
sScriptMgr->OnPlayerLevelChanged(this, oldLevel);
@@ -4789,7 +4800,7 @@ Corpse* Player::CreateCorpse()
// prevent the existence of 2 corpses for one player
SpawnCorpseBones();
- uint32 _pb, _pb2, _cfb1, _cfb2;
+ uint32 _cfb1, _cfb2;
Corpse* corpse = new Corpse((m_ExtraFlags & PLAYER_EXTRA_PVP_DEATH) ? CORPSE_RESURRECTABLE_PVP : CORPSE_RESURRECTABLE_PVE);
SetPvPDeath(false);
@@ -4802,16 +4813,13 @@ Corpse* Player::CreateCorpse()
_corpseLocation.WorldRelocate(*this);
- _pb = GetUInt32Value(PLAYER_BYTES);
- _pb2 = GetUInt32Value(PLAYER_BYTES_2);
-
- uint8 skin = (uint8)(_pb);
- uint8 face = (uint8)(_pb >> 8);
- uint8 hairstyle = (uint8)(_pb >> 16);
- uint8 haircolor = (uint8)(_pb >> 24);
- uint8 facialhair = (uint8)(_pb2);
+ uint8 skin = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID);
+ uint8 face = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID);
+ uint8 hairstyle = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID);
+ uint8 haircolor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID);
+ uint8 facialhair = GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE);
- _cfb1 = ((0x00) | (getRace() << 8) | (GetByteValue(PLAYER_BYTES_3, 0) << 16) | (skin << 24));
+ _cfb1 = ((0x00) | (getRace() << 8) | (GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER) << 16) | (skin << 24));
_cfb2 = ((face) | (hairstyle << 8) | (haircolor << 16) | (facialhair << 24));
corpse->SetUInt32Value(CORPSE_FIELD_BYTES_1, _cfb1);
@@ -6356,15 +6364,6 @@ bool Player::UpdatePosition(float x, float y, float z, float orientation, bool t
return true;
}
-void Player::SaveRecallPosition()
-{
- m_recallMap = GetMapId();
- m_recallX = GetPositionX();
- m_recallY = GetPositionY();
- m_recallZ = GetPositionZ();
- m_recallO = GetOrientation();
-}
-
void Player::SendMessageToSetInRange(WorldPacket* data, float dist, bool self)
{
if (self)
@@ -6399,11 +6398,13 @@ void Player::SendDirectMessage(WorldPacket const* data) const
m_session->SendPacket(data);
}
-void Player::SendCinematicStart(uint32 CinematicSequenceId) const
+void Player::SendCinematicStart(uint32 CinematicSequenceId)
{
WorldPacket data(SMSG_TRIGGER_CINEMATIC, 4);
data << uint32(CinematicSequenceId);
SendDirectMessage(&data);
+ if (const CinematicSequencesEntry* sequence = sCinematicSequencesStore.LookupEntry(CinematicSequenceId))
+ SetActiveCinematicCamera(sequence->cinematicCamera);
}
void Player::SendMovieStart(uint32 MovieId) const
@@ -16859,12 +16860,9 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
return false;
}
- // overwrite some data fields
- uint32 bytes0 = 0;
- bytes0 |= fields[3].GetUInt8(); // race
- bytes0 |= fields[4].GetUInt8() << 8; // class
- bytes0 |= gender << 16; // gender
- SetUInt32Value(UNIT_FIELD_BYTES_0, bytes0);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_RACE, fields[3].GetUInt8());
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, fields[4].GetUInt8());
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, gender);
// check if race/class combination is valid
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(), getClass());
@@ -16891,25 +16889,25 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
money = MAX_MONEY_AMOUNT;
SetMoney(money);
- SetByteValue(PLAYER_BYTES, 0, fields[9].GetUInt8());
- SetByteValue(PLAYER_BYTES, 1, fields[10].GetUInt8());
- SetByteValue(PLAYER_BYTES, 2, fields[11].GetUInt8());
- SetByteValue(PLAYER_BYTES, 3, fields[12].GetUInt8());
- SetByteValue(PLAYER_BYTES_2, 0, fields[13].GetUInt8());
- SetByteValue(PLAYER_BYTES_2, 2, fields[14].GetUInt8());
- SetByteValue(PLAYER_BYTES_2, 3, fields[15].GetUInt8());
- SetByteValue(PLAYER_BYTES_3, 0, fields[5].GetUInt8());
- SetByteValue(PLAYER_BYTES_3, 1, fields[54].GetUInt8());
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID, fields[9].GetUInt8());
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID, fields[10].GetUInt8());
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID, fields[11].GetUInt8());
+ SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID, fields[12].GetUInt8());
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE, fields[13].GetUInt8());
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS, fields[14].GetUInt8());
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, fields[15].GetUInt8());
+ SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER, fields[5].GetUInt8());
+ SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION, fields[54].GetUInt8());
if (!ValidateAppearance(
fields[3].GetUInt8(), // race
fields[4].GetUInt8(), // class
gender,
- GetByteValue(PLAYER_BYTES, 2),
- GetByteValue(PLAYER_BYTES, 3),
- GetByteValue(PLAYER_BYTES, 1),
- GetByteValue(PLAYER_BYTES_2, 0),
- GetByteValue(PLAYER_BYTES, 0)))
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID),
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID),
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID),
+ GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE),
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID)))
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong Appearance values (Hair/Skin/Color), can't load.", guid.ToString().c_str());
return false;
@@ -16923,7 +16921,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
SetUInt32Value(PLAYER_AMMO_ID, fields[68].GetUInt32());
// set which actionbars the client has active - DO NOT REMOVE EVER AGAIN (can be changed though, if it does change fieldwise)
- SetByteValue(PLAYER_FIELD_BYTES, 2, fields[70].GetUInt8());
+ SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES, fields[70].GetUInt8());
InitDisplayIds();
@@ -17506,7 +17504,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
SetFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_REFER_A_FRIEND);
if (m_grantableLevels > 0)
- SetByteValue(PLAYER_FIELD_BYTES, 1, 0x01);
+ SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL, 0x01);
_LoadDeclinedNames(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_DECLINED_NAMES));
@@ -17713,7 +17711,7 @@ void Player::LoadCorpse(PreparedQueryResult result)
{
Field* fields = result->Fetch();
_corpseLocation.WorldRelocate(fields[0].GetUInt16(), fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat());
- ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(_corpseLocation.GetMapId())->Instanceable());
+ ApplyModByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_RELEASE_TIMER, !sMapStore.LookupEntry(_corpseLocation.GetMapId())->Instanceable());
}
else
ResurrectPlayer(0.5f);
@@ -18947,17 +18945,17 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setString(index++, GetName());
stmt->setUInt8(index++, getRace());
stmt->setUInt8(index++, getClass());
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, 0)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
stmt->setUInt32(index++, GetMoney());
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 0));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 1));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 2));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 3));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 0));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 2));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 3));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS));
stmt->setUInt16(index++, (uint16)GetMapId());
stmt->setUInt32(index++, (uint32)GetInstanceId());
@@ -19047,7 +19045,7 @@ void Player::SaveToDB(bool create /*=false*/)
ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << ' ';
stmt->setString(index++, ss.str());
- stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, 2));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES));
stmt->setUInt32(index, m_grantableLevels);
}
else
@@ -19057,17 +19055,17 @@ void Player::SaveToDB(bool create /*=false*/)
stmt->setString(index++, GetName());
stmt->setUInt8(index++, getRace());
stmt->setUInt8(index++, getClass());
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, 0)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)); // save gender from PLAYER_BYTES_3, UNIT_BYTES_0 changes with every transform effect
stmt->setUInt8(index++, getLevel());
stmt->setUInt32(index++, GetUInt32Value(PLAYER_XP));
stmt->setUInt32(index++, GetMoney());
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 0));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 1));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 2));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, 3));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 0));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 2));
- stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, 3));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE));
stmt->setUInt32(index++, GetUInt32Value(PLAYER_FLAGS));
if (!IsBeingTeleported())
@@ -19172,7 +19170,7 @@ void Player::SaveToDB(bool create /*=false*/)
ss << GetUInt32Value(PLAYER__FIELD_KNOWN_TITLES + i) << ' ';
stmt->setString(index++, ss.str());
- stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, 2));
+ stmt->setUInt8(index++, GetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES));
stmt->setUInt32(index++, m_grantableLevels);
stmt->setUInt8(index++, IsInWorld() && !GetSession()->PlayerLogout() ? 1 : 0);
@@ -20311,6 +20309,11 @@ void Player::Say(std::string const& text, Language language, WorldObject const*
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
}
+void Player::Say(uint32 textId, WorldObject const* target /*= nullptr*/)
+{
+ Talk(textId, CHAT_MSG_SAY, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), target);
+}
+
void Player::Yell(std::string const& text, Language language, WorldObject const* /*= nullptr*/)
{
std::string _text(text);
@@ -20321,6 +20324,11 @@ void Player::Yell(std::string const& text, Language language, WorldObject const*
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), true);
}
+void Player::Yell(uint32 textId, WorldObject const* target /*= nullptr*/)
+{
+ Talk(textId, CHAT_MSG_YELL, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_YELL), target);
+}
+
void Player::TextEmote(std::string const& text, WorldObject const* /*= nullptr*/, bool /*= false*/)
{
std::string _text(text);
@@ -20331,6 +20339,11 @@ void Player::TextEmote(std::string const& text, WorldObject const* /*= nullptr*/
SendMessageToSetInRange(&data, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), true, !GetSession()->HasPermission(rbac::RBAC_PERM_TWO_SIDE_INTERACTION_CHAT));
}
+void Player::TextEmote(uint32 textId, WorldObject const* target /*= nullptr*/, bool /*isBossEmote = false*/)
+{
+ Talk(textId, CHAT_MSG_EMOTE, sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE), target);
+}
+
void Player::Whisper(std::string const& text, Language language, Player* target, bool /*= false*/)
{
ASSERT(target);
@@ -20367,6 +20380,24 @@ void Player::Whisper(std::string const& text, Language language, Player* target,
ChatHandler(GetSession()).PSendSysMessage(LANG_PLAYER_DND, target->GetName().c_str(), target->autoReplyMsg.c_str());
}
+void Player::Whisper(uint32 textId, Player* target, bool /*isBossWhisper = false*/)
+{
+ if (!target)
+ return;
+
+ BroadcastText const* bct = sObjectMgr->GetBroadcastText(textId);
+ if (!bct)
+ {
+ TC_LOG_ERROR("entities.unit", "WorldObject::MonsterWhisper: `broadcast_text` was not %u found", textId);
+ return;
+ }
+
+ LocaleConstant locale = target->GetSession()->GetSessionDbLocaleIndex();
+ WorldPacket data;
+ ChatHandler::BuildChatPacket(data, CHAT_MSG_WHISPER, LANG_UNIVERSAL, this, target, bct->GetText(locale, getGender()), 0, "", locale);
+ target->SendDirectMessage(&data);
+}
+
Item* Player::GetMItem(uint32 id)
{
ItemMap::const_iterator itr = mMitems.find(id);
@@ -20892,13 +20923,13 @@ void Player::SetRestBonus(float rest_bonus_new)
// update data for client
if ((GetsRecruitAFriendBonus(true) && (GetSession()->IsARecruiter() || GetSession()->GetRecruiterId() != 0)))
- SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_RAF_LINKED);
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, REST_STATE_RAF_LINKED);
else
{
if (m_rest_bonus > 10)
- SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_RESTED);
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, REST_STATE_RESTED);
else if (m_rest_bonus <= 1)
- SetByteValue(PLAYER_BYTES_2, 3, REST_STATE_NOT_RAF_LINKED);
+ SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_REST_STATE, REST_STATE_NOT_RAF_LINKED);
}
//RestTickUpdate
@@ -21232,7 +21263,7 @@ void Player::InitDisplayIds()
return;
}
- uint8 gender = GetByteValue(PLAYER_BYTES_3, 0);
+ uint8 gender = GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER);
switch (gender)
{
case GENDER_FEMALE:
@@ -21840,7 +21871,7 @@ void Player::SetBattlegroundEntryPoint()
void Player::SetBGTeam(uint32 team)
{
m_bgData.bgTeam = team;
- SetByteValue(PLAYER_BYTES_3, 3, uint8(team == ALLIANCE ? 1 : 0));
+ SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_ARENA_FACTION, uint8(team == ALLIANCE ? 1 : 0));
}
uint32 Player::GetBGTeam() const
@@ -23159,13 +23190,32 @@ void Player::UpdateForQuestWorldObjects()
GetSession()->SendPacket(&packet);
}
-void Player::SetSummonPoint(uint32 mapid, float x, float y, float z)
+bool Player::HasSummonPending() const
+{
+ return m_summon_expire >= time(nullptr);
+}
+
+void Player::SendSummonRequestFrom(Unit* summoner)
{
+ if (!summoner)
+ return;
+
+ // Player already has active summon request
+ if (HasSummonPending())
+ return;
+
+ // Evil Twin (ignore player summon, but hide this for summoner)
+ if (HasAura(23445))
+ return;
+
m_summon_expire = time(nullptr) + MAX_PLAYER_SUMMON_DELAY;
- m_summon_mapid = mapid;
- m_summon_x = x;
- m_summon_y = y;
- m_summon_z = z;
+ m_summon_location.WorldRelocate(*summoner);
+
+ WorldPacket data(SMSG_SUMMON_REQUEST, 8 + 4 + 4);
+ data << uint64(summoner->GetGUID()); // summoner guid
+ data << uint32(summoner->GetZoneId()); // summoner zone
+ data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILLISECONDS); // auto decline after msecs
+ GetSession()->SendPacket(&data);
}
void Player::SummonIfPossible(bool agree)
@@ -23196,7 +23246,7 @@ void Player::SummonIfPossible(bool agree)
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS, 1);
- TeleportTo(m_summon_mapid, m_summon_x, m_summon_y, m_summon_z, GetOrientation());
+ TeleportTo(m_summon_location);
}
void Player::RemoveItemDurations(Item* item)
@@ -24061,10 +24111,10 @@ uint32 Player::GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 n
if (level > GT_MAX_LEVEL)
level = GT_MAX_LEVEL; // max level in this dbc
- uint8 hairstyle = GetByteValue(PLAYER_BYTES, 2);
- uint8 haircolor = GetByteValue(PLAYER_BYTES, 3);
- uint8 facialhair = GetByteValue(PLAYER_BYTES_2, 0);
- uint8 skincolor = GetByteValue(PLAYER_BYTES, 0);
+ uint8 hairstyle = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID);
+ uint8 haircolor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID);
+ uint8 facialhair = GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE);
+ uint8 skincolor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID);
if ((hairstyle == newhairstyle) && (haircolor == newhaircolor) && (facialhair == newfacialhair) && (!newSkin || (newSkin->hair_id == skincolor)))
return 0;
@@ -26094,6 +26144,9 @@ bool Player::SetCanFly(bool apply, bool packetOnly /*= false*/)
if (!packetOnly && !Unit::SetCanFly(apply))
return false;
+ if (!apply)
+ SetFallInformation(0, GetPositionZ());
+
WorldPacket data(apply ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, 12);
data << GetPackGUID();
data << uint32(0); //! movement counter
@@ -26190,6 +26243,125 @@ float Player::GetCollisionHeight(bool mounted) const
}
}
+void Player::BeginCinematic()
+{
+ // Sanity check for active camera set
+ if (m_activeCinematicCameraId == 0)
+ return;
+
+ auto itr = sFlyByCameraStore.find(m_activeCinematicCameraId);
+ if (itr != sFlyByCameraStore.end())
+ {
+ // Initialize diff, and set camera
+ m_cinematicDiff = 0;
+ m_cinematicCamera = &itr->second;
+
+ auto camitr = m_cinematicCamera->begin();
+ if (camitr != m_cinematicCamera->end())
+ {
+ Position pos(camitr->locations.x, camitr->locations.y, camitr->locations.z, camitr->locations.w);
+ if (!pos.IsPositionValid())
+ return;
+
+ m_mapRef->LoadGrid(camitr->locations.x, camitr->locations.y);
+ m_CinematicObject = SummonCreature(VISUAL_WAYPOINT, pos.m_positionX, pos.m_positionY, pos.m_positionZ, 0.0f, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 120000);
+ if (m_CinematicObject)
+ {
+ m_CinematicObject->setActive(true);
+ SetViewpoint(m_CinematicObject, true);
+ }
+ }
+ }
+}
+
+void Player::EndCinematic()
+{
+ m_cinematicDiff = 0;
+ m_cinematicCamera = nullptr;
+ m_activeCinematicCameraId = 0;
+ if (m_CinematicObject)
+ {
+ if (m_seer && m_seer == m_CinematicObject)
+ SetViewpoint(m_CinematicObject, false);
+ m_CinematicObject->AddObjectToRemoveList();
+ }
+}
+
+void Player::UpdateCinematicLocation(uint32 /*diff*/)
+{
+ Position lastPosition;
+ uint32 lastTimestamp = 0;
+ Position nextPosition;
+ uint32 nextTimestamp = 0;
+
+ if (m_cinematicCamera->size() == 0)
+ return;
+
+ // Obtain direction of travel
+ for (FlyByCamera cam : *m_cinematicCamera)
+ {
+ if (cam.timeStamp > m_cinematicDiff)
+ {
+ nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
+ nextTimestamp = cam.timeStamp;
+ break;
+ }
+ lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
+ lastTimestamp = cam.timeStamp;
+ }
+ float angle = lastPosition.GetAngle(&nextPosition);
+ angle -= lastPosition.GetOrientation();
+ if (angle < 0)
+ angle += 2 * float(M_PI);
+
+ // Look for position around 2 second ahead of us.
+ int32 workDiff = m_cinematicDiff;
+
+ // Modify result based on camera direction (Humans for example, have the camera point behind)
+ workDiff += static_cast<int32>(float(CINEMATIC_LOOKAHEAD) * cos(angle));
+
+ // Get an iterator to the last entry in the cameras, to make sure we don't go beyond the end
+ FlyByCameraCollection::const_reverse_iterator endItr = m_cinematicCamera->rbegin();
+ if (endItr != m_cinematicCamera->rend() && workDiff > static_cast<int32>(endItr->timeStamp))
+ workDiff = endItr->timeStamp;
+
+ // Never try to go back in time before the start of cinematic!
+ if (workDiff < 0)
+ workDiff = m_cinematicDiff;
+
+ // Obtain the previous and next waypoint based on timestamp
+ for (FlyByCamera cam : *m_cinematicCamera)
+ {
+ if (static_cast<int32>(cam.timeStamp) >= workDiff)
+ {
+ nextPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
+ nextTimestamp = cam.timeStamp;
+ break;
+ }
+ lastPosition = Position(cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w);
+ lastTimestamp = cam.timeStamp;
+ }
+
+ // Never try to go beyond the end of the cinematic
+ if (workDiff > static_cast<int32>(nextTimestamp))
+ workDiff = static_cast<int32>(nextTimestamp);
+
+ // Interpolate the position for this moment in time (or the adjusted moment in time)
+ uint32 timeDiff = nextTimestamp - lastTimestamp;
+ uint32 interDiff = workDiff - lastTimestamp;
+ float xDiff = nextPosition.m_positionX - lastPosition.m_positionX;
+ float yDiff = nextPosition.m_positionY - lastPosition.m_positionY;
+ float zDiff = nextPosition.m_positionZ - lastPosition.m_positionZ;
+ Position interPosition(lastPosition.m_positionX + (xDiff * (float(interDiff)/float(timeDiff))), lastPosition.m_positionY +
+ (yDiff * (float(interDiff) / float(timeDiff))), lastPosition.m_positionZ + (zDiff * (float(interDiff) / float(timeDiff))));
+
+ // Advance (at speed) to this position. The remote sight object is used
+ // to send update information to player in cinematic
+ if (m_CinematicObject && interPosition.IsPositionValid())
+ m_CinematicObject->MonsterMoveWithSpeed(interPosition.m_positionX, interPosition.m_positionY, interPosition.m_positionZ, 200.0f, false, true);
+}
+
+
std::string Player::GetMapAreaAndZoneString() const
{
uint32 areaId = GetAreaId();
@@ -26285,7 +26457,7 @@ Pet* Player::SummonPet(uint32 entry, float x, float y, float z, float ang, PetTy
case SUMMON_PET:
// this enables pet details window (Shift+P)
pet->GetCharmInfo()->SetPetNumber(pet_number, true);
- pet->SetUInt32Value(UNIT_FIELD_BYTES_0, 2048);
+ pet->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_MAGE);
pet->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE, 0);
pet->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP, 1000);
pet->SetFullHealth();
@@ -26422,3 +26594,22 @@ void Player::RemoveRestFlag(RestFlag restFlag)
RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_RESTING);
}
}
+
+uint32 Player::DoRandomRoll(uint32 minimum, uint32 maximum)
+{
+ ASSERT(maximum <= 10000);
+
+ uint32 roll = urand(minimum, maximum);
+
+ WorldPacket data(MSG_RANDOM_ROLL, 4 + 4 + 4 + 8);
+ data << uint32(minimum);
+ data << uint32(maximum);
+ data << uint32(roll);
+ data << GetGUID();
+ if (Group* group = GetGroup())
+ group->BroadcastPacket(&data, false);
+ else
+ SendDirectMessage(&data);
+
+ return roll;
+}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index d817969f6da..7657c0d4b7f 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -415,50 +415,48 @@ enum PlayerFlags
PLAYER_FLAGS_UNK31 = 0x80000000
};
-// used for PLAYER__FIELD_KNOWN_TITLES field (uint64), (1<<bit_index) without (-1)
-// can't use enum for uint64 values
-#define PLAYER_TITLE_DISABLED UI64LIT(0x0000000000000000)
-#define PLAYER_TITLE_NONE UI64LIT(0x0000000000000001)
-#define PLAYER_TITLE_PRIVATE UI64LIT(0x0000000000000002) // 1
-#define PLAYER_TITLE_CORPORAL UI64LIT(0x0000000000000004) // 2
-#define PLAYER_TITLE_SERGEANT_A UI64LIT(0x0000000000000008) // 3
-#define PLAYER_TITLE_MASTER_SERGEANT UI64LIT(0x0000000000000010) // 4
-#define PLAYER_TITLE_SERGEANT_MAJOR UI64LIT(0x0000000000000020) // 5
-#define PLAYER_TITLE_KNIGHT UI64LIT(0x0000000000000040) // 6
-#define PLAYER_TITLE_KNIGHT_LIEUTENANT UI64LIT(0x0000000000000080) // 7
-#define PLAYER_TITLE_KNIGHT_CAPTAIN UI64LIT(0x0000000000000100) // 8
-#define PLAYER_TITLE_KNIGHT_CHAMPION UI64LIT(0x0000000000000200) // 9
-#define PLAYER_TITLE_LIEUTENANT_COMMANDER UI64LIT(0x0000000000000400) // 10
-#define PLAYER_TITLE_COMMANDER UI64LIT(0x0000000000000800) // 11
-#define PLAYER_TITLE_MARSHAL UI64LIT(0x0000000000001000) // 12
-#define PLAYER_TITLE_FIELD_MARSHAL UI64LIT(0x0000000000002000) // 13
-#define PLAYER_TITLE_GRAND_MARSHAL UI64LIT(0x0000000000004000) // 14
-#define PLAYER_TITLE_SCOUT UI64LIT(0x0000000000008000) // 15
-#define PLAYER_TITLE_GRUNT UI64LIT(0x0000000000010000) // 16
-#define PLAYER_TITLE_SERGEANT_H UI64LIT(0x0000000000020000) // 17
-#define PLAYER_TITLE_SENIOR_SERGEANT UI64LIT(0x0000000000040000) // 18
-#define PLAYER_TITLE_FIRST_SERGEANT UI64LIT(0x0000000000080000) // 19
-#define PLAYER_TITLE_STONE_GUARD UI64LIT(0x0000000000100000) // 20
-#define PLAYER_TITLE_BLOOD_GUARD UI64LIT(0x0000000000200000) // 21
-#define PLAYER_TITLE_LEGIONNAIRE UI64LIT(0x0000000000400000) // 22
-#define PLAYER_TITLE_CENTURION UI64LIT(0x0000000000800000) // 23
-#define PLAYER_TITLE_CHAMPION UI64LIT(0x0000000001000000) // 24
-#define PLAYER_TITLE_LIEUTENANT_GENERAL UI64LIT(0x0000000002000000) // 25
-#define PLAYER_TITLE_GENERAL UI64LIT(0x0000000004000000) // 26
-#define PLAYER_TITLE_WARLORD UI64LIT(0x0000000008000000) // 27
-#define PLAYER_TITLE_HIGH_WARLORD UI64LIT(0x0000000010000000) // 28
-#define PLAYER_TITLE_GLADIATOR UI64LIT(0x0000000020000000) // 29
-#define PLAYER_TITLE_DUELIST UI64LIT(0x0000000040000000) // 30
-#define PLAYER_TITLE_RIVAL UI64LIT(0x0000000080000000) // 31
-#define PLAYER_TITLE_CHALLENGER UI64LIT(0x0000000100000000) // 32
-#define PLAYER_TITLE_SCARAB_LORD UI64LIT(0x0000000200000000) // 33
-#define PLAYER_TITLE_CONQUEROR UI64LIT(0x0000000400000000) // 34
-#define PLAYER_TITLE_JUSTICAR UI64LIT(0x0000000800000000) // 35
-#define PLAYER_TITLE_CHAMPION_OF_THE_NAARU UI64LIT(0x0000001000000000) // 36
-#define PLAYER_TITLE_MERCILESS_GLADIATOR UI64LIT(0x0000002000000000) // 37
-#define PLAYER_TITLE_OF_THE_SHATTERED_SUN UI64LIT(0x0000004000000000) // 38
-#define PLAYER_TITLE_HAND_OF_ADAL UI64LIT(0x0000008000000000) // 39
-#define PLAYER_TITLE_VENGEFUL_GLADIATOR UI64LIT(0x0000010000000000) // 40
+enum PlayerBytesOffsets
+{
+ PLAYER_BYTES_OFFSET_SKIN_ID = 0,
+ PLAYER_BYTES_OFFSET_FACE_ID = 1,
+ PLAYER_BYTES_OFFSET_HAIR_STYLE_ID = 2,
+ PLAYER_BYTES_OFFSET_HAIR_COLOR_ID = 3
+};
+
+enum PlayerBytes2Offsets
+{
+ PLAYER_BYTES_2_OFFSET_FACIAL_STYLE = 0,
+ PLAYER_BYTES_2_OFFSET_PARTY_TYPE = 1,
+ PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS = 2,
+ PLAYER_BYTES_2_OFFSET_REST_STATE = 3
+};
+
+enum PlayerBytes3Offsets
+{
+ PLAYER_BYTES_3_OFFSET_GENDER = 0,
+ PLAYER_BYTES_3_OFFSET_INEBRIATION = 1,
+ PLAYER_BYTES_3_OFFSET_PVP_TITLE = 2,
+ PLAYER_BYTES_3_OFFSET_ARENA_FACTION = 3
+};
+
+enum PlayerFieldBytesOffsets
+{
+ PLAYER_FIELD_BYTES_OFFSET_FLAGS = 0,
+ PLAYER_FIELD_BYTES_OFFSET_RAF_GRANTABLE_LEVEL = 1,
+ PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES = 2,
+ PLAYER_FIELD_BYTES_OFFSET_LIFETIME_MAX_PVP_RANK = 3
+};
+
+enum PlayerFieldBytes2Offsets
+{
+ PLAYER_FIELD_BYTES_2_OFFSET_OVERRIDE_SPELLS_ID = 0, // uint16!
+ PLAYER_FIELD_BYTES_2_OFFSET_IGNORE_POWER_REGEN_PREDICTION_MASK = 2,
+ PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION = 3
+};
+
+static_assert((PLAYER_FIELD_BYTES_2_OFFSET_OVERRIDE_SPELLS_ID & 1) == 0, "PLAYER_FIELD_BYTES_2_OFFSET_OVERRIDE_SPELLS_ID must be aligned to 2 byte boundary");
+
+#define PLAYER_BYTES_2_OVERRIDE_SPELLS_UINT16_OFFSET (PLAYER_FIELD_BYTES_2_OFFSET_OVERRIDE_SPELLS_ID / 2)
#define KNOWN_TITLES_SIZE 3
#define MAX_TITLE_INDEX (KNOWN_TITLES_SIZE*64) // 3 uint64 fields
@@ -1052,7 +1050,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool TeleportTo(WorldLocation const &loc, uint32 options = 0);
bool TeleportToBGEntryPoint();
- void SetSummonPoint(uint32 mapid, float x, float y, float z);
+ bool HasSummonPending() const;
+ void SendSummonRequestFrom(Unit* summoner);
void SummonIfPossible(bool agree);
bool Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo);
@@ -1150,12 +1149,16 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
/// Handles said message in regular chat based on declared language and in config pre-defined Range.
void Say(std::string const& text, Language language, WorldObject const* = nullptr) override;
+ void Say(uint32 textId, WorldObject const* target = nullptr) override;
/// Handles yelled message in regular chat based on declared language and in config pre-defined Range.
void Yell(std::string const& text, Language language, WorldObject const* = nullptr) override;
+ void Yell(uint32 textId, WorldObject const* target = nullptr) override;
/// Outputs an universal text which is supposed to be an action.
void TextEmote(std::string const& text, WorldObject const* = nullptr, bool = false) override;
+ void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false) override;
/// Handles whispers from Addons and players based on sender, receiver's guid and language.
void Whisper(std::string const& text, Language language, Player* receiver, bool = false) override;
+ void Whisper(uint32 textId, Player* target, bool isBossWhisper = false) override;
/*********************************************************/
/*** STORAGE SYSTEM ***/
@@ -1185,8 +1188,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
static bool IsBankPos(uint8 bag, uint8 slot);
bool IsValidPos(uint16 pos, bool explicit_pos) const { return IsValidPos(pos >> 8, pos & 255, explicit_pos); }
bool IsValidPos(uint8 bag, uint8 slot, bool explicit_pos) const;
- uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, 2); }
- void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, 2, count); }
+ uint8 GetBankBagSlotCount() const { return GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS); }
+ void SetBankBagSlotCount(uint8 count) { SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_BANK_BAG_SLOTS, count); }
bool HasItemCount(uint32 item, uint32 count = 1, bool inBankAlso = false) const;
bool HasItemFitToSpellRequirements(SpellInfo const* spellInfo, Item const* ignoreItem = nullptr) const;
bool CanNoReagentCast(SpellInfo const* spellInfo) const;
@@ -1911,7 +1914,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
//End of PvP System
void SetDrunkValue(uint8 newDrunkValue, uint32 itemId = 0);
- uint8 GetDrunkValue() const { return GetByteValue(PLAYER_BYTES_3, 1); }
+ uint8 GetDrunkValue() const { return GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_INEBRIATION); }
static DrunkenState GetDrunkenstateByValue(uint8 value);
uint32 GetDeathTimer() const { return m_deathTimer; }
@@ -2075,13 +2078,8 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 GetSaveTimer() const { return m_nextSave; }
void SetSaveTimer(uint32 timer) { m_nextSave = timer; }
- // Recall position
- uint32 m_recallMap;
- float m_recallX;
- float m_recallY;
- float m_recallZ;
- float m_recallO;
- void SaveRecallPosition();
+ void SaveRecallPosition() { m_recall_location.WorldRelocate(*this); }
+ void Recall() { TeleportTo(m_recall_location); }
void SetHomebind(WorldLocation const& loc, uint32 areaId);
@@ -2131,9 +2129,11 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void ResummonPetTemporaryUnSummonedIfAny();
bool IsPetNeedBeTemporaryUnsummoned() const;
- void SendCinematicStart(uint32 CinematicSequenceId) const;
+ void SendCinematicStart(uint32 CinematicSequenceId);
void SendMovieStart(uint32 MovieId) const;
+ uint32 DoRandomRoll(uint32 minimum, uint32 maximum);
+
/*********************************************************/
/*** INSTANCE SYSTEM ***/
/*********************************************************/
@@ -2267,6 +2267,17 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
std::string GetMapAreaAndZoneString() const;
std::string GetCoordsMapAreaAndZoneString() const;
+ // Cinematic camera data and remote sight functions
+ uint32 GetActiveCinematicCamera() const { return m_activeCinematicCameraId; }
+ void SetActiveCinematicCamera(uint32 cinematicCameraId = 0) { m_activeCinematicCameraId = cinematicCameraId; }
+ bool IsOnCinematic() const { return (m_cinematicCamera != nullptr); }
+ void BeginCinematic();
+ void EndCinematic();
+ void UpdateCinematicLocation(uint32 diff);
+
+ std::string GetMapAreaAndZoneString();
+ std::string GetCoordsMapAreaAndZoneString();
+
protected:
// Gamemaster whisper whitelist
GuidList WhisperList;
@@ -2501,10 +2512,10 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
// Player summoning
time_t m_summon_expire;
- uint32 m_summon_mapid;
- float m_summon_x;
- float m_summon_y;
- float m_summon_z;
+ WorldLocation m_summon_location;
+
+ // Recall position
+ WorldLocation m_recall_location;
DeclinedName *m_declinedname;
Runes *m_runes;
@@ -2592,6 +2603,14 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
uint32 manaBeforeDuel;
WorldLocation _corpseLocation;
+
+ // Remote location information
+ uint32 m_cinematicDiff;
+ uint32 m_lastCinematicCheck;
+ uint32 m_activeCinematicCameraId;
+ FlyByCameraCollection* m_cinematicCamera;
+ Position m_remoteSightPosition;
+ Creature* m_CinematicObject;
};
TC_GAME_API void AddItemsSetItem(Player* player, Item* item);
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 45577f5cf1c..ab0f286bca8 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -4185,6 +4185,16 @@ void Unit::RemoveArenaAuras()
}
}
+void Unit::RemoveAurasOnEvade()
+{
+ if (IsCharmedOwnedByPlayerOrPlayer()) // if it is a player owned creature it should not remove the aura
+ return;
+
+ // don't remove vehicle auras, passengers aren't supposed to drop off the vehicle
+ // don't remove clone caster on evade (to be verified)
+ RemoveAllAurasExceptType(SPELL_AURA_CONTROL_VEHICLE, SPELL_AURA_CLONE_CASTER);
+}
+
void Unit::RemoveAllAurasOnDeath()
{
// used just after dieing to remove all visible auras
@@ -8715,7 +8725,7 @@ void Unit::setPowerType(Powers new_powertype)
if (getPowerType() == new_powertype)
return;
- SetByteValue(UNIT_FIELD_BYTES_0, 3, new_powertype);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, new_powertype);
if (GetTypeId() == TYPEID_PLAYER)
{
@@ -9106,7 +9116,7 @@ bool Unit::AttackStop()
if (creature->HasSearchedAssistance())
{
creature->SetNoSearchAssistance(false);
- UpdateSpeed(MOVE_RUN, false);
+ UpdateSpeed(MOVE_RUN);
}
}
@@ -9440,7 +9450,7 @@ void Unit::SetMinion(Minion *minion, bool apply)
// FIXME: hack, speed must be set only at follow
if (GetTypeId() == TYPEID_PLAYER && minion->IsPet())
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
- minion->SetSpeed(UnitMoveType(i), m_speed_rate[i], true);
+ minion->SetSpeedRate(UnitMoveType(i), m_speed_rate[i]);
// Ghoul pets have energy instead of mana (is anywhere better place for this code?)
if (minion->IsPetGhoul() || minion->IsRisenAlly())
@@ -11870,9 +11880,9 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy)
if (IsPet())
{
- UpdateSpeed(MOVE_RUN, true);
- UpdateSpeed(MOVE_SWIM, true);
- UpdateSpeed(MOVE_FLIGHT, true);
+ UpdateSpeed(MOVE_RUN);
+ UpdateSpeed(MOVE_SWIM);
+ UpdateSpeed(MOVE_FLIGHT);
}
if (!(creature->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_MOUNTED_COMBAT))
@@ -11916,7 +11926,7 @@ void Unit::ClearInCombat()
if (Unit* owner = GetOwner())
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
if (owner->GetSpeedRate(UnitMoveType(i)) > GetSpeedRate(UnitMoveType(i)))
- SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true);
+ SetSpeedRate(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)));
}
else if (!IsCharmed())
return;
@@ -12003,25 +12013,26 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
|| target->GetReactionTo(this) > REP_NEUTRAL)
return false;
+ Player const* playerAffectingAttacker = HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? GetAffectingPlayer() : nullptr;
+ Player const* playerAffectingTarget = target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? target->GetAffectingPlayer() : nullptr;
+
// Not all neutral creatures can be attacked (even some unfriendly faction does not react aggresive to you, like Sporaggar)
- if (GetReactionTo(target) == REP_NEUTRAL &&
- target->GetReactionTo(this) <= REP_NEUTRAL)
+ if (
+ (playerAffectingAttacker && !playerAffectingTarget) ||
+ (!playerAffectingAttacker && playerAffectingTarget)
+ )
{
- if (!(target->GetTypeId() == TYPEID_PLAYER && GetTypeId() == TYPEID_PLAYER) &&
- !(target->GetTypeId() == TYPEID_UNIT && GetTypeId() == TYPEID_UNIT))
- {
- Player const* player = target->GetTypeId() == TYPEID_PLAYER ? target->ToPlayer() : ToPlayer();
- Unit const* creature = target->GetTypeId() == TYPEID_UNIT ? target : this;
+ Player const* player = playerAffectingAttacker ? playerAffectingAttacker : playerAffectingTarget;
+ Unit const* creature = playerAffectingAttacker ? target : this;
- if (FactionTemplateEntry const* factionTemplate = creature->GetFactionTemplateEntry())
- {
- if (!(player->GetReputationMgr().GetForcedRankIfAny(factionTemplate)))
- if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction))
- if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry))
- if (!(repState->Flags & FACTION_FLAG_AT_WAR))
- return false;
+ if (FactionTemplateEntry const* factionTemplate = creature->GetFactionTemplateEntry())
+ {
+ if (!(player->GetReputationMgr().GetForcedRankIfAny(factionTemplate)))
+ if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionTemplate->faction))
+ if (FactionState const* repState = player->GetReputationMgr().GetState(factionEntry))
+ if (!(repState->Flags & FACTION_FLAG_AT_WAR))
+ return false;
- }
}
}
@@ -12029,9 +12040,6 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
if (creatureAttacker && creatureAttacker->GetCreatureTemplate()->type_flags & CREATURE_TYPEFLAGS_PARTY_MEMBER)
return false;
- Player const* playerAffectingAttacker = HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? GetAffectingPlayer() : NULL;
- Player const* playerAffectingTarget = target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE) ? target->GetAffectingPlayer() : NULL;
-
// check duel - before sanctuary checks
if (playerAffectingAttacker && playerAffectingTarget)
if (playerAffectingAttacker->duel && playerAffectingAttacker->duel->opponent == playerAffectingTarget && playerAffectingAttacker->duel->startTime != 0)
@@ -12302,7 +12310,7 @@ void Unit::SetVisible(bool x)
UpdateObjectVisibility();
}
-void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
+void Unit::UpdateSpeed(UnitMoveType mtype)
{
int32 main_speed_mod = 0;
float stack_bonus = 1.0f;
@@ -12365,7 +12373,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
// Update speed for vehicle if available
if (GetTypeId() == TYPEID_PLAYER && GetVehicle())
- GetVehicleBase()->UpdateSpeed(MOVE_FLIGHT, true);
+ GetVehicleBase()->UpdateSpeed(MOVE_FLIGHT);
break;
}
default:
@@ -12447,7 +12455,7 @@ void Unit::UpdateSpeed(UnitMoveType mtype, bool forced)
speed = min_speed;
}
- SetSpeed(mtype, speed, forced);
+ SetSpeedRate(mtype, speed);
}
float Unit::GetSpeed(UnitMoveType mtype) const
@@ -12455,7 +12463,12 @@ float Unit::GetSpeed(UnitMoveType mtype) const
return m_speed_rate[mtype]*(IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype]);
}
-void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
+void Unit::SetSpeed(UnitMoveType mtype, float newValue)
+{
+ SetSpeedRate(mtype, newValue / (IsControlledByPlayer() ? playerBaseMoveSpeed[mtype] : baseMoveSpeed[mtype]));
+}
+
+void Unit::SetSpeedRate(UnitMoveType mtype, float rate)
{
if (rate < 0)
rate = 0.0f;
@@ -12468,100 +12481,59 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
propagateSpeedChange();
- WorldPacket data;
- if (!forced)
+ // Spline packets are for units controlled by AI. "Force speed change" (wrongly named opcodes) and "move set speed" packets are for units controlled by a player.
+ static Opcodes const moveTypeToOpcode[MAX_MOVE_TYPE][3] =
+ {
+ {SMSG_SPLINE_SET_WALK_SPEED, SMSG_FORCE_WALK_SPEED_CHANGE, MSG_MOVE_SET_WALK_SPEED },
+ {SMSG_SPLINE_SET_RUN_SPEED, SMSG_FORCE_RUN_SPEED_CHANGE, MSG_MOVE_SET_RUN_SPEED },
+ {SMSG_SPLINE_SET_RUN_BACK_SPEED, SMSG_FORCE_RUN_BACK_SPEED_CHANGE, MSG_MOVE_SET_RUN_BACK_SPEED },
+ {SMSG_SPLINE_SET_SWIM_SPEED, SMSG_FORCE_SWIM_SPEED_CHANGE, MSG_MOVE_SET_SWIM_SPEED },
+ {SMSG_SPLINE_SET_SWIM_BACK_SPEED, SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, MSG_MOVE_SET_SWIM_BACK_SPEED },
+ {SMSG_SPLINE_SET_TURN_RATE, SMSG_FORCE_TURN_RATE_CHANGE, MSG_MOVE_SET_TURN_RATE },
+ {SMSG_SPLINE_SET_FLIGHT_SPEED, SMSG_FORCE_FLIGHT_SPEED_CHANGE, MSG_MOVE_SET_FLIGHT_SPEED },
+ {SMSG_SPLINE_SET_FLIGHT_BACK_SPEED, SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, MSG_MOVE_SET_FLIGHT_BACK_SPEED },
+ {SMSG_SPLINE_SET_PITCH_RATE, SMSG_FORCE_PITCH_RATE_CHANGE, MSG_MOVE_SET_PITCH_RATE },
+ };
+
+ if (GetTypeId() == TYPEID_PLAYER)
{
- switch (mtype)
- {
- case MOVE_WALK:
- data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_RUN:
- data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_RUN_BACK:
- data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_SWIM:
- data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_SWIM_BACK:
- data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_TURN_RATE:
- data.Initialize(MSG_MOVE_SET_TURN_RATE, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_FLIGHT:
- data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_FLIGHT_BACK:
- data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8+4+2+4+4+4+4+4+4+4);
- break;
- case MOVE_PITCH_RATE:
- data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8+4+2+4+4+4+4+4+4+4);
- break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype);
- return;
- }
+ // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
+ // and do it only for real sent packets and use run for run/mounted as client expected
+ ++ToPlayer()->m_forced_speed_changes[mtype];
+ if (!IsInCombat())
+ if (Pet* pet = ToPlayer()->GetPet())
+ pet->SetSpeedRate(mtype, m_speed_rate[mtype]);
+ }
+
+ if (m_movedPlayer) // unit controlled by a player.
+ {
+ // Send notification to self. this packet is only sent to one client (the client of the player concerned by the change).
+ WorldPacket self;
+ self.Initialize(moveTypeToOpcode[mtype][1], mtype != MOVE_RUN ? 8 + 4 + 4 : 8 + 4 + 1 + 4);
+ self << GetPackGUID();
+ self << (uint32)0; // Movement counter. Unimplemented at the moment! NUM_PMOVE_EVTS = 0x39Z.
+ if (mtype == MOVE_RUN)
+ self << uint8(1); // unknown byte added in 2.1.0
+ self << float(GetSpeed(mtype));
+ m_movedPlayer->GetSession()->SendPacket(&self);
+
+ // Send notification to other players. sent to every clients (if in range) except one: the client of the player concerned by the change.
+ WorldPacket data;
+ data.Initialize(moveTypeToOpcode[mtype][2], 8 + 30 + 4);
data << GetPackGUID();
BuildMovementPacket(&data);
data << float(GetSpeed(mtype));
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
}
- else
+ else // unit controlled by AI.
{
- if (GetTypeId() == TYPEID_PLAYER)
- {
- // register forced speed changes for WorldSession::HandleForceSpeedChangeAck
- // and do it only for real sent packets and use run for run/mounted as client expected
- ++ToPlayer()->m_forced_speed_changes[mtype];
-
- if (!IsInCombat())
- if (Pet* pet = ToPlayer()->GetPet())
- pet->SetSpeed(mtype, m_speed_rate[mtype], forced);
- }
-
- switch (mtype)
- {
- case MOVE_WALK:
- data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16);
- break;
- case MOVE_RUN:
- data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17);
- break;
- case MOVE_RUN_BACK:
- data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16);
- break;
- case MOVE_SWIM:
- data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16);
- break;
- case MOVE_SWIM_BACK:
- data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16);
- break;
- case MOVE_TURN_RATE:
- data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16);
- break;
- case MOVE_FLIGHT:
- data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16);
- break;
- case MOVE_FLIGHT_BACK:
- data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16);
- break;
- case MOVE_PITCH_RATE:
- data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16);
- break;
- default:
- TC_LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type (%d), data not sent to client.", mtype);
- return;
- }
+ // send notification to every clients.
+ WorldPacket data;
+ data.Initialize(moveTypeToOpcode[mtype][0], 8 + 4);
data << GetPackGUID();
- data << (uint32)0; // moveEvent, NUM_PMOVE_EVTS = 0x39
- if (mtype == MOVE_RUN)
- data << uint8(0); // new 2.1.0
data << float(GetSpeed(mtype));
- SendMessageToSet(&data, true);
+ SendMessageToSet(&data, false);
}
}
@@ -12827,7 +12799,7 @@ Unit* Creature::SelectVictim()
if (target && _IsTargetAcceptable(target) && CanCreatureAttack(target))
{
- if(!IsFocusing())
+ if (!IsFocusing())
SetInFront(target);
return target;
}
@@ -13740,6 +13712,9 @@ void Unit::UpdateCharmAI()
delete i_AI;
i_AI = i_disabledAI;
i_disabledAI = nullptr;
+
+ if (GetTypeId() == TYPEID_UNIT)
+ ToCreature()->AI()->OnCharmed(false);
}
}
else
@@ -14769,7 +14744,7 @@ void Unit::SetDisplayId(uint32 modelId)
SetUInt32Value(UNIT_FIELD_DISPLAYID, modelId);
// Set Gender by modelId
if (CreatureModelInfo const* minfo = sObjectMgr->GetCreatureModelInfo(modelId))
- SetByteValue(UNIT_FIELD_BYTES_0, 2, minfo->gender);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, minfo->gender);
}
void Unit::RestoreDisplayId()
@@ -15625,12 +15600,19 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
Player* creditedPlayer = GetCharmerOrOwnerPlayerOrPlayerItself();
/// @todo do instance binding anyway if the charmer/owner is offline
- if (instanceMap->IsDungeon() && creditedPlayer)
+ if (instanceMap->IsDungeon() && (creditedPlayer || this == victim))
{
if (instanceMap->IsRaidOrHeroicDungeon())
{
if (creature->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
- ((InstanceMap*)instanceMap)->PermBindAllPlayers(creditedPlayer);
+ {
+ // if the boss killed itself we still need to bind players to the instance
+ if (!creditedPlayer && instanceMap->HavePlayers())
+ creditedPlayer = instanceMap->GetPlayers().getFirst()->GetSource();
+
+ if (creditedPlayer)
+ ((InstanceMap*)instanceMap)->PermBindAllPlayers(creditedPlayer);
+ }
}
else
{
@@ -15638,7 +15620,8 @@ void Unit::Kill(Unit* victim, bool durabilityLoss)
// until the players leave the instance
time_t resettime = creature->GetRespawnTimeEx() + 2 * HOUR;
if (InstanceSave* save = sInstanceSaveMgr->GetInstanceSave(creature->GetInstanceId()))
- if (save->GetResetTime() < resettime) save->SetResetTime(resettime);
+ if (save->GetResetTime() < resettime)
+ save->SetResetTime(resettime);
}
}
}
@@ -16080,7 +16063,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
{
// to prevent client crash
- SetByteValue(UNIT_FIELD_BYTES_0, 1, (uint8)CLASS_MAGE);
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, (uint8)CLASS_MAGE);
// just to enable stat window
if (GetCharmInfo())
@@ -16182,7 +16165,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
{
- SetByteValue(UNIT_FIELD_BYTES_0, 1, uint8(cinfo->unit_class));
+ SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, uint8(cinfo->unit_class));
if (GetCharmInfo())
GetCharmInfo()->SetPetNumber(0, true);
else
@@ -16700,7 +16683,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
// Based on Hair color
if (getRace() == RACE_NIGHTELF)
{
- uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
+ uint8 hairColor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID);
switch (hairColor)
{
case 7: // Violet
@@ -16721,7 +16704,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
// Based on Skin color
else if (getRace() == RACE_TAUREN)
{
- uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
+ uint8 skinColor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID);
// Male
if (getGender() == GENDER_MALE)
{
@@ -16780,7 +16763,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
// Based on Hair color
if (getRace() == RACE_NIGHTELF)
{
- uint8 hairColor = GetByteValue(PLAYER_BYTES, 3);
+ uint8 hairColor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID);
switch (hairColor)
{
case 0: // Green
@@ -16800,7 +16783,7 @@ uint32 Unit::GetModelForForm(ShapeshiftForm form) const
// Based on Skin color
else if (getRace() == RACE_TAUREN)
{
- uint8 skinColor = GetByteValue(PLAYER_BYTES, 0);
+ uint8 skinColor = GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID);
// Male
if (getGender() == GENDER_MALE)
{
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index cc1f6465766..1a6fbeb44fb 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -190,6 +190,30 @@ enum UnitStandFlags
UNIT_STAND_FLAGS_ALL = 0xFF
};
+enum UnitBytes0Offsets
+{
+ UNIT_BYTES_0_OFFSET_RACE = 0,
+ UNIT_BYTES_0_OFFSET_CLASS = 1,
+ UNIT_BYTES_0_OFFSET_GENDER = 2,
+ UNIT_BYTES_0_OFFSET_POWER_TYPE = 3,
+};
+
+enum UnitBytes1Offsets
+{
+ UNIT_BYTES_1_OFFSET_STAND_STATE = 0,
+ UNIT_BYTES_1_OFFSET_PET_TALENTS = 1,
+ UNIT_BYTES_1_OFFSET_VIS_FLAG = 2,
+ UNIT_BYTES_1_OFFSET_ANIM_TIER = 3
+};
+
+enum UnitBytes2Offsets
+{
+ UNIT_BYTES_2_OFFSET_SHEATH_STATE = 0,
+ UNIT_BYTES_2_OFFSET_PVP_FLAG = 1,
+ UNIT_BYTES_2_OFFSET_PET_FLAG = 2,
+ UNIT_BYTES_2_OFFSET_SHAPESHIFT = 3,
+};
+
// byte flags value (UNIT_FIELD_BYTES_1, 3)
enum UnitBytes1_Flags
{
@@ -1314,11 +1338,11 @@ class TC_GAME_API Unit : public WorldObject
uint8 getLevel() const { return uint8(GetUInt32Value(UNIT_FIELD_LEVEL)); }
uint8 getLevelForTarget(WorldObject const* /*target*/) const override { return getLevel(); }
void SetLevel(uint8 lvl);
- uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, 0); }
+ uint8 getRace() const { return GetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_RACE); }
uint32 getRaceMask() const { return 1 << (getRace()-1); }
- uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); }
+ uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS); }
uint32 getClassMask() const { return 1 << (getClass()-1); }
- uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); }
+ uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER); }
float GetStat(Stats stat) const { return float(GetUInt32Value(UNIT_FIELD_STAT0+stat)); }
void SetStat(Stats stat, int32 val) { SetStatInt32Value(UNIT_FIELD_STAT0+stat, val); }
@@ -1347,7 +1371,7 @@ class TC_GAME_API Unit : public WorldObject
int32 ModifyHealth(int32 val);
int32 GetHealthGain(int32 dVal);
- Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
+ Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE)); }
void setPowerType(Powers power);
uint32 GetPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_POWER1 +power); }
uint32 GetMaxPower(Powers power) const { return GetUInt32Value(UNIT_FIELD_MAXPOWER1+power); }
@@ -1731,6 +1755,7 @@ class TC_GAME_API Unit : public WorldObject
void RemoveAreaAurasDueToLeaveWorld();
void RemoveAllAuras();
void RemoveArenaAuras();
+ void RemoveAurasOnEvade();
void RemoveAllAurasOnDeath();
void RemoveAllAurasRequiringDeadTarget();
void RemoveAllAurasExceptType(AuraType type);
@@ -1994,10 +2019,11 @@ class TC_GAME_API Unit : public WorldObject
void CalcAbsorbResist(Unit* victim, SpellSchoolMask schoolMask, DamageEffectType damagetype, uint32 const damage, uint32* absorb, uint32* resist, SpellInfo const* spellInfo = NULL);
void CalcHealAbsorb(Unit* victim, SpellInfo const* spellInfo, uint32& healAmount, uint32& absorb);
- void UpdateSpeed(UnitMoveType mtype, bool forced);
+ void UpdateSpeed(UnitMoveType mtype);
float GetSpeed(UnitMoveType mtype) const;
float GetSpeedRate(UnitMoveType mtype) const { return m_speed_rate[mtype]; }
- void SetSpeed(UnitMoveType mtype, float rate, bool forced = false);
+ void SetSpeed(UnitMoveType mtype, float newValue);
+ void SetSpeedRate(UnitMoveType mtype, float rate);
float ApplyEffectModifiers(SpellInfo const* spellProto, uint8 effect_index, float value) const;
int32 CalculateSpellDamage(Unit const* target, SpellInfo const* spellProto, uint8 effect_index, int32 const* basePoints = NULL) const;
@@ -2141,11 +2167,11 @@ class TC_GAME_API Unit : public WorldObject
virtual void Yell(std::string const& text, Language language, WorldObject const* target = nullptr);
virtual void TextEmote(std::string const& text, WorldObject const* target = nullptr, bool isBossEmote = false);
virtual void Whisper(std::string const& text, Language language, Player* target, bool isBossWhisper = false);
- void Talk(uint32 textId, ChatMsg msgType, float textRange, WorldObject const* target);
- void Say(uint32 textId, WorldObject const* target = nullptr);
- void Yell(uint32 textId, WorldObject const* target = nullptr);
- void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false);
- void Whisper(uint32 textId, Player* target, bool isBossWhisper = false);
+ virtual void Talk(uint32 textId, ChatMsg msgType, float textRange, WorldObject const* target);
+ virtual void Say(uint32 textId, WorldObject const* target = nullptr);
+ virtual void Yell(uint32 textId, WorldObject const* target = nullptr);
+ virtual void TextEmote(uint32 textId, WorldObject const* target = nullptr, bool isBossEmote = false);
+ virtual void Whisper(uint32 textId, Player* target, bool isBossWhisper = false);
protected:
explicit Unit (bool isWorldObject);
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 3098fec9b1f..fc0abf5a8c7 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -4715,7 +4715,7 @@ void ObjectMgr::LoadScripts(ScriptsType type)
if (tableName.empty())
return;
- if (sScriptMgr->IsScriptScheduled()) // function cannot be called when scripts are in use.
+ if (sMapMgr->IsScriptScheduled()) // function cannot be called when scripts are in use.
return;
TC_LOG_INFO("server.loading", "Loading %s...", tableName.c_str());
@@ -5162,7 +5162,7 @@ void ObjectMgr::LoadSpellScriptNames()
while (spellInfo)
{
- _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName)));
+ _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, std::make_pair(GetScriptId(scriptName), true)));
spellInfo = spellInfo->GetNextRankSpell();
}
}
@@ -5171,7 +5171,7 @@ void ObjectMgr::LoadSpellScriptNames()
if (spellInfo->IsRanked())
TC_LOG_ERROR("sql.sql", "Scriptname: `%s` spell (Id: %d) is ranked spell. Perhaps not all ranks are assigned to this script.", scriptName.c_str(), spellId);
- _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, GetScriptId(scriptName)));
+ _spellScriptsStore.insert(SpellScriptsContainer::value_type(spellInfo->Id, std::make_pair(GetScriptId(scriptName), true)));
}
++count;
@@ -5193,45 +5193,59 @@ void ObjectMgr::ValidateSpellScripts()
uint32 count = 0;
- for (SpellScriptsContainer::iterator itr = _spellScriptsStore.begin(); itr != _spellScriptsStore.end();)
+ for (auto spell : _spellScriptsStore)
{
- SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(itr->first);
- std::vector<std::pair<SpellScriptLoader *, SpellScriptsContainer::iterator> > SpellScriptLoaders;
- sScriptMgr->CreateSpellScriptLoaders(itr->first, SpellScriptLoaders);
- itr = _spellScriptsStore.upper_bound(itr->first);
+ SpellInfo const* spellEntry = sSpellMgr->GetSpellInfo(spell.first);
- for (std::vector<std::pair<SpellScriptLoader *, SpellScriptsContainer::iterator> >::iterator sitr = SpellScriptLoaders.begin(); sitr != SpellScriptLoaders.end(); ++sitr)
+ auto const bounds = sObjectMgr->GetSpellScriptsBounds(spell.first);
+
+ for (auto itr = bounds.first; itr != bounds.second; ++itr)
{
- SpellScript* spellScript = sitr->first->GetSpellScript();
- AuraScript* auraScript = sitr->first->GetAuraScript();
- bool valid = true;
- if (!spellScript && !auraScript)
- {
- TC_LOG_ERROR("scripts", "Functions GetSpellScript() and GetAuraScript() of script `%s` do not return objects - script skipped", GetScriptName(sitr->second->second).c_str());
- valid = false;
- }
- if (spellScript)
- {
- spellScript->_Init(&sitr->first->GetName(), spellEntry->Id);
- spellScript->_Register();
- if (!spellScript->_Validate(spellEntry))
- valid = false;
- delete spellScript;
- }
- if (auraScript)
+ if (SpellScriptLoader* spellScriptLoader = sScriptMgr->GetSpellScriptLoader(itr->second.first))
{
- auraScript->_Init(&sitr->first->GetName(), spellEntry->Id);
- auraScript->_Register();
- if (!auraScript->_Validate(spellEntry))
- valid = false;
- delete auraScript;
- }
- if (!valid)
- {
- _spellScriptsStore.erase(sitr->second);
+ ++count;
+
+ std::unique_ptr<SpellScript> spellScript(spellScriptLoader->GetSpellScript());
+ std::unique_ptr<AuraScript> auraScript(spellScriptLoader->GetAuraScript());
+
+ if (!spellScript && !auraScript)
+ {
+ TC_LOG_ERROR("scripts", "Functions GetSpellScript() and GetAuraScript() of script `%s` do not return objects - script skipped", GetScriptName(itr->second.first).c_str());
+
+ itr->second.second = false;
+ continue;
+ }
+
+ if (spellScript)
+ {
+ spellScript->_Init(&spellScriptLoader->GetName(), spellEntry->Id);
+ spellScript->_Register();
+
+ if (!spellScript->_Validate(spellEntry))
+ {
+ itr->second.second = false;
+ continue;
+ }
+ }
+
+ if (auraScript)
+ {
+ auraScript->_Init(&spellScriptLoader->GetName(), spellEntry->Id);
+ auraScript->_Register();
+
+ if (!auraScript->_Validate(spellEntry))
+ {
+ itr->second.second = false;
+ continue;
+ }
+ }
+
+ // Enable the script when all checks passed
+ itr->second.second = true;
}
+ else
+ itr->second.second = false;
}
- ++count;
}
TC_LOG_INFO("server.loading", ">> Validated %u scripts in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
@@ -8571,6 +8585,8 @@ void ObjectMgr::LoadScriptNames()
{
uint32 oldMSTime = getMSTime();
+ // We insert an empty placeholder here so we can use the
+ // script id 0 as dummy for "no script found".
_scriptNamesStore.emplace_back("");
QueryResult result = WorldDatabase.Query(
@@ -8612,18 +8628,18 @@ void ObjectMgr::LoadScriptNames()
std::sort(_scriptNamesStore.begin(), _scriptNamesStore.end());
-#ifdef SCRIPTS
- for (size_t i = 1; i < _scriptNamesStore.size(); ++i)
- UnusedScriptNames.push_back(_scriptNamesStore[i]);
-#endif
-
TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " ScriptNames in %u ms", _scriptNamesStore.size(), GetMSTimeDiffToNow(oldMSTime));
}
+ObjectMgr::ScriptNameContainer const& ObjectMgr::GetAllScriptNames() const
+{
+ return _scriptNamesStore;
+}
+
std::string const& ObjectMgr::GetScriptName(uint32 id) const
{
static std::string const empty = "";
- return id < _scriptNamesStore.size() ? _scriptNamesStore[id] : empty;
+ return (id < _scriptNamesStore.size()) ? _scriptNamesStore[id] : empty;
}
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 73c03849699..576a8d2ccac 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -370,7 +370,7 @@ struct ScriptInfo
typedef std::multimap<uint32, ScriptInfo> ScriptMap;
typedef std::map<uint32, ScriptMap > ScriptMapMap;
-typedef std::multimap<uint32, uint32> SpellScriptsContainer;
+typedef std::multimap<uint32 /*spell id*/, std::pair<uint32 /*script id*/, bool /*enabled*/>> SpellScriptsContainer;
typedef std::pair<SpellScriptsContainer::iterator, SpellScriptsContainer::iterator> SpellScriptsBounds;
TC_GAME_API extern ScriptMapMap sSpellScripts;
TC_GAME_API extern ScriptMapMap sEventScripts;
@@ -1272,6 +1272,7 @@ class TC_GAME_API ObjectMgr
bool IsVendorItemValid(uint32 vendor_entry, uint32 item, int32 maxcount, uint32 ptime, uint32 ExtendedCost, Player* player = NULL, std::set<uint32>* skip_vendors = NULL, uint32 ORnpcflag = 0) const;
void LoadScriptNames();
+ ScriptNameContainer const& GetAllScriptNames() const;
std::string const& GetScriptName(uint32 id) const;
uint32 GetScriptId(std::string const& name);
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index c3c78a4cf66..19638ec1bf8 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -642,7 +642,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
TC_LOG_INFO("entities.player.character", "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), GetRemoteAddress().c_str(), createInfo->Name.c_str(), newChar.GetGUID().GetCounter());
sScriptMgr->OnPlayerCreate(&newChar);
- sWorld->AddCharacterInfo(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.GetByteValue(PLAYER_BYTES_3, 0), newChar.getRace(), newChar.getClass(), newChar.getLevel());
+ sWorld->AddCharacterInfo(newChar.GetGUID(), GetAccountId(), newChar.GetName(), newChar.GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER), newChar.getRace(), newChar.getClass(), newChar.getLevel());
newChar.CleanupsBeforeDelete();
delete createInfo;
@@ -1242,20 +1242,25 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData)
BarberShopStyleEntry const* bs_hair = sBarberShopStyleStore.LookupEntry(Hair);
- if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->GetByteValue(PLAYER_BYTES_3, 0))
+ if (!bs_hair || bs_hair->type != 0 || bs_hair->race != _player->getRace() || bs_hair->gender != _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER))
return;
BarberShopStyleEntry const* bs_facialHair = sBarberShopStyleStore.LookupEntry(FacialHair);
- if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->GetByteValue(PLAYER_BYTES_3, 0))
+ if (!bs_facialHair || bs_facialHair->type != 2 || bs_facialHair->race != _player->getRace() || bs_facialHair->gender != _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER))
return;
BarberShopStyleEntry const* bs_skinColor = sBarberShopStyleStore.LookupEntry(SkinColor);
- if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->GetByteValue(PLAYER_BYTES_3, 0)))
+ if (bs_skinColor && (bs_skinColor->type != 3 || bs_skinColor->race != _player->getRace() || bs_skinColor->gender != _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER)))
return;
- if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->GetByteValue(PLAYER_BYTES_3, 0), bs_hair->hair_id, Color, _player->GetByteValue(PLAYER_BYTES, 1), bs_facialHair->hair_id, bs_skinColor ? bs_skinColor->hair_id : _player->GetByteValue(PLAYER_BYTES, 0)))
+ if (!Player::ValidateAppearance(_player->getRace(), _player->getClass(), _player->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER),
+ bs_hair->hair_id,
+ Color,
+ _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID),
+ bs_facialHair->hair_id,
+ bs_skinColor ? bs_skinColor->hair_id : _player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID)))
return;
GameObject* go = _player->FindNearestGameObjectOfType(GAMEOBJECT_TYPE_BARBER_CHAIR, 5.0f);
@@ -1287,11 +1292,11 @@ void WorldSession::HandleAlterAppearance(WorldPacket& recvData)
_player->ModifyMoney(-int32(cost)); // it isn't free
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER, cost);
- _player->SetByteValue(PLAYER_BYTES, 2, uint8(bs_hair->hair_id));
- _player->SetByteValue(PLAYER_BYTES, 3, uint8(Color));
- _player->SetByteValue(PLAYER_BYTES_2, 0, uint8(bs_facialHair->hair_id));
+ _player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID, uint8(bs_hair->hair_id));
+ _player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID, uint8(Color));
+ _player->SetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE, uint8(bs_facialHair->hair_id));
if (bs_skinColor)
- _player->SetByteValue(PLAYER_BYTES, 0, uint8(bs_skinColor->hair_id));
+ _player->SetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID, uint8(bs_skinColor->hair_id));
_player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP, 1);
diff --git a/src/server/game/Handlers/GroupHandler.cpp b/src/server/game/Handlers/GroupHandler.cpp
index 84cbb86345d..1c1982600ca 100644
--- a/src/server/game/Handlers/GroupHandler.cpp
+++ b/src/server/game/Handlers/GroupHandler.cpp
@@ -488,9 +488,7 @@ void WorldSession::HandleMinimapPingOpcode(WorldPacket& recvData)
void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData)
{
- TC_LOG_DEBUG("network", "WORLD: Received MSG_RANDOM_ROLL");
-
- uint32 minimum, maximum, roll;
+ uint32 minimum, maximum;
recvData >> minimum;
recvData >> maximum;
@@ -499,20 +497,7 @@ void WorldSession::HandleRandomRollOpcode(WorldPacket& recvData)
return;
/********************/
- // everything's fine, do it
- roll = urand(minimum, maximum);
-
- //TC_LOG_DEBUG("ROLL: MIN: %u, MAX: %u, ROLL: %u", minimum, maximum, roll);
-
- WorldPacket data(MSG_RANDOM_ROLL, 4+4+4+8);
- data << uint32(minimum);
- data << uint32(maximum);
- data << uint32(roll);
- data << uint64(GetPlayer()->GetGUID());
- if (GetPlayer()->GetGroup())
- GetPlayer()->GetGroup()->BroadcastPacket(&data, false);
- else
- SendPacket(&data);
+ GetPlayer()->DoRandomRoll(minimum, maximum);
}
void WorldSession::HandleRaidTargetUpdateOpcode(WorldPacket& recvData)
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index 8ae37065726..629c6f42d15 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -284,7 +284,7 @@ void WorldSession::HandleWhoOpcode(WorldPacket& recvData)
continue;
uint32 pzoneid = target->GetZoneId();
- uint8 gender = target->GetByteValue(PLAYER_BYTES_3, 0);
+ uint8 gender = target->GetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER);
bool z_show = true;
for (uint32 i = 0; i < zones_count; ++i)
@@ -884,15 +884,15 @@ void WorldSession::HandleAreaTriggerOpcode(WorldPacket& recvData)
player->SendTransferAborted(entry->MapID, TRANSFER_ABORT_DIFFICULTY, player->GetDifficulty(entry->IsRaid()));
break;
case Map::CANNOT_ENTER_NOT_IN_RAID:
- if (MapEntry const* entry = sMapStore.LookupEntry(at->target_mapId))
- {
- char const* mapName = entry->name[player->GetSession()->GetSessionDbcLocale()];
- TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance '%s'", player->GetName().c_str(), mapName);
- // probably there must be special opcode, because client has this string constant in GlobalStrings.lua
- player->GetSession()->SendAreaTriggerMessage(player->GetSession()->GetTrinityString(LANG_INSTANCE_RAID_GROUP_ONLY), mapName);
- }
+ {
+ WorldPacket data(SMSG_RAID_GROUP_ONLY, 4 + 4);
+ data << uint32(0);
+ data << uint32(2); // You must be in a raid group to enter this instance.
+ player->GetSession()->SendPacket(&data);
+ TC_LOG_DEBUG("maps", "MAP: Player '%s' must be in a raid group to enter instance map %d", player->GetName().c_str(), at->target_mapId);
reviveAtTrigger = true;
break;
+ }
case Map::CANNOT_ENTER_CORPSE_IN_DIFFERENT_INSTANCE:
{
WorldPacket data(SMSG_CORPSE_NOT_IN_INSTANCE);
@@ -1056,12 +1056,14 @@ void WorldSession::HandleSetActionButtonOpcode(WorldPacket& recvData)
void WorldSession::HandleCompleteCinematic(WorldPacket& /*recvData*/)
{
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_COMPLETE_CINEMATIC");
+ // If player has sight bound to visual waypoint NPC we should remove it
+ GetPlayer()->EndCinematic();
}
void WorldSession::HandleNextCinematicCamera(WorldPacket& /*recvData*/)
{
- TC_LOG_DEBUG("network", "WORLD: Received CMSG_NEXT_CINEMATIC_CAMERA");
+ // Sent by client when cinematic actually begun. So we begin the server side process
+ GetPlayer()->BeginCinematic();
}
void WorldSession::HandleMoveTimeSkippedOpcode(WorldPacket& recvData)
@@ -1157,7 +1159,7 @@ void WorldSession::HandleSetActionBarToggles(WorldPacket& recvData)
return;
}
- GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, 2, actionBar);
+ GetPlayer()->SetByteValue(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_ACTION_BAR_TOGGLES, actionBar);
}
void WorldSession::HandlePlayedTime(WorldPacket& recvData)
diff --git a/src/server/game/Handlers/MovementHandler.cpp b/src/server/game/Handlers/MovementHandler.cpp
index 02702fc5622..64f927a987f 100644
--- a/src/server/game/Handlers/MovementHandler.cpp
+++ b/src/server/game/Handlers/MovementHandler.cpp
@@ -473,7 +473,7 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket &recvData)
{
TC_LOG_ERROR("network", "%sSpeedChange player %s is NOT correct (must be %f instead %f), force set to correct value",
move_type_name[move_type], _player->GetName().c_str(), _player->GetSpeed(move_type), newspeed);
- _player->SetSpeed(move_type, _player->GetSpeedRate(move_type), true);
+ _player->SetSpeedRate(move_type, _player->GetSpeedRate(move_type));
}
else // must be lesser - cheating
{
diff --git a/src/server/game/Handlers/SpellHandler.cpp b/src/server/game/Handlers/SpellHandler.cpp
index 6be1fd30ae3..e07e10ab00c 100644
--- a/src/server/game/Handlers/SpellHandler.cpp
+++ b/src/server/game/Handlers/SpellHandler.cpp
@@ -594,11 +594,11 @@ void WorldSession::HandleMirrorImageDataRequest(WorldPacket& recvData)
if (creator->GetTypeId() == TYPEID_PLAYER)
{
Player* player = creator->ToPlayer();
- data << uint8(player->GetByteValue(PLAYER_BYTES, 0)); // skin
- data << uint8(player->GetByteValue(PLAYER_BYTES, 1)); // face
- data << uint8(player->GetByteValue(PLAYER_BYTES, 2)); // hair
- data << uint8(player->GetByteValue(PLAYER_BYTES, 3)); // haircolor
- data << uint8(player->GetByteValue(PLAYER_BYTES_2, 0)); // facialhair
+ data << uint8(player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID));
+ data << uint8(player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID));
+ data << uint8(player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_STYLE_ID));
+ data << uint8(player->GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID));
+ data << uint8(player->GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE));
data << uint32(player->GetGuildId()); // unk
static EquipmentSlots const itemSlots[] =
diff --git a/src/server/game/Instances/InstanceScript.cpp b/src/server/game/Instances/InstanceScript.cpp
index 1575b50098f..0887d183a8b 100644
--- a/src/server/game/Instances/InstanceScript.cpp
+++ b/src/server/game/Instances/InstanceScript.cpp
@@ -29,6 +29,8 @@
#include "Pet.h"
#include "WorldSession.h"
#include "Opcodes.h"
+#include "ScriptReloadMgr.h"
+#include "ScriptMgr.h"
BossBoundaryData::~BossBoundaryData()
{
@@ -36,6 +38,18 @@ BossBoundaryData::~BossBoundaryData()
delete it->Boundary;
}
+InstanceScript::InstanceScript(Map* map) : instance(map), completedEncounters(0)
+{
+#ifdef TRINITY_API_USE_DYNAMIC_LINKING
+ uint32 scriptId = sObjectMgr->GetInstanceTemplate(map->GetId())->ScriptId;
+ auto const scriptname = sObjectMgr->GetScriptName(scriptId);
+ ASSERT(!scriptname.empty());
+ // Acquire a strong reference from the script module
+ // to keep it loaded until this object is destroyed.
+ module_reference = sScriptMgr->AcquireModuleReferenceOfScriptName(scriptname);
+#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING
+}
+
void InstanceScript::SaveToDB()
{
std::string data = GetSaveData();
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index 949cdf5abcb..3814afe2f4b 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -36,6 +36,7 @@ class Unit;
class Player;
class GameObject;
class Creature;
+class ModuleReference;
enum EncounterFrameType
{
@@ -137,7 +138,7 @@ typedef std::map<uint32 /*entry*/, uint32 /*type*/> ObjectInfoMap;
class TC_GAME_API InstanceScript : public ZoneScript
{
public:
- explicit InstanceScript(Map* map) : instance(map), completedEncounters(0) { }
+ explicit InstanceScript(Map* map);
virtual ~InstanceScript() { }
@@ -289,6 +290,11 @@ class TC_GAME_API InstanceScript : public ZoneScript
ObjectInfoMap _gameObjectInfo;
ObjectGuidMap _objectGuids;
uint32 completedEncounters; // completed encounter mask, bit indexes are DungeonEncounter.dbc boss numbers, used for packets
+
+ #ifdef TRINITY_API_USE_DYNAMIC_LINKING
+ // Strong reference to the associated script module
+ std::shared_ptr<ModuleReference> module_reference;
+ #endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING
};
template<class AI, class T>
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 8640150d86b..794be12ee7c 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -17,6 +17,7 @@
*/
#include "Map.h"
+#include "MapManager.h"
#include "Battleground.h"
#include "MMapFactory.h"
#include "CellImpl.h"
@@ -64,7 +65,7 @@ Map::~Map()
}
if (!m_scriptSchedule.empty())
- sScriptMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size());
+ sMapMgr->DecreaseScheduledScriptCount(m_scriptSchedule.size());
MMAP::MMapFactory::createOrGetMMapManager()->unloadMapInstance(GetId(), i_InstanceId);
}
@@ -713,6 +714,15 @@ void Map::Update(const uint32 t_diff)
VisitNearbyCellsOf(player, grid_object_update, world_object_update);
+ // If player is using far sight, visit that object too
+ if (WorldObject* viewPoint = player->GetViewpoint())
+ {
+ if (Creature* viewCreature = viewPoint->ToCreature())
+ VisitNearbyCellsOf(viewCreature, grid_object_update, world_object_update);
+ else if (DynamicObject* viewObject = viewPoint->ToDynObject())
+ VisitNearbyCellsOf(viewObject, grid_object_update, world_object_update);
+ }
+
// Handle updates for creatures in combat with player and are more than 60 yards away
if (player->IsInCombat())
{
@@ -2335,9 +2345,9 @@ float Map::GetHeight(float x, float y, float z, bool checkVMap /*= true*/, float
{
// we have mapheight and vmapheight and must select more appropriate
- // we are already under the surface or vmap height above map heigt
+ // vmap height above map height
// or if the distance of the vmap height is less the land height distance
- if (z < mapHeight || vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z))
+ if (vmapHeight > mapHeight || std::fabs(mapHeight - z) > std::fabs(vmapHeight - z))
return vmapHeight;
else
return mapHeight; // better use .map surface height
@@ -2657,8 +2667,8 @@ void Map::UpdateObjectsVisibilityFor(Player* player, Cell cell, CellCoord cellpa
cell.SetNoCreate();
TypeContainerVisitor<Trinity::VisibleNotifier, WorldTypeMapContainer > world_notifier(notifier);
TypeContainerVisitor<Trinity::VisibleNotifier, GridTypeMapContainer > grid_notifier(notifier);
- cell.Visit(cellpair, world_notifier, *this, *player, player->GetSightRange());
- cell.Visit(cellpair, grid_notifier, *this, *player, player->GetSightRange());
+ cell.Visit(cellpair, world_notifier, *this, *player->m_seer, player->GetSightRange());
+ cell.Visit(cellpair, grid_notifier, *this, *player->m_seer, player->GetSightRange());
// send data
notifier.SendToSelf();
diff --git a/src/server/game/Maps/MapManager.cpp b/src/server/game/Maps/MapManager.cpp
index c1882b3dc75..79a8b3855e8 100644
--- a/src/server/game/Maps/MapManager.cpp
+++ b/src/server/game/Maps/MapManager.cpp
@@ -38,10 +38,10 @@
#include "AchievementMgr.h"
MapManager::MapManager()
+ : _nextInstanceId(0), _scheduledScripts(0)
{
i_gridCleanUpDelay = sWorld->getIntConfig(CONFIG_INTERVAL_GRIDCLEAN);
i_timer.SetInterval(sWorld->getIntConfig(CONFIG_INTERVAL_MAPUPDATE));
- _nextInstanceId = 0;
}
MapManager::~MapManager() { }
diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h
index e74453a1196..a7fdc37d324 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -126,6 +126,11 @@ class TC_GAME_API MapManager
template<typename Worker>
void DoForAllMapsWithMapId(uint32 mapId, Worker&& worker);
+ uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; }
+ uint32 DecreaseScheduledScriptCount() { return --_scheduledScripts; }
+ uint32 DecreaseScheduledScriptCount(size_t count) { return _scheduledScripts -= count; }
+ bool IsScriptScheduled() const { return _scheduledScripts > 0; }
+
private:
typedef std::unordered_map<uint32, Map*> MapMapType;
typedef std::vector<bool> InstanceIds;
@@ -150,6 +155,9 @@ class TC_GAME_API MapManager
InstanceIds _instanceIds;
uint32 _nextInstanceId;
MapUpdater m_updater;
+
+ // atomic op counter for active scripts amount
+ std::atomic<uint32> _scheduledScripts;
};
template<typename Worker>
diff --git a/src/server/game/Scripting/MapScripts.cpp b/src/server/game/Maps/MapScripts.cpp
index a01c109b9ca..c5d7bdc64ce 100644
--- a/src/server/game/Scripting/MapScripts.cpp
+++ b/src/server/game/Maps/MapScripts.cpp
@@ -21,6 +21,7 @@
#include "GridNotifiersImpl.h"
#include "GossipDef.h"
#include "Map.h"
+#include "MapManager.h"
#include "ObjectMgr.h"
#include "Pet.h"
#include "Item.h"
@@ -58,7 +59,7 @@ void Map::ScriptsStart(ScriptMapMap const& scripts, uint32 id, Object* source, O
if (iter->first == 0)
immedScript = true;
- sScriptMgr->IncreaseScheduledScriptsCount();
+ sMapMgr->IncreaseScheduledScriptsCount();
}
///- If one of the effects should be immediate, launch the script execution
if (/*start &&*/ immedScript && !i_scriptLock)
@@ -86,7 +87,7 @@ void Map::ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* sou
sa.script = &script;
m_scriptSchedule.insert(ScriptScheduleMap::value_type(time_t(sWorld->GetGameTime() + delay), sa));
- sScriptMgr->IncreaseScheduledScriptsCount();
+ sMapMgr->IncreaseScheduledScriptsCount();
///- If effects should be immediate, launch the script execution
if (delay == 0 && !i_scriptLock)
@@ -878,6 +879,6 @@ void Map::ScriptsProcess()
m_scriptSchedule.erase(iter);
iter = m_scriptSchedule.begin();
- sScriptMgr->DecreaseScheduledScriptCount();
+ sMapMgr->DecreaseScheduledScriptCount();
}
}
diff --git a/src/server/game/Miscellaneous/Language.h b/src/server/game/Miscellaneous/Language.h
index ca63137ac93..96826095a9c 100644
--- a/src/server/game/Miscellaneous/Language.h
+++ b/src/server/game/Miscellaneous/Language.h
@@ -1063,7 +1063,7 @@ enum TrinityStrings
LANG_COMMAND_NO_FROZEN_PLAYERS = 5004,
LANG_COMMAND_LIST_FREEZE = 5005,
LANG_COMMAND_PERMA_FROZEN_PLAYER = 5006,
- LANG_INSTANCE_RAID_GROUP_ONLY = 5007,
+ // = 5007, unused
LANG_INSTANCE_CLOSED = 5008,
LANG_COMMAND_PLAYED_TO_ALL = 5009,
LANG_NPCINFO_LINKGUID = 5010,
diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h
index aa45c5024e6..f9a98cffd0e 100644
--- a/src/server/game/Miscellaneous/SharedDefines.h
+++ b/src/server/game/Miscellaneous/SharedDefines.h
@@ -828,7 +828,7 @@ enum SpellEffects
SPELL_EFFECT_CREATE_ITEM_2 = 157,
SPELL_EFFECT_MILLING = 158,
SPELL_EFFECT_ALLOW_RENAME_PET = 159,
- SPELL_EFFECT_160 = 160,
+ SPELL_EFFECT_FORCE_CAST_2 = 160,
SPELL_EFFECT_TALENT_SPEC_COUNT = 161,
SPELL_EFFECT_TALENT_SPEC_SELECT = 162,
SPELL_EFFECT_163 = 163,
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index 2a57524cb3c..f27e47fba21 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -302,6 +302,27 @@ void MotionMaster::MovePoint(uint32 id, float x, float y, float z, bool generate
}
}
+void MotionMaster::MoveCloserAndStop(uint32 id, Unit* target, float distance)
+{
+ float distanceToTravel = _owner->GetExactDist2d(target) - distance;
+ if (distanceToTravel > 0.0f)
+ {
+ float angle = _owner->GetAngle(target);
+ float destx = _owner->GetPositionX() + distanceToTravel * std::cos(angle);
+ float desty = _owner->GetPositionY() + distanceToTravel * std::sin(angle);
+ MovePoint(id, destx, desty, target->GetPositionZ());
+ }
+ else
+ {
+ // we are already close enough. We just need to turn toward the target without changing position.
+ Movement::MoveSplineInit init(_owner);
+ init.MoveTo(_owner->GetPositionX(), _owner->GetPositionY(), _owner->GetPositionZMinusOffset());
+ init.SetFacing(target);
+ init.Launch();
+ Mutate(new EffectMovementGenerator(id), MOTION_SLOT_ACTIVE);
+ }
+}
+
void MotionMaster::MoveLand(uint32 id, Position const& pos)
{
float x, y, z;
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index d1c6474fb36..005f10b44af 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -173,6 +173,12 @@ class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *>
{ MovePoint(id, pos.m_positionX, pos.m_positionY, pos.m_positionZ, generatePath); }
void MovePoint(uint32 id, float x, float y, float z, bool generatePath = true);
+ /* Makes the unit move toward the target until it is at a certain distance from it. The unit then stops.
+ Only works in 2D.
+ This method doesn't account for any movement done by the target. in other words, it only works if the target is stationary.
+ */
+ void MoveCloserAndStop(uint32 id, Unit* target, float distance);
+
// These two movement types should only be used with creatures having landing/takeoff animations
void MoveLand(uint32 id, Position const& pos);
void MoveTakeoff(uint32 id, Position const& pos);
diff --git a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
index d67db4b7ba5..403ccf684e7 100644
--- a/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/TargetedMovementGenerator.cpp
@@ -51,6 +51,9 @@ void TargetedMovementGeneratorMedium<T, D>::_setTargetLocation(T* owner, bool up
{
if (!i_offset)
{
+ if (i_target->IsWithinDistInMap(owner, CONTACT_DISTANCE))
+ return;
+
// to nearest contact position
i_target->GetContactPoint(owner, x, y, z);
}
@@ -274,9 +277,9 @@ void FollowMovementGenerator<Creature>::_updateSpeed(Creature* owner)
if (!owner->IsPet() || !owner->IsInWorld() || !i_target.isValid() || i_target->GetGUID() != owner->GetOwnerGUID())
return;
- owner->UpdateSpeed(MOVE_RUN, true);
- owner->UpdateSpeed(MOVE_WALK, true);
- owner->UpdateSpeed(MOVE_SWIM, true);
+ owner->UpdateSpeed(MOVE_RUN);
+ owner->UpdateSpeed(MOVE_WALK);
+ owner->UpdateSpeed(MOVE_SWIM);
}
template<>
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index 48d29b3259b..dd1cf494325 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -213,7 +213,7 @@ bool WaypointMovementGenerator<Creature>::DoUpdate(Creature* creature, uint32 di
creature->SetHomePosition(creature->GetPosition());
if (creature->IsStopped())
- Stop(STOP_TIME_FOR_PLAYER);
+ Stop(sWorld->getIntConfig(CONFIG_CREATURE_STOP_FOR_PLAYER));
else if (creature->movespline->Finalized())
{
OnArrived(creature);
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
index 1dd4611d53b..72309822dab 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.h
@@ -28,9 +28,9 @@
#include "MovementGenerator.h"
#include "WaypointManager.h"
#include "Player.h"
+#include "World.h"
#define FLIGHT_TRAVEL_UPDATE 100
-#define STOP_TIME_FOR_PLAYER 3 * MINUTE * IN_MILLISECONDS // 3 Minutes
#define TIMEDIFF_NEXT_WP 250
template<class T, class P>
diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
index 7f0695e16b3..aa00d211d6e 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
+++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.cpp
@@ -33,8 +33,14 @@ void OutdoorPvPMgr::Die()
for (OutdoorPvPSet::iterator itr = m_OutdoorPvPSet.begin(); itr != m_OutdoorPvPSet.end(); ++itr)
delete *itr;
+ m_OutdoorPvPSet.clear();
+
for (OutdoorPvPDataMap::iterator itr = m_OutdoorPvPDatas.begin(); itr != m_OutdoorPvPDatas.end(); ++itr)
delete itr->second;
+
+ m_OutdoorPvPDatas.clear();
+
+ m_OutdoorPvPMap.clear();
}
OutdoorPvPMgr* OutdoorPvPMgr::instance()
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 4218746893f..ac440da3f24 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -17,6 +17,7 @@
*/
#include "ScriptMgr.h"
+#include "ScriptReloadMgr.h"
#include "Config.h"
#include "DatabaseEnv.h"
#include "DBCStores.h"
@@ -34,11 +35,9 @@
#include "WorldPacket.h"
#include "WorldSession.h"
#include "Chat.h"
-
-// namespace
-// {
- UnusedScriptNamesContainer UnusedScriptNames;
-// }
+#include "MapManager.h"
+#include "LFGScripts.h"
+#include "InstanceScript.h"
// Trait which indicates whether this script type
// must be assigned in the database.
@@ -67,6 +66,10 @@ struct is_script_database_bound<GameObjectScript>
: std::true_type { };
template<>
+struct is_script_database_bound<VehicleScript>
+ : std::true_type { };
+
+template<>
struct is_script_database_bound<AreaTriggerScript>
: std::true_type { };
@@ -94,143 +97,848 @@ template<>
struct is_script_database_bound<AchievementCriteriaScript>
: std::true_type { };
+enum Spells
+{
+ SPELL_HOTSWAP_VISUAL_SPELL_EFFECT = 40162 // 59084
+};
+
+class ScriptRegistryInterface
+{
+public:
+ ScriptRegistryInterface() { }
+ virtual ~ScriptRegistryInterface() { }
+
+ ScriptRegistryInterface(ScriptRegistryInterface const&) = delete;
+ ScriptRegistryInterface(ScriptRegistryInterface&&) = delete;
+
+ ScriptRegistryInterface& operator= (ScriptRegistryInterface const&) = delete;
+ ScriptRegistryInterface& operator= (ScriptRegistryInterface&&) = delete;
+
+ /// Removes all scripts associated with the given script context.
+ /// Requires ScriptRegistryBase::SwapContext to be called after all transfers have finished.
+ virtual void ReleaseContext(std::string const& context) = 0;
+
+ /// Injects and updates the changed script objects.
+ virtual void SwapContext(bool initialize) = 0;
+
+ /// Removes the scripts used by this registry from the given container.
+ /// Used to find unused script names.
+ virtual void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) = 0;
+
+ /// Unloads the script registry.
+ virtual void Unload() = 0;
+};
+
+template<class>
+class ScriptRegistry;
+
+class ScriptRegistryCompositum
+ : public ScriptRegistryInterface
+{
+ ScriptRegistryCompositum() { }
+
+ template<class>
+ friend class ScriptRegistry;
+
+ /// Type erasure wrapper for objects
+ class DeleteableObjectBase
+ {
+ public:
+ DeleteableObjectBase() { }
+ virtual ~DeleteableObjectBase() { }
+
+ DeleteableObjectBase(DeleteableObjectBase const&) = delete;
+ DeleteableObjectBase& operator= (DeleteableObjectBase const&) = delete;
+ };
+
+ template<typename T>
+ class DeleteableObject
+ : public DeleteableObjectBase
+ {
+ public:
+ DeleteableObject(T&& object)
+ : _object(std::forward<T>(object)) { }
+
+ private:
+ T _object;
+ };
+
+public:
+ void SetScriptNameInContext(std::string const& scriptname, std::string const& context)
+ {
+ ASSERT(_scriptnames_to_context.find(scriptname) == _scriptnames_to_context.end(),
+ "Scriptname was assigned to this context already!");
+ _scriptnames_to_context.insert(std::make_pair(scriptname, context));
+ }
+
+ std::string const& GetScriptContextOfScriptName(std::string const& scriptname) const
+ {
+ auto itr = _scriptnames_to_context.find(scriptname);
+ ASSERT(itr != _scriptnames_to_context.end() &&
+ "Given scriptname doesn't exist!");
+ return itr->second;
+ }
+
+ void ReleaseContext(std::string const& context) final override
+ {
+ for (auto const registry : _registries)
+ registry->ReleaseContext(context);
+
+ // Clear the script names in context after calling the release hooks
+ // since it's possible that new references to a shared library
+ // are acquired when releasing.
+ for (auto itr = _scriptnames_to_context.begin();
+ itr != _scriptnames_to_context.end();)
+ if (itr->second == context)
+ itr = _scriptnames_to_context.erase(itr);
+ else
+ ++itr;
+ }
+
+ void SwapContext(bool initialize) final override
+ {
+ for (auto const registry : _registries)
+ registry->SwapContext(initialize);
+
+ DoDelayedDelete();
+ }
+
+ void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override
+ {
+ for (auto const registry : _registries)
+ registry->RemoveUsedScriptsFromContainer(scripts);
+ }
+
+ void Unload() final override
+ {
+ for (auto const registry : _registries)
+ registry->Unload();
+ }
+
+ template<typename T>
+ void QueueForDelayedDelete(T&& any)
+ {
+ _delayed_delete_queue.push_back(
+ Trinity::make_unique<
+ DeleteableObject<typename std::decay<T>::type>
+ >(std::forward<T>(any))
+ );
+ }
+
+ static ScriptRegistryCompositum* Instance()
+ {
+ static ScriptRegistryCompositum instance;
+ return &instance;
+ }
+
+private:
+ void Register(ScriptRegistryInterface* registry)
+ {
+ _registries.insert(registry);
+ }
+
+ void DoDelayedDelete()
+ {
+ _delayed_delete_queue.clear();
+ }
+
+ std::unordered_set<ScriptRegistryInterface*> _registries;
+
+ std::vector<std::unique_ptr<DeleteableObjectBase>> _delayed_delete_queue;
+
+ std::unordered_map<
+ std::string /*script name*/,
+ std::string /*context*/
+ > _scriptnames_to_context;
+};
+
+#define sScriptRegistryCompositum ScriptRegistryCompositum::Instance()
+
+template<typename /*ScriptType*/, bool /*IsDatabaseBound*/>
+class SpecializedScriptRegistry;
+
// This is the global static registry of scripts.
-template<class TScript>
-class ScriptRegistry
+template<class ScriptType>
+class ScriptRegistry final
+ : public SpecializedScriptRegistry<
+ ScriptType, is_script_database_bound<ScriptType>::value>
+{
+ ScriptRegistry()
+ {
+ sScriptRegistryCompositum->Register(this);
+ }
+
+public:
+ static ScriptRegistry* Instance()
+ {
+ static ScriptRegistry instance;
+ return &instance;
+ }
+
+ void LogDuplicatedScriptPointerError(ScriptType const* first, ScriptType const* second)
+ {
+ // See if the script is using the same memory as another script. If this happens, it means that
+ // someone forgot to allocate new memory for a script.
+ TC_LOG_ERROR("scripts", "Script '%s' has same memory pointer as '%s'.",
+ first->GetName().c_str(), second->GetName().c_str());
+ }
+};
+
+class ScriptRegistrySwapHookBase
+{
+public:
+ ScriptRegistrySwapHookBase() { }
+ virtual ~ScriptRegistrySwapHookBase() { }
+
+ ScriptRegistrySwapHookBase(ScriptRegistrySwapHookBase const&) = delete;
+ ScriptRegistrySwapHookBase(ScriptRegistrySwapHookBase&&) = delete;
+
+ ScriptRegistrySwapHookBase& operator= (ScriptRegistrySwapHookBase const&) = delete;
+ ScriptRegistrySwapHookBase& operator= (ScriptRegistrySwapHookBase&&) = delete;
+
+ /// Called before the actual context release happens
+ virtual void BeforeReleaseContext(std::string const& /*context*/) { }
+
+ /// Called before SwapContext
+ virtual void BeforeSwapContext(bool /*initialize*/) { }
+
+ /// Called before Unload
+ virtual void BeforeUnload() { }
+};
+
+template<typename ScriptType, typename Base>
+class ScriptRegistrySwapHooks
+ : public ScriptRegistrySwapHookBase
+{
+};
+
+/// This hook is responsible for swapping OutdoorPvP's
+template<typename Base>
+class UnsupportedScriptRegistrySwapHooks
+ : public ScriptRegistrySwapHookBase
+{
+public:
+ void BeforeReleaseContext(std::string const& context) final override
+ {
+ auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context);
+ ASSERT(bounds.first == bounds.second);
+ }
+};
+
+/// This hook is responsible for swapping Creature and GameObject AI's
+template<typename ObjectType, typename ScriptType, typename Base>
+class CreatureGameObjectScriptRegistrySwapHooks
+ : public ScriptRegistrySwapHookBase
{
+ template<typename W>
+ class AIFunctionMapWorker
+ {
+ public:
+ template<typename T>
+ AIFunctionMapWorker(T&& worker)
+ : _worker(std::forward<T>(worker)) { }
+
+ void Visit(std::unordered_map<ObjectGuid, ObjectType*>& objects)
+ {
+ _worker(objects);
+ }
+
+ template<typename O>
+ void Visit(std::unordered_map<ObjectGuid, O*>&) { }
+
+ private:
+ W _worker;
+ };
+
+ class AsyncCastHotswapEffectEvent : public BasicEvent
+ {
public:
+ explicit AsyncCastHotswapEffectEvent(Unit* owner) : owner_(owner) { }
+
+ bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
+ {
+ owner_->CastSpell(owner_, SPELL_HOTSWAP_VISUAL_SPELL_EFFECT, true);
+ return true;
+ }
+
+ private:
+ Unit* owner_;
+ };
+
+ // Hook which is called before a creature is swapped
+ static void UnloadStage1(Creature* creature)
+ {
+ creature->m_Events.KillAllEvents(true);
+
+ if (creature->IsCharmed())
+ creature->RemoveCharmedBy(nullptr);
+
+ ASSERT(!creature->IsCharmed(),
+ "There is a disabled AI which is still loaded.");
+
+ creature->AI()->EnterEvadeMode();
+ }
+
+ static void UnloadStage2(Creature* creature)
+ {
+ bool const destroyed = creature->AIM_Destroy();
+ ASSERT(destroyed,
+ "Destroying the AI should never fail here!");
+ (void)destroyed;
+
+ ASSERT(!creature->AI(),
+ "The AI should be null here!");
+ }
+
+ // Hook which is called before a gameobject is swapped
+ static void UnloadStage1(GameObject* gameobject)
+ {
+ gameobject->AI()->Reset();
+ }
+
+ static void UnloadStage2(GameObject* gameobject)
+ {
+ gameobject->AIM_Destroy();
+
+ ASSERT(!gameobject->AI(),
+ "The AI should be null here!");
+ }
+
+ // Hook which is called after a creature was swapped
+ static void LoadStage1(Creature* creature)
+ {
+ ASSERT(!creature->AI(),
+ "The AI should be null here!");
+
+ if (creature->IsAlive())
+ creature->ClearUnitState(UNIT_STATE_EVADE);
+
+ bool const created = creature->AIM_Initialize();
+ ASSERT(created,
+ "Creating the AI should never fail here!");
+ (void)created;
+ }
+
+ static void LoadStage2(Creature* creature)
+ {
+ if (!creature->IsAlive())
+ return;
+
+ creature->AI()->EnterEvadeMode();
+
+ // Cast a dummy visual spell asynchronously here to signal
+ // that the AI was hot swapped
+ creature->m_Events.AddEvent(new AsyncCastHotswapEffectEvent(creature),
+ creature->m_Events.CalculateTime(0));
+ }
+
+ // Hook which is called after a gameobject was swapped
+ static void LoadStage1(GameObject* gameobject)
+ {
+ ASSERT(!gameobject->AI(),
+ "The AI should be null here!");
+
+ gameobject->AIM_Initialize();
+ }
+
+ static void LoadStage2(GameObject* gameobject)
+ {
+ gameobject->AI()->Reset();
+ }
- typedef std::map<uint32, TScript*> ScriptMap;
- typedef typename ScriptMap::iterator ScriptMapIterator;
+ template<typename T>
+ void RunOverAllEntities(T fn)
+ {
+ auto evaluator = [&](std::unordered_map<ObjectGuid, ObjectType*>& objects)
+ {
+ for (auto object : objects)
+ fn(object.second);
+ };
- // The actual list of scripts. This will be accessed concurrently, so it must not be modified
- // after server startup.
- static ScriptMap ScriptPointerList;
- static std::vector<TScript*> Scripts;
+ AIFunctionMapWorker<typename std::decay<decltype(evaluator)>::type> worker(std::move(evaluator));
+ TypeContainerVisitor<decltype(worker), MapStoredObjectTypesContainer> visitor(worker);
- static void AddScript(TScript* const script, bool addToDeleteContainer = true)
+ sMapMgr->DoForAllMaps([&](Map* map)
{
- ASSERT(script);
+ // Run the worker over all maps
+ visitor.Visit(map->GetObjectsStore());
+ });
+ }
+
+public:
+ void BeforeReleaseContext(std::string const& context) final override
+ {
+ auto ids_to_remove = static_cast<Base*>(this)->GetScriptIDsToRemove(context);
+
+ std::vector<ObjectType*> stage2;
- // See if the script is using the same memory as another script. If this happens, it means that
- // someone forgot to allocate new memory for a script.
- for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
+ RunOverAllEntities([&](ObjectType* object)
+ {
+ if (ids_to_remove.find(object->GetScriptId()) != ids_to_remove.end())
{
- if (it->second == script)
- {
- TC_LOG_ERROR("scripts", "Script '%s' has same memory pointer as '%s'.",
- script->GetName().c_str(), it->second->GetName().c_str());
+ UnloadStage1(object);
+ stage2.push_back(object);
+ }
+ });
- return;
+ for (auto object : stage2)
+ UnloadStage2(object);
+
+ // Add the new ids which are removed to the global ids to remove set
+ ids_removed_.insert(ids_to_remove.begin(), ids_to_remove.end());
+ }
+
+ void BeforeSwapContext(bool initialize) override
+ {
+ // Never swap creature or gameobject scripts when initializing
+ if (initialize)
+ return;
+
+ // Add the recently added scripts to the deleted scripts to replace
+ // default AI's with recently added core scripts.
+ ids_removed_.insert(static_cast<Base*>(this)->GetRecentlyAddedScriptIDs().begin(),
+ static_cast<Base*>(this)->GetRecentlyAddedScriptIDs().end());
+
+ std::vector<ObjectType*> remove;
+ std::vector<ObjectType*> stage2;
+
+ RunOverAllEntities([&](ObjectType* object)
+ {
+ if (ids_removed_.find(object->GetScriptId()) != ids_removed_.end())
+ {
+ if (object->AI())
+ {
+ // Overwrite existing (default) AI's which are replaced by a new script
+ UnloadStage1(object);
+ remove.push_back(object);
}
+
+ stage2.push_back(object);
}
+ });
+
+ for (auto object : remove)
+ UnloadStage2(object);
- AddScript(is_script_database_bound<TScript>{}, script);
- if (addToDeleteContainer)
- Scripts.push_back(script);
+ for (auto object : stage2)
+ LoadStage1(object);
+
+ for (auto object : stage2)
+ LoadStage2(object);
+
+ ids_removed_.clear();
+ }
+
+ void BeforeUnload() final override
+ {
+ ASSERT(ids_removed_.empty());
+ }
+
+private:
+ std::unordered_set<uint32> ids_removed_;
+};
+
+// This hook is responsible for swapping CreatureAI's
+template<typename Base>
+class ScriptRegistrySwapHooks<CreatureScript, Base>
+ : public CreatureGameObjectScriptRegistrySwapHooks<
+ Creature, CreatureScript, Base
+ > { };
+
+// This hook is responsible for swapping GameObjectAI's
+template<typename Base>
+class ScriptRegistrySwapHooks<GameObjectScript, Base>
+ : public CreatureGameObjectScriptRegistrySwapHooks<
+ GameObject, GameObjectScript, Base
+ > { };
+
+/// This hook is responsible for swapping BattlegroundScript's
+template<typename Base>
+class ScriptRegistrySwapHooks<BattlegroundScript, Base>
+ : public UnsupportedScriptRegistrySwapHooks<Base> { };
+
+/// This hook is responsible for swapping OutdoorPvP's
+template<typename Base>
+class ScriptRegistrySwapHooks<OutdoorPvPScript, Base>
+ : public ScriptRegistrySwapHookBase
+{
+public:
+ ScriptRegistrySwapHooks() : swapped(false) { }
+
+ void BeforeReleaseContext(std::string const& context) final override
+ {
+ auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context);
+
+ if ((!swapped) && (bounds.first != bounds.second))
+ {
+ swapped = true;
+ sOutdoorPvPMgr->Die();
}
+ }
- // Gets a script by its ID (assigned by ObjectMgr).
- static TScript* GetScriptById(uint32 id)
+ void BeforeSwapContext(bool initialize) override
+ {
+ // Never swap outdoor pvp scripts when initializing
+ if ((!initialize) && swapped)
{
- ScriptMapIterator it = ScriptPointerList.find(id);
- if (it != ScriptPointerList.end())
- return it->second;
+ sOutdoorPvPMgr->InitOutdoorPvP();
+ swapped = false;
+ }
+ }
+
+ void BeforeUnload() final override
+ {
+ ASSERT(!swapped);
+ }
+
+private:
+ bool swapped;
+};
+
+/// This hook is responsible for swapping InstanceMapScript's
+template<typename Base>
+class ScriptRegistrySwapHooks<InstanceMapScript, Base>
+ : public ScriptRegistrySwapHookBase
+{
+public:
+ ScriptRegistrySwapHooks() : swapped(false) { }
- return NULL;
+ void BeforeReleaseContext(std::string const& context) final override
+ {
+ auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context);
+ if (bounds.first != bounds.second)
+ swapped = true;
+ }
+
+ void BeforeSwapContext(bool /*initialize*/) override
+ {
+ swapped = false;
+ }
+
+ void BeforeUnload() final override
+ {
+ ASSERT(!swapped);
+ }
+
+private:
+ bool swapped;
+};
+
+/// This hook is responsible for swapping SpellScriptLoader's
+template<typename Base>
+class ScriptRegistrySwapHooks<SpellScriptLoader, Base>
+ : public ScriptRegistrySwapHookBase
+{
+public:
+ ScriptRegistrySwapHooks() : swapped(false) { }
+
+ void BeforeReleaseContext(std::string const& context) final override
+ {
+ auto const bounds = static_cast<Base*>(this)->_ids_of_contexts.equal_range(context);
+
+ if (bounds.first != bounds.second)
+ swapped = true;
+ }
+
+ void BeforeSwapContext(bool /*initialize*/) override
+ {
+ if (swapped)
+ {
+ sObjectMgr->ValidateSpellScripts();
+ swapped = false;
}
+ }
- private:
+ void BeforeUnload() final override
+ {
+ ASSERT(!swapped);
+ }
+
+private:
+ bool swapped;
+};
+
+// Database bound script registry
+template<typename ScriptType>
+class SpecializedScriptRegistry<ScriptType, true>
+ : public ScriptRegistryInterface,
+ public ScriptRegistrySwapHooks<ScriptType, ScriptRegistry<ScriptType>>
+{
+ template<typename>
+ friend class UnsupportedScriptRegistrySwapHooks;
+
+ template<typename, typename>
+ friend class ScriptRegistrySwapHooks;
+
+ template<typename, typename, typename>
+ friend class CreatureGameObjectScriptRegistrySwapHooks;
+
+public:
+ SpecializedScriptRegistry() { }
+
+ typedef std::unordered_map<
+ uint32 /*script id*/,
+ std::unique_ptr<ScriptType>
+ > ScriptStoreType;
+
+ typedef typename ScriptStoreType::iterator ScriptStoreIteratorType;
+
+ void ReleaseContext(std::string const& context) final override
+ {
+ this->BeforeReleaseContext(context);
+
+ auto const bounds = _ids_of_contexts.equal_range(context);
+ for (auto itr = bounds.first; itr != bounds.second; ++itr)
+ _scripts.erase(itr->second);
+ }
+
+ void SwapContext(bool initialize) final override
+ {
+ this->BeforeSwapContext(initialize);
+
+ _recently_added_ids.clear();
+ }
+
+ void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override
+ {
+ for (auto const& script : _scripts)
+ scripts.erase(script.second->GetName());
+ }
+
+ void Unload() final override
+ {
+ this->BeforeUnload();
+
+ ASSERT(_recently_added_ids.empty(),
+ "Recently added script ids should be empty here!");
+
+ _scripts.clear();
+ _ids_of_contexts.clear();
+ }
+
+ // Adds a database bound script
+ void AddScript(ScriptType* script)
+ {
+ ASSERT(script,
+ "Tried to call AddScript with a nullpointer!");
+ ASSERT(!sScriptMgr->GetCurrentScriptContext().empty(),
+ "Tried to register a script without being in a valid script context!");
- // Adds a database bound script
- static void AddScript(std::true_type, TScript* const script)
+ std::unique_ptr<ScriptType> script_ptr(script);
+
+ // Get an ID for the script. An ID only exists if it's a script that is assigned in the database
+ // through a script name (or similar).
+ if (uint32 const id = sObjectMgr->GetScriptId(script->GetName()))
{
- // Get an ID for the script. An ID only exists if it's a script that is assigned in the database
- // through a script name (or similar).
- uint32 id = sObjectMgr->GetScriptId(script->GetName());
- if (id)
+ // Try to find an existing script.
+ for (auto const& stored_script : _scripts)
{
- // Try to find an existing script.
- bool existing = false;
- for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it)
- {
- // If the script names match...
- if (it->second->GetName() == script->GetName())
- {
- // ... It exists.
- existing = true;
- break;
- }
- }
-
- // If the script isn't assigned -> assign it!
- if (!existing)
- {
- ScriptPointerList[id] = script;
- sScriptMgr->IncrementScriptCount();
-
- #ifdef SCRIPTS
- UnusedScriptNamesContainer::iterator itr = std::lower_bound(UnusedScriptNames.begin(), UnusedScriptNames.end(), script->GetName());
- if (itr != UnusedScriptNames.end() && *itr == script->GetName())
- UnusedScriptNames.erase(itr);
- #endif
- }
- else
+ // If the script names match...
+ if (stored_script.second->GetName() == script->GetName())
{
// If the script is already assigned -> delete it!
- TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, so the script can't work.",
- script->GetName().c_str());
+ TC_LOG_ERROR("scripts", "Script '%s' already assigned with the same script name, "
+ "so the script can't work.", script->GetName().c_str());
- ABORT(); // Error that should be fixed ASAP.
+ // Error that should be fixed ASAP.
+ sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr));
+ ABORT();
+ return;
}
}
- else
- {
- // The script uses a script name from database, but isn't assigned to anything.
- TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.", script->GetName().c_str());
- }
- }
- // Adds a non database bound script
- static void AddScript(std::false_type, TScript* const script)
+ // If the script isn't assigned -> assign it!
+ _scripts.insert(std::make_pair(id, std::move(script_ptr)));
+ _ids_of_contexts.insert(std::make_pair(sScriptMgr->GetCurrentScriptContext(), id));
+ _recently_added_ids.insert(id);
+
+ sScriptRegistryCompositum->SetScriptNameInContext(script->GetName(),
+ sScriptMgr->GetCurrentScriptContext());
+ }
+ else
{
- // We're dealing with a code-only script; just add it.
- ScriptPointerList[_scriptIdCounter++] = script;
- sScriptMgr->IncrementScriptCount();
+ // The script uses a script name from database, but isn't assigned to anything.
+ TC_LOG_ERROR("sql.sql", "Script named '%s' does not have a script name assigned in database.",
+ script->GetName().c_str());
+
+ // Avoid calling "delete script;" because we are currently in the script constructor
+ // In a valid scenario this will not happen because every script has a name assigned in the database
+ sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr));
+ return;
}
+ }
+
+ // Gets a script by its ID (assigned by ObjectMgr).
+ ScriptType* GetScriptById(uint32 id)
+ {
+ auto const itr = _scripts.find(id);
+ if (itr != _scripts.end())
+ return itr->second.get();
+
+ return nullptr;
+ }
+
+ ScriptStoreType& GetScripts()
+ {
+ return _scripts;
+ }
- // Counter used for code-only scripts.
- static uint32 _scriptIdCounter;
+protected:
+ // Returns the script id's which are registered to a certain context
+ std::unordered_set<uint32> GetScriptIDsToRemove(std::string const& context) const
+ {
+ // Create a set of all ids which are removed
+ std::unordered_set<uint32> scripts_to_remove;
+
+ auto const bounds = _ids_of_contexts.equal_range(context);
+ for (auto itr = bounds.first; itr != bounds.second; ++itr)
+ scripts_to_remove.insert(itr->second);
+
+ return scripts_to_remove;
+ }
+
+ std::unordered_set<uint32> const& GetRecentlyAddedScriptIDs() const
+ {
+ return _recently_added_ids;
+ }
+
+private:
+ ScriptStoreType _scripts;
+
+ // Scripts of a specific context
+ std::unordered_multimap<std::string /*context*/, uint32 /*id*/> _ids_of_contexts;
+
+ // Script id's which were registered recently
+ std::unordered_set<uint32> _recently_added_ids;
+};
+
+/// This hook is responsible for swapping CommandScript's
+template<typename Base>
+class ScriptRegistrySwapHooks<CommandScript, Base>
+ : public ScriptRegistrySwapHookBase
+{
+public:
+ void BeforeReleaseContext(std::string const& /*context*/) final override
+ {
+ ChatHandler::invalidateCommandTable();
+ }
+
+ void BeforeSwapContext(bool /*initialize*/) override
+ {
+ ChatHandler::invalidateCommandTable();
+ }
+
+ void BeforeUnload() final override
+ {
+ ChatHandler::invalidateCommandTable();
+ }
+};
+
+// Database unbound script registry
+template<typename ScriptType>
+class SpecializedScriptRegistry<ScriptType, false>
+ : public ScriptRegistryInterface,
+ public ScriptRegistrySwapHooks<ScriptType, ScriptRegistry<ScriptType>>
+{
+ template<typename, typename>
+ friend class ScriptRegistrySwapHooks;
+
+public:
+ typedef std::unordered_multimap<std::string /*context*/, std::unique_ptr<ScriptType>> ScriptStoreType;
+ typedef typename ScriptStoreType::iterator ScriptStoreIteratorType;
+
+ SpecializedScriptRegistry() { }
+
+ void ReleaseContext(std::string const& context) final override
+ {
+ this->BeforeReleaseContext(context);
+
+ _scripts.erase(context);
+ }
+
+ void SwapContext(bool initialize) final override
+ {
+ this->BeforeSwapContext(initialize);
+ }
+
+ void RemoveUsedScriptsFromContainer(std::unordered_set<std::string>& scripts) final override
+ {
+ for (auto const& script : _scripts)
+ scripts.erase(script.second->GetName());
+ }
+
+ void Unload() final override
+ {
+ this->BeforeUnload();
+
+ _scripts.clear();
+ }
+
+ // Adds a non database bound script
+ void AddScript(ScriptType* script)
+ {
+ ASSERT(script,
+ "Tried to call AddScript with a nullpointer!");
+ ASSERT(!sScriptMgr->GetCurrentScriptContext().empty(),
+ "Tried to register a script without being in a valid script context!");
+
+ std::unique_ptr<ScriptType> script_ptr(script);
+
+ for (auto const& entry : _scripts)
+ if (entry.second.get() == script)
+ {
+ static_cast<ScriptRegistry<ScriptType>*>(this)->
+ LogDuplicatedScriptPointerError(script, entry.second.get());
+
+ sScriptRegistryCompositum->QueueForDelayedDelete(std::move(script_ptr));
+ return;
+ }
+
+ // We're dealing with a code-only script, just add it.
+ _scripts.insert(std::make_pair(sScriptMgr->GetCurrentScriptContext(), std::move(script_ptr)));
+ }
+
+ ScriptStoreType& GetScripts()
+ {
+ return _scripts;
+ }
+
+private:
+ ScriptStoreType _scripts;
};
// Utility macros to refer to the script registry.
-#define SCR_REG_MAP(T) ScriptRegistry<T>::ScriptMap
-#define SCR_REG_ITR(T) ScriptRegistry<T>::ScriptMapIterator
-#define SCR_REG_LST(T) ScriptRegistry<T>::ScriptPointerList
-#define SCR_REG_VEC(T) ScriptRegistry<T>::Scripts
+#define SCR_REG_MAP(T) ScriptRegistry<T>::ScriptStoreType
+#define SCR_REG_ITR(T) ScriptRegistry<T>::ScriptStoreIteratorType
+#define SCR_REG_LST(T) ScriptRegistry<T>::Instance()->GetScripts()
// Utility macros for looping over scripts.
#define FOR_SCRIPTS(T, C, E) \
if (SCR_REG_LST(T).empty()) \
return; \
+ \
for (SCR_REG_ITR(T) C = SCR_REG_LST(T).begin(); \
C != SCR_REG_LST(T).end(); ++C)
+
#define FOR_SCRIPTS_RET(T, C, E, R) \
if (SCR_REG_LST(T).empty()) \
return R; \
+ \
for (SCR_REG_ITR(T) C = SCR_REG_LST(T).begin(); \
C != SCR_REG_LST(T).end(); ++C)
+
#define FOREACH_SCRIPT(T) \
FOR_SCRIPTS(T, itr, end) \
- itr->second
+ itr->second
// Utility macros for finding specific scripts.
#define GET_SCRIPT(T, I, V) \
- T* V = ScriptRegistry<T>::GetScriptById(I); \
+ T* V = ScriptRegistry<T>::Instance()->GetScriptById(I); \
if (!V) \
return;
+
#define GET_SCRIPT_RET(T, I, V, R) \
- T* V = ScriptRegistry<T>::GetScriptById(I); \
+ T* V = ScriptRegistry<T>::Instance()->GetScriptById(I); \
if (!V) \
return R;
@@ -240,8 +948,18 @@ struct TSpellSummary
uint8 Effects; // set of enum SelectEffect
} *SpellSummary;
+ScriptObject::ScriptObject(const char* name) : _name(name)
+{
+ sScriptMgr->IncreaseScriptCount();
+}
+
+ScriptObject::~ScriptObject()
+{
+ sScriptMgr->DecreaseScriptCount();
+}
+
ScriptMgr::ScriptMgr()
- : _scriptCount(0), _scheduledScripts(0), _script_loader_callback(nullptr)
+ : _scriptCount(0), _script_loader_callback(nullptr)
{
}
@@ -255,6 +973,9 @@ ScriptMgr* ScriptMgr::instance()
void ScriptMgr::Initialize()
{
+ ASSERT(sSpellMgr->GetSpellInfo(SPELL_HOTSWAP_VISUAL_SPELL_EFFECT)
+ && "Reload hotswap spell effect for creatures isn't valid!");
+
uint32 oldMSTime = getMSTime();
LoadDatabase();
@@ -263,59 +984,85 @@ void ScriptMgr::Initialize()
FillSpellSummary();
+ // Load core scripts
+ SetScriptContext("___static___");
+
+ // SmartAI
AddSC_SmartScripts();
+ // LFGScripts
+ lfg::AddSC_LFGScripts();
+
+ // Load all static linked scripts through the script loader function.
ASSERT(_script_loader_callback,
"Script loader callback wasn't registered!");
-
_script_loader_callback();
-#ifdef SCRIPTS
- for (std::string const& scriptName : UnusedScriptNames)
+ // Initialize all dynamic scripts
+ // and finishes the context switch to do
+ // bulk loading
+ sScriptReloadMgr->Initialize();
+
+ // Loads all scripts from the current context
+ sScriptMgr->SwapScriptContext(true);
+
+ // Print unused script names.
+ std::unordered_set<std::string> unusedScriptNames(
+ sObjectMgr->GetAllScriptNames().begin(),
+ sObjectMgr->GetAllScriptNames().end());
+
+ // Remove the used scripts from the given container.
+ sScriptRegistryCompositum->RemoveUsedScriptsFromContainer(unusedScriptNames);
+
+ for (std::string const& scriptName : unusedScriptNames)
{
- TC_LOG_ERROR("sql.sql", "ScriptName '%s' exists in database, but no core script found!", scriptName.c_str());
+ // Avoid complaining about empty script names since the
+ // script name container contains a placeholder as the 0 element.
+ if (scriptName.empty())
+ continue;
+
+ TC_LOG_ERROR("sql.sql", "ScriptName '%s' exists in database, "
+ "but no core script found!", scriptName.c_str());
}
-#endif
- TC_LOG_INFO("server.loading", ">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime));
+ TC_LOG_INFO("server.loading", ">> Loaded %u C++ scripts in %u ms",
+ GetScriptCount(), GetMSTimeDiffToNow(oldMSTime));
+}
+
+void ScriptMgr::SetScriptContext(std::string const& context)
+{
+ _currentContext = context;
+}
+
+void ScriptMgr::SwapScriptContext(bool initialize)
+{
+ sScriptRegistryCompositum->SwapContext(initialize);
+ _currentContext.clear();
+}
+
+void ScriptMgr::ReleaseScriptContext(std::string const& context)
+{
+ sScriptRegistryCompositum->ReleaseContext(context);
+}
+
+std::shared_ptr<ModuleReference>
+ ScriptMgr::AcquireModuleReferenceOfScriptName(std::string const& scriptname) const
+{
+#ifdef TRINITY_API_USE_DYNAMIC_LINKING
+ // Returns the reference to the module of the given scriptname
+ return ScriptReloadMgr::AcquireModuleReferenceOfContext(
+ sScriptRegistryCompositum->GetScriptContextOfScriptName(scriptname));
+#else
+ (void)scriptname;
+ // Something went wrong when this function is used in
+ // a static linked context.
+ WPAbort();
+#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING
}
void ScriptMgr::Unload()
{
- #define SCR_CLEAR(T) \
- for (T* scr : SCR_REG_VEC(T)) \
- delete scr; \
- SCR_REG_VEC(T).clear();
-
- // Clear scripts for every script type.
- SCR_CLEAR(SpellScriptLoader);
- SCR_CLEAR(ServerScript);
- SCR_CLEAR(WorldScript);
- SCR_CLEAR(FormulaScript);
- SCR_CLEAR(WorldMapScript);
- SCR_CLEAR(InstanceMapScript);
- SCR_CLEAR(BattlegroundMapScript);
- SCR_CLEAR(ItemScript);
- SCR_CLEAR(CreatureScript);
- SCR_CLEAR(GameObjectScript);
- SCR_CLEAR(AreaTriggerScript);
- SCR_CLEAR(BattlegroundScript);
- SCR_CLEAR(OutdoorPvPScript);
- SCR_CLEAR(CommandScript);
- SCR_CLEAR(WeatherScript);
- SCR_CLEAR(AuctionHouseScript);
- SCR_CLEAR(ConditionScript);
- SCR_CLEAR(VehicleScript);
- SCR_CLEAR(DynamicObjectScript);
- SCR_CLEAR(TransportScript);
- SCR_CLEAR(AchievementCriteriaScript);
- SCR_CLEAR(PlayerScript);
- SCR_CLEAR(AccountScript);
- SCR_CLEAR(GuildScript);
- SCR_CLEAR(GroupScript);
- SCR_CLEAR(UnitScript);
-
- #undef SCR_CLEAR
+ sScriptRegistryCompositum->Unload();
delete[] SpellSummary;
delete[] UnitAI::AISpellInfo;
@@ -413,38 +1160,22 @@ void ScriptMgr::FillSpellSummary()
}
}
-void ScriptMgr::CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector)
+template<typename T, typename F>
+void CreateSpellOrAuraScripts(uint32 spellId, std::list<T*>& scriptVector, F&& extractor)
{
SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId);
for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr)
{
- SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second);
- if (!tmpscript)
+ // When the script is disabled continue with the next one
+ if (!itr->second.second)
continue;
- SpellScript* script = tmpscript->GetSpellScript();
-
- if (!script)
- continue;
-
- script->_Init(&tmpscript->GetName(), spellId);
-
- scriptVector.push_back(script);
- }
-}
-
-void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector)
-{
- SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId);
-
- for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr)
- {
- SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second);
+ SpellScriptLoader* tmpscript = sScriptMgr->GetSpellScriptLoader(itr->second.first);
if (!tmpscript)
continue;
- AuraScript* script = tmpscript->GetAuraScript();
+ T* script = (*tmpscript.*extractor)();
if (!script)
continue;
@@ -455,19 +1186,19 @@ void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& script
}
}
-void ScriptMgr::CreateSpellScriptLoaders(uint32 spellId, std::vector<std::pair<SpellScriptLoader*, SpellScriptsContainer::iterator> >& scriptVector)
+void ScriptMgr::CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector)
{
- SpellScriptsBounds bounds = sObjectMgr->GetSpellScriptsBounds(spellId);
- scriptVector.reserve(std::distance(bounds.first, bounds.second));
+ CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetSpellScript);
+}
- for (SpellScriptsContainer::iterator itr = bounds.first; itr != bounds.second; ++itr)
- {
- SpellScriptLoader* tmpscript = ScriptRegistry<SpellScriptLoader>::GetScriptById(itr->second);
- if (!tmpscript)
- continue;
+void ScriptMgr::CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector)
+{
+ CreateSpellOrAuraScripts(spellId, scriptVector, &SpellScriptLoader::GetAuraScript);
+}
- scriptVector.push_back(std::make_pair(tmpscript, itr));
- }
+SpellScriptLoader* ScriptMgr::GetSpellScriptLoader(uint32 scriptId)
+{
+ return ScriptRegistry<SpellScriptLoader>::Instance()->GetScriptById(scriptId);
}
void ScriptMgr::OnNetworkStart()
@@ -1495,56 +2226,62 @@ void ScriptMgr::OnGroupDisband(Group* group)
void ScriptMgr::OnHeal(Unit* healer, Unit* reciever, uint32& gain)
{
FOREACH_SCRIPT(UnitScript)->OnHeal(healer, reciever, gain);
+ FOREACH_SCRIPT(PlayerScript)->OnHeal(healer, reciever, gain);
}
void ScriptMgr::OnDamage(Unit* attacker, Unit* victim, uint32& damage)
{
FOREACH_SCRIPT(UnitScript)->OnDamage(attacker, victim, damage);
+ FOREACH_SCRIPT(PlayerScript)->OnDamage(attacker, victim, damage);
}
void ScriptMgr::ModifyPeriodicDamageAurasTick(Unit* target, Unit* attacker, uint32& damage)
{
FOREACH_SCRIPT(UnitScript)->ModifyPeriodicDamageAurasTick(target, attacker, damage);
+ FOREACH_SCRIPT(PlayerScript)->ModifyPeriodicDamageAurasTick(target, attacker, damage);
}
void ScriptMgr::ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage)
{
FOREACH_SCRIPT(UnitScript)->ModifyMeleeDamage(target, attacker, damage);
+ FOREACH_SCRIPT(PlayerScript)->ModifyMeleeDamage(target, attacker, damage);
}
void ScriptMgr::ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage)
{
FOREACH_SCRIPT(UnitScript)->ModifySpellDamageTaken(target, attacker, damage);
+ FOREACH_SCRIPT(PlayerScript)->ModifySpellDamageTaken(target, attacker, damage);
}
SpellScriptLoader::SpellScriptLoader(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<SpellScriptLoader>::AddScript(this);
+ ScriptRegistry<SpellScriptLoader>::Instance()->AddScript(this);
}
ServerScript::ServerScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<ServerScript>::AddScript(this);
+ ScriptRegistry<ServerScript>::Instance()->AddScript(this);
}
WorldScript::WorldScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<WorldScript>::AddScript(this);
+ ScriptRegistry<WorldScript>::Instance()->AddScript(this);
}
FormulaScript::FormulaScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<FormulaScript>::AddScript(this);
+ ScriptRegistry<FormulaScript>::Instance()->AddScript(this);
}
UnitScript::UnitScript(const char* name, bool addToScripts)
: ScriptObject(name)
{
- ScriptRegistry<UnitScript>::AddScript(this, addToScripts);
+ if (addToScripts)
+ ScriptRegistry<UnitScript>::Instance()->AddScript(this);
}
WorldMapScript::WorldMapScript(const char* name, uint32 mapId)
@@ -1553,7 +2290,7 @@ WorldMapScript::WorldMapScript(const char* name, uint32 mapId)
if (GetEntry() && !GetEntry()->IsWorldMap())
TC_LOG_ERROR("scripts", "WorldMapScript for map %u is invalid.", mapId);
- ScriptRegistry<WorldMapScript>::AddScript(this);
+ ScriptRegistry<WorldMapScript>::Instance()->AddScript(this);
}
InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId)
@@ -1562,7 +2299,7 @@ InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId)
if (GetEntry() && !GetEntry()->IsDungeon())
TC_LOG_ERROR("scripts", "InstanceMapScript for map %u is invalid.", mapId);
- ScriptRegistry<InstanceMapScript>::AddScript(this);
+ ScriptRegistry<InstanceMapScript>::Instance()->AddScript(this);
}
BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId)
@@ -1571,122 +2308,117 @@ BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId)
if (GetEntry() && !GetEntry()->IsBattleground())
TC_LOG_ERROR("scripts", "BattlegroundMapScript for map %u is invalid.", mapId);
- ScriptRegistry<BattlegroundMapScript>::AddScript(this);
+ ScriptRegistry<BattlegroundMapScript>::Instance()->AddScript(this);
}
ItemScript::ItemScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<ItemScript>::AddScript(this);
+ ScriptRegistry<ItemScript>::Instance()->AddScript(this);
}
CreatureScript::CreatureScript(const char* name)
: UnitScript(name, false)
{
- ScriptRegistry<CreatureScript>::AddScript(this);
+ ScriptRegistry<CreatureScript>::Instance()->AddScript(this);
}
GameObjectScript::GameObjectScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<GameObjectScript>::AddScript(this);
+ ScriptRegistry<GameObjectScript>::Instance()->AddScript(this);
}
AreaTriggerScript::AreaTriggerScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<AreaTriggerScript>::AddScript(this);
+ ScriptRegistry<AreaTriggerScript>::Instance()->AddScript(this);
}
BattlegroundScript::BattlegroundScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<BattlegroundScript>::AddScript(this);
+ ScriptRegistry<BattlegroundScript>::Instance()->AddScript(this);
}
OutdoorPvPScript::OutdoorPvPScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<OutdoorPvPScript>::AddScript(this);
+ ScriptRegistry<OutdoorPvPScript>::Instance()->AddScript(this);
}
CommandScript::CommandScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<CommandScript>::AddScript(this);
+ ScriptRegistry<CommandScript>::Instance()->AddScript(this);
}
WeatherScript::WeatherScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<WeatherScript>::AddScript(this);
+ ScriptRegistry<WeatherScript>::Instance()->AddScript(this);
}
AuctionHouseScript::AuctionHouseScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<AuctionHouseScript>::AddScript(this);
+ ScriptRegistry<AuctionHouseScript>::Instance()->AddScript(this);
}
ConditionScript::ConditionScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<ConditionScript>::AddScript(this);
+ ScriptRegistry<ConditionScript>::Instance()->AddScript(this);
}
VehicleScript::VehicleScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<VehicleScript>::AddScript(this);
+ ScriptRegistry<VehicleScript>::Instance()->AddScript(this);
}
DynamicObjectScript::DynamicObjectScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<DynamicObjectScript>::AddScript(this);
+ ScriptRegistry<DynamicObjectScript>::Instance()->AddScript(this);
}
TransportScript::TransportScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<TransportScript>::AddScript(this);
+ ScriptRegistry<TransportScript>::Instance()->AddScript(this);
}
AchievementCriteriaScript::AchievementCriteriaScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<AchievementCriteriaScript>::AddScript(this);
+ ScriptRegistry<AchievementCriteriaScript>::Instance()->AddScript(this);
}
PlayerScript::PlayerScript(const char* name)
: UnitScript(name, false)
{
- ScriptRegistry<PlayerScript>::AddScript(this);
+ ScriptRegistry<PlayerScript>::Instance()->AddScript(this);
}
AccountScript::AccountScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<AccountScript>::AddScript(this);
+ ScriptRegistry<AccountScript>::Instance()->AddScript(this);
}
GuildScript::GuildScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<GuildScript>::AddScript(this);
+ ScriptRegistry<GuildScript>::Instance()->AddScript(this);
}
GroupScript::GroupScript(const char* name)
: ScriptObject(name)
{
- ScriptRegistry<GroupScript>::AddScript(this);
+ ScriptRegistry<GroupScript>::Instance()->AddScript(this);
}
-// Instantiate static members of ScriptRegistry.
-template<class TScript> std::map<uint32, TScript*> ScriptRegistry<TScript>::ScriptPointerList;
-template<class TScript> std::vector<TScript*> ScriptRegistry<TScript>::Scripts;
-template<class TScript> uint32 ScriptRegistry<TScript>::_scriptIdCounter = 0;
-
// Specialize for each script type class like so:
template class TC_GAME_API ScriptRegistry<SpellScriptLoader>;
template class TC_GAME_API ScriptRegistry<ServerScript>;
@@ -1714,13 +2446,3 @@ template class TC_GAME_API ScriptRegistry<GuildScript>;
template class TC_GAME_API ScriptRegistry<GroupScript>;
template class TC_GAME_API ScriptRegistry<UnitScript>;
template class TC_GAME_API ScriptRegistry<AccountScript>;
-
-// Undefine utility macros.
-#undef GET_SCRIPT_RET
-#undef GET_SCRIPT
-#undef FOREACH_SCRIPT
-#undef FOR_SCRIPTS_RET
-#undef FOR_SCRIPTS
-#undef SCR_REG_LST
-#undef SCR_REG_ITR
-#undef SCR_REG_MAP
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index 337e7de4861..cc1b65fa593 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -46,6 +46,7 @@ class InstanceMap;
class InstanceScript;
class Item;
class Map;
+class ModuleReference;
class OutdoorPvP;
class Player;
class Quest;
@@ -157,14 +158,8 @@ class TC_GAME_API ScriptObject
protected:
- ScriptObject(const char* name)
- : _name(name)
- {
- }
-
- virtual ~ScriptObject()
- {
- }
+ ScriptObject(const char* name);
+ virtual ~ScriptObject();
private:
@@ -338,7 +333,8 @@ class TC_GAME_API WorldMapScript : public ScriptObject, public MapScript<Map>
WorldMapScript(const char* name, uint32 mapId);
};
-class TC_GAME_API InstanceMapScript : public ScriptObject, public MapScript<InstanceMap>
+class TC_GAME_API InstanceMapScript
+ : public ScriptObject, public MapScript<InstanceMap>
{
protected:
@@ -834,15 +830,6 @@ class TC_GAME_API GroupScript : public ScriptObject
virtual void OnDisband(Group* /*group*/) { }
};
-// Placed here due to ScriptRegistry::AddScript dependency.
-#define sScriptMgr ScriptMgr::instance()
-
-// namespace
-// {
- typedef std::list<std::string> UnusedScriptNamesContainer;
- TC_GAME_API extern UnusedScriptNamesContainer UnusedScriptNames;
-// }
-
// Manages registration, loading, and execution of scripts.
class TC_GAME_API ScriptMgr
{
@@ -852,16 +839,17 @@ class TC_GAME_API ScriptMgr
ScriptMgr();
virtual ~ScriptMgr();
+ void FillSpellSummary();
+ void LoadDatabase();
+
+ void IncreaseScriptCount() { ++_scriptCount; }
+ void DecreaseScriptCount() { --_scriptCount; }
+
public: /* Initialization */
static ScriptMgr* instance();
void Initialize();
- void LoadDatabase();
- void FillSpellSummary();
-
- const char* ScriptsVersion() const { return "Integrated Trinity Scripts"; }
- void IncrementScriptCount() { ++_scriptCount; }
uint32 GetScriptCount() const { return _scriptCount; }
typedef void(*ScriptLoaderCallbackType)();
@@ -873,6 +861,27 @@ class TC_GAME_API ScriptMgr
_script_loader_callback = script_loader_callback;
}
+ public: /* Script contexts */
+ /// Set the current script context, which allows the ScriptMgr
+ /// to accept new scripts in this context.
+ /// Requires a SwapScriptContext() call afterwards to load the new scripts.
+ void SetScriptContext(std::string const& context);
+ /// Returns the current script context.
+ std::string const& GetCurrentScriptContext() const { return _currentContext; }
+ /// Releases all scripts associated with the given script context immediately.
+ /// Requires a SwapScriptContext() call afterwards to finish the unloading.
+ void ReleaseScriptContext(std::string const& context);
+ /// Executes all changed introduced by SetScriptContext and ReleaseScriptContext.
+ /// It is possible to combine multiple SetScriptContext and ReleaseScriptContext
+ /// calls for better performance (bulk changes).
+ void SwapScriptContext(bool initialize = false);
+
+ /// Acquires a strong module reference to the module containing the given script name,
+ /// which prevents the shared library which contains the script from unloading.
+ /// The shared library is lazy unloaded as soon as all references to it are released.
+ std::shared_ptr<ModuleReference> AcquireModuleReferenceOfScriptName(
+ std::string const& scriptname) const;
+
public: /* Unloading */
void Unload();
@@ -881,7 +890,7 @@ class TC_GAME_API ScriptMgr
void CreateSpellScripts(uint32 spellId, std::list<SpellScript*>& scriptVector);
void CreateAuraScripts(uint32 spellId, std::list<AuraScript*>& scriptVector);
- void CreateSpellScriptLoaders(uint32 spellId, std::vector<std::pair<SpellScriptLoader*, std::multimap<uint32, uint32>::iterator> >& scriptVector);
+ SpellScriptLoader* GetSpellScriptLoader(uint32 scriptId);
public: /* ServerScript */
@@ -1094,21 +1103,14 @@ class TC_GAME_API ScriptMgr
void ModifyMeleeDamage(Unit* target, Unit* attacker, uint32& damage);
void ModifySpellDamageTaken(Unit* target, Unit* attacker, int32& damage);
- public: /* Scheduled scripts */
-
- uint32 IncreaseScheduledScriptsCount() { return ++_scheduledScripts; }
- uint32 DecreaseScheduledScriptCount() { return --_scheduledScripts; }
- uint32 DecreaseScheduledScriptCount(size_t count) { return _scheduledScripts -= count; }
- bool IsScriptScheduled() const { return _scheduledScripts > 0; }
-
private:
-
uint32 _scriptCount;
- //atomic op counter for active scripts amount
- std::atomic<uint32> _scheduledScripts;
-
ScriptLoaderCallbackType _script_loader_callback;
+
+ std::string _currentContext;
};
+#define sScriptMgr ScriptMgr::instance()
+
#endif
diff --git a/src/server/game/Scripting/ScriptReloadMgr.cpp b/src/server/game/Scripting/ScriptReloadMgr.cpp
new file mode 100644
index 00000000000..d13fa9c30f0
--- /dev/null
+++ b/src/server/game/Scripting/ScriptReloadMgr.cpp
@@ -0,0 +1,1609 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ScriptReloadMgr.h"
+#include "Errors.h"
+
+#ifndef TRINITY_API_USE_DYNAMIC_LINKING
+
+// This method should never be called
+std::shared_ptr<ModuleReference>
+ ScriptReloadMgr::AcquireModuleReferenceOfContext(std::string const& /*context*/)
+{
+ WPAbort();
+}
+
+// Returns the empty implemented ScriptReloadMgr
+ScriptReloadMgr* ScriptReloadMgr::instance()
+{
+ static ScriptReloadMgr instance;
+ return &instance;
+}
+
+#else
+
+#include <algorithm>
+#include <regex>
+#include <vector>
+#include <future>
+#include <memory>
+#include <fstream>
+#include <type_traits>
+#include <unordered_set>
+#include <unordered_map>
+
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/filesystem.hpp>
+#include <boost/system/system_error.hpp>
+
+#include "efsw/efsw.hpp"
+
+#include "Log.h"
+#include "Config.h"
+#include "BuiltInConfig.h"
+#include "ScriptMgr.h"
+#include "SHA1.h"
+#include "StartProcess.h"
+#include "MPSCQueue.h"
+#include "GitRevision.h"
+
+namespace fs = boost::filesystem;
+
+#ifdef _WIN32
+ #include <windows.h>
+ #define HOTSWAP_PLATFORM_REQUIRES_CACHING
+#else // Posix
+ #include <dlfcn.h>
+ // #define HOTSWAP_PLATFORM_REQUIRES_CACHING
+#endif
+
+// Promote the sScriptReloadMgr to a HotSwapScriptReloadMgr
+// in this compilation unit.
+#undef sScriptReloadMgr
+#define sScriptReloadMgr static_cast<HotSwapScriptReloadMgr*>(ScriptReloadMgr::instance())
+
+// Returns "" on Windows and "lib" on posix.
+static char const* GetSharedLibraryPrefix()
+{
+#ifdef _WIN32
+ return "";
+#else // Posix
+ return "lib";
+#endif
+}
+
+// Returns "dll" on Windows and "so" on posix.
+static char const* GetSharedLibraryExtension()
+{
+#ifdef _WIN32
+ return "dll";
+#else // Posix
+ return "so";
+#endif
+}
+
+#ifdef _WIN32
+typedef HMODULE HandleType;
+#else // Posix
+typedef void* HandleType;
+#endif
+
+static fs::path GetDirectoryOfExecutable()
+{
+ ASSERT((!sConfigMgr->GetArguments().empty()),
+ "Expected the arguments to contain at least 1 element!");
+
+ fs::path path(sConfigMgr->GetArguments()[0]);
+ if (path.is_absolute())
+ return path.parent_path();
+ else
+ return fs::absolute(path).parent_path();
+}
+
+class SharedLibraryUnloader
+{
+public:
+ explicit SharedLibraryUnloader(fs::path path)
+ : path_(std::move(path)) { }
+ SharedLibraryUnloader(fs::path path, Optional<fs::path> cache_path)
+ : path_(std::move(path)), cache_path_(std::move(cache_path)) { }
+
+ void operator() (HandleType handle) const
+ {
+ // Unload the associated shared library.
+#ifdef _WIN32
+ bool success = (FreeLibrary(handle) != 0);
+#else // Posix
+ bool success = (dlclose(handle) == 0);
+#endif
+
+ if (!success)
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Failed to unload (syscall) the shared library \"%s\".",
+ path_.generic_string().c_str());
+
+ return;
+ }
+
+ /// When the shared library was cached delete it's shared version
+ if (cache_path_)
+ {
+ boost::system::error_code error;
+ if (!fs::remove(*cache_path_, error))
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Failed to delete the cached shared library \"%s\" (%s).",
+ cache_path_->generic_string().c_str(), error.message().c_str());
+
+ return;
+ }
+
+ TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded the shared library \"%s\" "
+ "and deleted it's cached version at \"%s\"",
+ path_.generic_string().c_str(), cache_path_->generic_string().c_str());
+ }
+ else
+ {
+ TC_LOG_TRACE("scripts.hotswap", "Lazy unloaded the shared library \"%s\".",
+ path_.generic_string().c_str());
+ }
+ }
+
+private:
+ fs::path const path_;
+ Optional<fs::path> const cache_path_;
+};
+
+typedef std::unique_ptr<typename std::remove_pointer<HandleType>::type, SharedLibraryUnloader> HandleHolder;
+
+typedef char const* (*GetScriptModuleRevisionHashType)();
+typedef void (*AddScriptsType)();
+typedef char const* (*GetScriptModuleType)();
+typedef char const* (*GetBuildDirectiveType)();
+
+class ScriptModule
+ : public ModuleReference
+{
+public:
+ explicit ScriptModule(HandleHolder handle, GetScriptModuleRevisionHashType getScriptModuleRevisionHash,
+ AddScriptsType addScripts, GetScriptModuleType getScriptModule,
+ GetBuildDirectiveType getBuildDirective, fs::path const& path)
+ : _handle(std::forward<HandleHolder>(handle)), _getScriptModuleRevisionHash(getScriptModuleRevisionHash),
+ _addScripts(addScripts), _getScriptModule(getScriptModule),
+ _getBuildDirective(getBuildDirective), _path(path) { }
+
+ ScriptModule(ScriptModule const&) = delete;
+ ScriptModule(ScriptModule&& right) = delete;
+
+ ScriptModule& operator= (ScriptModule const&) = delete;
+ ScriptModule& operator= (ScriptModule&& right) = delete;
+
+ static Optional<std::shared_ptr<ScriptModule>>
+ CreateFromPath(fs::path const& path, Optional<fs::path> cache_path);
+
+ char const* GetScriptModuleRevisionHash() const override
+ {
+ return _getScriptModuleRevisionHash();
+ }
+
+ void AddScripts() const
+ {
+ return _addScripts();
+ }
+
+ char const* GetScriptModule() const override
+ {
+ return _getScriptModule();
+ }
+
+ char const* GetBuildDirective() const
+ {
+ return _getBuildDirective();
+ }
+
+ fs::path const& GetModulePath() const override
+ {
+ return _path;
+ }
+
+private:
+ HandleHolder _handle;
+
+ GetScriptModuleRevisionHashType _getScriptModuleRevisionHash;
+ AddScriptsType _addScripts;
+ GetScriptModuleType _getScriptModule;
+ GetBuildDirectiveType _getBuildDirective;
+
+ fs::path _path;
+};
+
+template<typename Fn>
+static bool GetFunctionFromSharedLibrary(HandleType handle, std::string const& name, Fn& fn)
+{
+#ifdef _WIN32
+ fn = reinterpret_cast<Fn>(GetProcAddress(handle, name.c_str()));
+#else // Posix
+ fn = reinterpret_cast<Fn>(dlsym(handle, name.c_str()));
+#endif
+ return fn != nullptr;
+}
+
+// Load a shared library from the given path.
+Optional<std::shared_ptr<ScriptModule>>
+ ScriptModule::CreateFromPath(fs::path const& path, Optional<fs::path> cache_path)
+{
+ auto const load_path = [&] () -> fs::path {
+ if (cache_path)
+ return *cache_path;
+ else
+ return path;
+ }();
+
+#ifdef _WIN32
+ HandleType handle = LoadLibrary(load_path.generic_string().c_str());
+#else // Posix
+ HandleType handle = dlopen(load_path.generic_string().c_str(), RTLD_LAZY);
+#endif
+
+ if (!handle)
+ {
+ if (cache_path)
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Could not dynamic load the shared library \"%s\" "
+ "(the library is cached at %s)",
+ path.generic_string().c_str(), cache_path->generic_string().c_str());
+ }
+ else
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Could not dynamic load the shared library \"%s\".",
+ path.generic_string().c_str());
+ }
+
+ return boost::none;
+ }
+
+ // Use RAII to release the library on failure.
+ HandleHolder holder(handle, SharedLibraryUnloader(path, std::move(cache_path)));
+
+ GetScriptModuleRevisionHashType getScriptModuleRevisionHash;
+ AddScriptsType addScripts;
+ GetScriptModuleType getScriptModule;
+ GetBuildDirectiveType getBuildDirective;
+
+ if (GetFunctionFromSharedLibrary(handle, "GetScriptModuleRevisionHash", getScriptModuleRevisionHash) &&
+ GetFunctionFromSharedLibrary(handle, "AddScripts", addScripts) &&
+ GetFunctionFromSharedLibrary(handle, "GetScriptModule", getScriptModule) &&
+ GetFunctionFromSharedLibrary(handle, "GetBuildDirective", getBuildDirective))
+ return std::make_shared<ScriptModule>(std::move(holder), getScriptModuleRevisionHash,
+ addScripts, getScriptModule, getBuildDirective, path);
+ else
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Could not extract all required functions from the shared library \"%s\"!",
+ path.generic_string().c_str());
+
+ return boost::none;
+ }
+}
+
+static bool HasValidScriptModuleName(std::string const& name)
+{
+ // Detects scripts_NAME.dll's / .so's
+ static std::regex const regex(
+ Trinity::StringFormat("^%s[sS]cripts_[a-zA-Z0-9_]+\\.%s$",
+ GetSharedLibraryPrefix(),
+ GetSharedLibraryExtension()));
+
+ return std::regex_match(name, regex);
+}
+
+/// File watcher responsible for watching shared libraries
+class LibraryUpdateListener : public efsw::FileWatchListener
+{
+public:
+ LibraryUpdateListener() { }
+ virtual ~LibraryUpdateListener() { }
+
+ void handleFileAction(efsw::WatchID /*watchid*/, std::string const& dir,
+ std::string const& filename, efsw::Action action, std::string oldFilename = "") final override;
+};
+
+static LibraryUpdateListener libraryUpdateListener;
+
+/// File watcher responsible for watching source files
+class SourceUpdateListener : public efsw::FileWatchListener
+{
+ fs::path const path_;
+
+ std::string const script_module_name_;
+
+ efsw::WatchID const watcher_id_;
+
+public:
+ explicit SourceUpdateListener(fs::path path, std::string script_module_name);
+
+ virtual ~SourceUpdateListener();
+
+ void handleFileAction(efsw::WatchID /*watchid*/, std::string const& dir,
+ std::string const& filename, efsw::Action action, std::string oldFilename = "") final override;
+};
+
+namespace std
+{
+ template <>
+ struct hash<fs::path>
+ {
+ hash<string> hasher;
+
+ std::size_t operator()(fs::path const& key) const
+ {
+ return hasher(key.generic_string());
+ }
+ };
+}
+
+/// Invokes a synchronous CMake process with the given arguments
+template<typename... T>
+static int InvokeCMakeCommand(T&&... args)
+{
+ auto const executable = BuiltInConfig::GetCMakeCommand();
+ return Trinity::StartProcess(executable, {
+ executable,
+ std::forward<T>(args)...
+ }, "scripts.hotswap");
+}
+
+/// Invokes an asynchronous CMake process with the given arguments
+template<typename... T>
+static std::shared_ptr<Trinity::AsyncProcessResult> InvokeAsyncCMakeCommand(T&&... args)
+{
+ auto const executable = BuiltInConfig::GetCMakeCommand();
+ return Trinity::StartAsyncProcess(executable, {
+ executable,
+ std::forward<T>(args)...
+ }, "scripts.hotswap");
+}
+
+/// Calculates the C++ project name of the given module which is
+/// the lowercase string of scripts_${module}.
+static std::string CalculateScriptModuleProjectName(std::string const& module)
+{
+ std::string module_project = "scripts_" + module;
+ std::transform(module_project.begin(), module_project.end(),
+ module_project.begin(), ::tolower);
+
+ return module_project;
+}
+
+/// Returns false when there isn't any attached debugger to the process which
+/// could block the rebuild of new shared libraries.
+static bool IsDebuggerBlockingRebuild()
+{
+#ifdef _WIN32
+ if (IsDebuggerPresent())
+ return true;
+#endif
+ return false;
+}
+
+/// ScriptReloadMgr which is used when dynamic linking is enabled
+///
+/// This class manages shared library loading/unloading through watching
+/// the script module directory. Loaded shared libraries are mirrored
+/// into a cache subdirectory to allow lazy unloading as long as
+/// the shared library is still used which is useful for scripts
+/// which can't be instantly replaced like spells or instances.
+/// Several modules which reference different versions can be kept loaded
+/// to serve scripts of different versions to entities and spells.
+///
+/// Also this class invokes rebuilds as soon as the source of loaded
+/// scripts change and installs the modules correctly through CMake.
+class HotSwapScriptReloadMgr final
+ : public ScriptReloadMgr
+{
+ friend class ScriptReloadMgr;
+ friend class SourceUpdateListener;
+
+ /// Reflects a queued change on a shared library or shared library
+ /// which is waiting for processing
+ enum class ChangeStateRequest : uint8
+ {
+ CHANGE_REQUEST_ADDED,
+ CHANGE_REQUEST_MODIFIED,
+ CHANGE_REQUEST_REMOVED
+ };
+
+ /// Reflects a running job of an invoked asynchronous external process
+ enum class BuildJobType : uint8
+ {
+ BUILD_JOB_NONE,
+ BUILD_JOB_RERUN_CMAKE,
+ BUILD_JOB_COMPILE,
+ BUILD_JOB_INSTALL,
+ };
+
+ // Represents a job which was invoked through a source or shared library change
+ class BuildJob
+ {
+ // Script module which is processed in the current running job
+ std::string script_module_name_;
+ // The C++ project name of the module which is processed
+ std::string script_module_project_name_;
+ // The build directive of the current module which is processed
+ // like "Release" or "Debug". The build directive from the
+ // previous same module is used if there was any.
+ std::string script_module_build_directive_;
+ // The time where the build job started
+ uint32 start_time_;
+
+ // Type of the current running job
+ BuildJobType type_;
+ // The async process result of the current job
+ std::shared_ptr<Trinity::AsyncProcessResult> async_result_;
+
+ public:
+ explicit BuildJob(std::string script_module_name, std::string script_module_project_name,
+ std::string script_module_build_directive)
+ : script_module_name_(std::move(script_module_name)),
+ script_module_project_name_(std::move(script_module_project_name)),
+ script_module_build_directive_(std::move(script_module_build_directive)),
+ start_time_(getMSTime()), type_(BuildJobType::BUILD_JOB_NONE) { }
+
+ bool IsValid() const
+ {
+ return type_ != BuildJobType::BUILD_JOB_NONE;
+ }
+
+ std::string const& GetModuleName() const { return script_module_name_; }
+
+ std::string const& GetProjectName() const { return script_module_project_name_; }
+
+ std::string const& GetBuildDirective() const { return script_module_build_directive_; }
+
+ uint32 GetTimeFromStart() const { return GetMSTimeDiffToNow(start_time_); }
+
+ BuildJobType GetType() const { return type_; }
+
+ std::shared_ptr<Trinity::AsyncProcessResult> const& GetProcess() const
+ {
+ ASSERT(async_result_, "Tried to access an empty process handle!");
+ return async_result_;
+ }
+
+ /// Updates the current running job with the given type and async result
+ void UpdateCurrentJob(BuildJobType type,
+ std::shared_ptr<Trinity::AsyncProcessResult> async_result)
+ {
+ ASSERT(type != BuildJobType::BUILD_JOB_NONE, "None isn't allowed here!");
+ ASSERT(async_result, "The async result must not be empty!");
+
+ type_ = type;
+ async_result_ = std::move(async_result);
+ }
+ };
+
+ /// Base class for lockfree asynchronous messages to the script reloader
+ class ScriptReloaderMessage
+ {
+ public:
+ virtual ~ScriptReloaderMessage() { }
+
+ /// Invoke this function to run a message thread safe on the reloader
+ virtual void operator() (HotSwapScriptReloadMgr* reloader) = 0;
+ };
+
+ /// Implementation class which wraps functional types and dispatches
+ /// it in the overwritten implementation of the reloader messages.
+ template<typename T>
+ class ScriptReloaderMessageImplementation
+ : public ScriptReloaderMessage
+ {
+ T dispatcher_;
+
+ public:
+ explicit ScriptReloaderMessageImplementation(T dispatcher)
+ : dispatcher_(std::move(dispatcher)) { }
+
+ void operator() (HotSwapScriptReloadMgr* reloader) final override
+ {
+ dispatcher_(reloader);
+ }
+ };
+
+ /// Uses the given functional type and creates a asynchronous reloader
+ /// message on the heap, which requires deletion.
+ template<typename T>
+ auto MakeMessage(T&& dispatcher)
+ -> ScriptReloaderMessageImplementation<typename std::decay<T>::type>*
+ {
+ return new ScriptReloaderMessageImplementation<typename std::decay<T>::type>
+ (std::forward<T>(dispatcher));
+ }
+
+public:
+ HotSwapScriptReloadMgr()
+ : _libraryWatcher(-1), _unique_library_name_counter(0),
+ _last_time_library_changed(0), _last_time_sources_changed(0),
+ _last_time_user_informed(0), terminate_early(false) { }
+
+ virtual ~HotSwapScriptReloadMgr()
+ {
+ // Delete all messages
+ ScriptReloaderMessage* message;
+ while (_messages.Dequeue(message))
+ delete message;
+ }
+
+ /// Returns the absolute path to the script module directory
+ static fs::path GetLibraryDirectory()
+ {
+ // When an absolute path is given in the config use it,
+ // otherwise interpret paths relative to the executable.
+ fs::path path(sConfigMgr->GetStringDefault("HotSwap.ScriptDir", "scripts"));
+ if (path.is_absolute())
+ return path;
+ else
+ return fs::absolute(path, GetDirectoryOfExecutable());
+ }
+
+ /// Returns the absolute path to the scripts directory in the source tree.
+ static fs::path GetSourceDirectory()
+ {
+ fs::path dir = BuiltInConfig::GetSourceDirectory();
+ dir /= "src";
+ dir /= "server";
+ dir /= "scripts";
+ return dir;
+ }
+
+ /// Initializes the file watchers and loads all existing shared libraries
+ /// into the running server.
+ void Initialize() final override
+ {
+ if (!sWorld->getBoolConfig(CONFIG_HOTSWAP_ENABLED))
+ return;
+
+ if (BuiltInConfig::GetBuildDirectory().find(" ") != std::string::npos)
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Your build directory path \"%s\" "
+ "contains spaces, which isn't allowed for compatibility reasons! "
+ "You need to create a build directory which doesn't contain any space character "
+ "in it's path!",
+ BuiltInConfig::GetBuildDirectory().c_str());
+
+ return;
+ }
+
+ {
+ auto const library_directory = GetLibraryDirectory();
+ if (!fs::exists(library_directory) || !fs::is_directory(library_directory))
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Library directory \"%s\" doesn't exist!.",
+ library_directory.generic_string().c_str());
+ return;
+ }
+ }
+
+ #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING
+
+ temporary_cache_path_ = CalculateTemporaryCachePath();
+
+ // We use the boost filesystem function versions which accept
+ // an error code to prevent it from throwing exceptions.
+ boost::system::error_code code;
+ if ((!fs::exists(temporary_cache_path_, code)
+ || (fs::remove_all(temporary_cache_path_, code) > 0)) &&
+ !fs::create_directory(temporary_cache_path_, code))
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Couldn't create the cache directory at \"%s\".",
+ temporary_cache_path_.generic_string().c_str());
+
+ return;
+ }
+
+ // Used to silent compiler warnings
+ (void)code;
+
+ #endif // #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING
+
+ // Correct the CMake prefix when needed
+ if (sWorld->getBoolConfig(CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED))
+ DoCMakePrefixCorrectionIfNeeded();
+
+ InitializeDefaultLibraries();
+ InitializeFileWatchers();
+ }
+
+ /// Needs to be called periodically from the worldserver loop
+ /// to invoke queued actions like module loading/unloading and script
+ /// compilation.
+ /// This method should be invoked from a thread safe point to
+ /// prevent misbehavior.
+ void Update() final override
+ {
+ // Consume all messages
+ ScriptReloaderMessage* message;
+ while (_messages.Dequeue(message))
+ {
+ (*message)(this);
+ delete message;
+ }
+
+ DispatchRunningBuildJobs();
+ DispatchModuleChanges();
+ }
+
+ /// Unloads the manager and cancels all runnings jobs immediately
+ void Unload() final override
+ {
+ if (_libraryWatcher >= 0)
+ {
+ _fileWatcher.removeWatch(_libraryWatcher);
+ _libraryWatcher = -1;
+ }
+
+ // If a build is in progress cancel it
+ if (_build_job)
+ {
+ _build_job->GetProcess()->Terminate();
+ _build_job.reset();
+ }
+
+ // Release all strong references to script modules
+ // to trigger unload actions as early as possible,
+ // otherwise the worldserver will crash on exit.
+ _running_script_modules.clear();
+ }
+
+ /// Queue's a thread safe message to the reloader which is executed on
+ /// the next world server update tick.
+ template<typename T>
+ void QueueMessage(T&& message)
+ {
+ _messages.Enqueue(MakeMessage(std::forward<T>(message)));
+ }
+
+ /// Queues an action which marks the given shared library as changed
+ /// which will add, unload or reload it at the next world update tick.
+ /// This method is thread safe.
+ void QueueSharedLibraryChanged(fs::path const& path)
+ {
+ _last_time_library_changed = getMSTime();
+ _libraries_changed.insert(path);
+ }
+
+ /// Queues a notification that a source file was added
+ /// This method is thread unsafe.
+ void QueueAddSourceFile(std::string const& module_name, fs::path const& path)
+ {
+ UpdateSourceChangeRequest(module_name, path, ChangeStateRequest::CHANGE_REQUEST_ADDED);
+ }
+
+ /// Queues a notification that a source file was modified
+ /// This method is thread unsafe.
+ void QueueModifySourceFile(std::string const& module_name, fs::path const& path)
+ {
+ UpdateSourceChangeRequest(module_name, path, ChangeStateRequest::CHANGE_REQUEST_MODIFIED);
+ }
+
+ /// Queues a notification that a source file was removed
+ /// This method is thread unsafe.
+ void QueueRemoveSourceFile(std::string const& module_name, fs::path const& path)
+ {
+ UpdateSourceChangeRequest(module_name, path, ChangeStateRequest::CHANGE_REQUEST_REMOVED);
+ }
+
+private:
+ // Loads all shared libraries which are contained in the
+ // scripts directory on startup.
+ void InitializeDefaultLibraries()
+ {
+ fs::path const libraryDirectory(GetLibraryDirectory());
+ fs::directory_iterator const dir_end;
+
+ uint32 count = 0;
+
+ // Iterate through all shared libraries in the script directory and load it
+ for (fs::directory_iterator dir_itr(libraryDirectory); dir_itr != dir_end ; ++dir_itr)
+ if (fs::is_regular_file(dir_itr->path()) && HasValidScriptModuleName(dir_itr->path().filename().generic_string()))
+ {
+ TC_LOG_INFO("scripts.hotswap", "Loading script module \"%s\"...",
+ dir_itr->path().filename().generic_string().c_str());
+
+ // Don't swap the script context to do bulk loading
+ ProcessLoadScriptModule(dir_itr->path(), false);
+ ++count;
+ }
+
+ TC_LOG_INFO("scripts.hotswap", ">> Loaded %u script modules.", count);
+ }
+
+ // Initialize all enabled file watchers.
+ // Needs to be called after InitializeDefaultLibraries()!
+ void InitializeFileWatchers()
+ {
+ _libraryWatcher = _fileWatcher.addWatch(GetLibraryDirectory().generic_string(), &libraryUpdateListener, false);
+ if (_libraryWatcher >= 0)
+ {
+ TC_LOG_INFO("scripts.hotswap", ">> Library reloader is listening on \"%s\".",
+ GetLibraryDirectory().generic_string().c_str());
+ }
+ else
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Failed to initialize the library reloader on \"%s\".",
+ GetLibraryDirectory().generic_string().c_str());
+ }
+
+ _fileWatcher.watch();
+ }
+
+ static fs::path CalculateTemporaryCachePath()
+ {
+ auto path = fs::temp_directory_path();
+ path /= Trinity::StringFormat("tc_script_cache_%s_%s",
+ GitRevision::GetBranch(),
+ CalculateSHA1Hash(sConfigMgr->GetFilename()).c_str());
+
+ return path;
+ }
+
+ fs::path GenerateUniquePathForLibraryInCache(fs::path path)
+ {
+ ASSERT(!temporary_cache_path_.empty(),
+ "The temporary cache path wasn't set!");
+
+ // Create the cache path and increment the library counter to use an unique name for each library
+ auto cache_path = temporary_cache_path_;
+ cache_path /= Trinity::StringFormat("%s.%u%s",
+ path.stem().generic_string().c_str(),
+ _unique_library_name_counter++,
+ path.extension().generic_string().c_str());
+
+ return cache_path;
+ }
+
+ /// Updates the current state of the given source path
+ void UpdateSourceChangeRequest(std::string const& module_name,
+ fs::path const& path,
+ ChangeStateRequest state)
+ {
+ _last_time_sources_changed = getMSTime();
+
+ // Write when there is no module with the given name known
+ auto module_itr = _sources_changed.find(module_name);
+
+ // When the file was modified it's enough to mark the module as
+ // dirty by initializing the associated map.
+ if (module_itr == _sources_changed.end())
+ module_itr = _sources_changed.insert(std::make_pair(
+ module_name, decltype(_sources_changed)::mapped_type{})).first;
+
+ // Leave when the file was just modified as explained above
+ if (state == ChangeStateRequest::CHANGE_REQUEST_MODIFIED)
+ return;
+
+ // Insert when the given path isn't existent
+ auto const itr = module_itr->second.find(path);
+ if (itr == module_itr->second.end())
+ {
+ module_itr->second.insert(std::make_pair(path, state));
+ return;
+ }
+
+ ASSERT((itr->second == ChangeStateRequest::CHANGE_REQUEST_ADDED)
+ || (itr->second == ChangeStateRequest::CHANGE_REQUEST_REMOVED),
+ "Stored value is invalid!");
+
+ ASSERT((state == ChangeStateRequest::CHANGE_REQUEST_ADDED)
+ || (state == ChangeStateRequest::CHANGE_REQUEST_REMOVED),
+ "The given state is invalid!");
+
+ ASSERT(state != itr->second,
+ "Tried to apply a state which is stored already!");
+
+ module_itr->second.erase(itr);
+ }
+
+ /// Called periodically on the worldserver tick to process all
+ /// load/unload/reload requests of shared libraries.
+ void DispatchModuleChanges()
+ {
+ // When there are no libraries to change return
+ if (_libraries_changed.empty())
+ return;
+
+ // Wait some time after changes to catch bulk changes
+ if (GetMSTimeDiffToNow(_last_time_library_changed) < 500)
+ return;
+
+ for (auto const& path : _libraries_changed)
+ {
+ bool const is_running =
+ _running_script_module_names.find(path) != _running_script_module_names.end();
+
+ bool const exists = fs::exists(path);
+
+ if (is_running)
+ {
+ if (exists)
+ ProcessReloadScriptModule(path);
+ else
+ ProcessUnloadScriptModule(path);
+ }
+ else if (exists)
+ ProcessLoadScriptModule(path);
+ }
+
+ _libraries_changed.clear();
+ }
+
+ void ProcessLoadScriptModule(fs::path const& path, bool swap_context = true)
+ {
+ ASSERT(_running_script_module_names.find(path) == _running_script_module_names.end(),
+ "Can't load a module which is running already!");
+
+ Optional<fs::path> cache_path;
+
+ #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING
+
+ // Copy the shared library into a cache on platforms which lock files on use (windows).
+ cache_path = GenerateUniquePathForLibraryInCache(path);
+
+ {
+ boost::system::error_code code;
+ fs::copy_file(path, *cache_path, fs::copy_option::fail_if_exists, code);
+ if (code)
+ {
+ TC_LOG_FATAL("scripts.hotswap", ">> Failed to create cache entry for module "
+ "\"%s\" at \"%s\" with reason (\"%s\")!",
+ path.filename().generic_string().c_str(), cache_path->generic_string().c_str(),
+ code.message().c_str());
+
+ // Find a better solution for this but it's much better
+ // to start the core without scripts
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ ABORT();
+ return;
+ }
+
+ TC_LOG_TRACE("scripts.hotswap", ">> Copied the shared library \"%s\" to \"%s\" for caching.",
+ path.filename().generic_string().c_str(), cache_path->generic_string().c_str());
+ }
+
+ #endif // #ifdef HOTSWAP_PLATFORM_REQUIRES_CACHING
+
+ auto module = ScriptModule::CreateFromPath(path, cache_path);
+ if (!module)
+ {
+ TC_LOG_FATAL("scripts.hotswap", ">> Failed to load script module \"%s\"!",
+ path.filename().generic_string().c_str());
+
+ // Find a better solution for this but it's much better
+ // to start the core without scripts
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ ABORT();
+ return;
+ }
+
+ // Limit the git revision hash to 7 characters.
+ std::string module_revision((*module)->GetScriptModuleRevisionHash());
+ if (module_revision.size() >= 7)
+ module_revision = module_revision.substr(0, 7);
+
+ std::string const module_name = (*module)->GetScriptModule();
+ TC_LOG_INFO("scripts.hotswap", ">> Loaded script module \"%s\" (\"%s\" - %s).",
+ path.filename().generic_string().c_str(), module_name.c_str(), module_revision.c_str());
+
+ if (module_revision.empty())
+ {
+ TC_LOG_WARN("scripts.hotswap", ">> Script module \"%s\" has an empty revision hash!",
+ path.filename().generic_string().c_str());
+ }
+ else
+ {
+ // Trim the revision hash
+ std::string my_revision_hash = GitRevision::GetHash();
+ std::size_t const trim = std::min(module_revision.size(), my_revision_hash.size());
+ my_revision_hash = my_revision_hash.substr(0, trim);
+ module_revision = module_revision.substr(0, trim);
+
+ if (my_revision_hash != module_revision)
+ {
+ TC_LOG_WARN("scripts.hotswap", ">> Script module \"%s\" has a different revision hash! "
+ "Binary incompatibility could lead to unknown behaviour!", path.filename().generic_string().c_str());
+ }
+ }
+
+ {
+ auto const itr = _running_script_modules.find(module_name);
+ if (itr != _running_script_modules.end())
+ {
+ TC_LOG_ERROR("scripts.hotswap", ">> Attempt to load a module twice \"%s\" (loaded module is at %s)!",
+ path.generic_string().c_str(), itr->second.first->GetModulePath().generic_string().c_str());
+
+ return;
+ }
+ }
+
+ sScriptMgr->SetScriptContext(module_name);
+ (*module)->AddScripts();
+ TC_LOG_TRACE("scripts.hotswap", ">> Registered all scripts of module %s.", module_name.c_str());
+
+ if (swap_context)
+ sScriptMgr->SwapScriptContext();
+
+ // Create the source listener
+ auto listener = Trinity::make_unique<SourceUpdateListener>(
+ sScriptReloadMgr->GetSourceDirectory() / module_name,
+ module_name);
+
+ // Store the module
+ _known_modules_build_directives.insert(std::make_pair(module_name, (*module)->GetBuildDirective()));
+ _running_script_modules.insert(std::make_pair(module_name,
+ std::make_pair(std::move(*module), std::move(listener))));
+ _running_script_module_names.insert(std::make_pair(path, module_name));
+ }
+
+ void ProcessReloadScriptModule(fs::path const& path)
+ {
+ ProcessUnloadScriptModule(path, false);
+ ProcessLoadScriptModule(path);
+ }
+
+ void ProcessUnloadScriptModule(fs::path const& path, bool finish = true)
+ {
+ auto const itr = _running_script_module_names.find(path);
+
+ ASSERT(itr != _running_script_module_names.end(),
+ "Can't unload a module which isn't running!");
+
+ // Unload the script context
+ sScriptMgr->ReleaseScriptContext(itr->second);
+
+ if (finish)
+ sScriptMgr->SwapScriptContext();
+
+ TC_LOG_INFO("scripts.hotswap", "Released script module \"%s\" (\"%s\")...",
+ path.filename().generic_string().c_str(), itr->second.c_str());
+
+ // Unload the script module
+ auto ref = _running_script_modules.find(itr->second);
+ ASSERT(ref != _running_script_modules.end() &&
+ "Expected the script reference to be present!");
+
+ // Yield a message when there are other owning references to
+ // the module which prevents it from unloading.
+ // The module will be unloaded once all scripts provided from the module
+ // are destroyed.
+ if (!ref->second.first.unique())
+ {
+ TC_LOG_INFO("scripts.hotswap",
+ "Script module %s is still used by %lu spell, aura or instance scripts. "
+ "Will lazy unload the module once all scripts stopped using it, "
+ "to use the latest version of an edited script unbind yourself from "
+ "the instance or re-cast the spell.",
+ ref->second.first->GetScriptModule(), ref->second.first.use_count() - 1);
+ }
+
+ // Remove the owning reference from the reloader
+ _running_script_modules.erase(ref);
+ _running_script_module_names.erase(itr);
+ }
+
+ /// Called periodically on the worldserver tick to process all recompile
+ /// requests. This method invokes one build or install job at the time
+ void DispatchRunningBuildJobs()
+ {
+ if (_build_job)
+ {
+ // Terminate the current build job when an associated source was changed
+ // while compiling and the terminate early option is enabled.
+ if (sWorld->getBoolConfig(CONFIG_HOTSWAP_EARLY_TERMINATION_ENABLED))
+ {
+ if (!terminate_early && _sources_changed.find(_build_job->GetModuleName()) != _sources_changed.end())
+ {
+ /*
+ FIXME: Currently crashes the server
+ TC_LOG_INFO("scripts.hotswap", "Terminating the running build of module \"%s\"...",
+ _build_job->GetModuleName().c_str());
+
+ _build_job->GetProcess()->Terminate();
+ _build_job.reset();
+
+ // Continue with the default execution path
+ DispatchRunningBuildJobs();
+ return;
+ */
+
+ terminate_early = true;
+ return;
+ }
+ }
+
+ // Wait for the current build job to finish, if the job finishes in time
+ // evaluate it and continue with the next one.
+ if (_build_job->GetProcess()->GetFutureResult().
+ wait_for(std::chrono::seconds(0)) == std::future_status::ready)
+ ProcessReadyBuildJob();
+ else
+ return; // Return when the job didn't finish in time
+
+ // Skip this cycle when the previous job scheduled a new one
+ if (_build_job)
+ return;
+ }
+
+ // Avoid burst updates through waiting for a short time after changes
+ if ((_last_time_sources_changed != 0) &&
+ (GetMSTimeDiffToNow(_last_time_sources_changed) < 500))
+ return;
+
+ // If the changed sources are empty do nothing
+ if (_sources_changed.empty())
+ return;
+
+ // Wait until are attached debugger were detached.
+ if (IsDebuggerBlockingRebuild())
+ {
+ if ((_last_time_user_informed == 0) ||
+ (GetMSTimeDiffToNow(_last_time_user_informed) > 7500))
+ {
+ _last_time_user_informed = getMSTime();
+
+ // Informs the user that the attached debugger is blocking the automatic script rebuild.
+ TC_LOG_INFO("scripts.hotswap", "Your attached debugger is blocking the TrinityCore "
+ "automatic script rebuild, please detach it!");
+ }
+
+ return;
+ }
+
+ // Find all source files of a changed script module and removes
+ // it from the changed source list, invoke the build afterwards.
+ bool rebuild_buildfiles;
+ auto module_name = [&]
+ {
+ auto itr = _sources_changed.begin();
+ auto name = itr->first;
+ rebuild_buildfiles = !itr->second.empty();
+
+ if (sLog->ShouldLog("scripts.hotswap", LogLevel::LOG_LEVEL_TRACE))
+ for (auto const& entry : itr->second)
+ {
+ TC_LOG_TRACE("scripts.hotswap", "Source file %s was %s.",
+ entry.first.generic_string().c_str(),
+ ((entry.second == ChangeStateRequest::CHANGE_REQUEST_ADDED) ?
+ "added" : "removed"));
+ }
+
+ _sources_changed.erase(itr);
+ return name;
+ }();
+
+ // Erase the added delete history all modules when we
+ // invoke a cmake rebuild since we add all
+ // added files of other modules to the build as well
+ if (rebuild_buildfiles)
+ {
+ for (auto& entry : _sources_changed)
+ entry.second.clear();
+ }
+
+ ASSERT(!module_name.empty(),
+ "The current module name is invalid!");
+
+ TC_LOG_INFO("scripts.hotswap", "Recompiling Module \"%s\"...",
+ module_name.c_str());
+
+ // Calculate the project name of the script module
+ auto project_name = CalculateScriptModuleProjectName(module_name);
+
+ // Find the best build directive for the module
+ auto build_directive = [&] () -> std::string
+ {
+ auto directive = sConfigMgr->GetStringDefault("HotSwap.ReCompilerBuildType", "");
+ if (!directive.empty())
+ return directive;
+
+ auto const itr = _known_modules_build_directives.find(module_name);
+ if (itr != _known_modules_build_directives.end())
+ return itr->second;
+ else // If no build directive of the module was found use the one from the game library
+ return _BUILD_DIRECTIVE;
+ }();
+
+ // Initiate the new build job
+ _build_job = BuildJob(std::move(module_name),
+ std::move(project_name), std::move(build_directive));
+
+ // Rerun CMake when we need to recreate the build files
+ if (rebuild_buildfiles
+ && sWorld->getBoolConfig(CONFIG_HOTSWAP_BUILD_FILE_RECREATION_ENABLED))
+ DoRerunCMake();
+ else
+ DoCompileCurrentProcessedModule();
+ }
+
+ void ProcessReadyBuildJob()
+ {
+ ASSERT(_build_job->IsValid(), "Invalid build job!");
+
+ // Retrieve the result
+ auto const error = _build_job->GetProcess()->GetFutureResult().get();
+
+ if (terminate_early)
+ {
+ _build_job.reset();
+ terminate_early = false;
+ return;
+ }
+
+ switch (_build_job->GetType())
+ {
+ case BuildJobType::BUILD_JOB_RERUN_CMAKE:
+ {
+ if (!error)
+ {
+ TC_LOG_INFO("scripts.hotswap", ">> Successfully updated the build files!");
+ }
+ else
+ {
+ TC_LOG_INFO("scripts.hotswap", ">> Failed to update the build files at \"%s\", "
+ "it's possible that recently added sources are not included "
+ "in your next builds, rerun CMake manually.",
+ BuiltInConfig::GetBuildDirectory().c_str());
+ }
+ // Continue with building the changes sources
+ DoCompileCurrentProcessedModule();
+ return;
+ }
+ case BuildJobType::BUILD_JOB_COMPILE:
+ {
+ if (!error) // Build was successful
+ {
+ if (sWorld->getBoolConfig(CONFIG_HOTSWAP_INSTALL_ENABLED))
+ {
+ // Continue with the installation when it's enabled
+ TC_LOG_INFO("scripts.hotswap",
+ ">> Successfully build module %s, continue with installing...",
+ _build_job->GetModuleName().c_str());
+
+ DoInstallCurrentProcessedModule();
+ return;
+ }
+
+ // Skip the installation because it's disabled in config
+ TC_LOG_INFO("scripts.hotswap",
+ ">> Successfully build module %s, skipped the installation.",
+ _build_job->GetModuleName().c_str());
+ }
+ else // Build wasn't successful
+ {
+ TC_LOG_ERROR("scripts.hotswap",
+ ">> The build of module %s failed! See the log for details.",
+ _build_job->GetModuleName().c_str());
+ }
+ break;
+ }
+ case BuildJobType::BUILD_JOB_INSTALL:
+ {
+ if (!error)
+ {
+ // Installation was successful
+ TC_LOG_INFO("scripts.hotswap", ">> Successfully installed module %s in %us",
+ _build_job->GetModuleName().c_str(),
+ _build_job->GetTimeFromStart() / IN_MILLISECONDS);
+ }
+ else
+ {
+ // Installation wasn't successful
+ TC_LOG_INFO("scripts.hotswap",
+ ">> The installation of module %s failed! See the log for details.",
+ _build_job->GetModuleName().c_str());
+ }
+ break;
+ }
+ default:
+ break;
+ }
+
+ // Clear the current job
+ _build_job.reset();
+ }
+
+ /// Reruns CMake asynchronously over the build directory
+ void DoRerunCMake()
+ {
+ ASSERT(_build_job, "There isn't any active build job!");
+
+ TC_LOG_INFO("scripts.hotswap", "Rerunning CMake because there were sources added or removed...");
+
+ _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_RERUN_CMAKE,
+ InvokeAsyncCMakeCommand(BuiltInConfig::GetBuildDirectory()));
+ }
+
+ /// Invokes a new build of the current active module job
+ void DoCompileCurrentProcessedModule()
+ {
+ ASSERT(_build_job, "There isn't any active build job!");
+
+ TC_LOG_INFO("scripts.hotswap", "Starting asynchronous build job for module %s...",
+ _build_job->GetModuleName().c_str());
+
+ _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_COMPILE,
+ InvokeAsyncCMakeCommand(
+ "--build", BuiltInConfig::GetBuildDirectory(),
+ "--target", _build_job->GetProjectName(),
+ "--config", _build_job->GetBuildDirective()));
+ }
+
+ /// Invokes a new asynchronous install of the current active module job
+ void DoInstallCurrentProcessedModule()
+ {
+ ASSERT(_build_job, "There isn't any active build job!");
+
+ TC_LOG_INFO("scripts.hotswap", "Starting asynchronous install job for module %s...",
+ _build_job->GetModuleName().c_str());
+
+ _build_job->UpdateCurrentJob(BuildJobType::BUILD_JOB_INSTALL,
+ InvokeAsyncCMakeCommand(
+ "-DCOMPONENT=" + _build_job->GetProjectName(),
+ "-DBUILD_TYPE=" + _build_job->GetBuildDirective(),
+ "-P", fs::absolute("cmake_install.cmake",
+ BuiltInConfig::GetBuildDirectory()).generic_string()));
+ }
+
+ /// Sets the CMAKE_INSTALL_PREFIX variable in the CMake cache
+ /// to point to the current worldserver position,
+ /// since most users will forget this.
+ void DoCMakePrefixCorrectionIfNeeded()
+ {
+ TC_LOG_INFO("scripts.hotswap", "Correcting your CMAKE_INSTALL_PREFIX in \"%s\"...",
+ BuiltInConfig::GetBuildDirectory().c_str());
+
+ auto const cmake_cache_path = fs::absolute("CMakeCache.txt",
+ BuiltInConfig::GetBuildDirectory());
+
+ // Stop when the CMakeCache wasn't found
+ if (![&]
+ {
+ boost::system::error_code error;
+ if (!fs::exists(cmake_cache_path, error))
+ {
+ TC_LOG_ERROR("scripts.hotswap", ">> CMake cache \"%s\" doesn't exist, "
+ "set the \"BuildDirectory\" option in your worldserver.conf to point"
+ "to your build directory!",
+ cmake_cache_path.generic_string().c_str());
+
+ return false;
+ }
+ else
+ return true;
+ }())
+ return;
+
+ TC_LOG_TRACE("scripts.hotswap", "Checking CMake cache (\"%s\") "
+ "for the correct CMAKE_INSTALL_PREFIX location...",
+ cmake_cache_path.generic_string().c_str());
+
+ std::string cmake_cache_content;
+ {
+ std::ifstream in(cmake_cache_path.generic_string());
+ if (!in.is_open())
+ {
+ TC_LOG_ERROR("scripts.hotswap", ">> Failed to read the CMake cache at \"%s\"!",
+ cmake_cache_path.generic_string().c_str());
+
+ return;
+ }
+
+ std::ostringstream ss;
+ ss << in.rdbuf();
+ cmake_cache_content = ss.str();
+
+ in.close();
+ }
+
+ static std::string const prefix_key = "CMAKE_INSTALL_PREFIX:PATH=";
+
+ // Extract the value of CMAKE_INSTALL_PREFIX
+ auto begin = cmake_cache_content.find(prefix_key);
+ if (begin != std::string::npos)
+ {
+ begin += prefix_key.length();
+ auto const end = cmake_cache_content.find("\n", begin);
+ if (end != std::string::npos)
+ {
+ fs::path value = cmake_cache_content.substr(begin, end - begin);
+
+ auto current_path = fs::current_path();
+
+ #ifndef _WIN32
+ // The worldserver location is ${CMAKE_INSTALL_PREFIX}/bin
+ // on all other platforms then windows
+ current_path = current_path.parent_path();
+ #endif
+
+ if (value != current_path)
+ {
+ // Prevent correction of the install prefix
+ // when we are starting the core from inside the build tree
+ bool const is_in_path = [&]
+ {
+ fs::path base = BuiltInConfig::GetBuildDirectory();
+ fs::path branch = value;
+ while (!branch.empty())
+ {
+ if (base == branch)
+ return true;
+
+ branch = branch.parent_path();
+ }
+
+ return false;
+ }();
+
+ if (is_in_path)
+ return;
+
+ TC_LOG_INFO("scripts.hotswap", ">> Found outdated CMAKE_INSTALL_PREFIX (\"%s\"), "
+ "worldserver is currently installed at %s...",
+ value.generic_string().c_str(), current_path.generic_string().c_str());
+ }
+ else
+ {
+ TC_LOG_INFO("scripts.hotswap", ">> CMAKE_INSTALL_PREFIX is equal to the current path of execution.");
+ return;
+ }
+ }
+ }
+
+ TC_LOG_INFO("scripts.hotswap", "Invoking CMake cache correction...");
+
+ auto const error = InvokeCMakeCommand(
+ "-DCMAKE_INSTALL_PREFIX:PATH=" + fs::current_path().generic_string(),
+ BuiltInConfig::GetBuildDirectory());
+
+ if (error)
+ {
+ TC_LOG_ERROR("scripts.hotswap", ">> Failed to update the CMAKE_INSTALL_PREFIX! "
+ "This could lead to unexpected behaviour!");
+ }
+ else
+ {
+ TC_LOG_ERROR("scripts.hotswap", ">> Successfully corrected your CMAKE_INSTALL_PREFIX variable"
+ "to point at your current path of execution.");
+ }
+ }
+
+ // File watcher instance and watcher ID's
+ efsw::FileWatcher _fileWatcher;
+ efsw::WatchID _libraryWatcher;
+
+ // Unique library name counter which is used to
+ // generate unique names for every shared library version.
+ uint32 _unique_library_name_counter;
+
+ // Queue which is used for thread safe message processing
+ MPSCQueue<ScriptReloaderMessage> _messages;
+
+ // Change requests to load or unload shared libraries
+ std::unordered_set<fs::path /*path*/> _libraries_changed;
+ // The timestamp which indicates the last time a library was changed
+ uint32 _last_time_library_changed;
+
+ // Contains all running script modules
+ // The associated shared libraries are unloaded immediately
+ // on loosing ownership through RAII.
+ std::unordered_map<std::string /*module name*/,
+ std::pair<std::shared_ptr<ScriptModule>, std::unique_ptr<SourceUpdateListener>>
+ > _running_script_modules;
+ // Container which maps the path of a shared library to it's module name
+ std::unordered_map<fs::path, std::string /*module name*/> _running_script_module_names;
+ // Container which maps the module name to it's last known build directive
+ std::unordered_map<std::string /*module name*/, std::string /*build directive*/> _known_modules_build_directives;
+
+ // Modules which were changed and are queued for recompilation
+ std::unordered_map<std::string /*module*/,
+ std::unordered_map<fs::path /*path*/, ChangeStateRequest /*state*/>> _sources_changed;
+ // Tracks the time since the last module has changed to avoid burst updates
+ uint32 _last_time_sources_changed;
+
+ // Tracks the last timestamp the user was informed about a certain repeating event.
+ uint32 _last_time_user_informed;
+
+ // Represents the current build job which is in progress
+ Optional<BuildJob> _build_job;
+
+ // Is true when the build job dispatcher should stop after
+ // the current job has finished
+ bool terminate_early;
+
+ // The path to the tc_scripts temporary cache
+ fs::path temporary_cache_path_;
+};
+
+/// Maps efsw actions to strings
+static char const* ActionToString(efsw::Action action)
+{
+ switch (action)
+ {
+ case efsw::Action::Add:
+ return "added";
+ case efsw::Action::Delete:
+ return "deleted";
+ case efsw::Action::Moved:
+ return "moved";
+ default:
+ return "modified";
+ }
+}
+
+void LibraryUpdateListener::handleFileAction(efsw::WatchID watchid, std::string const& dir,
+ std::string const& filename, efsw::Action action, std::string oldFilename)
+{
+ // TC_LOG_TRACE("scripts.hotswap", "Library listener detected change on possible module \"%s\ (%s)".", filename.c_str(), ActionToString(action));
+
+ // Split moved actions into a delete and an add action
+ if (action == efsw::Action::Moved)
+ {
+ ASSERT(!oldFilename.empty(), "Old filename doesn't exist!");
+ handleFileAction(watchid, dir, oldFilename, efsw::Action::Delete);
+ handleFileAction(watchid, dir, filename, efsw::Action::Add);
+ return;
+ }
+
+ sScriptReloadMgr->QueueMessage([=](HotSwapScriptReloadMgr* reloader) mutable
+ {
+ auto const path = fs::absolute(
+ filename,
+ sScriptReloadMgr->GetLibraryDirectory());
+
+ if (!HasValidScriptModuleName(filename))
+ return;
+
+ switch (action)
+ {
+ case efsw::Actions::Add:
+ TC_LOG_TRACE("scripts.hotswap", ">> Loading \"%s\" (%s)...",
+ path.generic_string().c_str(), ActionToString(action));
+ reloader->QueueSharedLibraryChanged(path);
+ break;
+ case efsw::Actions::Delete:
+ TC_LOG_TRACE("scripts.hotswap", ">> Unloading \"%s\" (%s)...",
+ path.generic_string().c_str(), ActionToString(action));
+ reloader->QueueSharedLibraryChanged(path);
+ break;
+ case efsw::Actions::Modified:
+ TC_LOG_TRACE("scripts.hotswap", ">> Reloading \"%s\" (%s)...",
+ path.generic_string().c_str(), ActionToString(action));
+ reloader->QueueSharedLibraryChanged(path);
+ break;
+ default:
+ WPAbort();
+ break;
+ }
+ });
+}
+
+/// Returns true when the given path has a known C++ file extension
+static bool HasCXXSourceFileExtension(fs::path const& path)
+{
+ static std::regex const regex("^\\.(h|hpp|c|cc|cpp)$");
+ return std::regex_match(path.extension().generic_string(), regex);
+}
+
+SourceUpdateListener::SourceUpdateListener(fs::path path, std::string script_module_name)
+ : path_(std::move(path)), script_module_name_(std::move(script_module_name)),
+ watcher_id_(sScriptReloadMgr->_fileWatcher.addWatch(path_.generic_string(), this, true))
+{
+ if (watcher_id_ >= 0)
+ {
+ TC_LOG_TRACE("scripts.hotswap", ">> Attached the source recompiler to \"%s\".",
+ path_.generic_string().c_str());
+ }
+ else
+ {
+ TC_LOG_ERROR("scripts.hotswap", "Failed to initialize thesource recompiler on \"%s\".",
+ path_.generic_string().c_str());
+ }
+}
+
+SourceUpdateListener::~SourceUpdateListener()
+{
+ if (watcher_id_ >= 0)
+ {
+ sScriptReloadMgr->_fileWatcher.removeWatch(watcher_id_);
+
+ TC_LOG_TRACE("scripts.hotswap", ">> Detached the source recompiler from \"%s\".",
+ path_.generic_string().c_str());
+ }
+}
+
+void SourceUpdateListener::handleFileAction(efsw::WatchID watchid, std::string const& dir,
+ std::string const& filename, efsw::Action action, std::string oldFilename)
+{
+ // TC_LOG_TRACE("scripts.hotswap", "Source listener detected change on possible file \"%s/%s\" (%s).", dir.c_str(), filename.c_str(), ActionToString(action));
+
+ // Skip the file change notification if the recompiler is disabled
+ if (!sWorld->getBoolConfig(CONFIG_HOTSWAP_RECOMPILER_ENABLED))
+ return;
+
+ // Split moved actions into a delete and an add action
+ if (action == efsw::Action::Moved)
+ {
+ ASSERT(!oldFilename.empty(), "Old filename doesn't exist!");
+ handleFileAction(watchid, dir, oldFilename, efsw::Action::Delete);
+ handleFileAction(watchid, dir, filename, efsw::Action::Add);
+ return;
+ }
+
+ auto const path = fs::absolute(
+ filename,
+ dir);
+
+ // Check if the file is a C/C++ source file.
+ if (!path.has_extension() || !HasCXXSourceFileExtension(path))
+ return;
+
+ /// Thread safe part
+ sScriptReloadMgr->QueueMessage([=](HotSwapScriptReloadMgr* reloader)
+ {
+ TC_LOG_TRACE("scripts.hotswap", "Detected source change on module \"%s\", "
+ "queued for recompilation...", script_module_name_.c_str());
+
+ switch (action)
+ {
+ case efsw::Actions::Add:
+ TC_LOG_TRACE("scripts.hotswap", "Source file %s of module %s was added.",
+ path.generic_string().c_str(), script_module_name_.c_str());
+ reloader->QueueAddSourceFile(script_module_name_, path);
+ break;
+ case efsw::Actions::Delete:
+ TC_LOG_TRACE("scripts.hotswap", "Source file %s of module %s was deleted.",
+ path.generic_string().c_str(), script_module_name_.c_str());
+ reloader->QueueRemoveSourceFile(script_module_name_, path);
+ break;
+ case efsw::Actions::Modified:
+ TC_LOG_TRACE("scripts.hotswap", "Source file %s of module %s was modified.",
+ path.generic_string().c_str(), script_module_name_.c_str());
+ reloader->QueueModifySourceFile(script_module_name_, path);
+ break;
+ default:
+ WPAbort();
+ break;
+ }
+ });
+}
+
+// Returns the module reference of the given context
+std::shared_ptr<ModuleReference>
+ ScriptReloadMgr::AcquireModuleReferenceOfContext(std::string const& context)
+{
+ auto const itr = sScriptReloadMgr->_running_script_modules.find(context);
+ if (itr != sScriptReloadMgr->_running_script_modules.end())
+ return itr->second.first;
+ else
+ return { };
+}
+
+// Returns the full hot swap implemented ScriptReloadMgr
+ScriptReloadMgr* ScriptReloadMgr::instance()
+{
+ static HotSwapScriptReloadMgr instance;
+ return &instance;
+}
+
+#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING
diff --git a/src/server/game/Scripting/ScriptReloadMgr.h b/src/server/game/Scripting/ScriptReloadMgr.h
new file mode 100644
index 00000000000..f9b388f8eb0
--- /dev/null
+++ b/src/server/game/Scripting/ScriptReloadMgr.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SCRIPT_RELOADER_H
+#define SCRIPT_RELOADER_H
+
+#include <memory>
+#include <string>
+#include "Define.h"
+#include <boost/filesystem/path.hpp>
+
+/// Represents a strong reference to a dynamic library which
+/// provides C++ scripts. As long as one reference to the library exists
+/// the library is kept loaded in the server, which makes it possible to lazy
+/// unload several script types on demand (like SpellScripts), and to
+/// provide multiple versions of the same script to the script factories.
+///
+/// Acquire a new reference through using:
+/// `ScriptReloadMgr::AcquireModuleReferenceOfContext`
+class ModuleReference
+{
+public:
+ virtual ~ModuleReference() { }
+
+ /// Returns the git revision hash of the referenced script module
+ virtual char const* GetScriptModuleRevisionHash() const = 0;
+ /// Returns the name of the referenced script module
+ virtual char const* GetScriptModule() const = 0;
+ /// Returns the path to the script module
+ virtual boost::filesystem::path const& GetModulePath() const = 0;
+};
+
+/// Provides the whole physical dynamic library unloading capability.
+/// Loads, Reloads and Unloads dynamic libraries on changes and
+/// informs the ScriptMgr about changes which were made.
+/// The ScriptReloadMgr is also responsible for watching the source directory
+/// and to invoke a build on changes.
+class TC_GAME_API ScriptReloadMgr
+{
+protected:
+ ScriptReloadMgr() { }
+
+public:
+ virtual ~ScriptReloadMgr() { }
+
+ /// Initializes the ScriptReloadMgr
+ virtual void Initialize() { }
+
+ /// Needs to be called periodically to check for updates on script modules.
+ /// Expects to be invoked in a thread safe way which means it's required that
+ /// the current thread is the only one which accesses the world data.
+ virtual void Update() { }
+
+ /// Unloads the ScriptReloadMgr
+ virtual void Unload() { }
+
+ /// Returns an owning reference to the current module of the given context
+ static std::shared_ptr<ModuleReference> AcquireModuleReferenceOfContext(
+ std::string const& context);
+
+ /// Returns the unique ScriptReloadMgr singleton instance
+ static ScriptReloadMgr* instance();
+};
+
+#define sScriptReloadMgr ScriptReloadMgr::instance()
+
+#endif // SCRIPT_RELOADER_H
diff --git a/src/server/game/Server/Protocol/PacketLog.cpp b/src/server/game/Server/Protocol/PacketLog.cpp
index 11a02828998..114b2ae0ecc 100644
--- a/src/server/game/Server/Protocol/PacketLog.cpp
+++ b/src/server/game/Server/Protocol/PacketLog.cpp
@@ -45,7 +45,7 @@ struct PacketHeader
uint32 SocketPort;
};
- char Direction[4];
+ uint32 Direction;
uint32 ConnectionId;
uint32 ArrivalTicks;
uint32 OptionalDataSize;
@@ -109,7 +109,7 @@ void PacketLog::LogPacket(WorldPacket const& packet, Direction direction, boost:
std::lock_guard<std::mutex> lock(_logPacketLock);
PacketHeader header;
- *reinterpret_cast<uint32*>(header.Direction) = direction == CLIENT_TO_SERVER ? 0x47534d43 : 0x47534d53;
+ header.Direction = direction == CLIENT_TO_SERVER ? 0x47534d43 : 0x47534d53;
header.ConnectionId = 0;
header.ArrivalTicks = getMSTime();
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index e3c6179a34a..1c77283d812 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -344,11 +344,12 @@ WorldSocket::ReadDataHandlerResult WorldSocket::ReadDataHandler()
default:
{
sessionGuard.lock();
+
LogOpcodeText(opcode, sessionGuard);
+
if (!_worldSession)
{
TC_LOG_ERROR("network.opcode", "ProcessIncoming: Client not authed opcode = %u", uint32(opcode));
- CloseSocket();
return ReadDataHandlerResult::Error;
}
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index d6cdb99e75c..92e60df0b04 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -1325,7 +1325,7 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode
{
// apply glow vision
if (target->GetTypeId() == TYPEID_PLAYER)
- target->SetByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
+ target->SetByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
target->m_invisibility.AddFlag(type);
target->m_invisibility.AddValue(type, GetAmount());
@@ -1337,7 +1337,7 @@ void AuraEffect::HandleModInvisibility(AuraApplication const* aurApp, uint8 mode
// if not have different invisibility auras.
// remove glow vision
if (target->GetTypeId() == TYPEID_PLAYER)
- target->RemoveByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
+ target->RemoveByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_INVISIBILITY_GLOW);
target->m_invisibility.DelFlag(type);
}
@@ -1409,7 +1409,7 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo
target->SetStandFlags(UNIT_STAND_FLAGS_CREEP);
if (target->GetTypeId() == TYPEID_PLAYER)
- target->SetByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_STEALTH);
+ target->SetByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_STEALTH);
}
else
{
@@ -1421,7 +1421,7 @@ void AuraEffect::HandleModStealth(AuraApplication const* aurApp, uint8 mode, boo
target->RemoveStandFlags(UNIT_STAND_FLAGS_CREEP);
if (target->GetTypeId() == TYPEID_PLAYER)
- target->RemoveByteFlag(PLAYER_FIELD_BYTES2, 3, PLAYER_FIELD_BYTE2_STEALTH);
+ target->RemoveByteFlag(PLAYER_FIELD_BYTES2, PLAYER_FIELD_BYTES_2_OFFSET_AURA_VISION, PLAYER_FIELD_BYTE2_STEALTH);
}
}
@@ -2400,7 +2400,7 @@ void AuraEffect::HandleAuraTrackStealthed(AuraApplication const* aurApp, uint8 m
if (target->HasAuraType(GetAuraType()))
return;
}
- target->ApplyModFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTE_TRACK_STEALTHED, apply);
+ target->ApplyModByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_TRACK_STEALTHED, apply);
}
void AuraEffect::HandleAuraModStalked(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -2915,7 +2915,7 @@ void AuraEffect::HandleAuraModIncreaseSpeed(AuraApplication const* aurApp, uint8
Unit* target = aurApp->GetTarget();
- target->UpdateSpeed(MOVE_RUN, true);
+ target->UpdateSpeed(MOVE_RUN);
}
void AuraEffect::HandleAuraModIncreaseMountedSpeed(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -2930,7 +2930,7 @@ void AuraEffect::HandleAuraModIncreaseFlightSpeed(AuraApplication const* aurApp,
Unit* target = aurApp->GetTarget();
if (mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK)
- target->UpdateSpeed(MOVE_FLIGHT, true);
+ target->UpdateSpeed(MOVE_FLIGHT);
//! Update ability to fly
if (GetAuraType() == SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED)
@@ -2965,7 +2965,7 @@ void AuraEffect::HandleAuraModIncreaseSwimSpeed(AuraApplication const* aurApp, u
Unit* target = aurApp->GetTarget();
- target->UpdateSpeed(MOVE_SWIM, true);
+ target->UpdateSpeed(MOVE_SWIM);
}
void AuraEffect::HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
@@ -2975,12 +2975,12 @@ void AuraEffect::HandleAuraModDecreaseSpeed(AuraApplication const* aurApp, uint8
Unit* target = aurApp->GetTarget();
- target->UpdateSpeed(MOVE_RUN, true);
- target->UpdateSpeed(MOVE_SWIM, true);
- target->UpdateSpeed(MOVE_FLIGHT, true);
- target->UpdateSpeed(MOVE_RUN_BACK, true);
- target->UpdateSpeed(MOVE_SWIM_BACK, true);
- target->UpdateSpeed(MOVE_FLIGHT_BACK, true);
+ target->UpdateSpeed(MOVE_RUN);
+ target->UpdateSpeed(MOVE_SWIM);
+ target->UpdateSpeed(MOVE_FLIGHT);
+ target->UpdateSpeed(MOVE_RUN_BACK);
+ target->UpdateSpeed(MOVE_SWIM_BACK);
+ target->UpdateSpeed(MOVE_FLIGHT_BACK);
}
void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint8 mode, bool /*apply*/) const
@@ -2990,9 +2990,9 @@ void AuraEffect::HandleAuraModUseNormalSpeed(AuraApplication const* aurApp, uint
Unit* target = aurApp->GetTarget();
- target->UpdateSpeed(MOVE_RUN, true);
- target->UpdateSpeed(MOVE_SWIM, true);
- target->UpdateSpeed(MOVE_FLIGHT, true);
+ target->UpdateSpeed(MOVE_RUN);
+ target->UpdateSpeed(MOVE_SWIM);
+ target->UpdateSpeed(MOVE_FLIGHT);
}
/*********************************************************/
@@ -4686,7 +4686,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool
case 71563:
if (Aura* newAura = target->AddAura(71564, target))
newAura->SetStackAmount(newAura->GetSpellInfo()->StackAmount);
- break;
+ break;
}
}
// AT REMOVE
@@ -5248,7 +5248,7 @@ void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 m
if (apply)
{
- target->SetUInt16Value(PLAYER_FIELD_BYTES2, 0, overrideId);
+ target->SetUInt16Value(PLAYER_FIELD_BYTES2, PLAYER_BYTES_2_OVERRIDE_SPELLS_UINT16_OFFSET, overrideId);
if (OverrideSpellDataEntry const* overrideSpells = sOverrideSpellDataStore.LookupEntry(overrideId))
for (uint8 i = 0; i < MAX_OVERRIDE_SPELL; ++i)
if (uint32 spellId = overrideSpells->spellId[i])
@@ -5256,7 +5256,7 @@ void AuraEffect::HandleAuraOverrideSpells(AuraApplication const* aurApp, uint8 m
}
else
{
- target->SetUInt16Value(PLAYER_FIELD_BYTES2, 0, 0);
+ target->SetUInt16Value(PLAYER_FIELD_BYTES2, PLAYER_BYTES_2_OVERRIDE_SPELLS_UINT16_OFFSET, 0);
if (OverrideSpellDataEntry const* overrideSpells = sOverrideSpellDataStore.LookupEntry(overrideId))
for (uint8 i = 0; i < MAX_OVERRIDE_SPELL; ++i)
if (uint32 spellId = overrideSpells->spellId[i])
@@ -5302,9 +5302,9 @@ void AuraEffect::HandlePreventResurrection(AuraApplication const* aurApp, uint8
return;
if (apply)
- aurApp->GetTarget()->RemoveByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER);
+ aurApp->GetTarget()->RemoveByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_RELEASE_TIMER);
else if (!aurApp->GetTarget()->GetBaseMap()->Instanceable())
- aurApp->GetTarget()->SetByteFlag(PLAYER_FIELD_BYTES, 0, PLAYER_FIELD_BYTE_RELEASE_TIMER);
+ aurApp->GetTarget()->SetByteFlag(PLAYER_FIELD_BYTES, PLAYER_FIELD_BYTES_OFFSET_FLAGS, PLAYER_FIELD_BYTE_RELEASE_TIMER);
}
void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
@@ -5974,14 +5974,14 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
caster->CalcAbsorbResist(target, GetSpellInfo()->GetSchoolMask(), DOT, damage, &absorb, &resist, m_spellInfo);
- if (target->GetHealth() < damage)
- damage = uint32(target->GetHealth());
-
TC_LOG_DEBUG("spells.periodic", "PeriodicTick: %s health leech of %s for %u dmg inflicted by %u abs is %u",
GetCasterGUID().ToString().c_str(), target->GetGUID().ToString().c_str(), damage, GetId(), absorb);
caster->SendSpellNonMeleeDamageLog(target, GetId(), damage, GetSpellInfo()->GetSchoolMask(), absorb, resist, false, 0, crit);
+ if (target->GetHealth() < damage)
+ damage = uint32(target->GetHealth());
+
// Set trigger flag
uint32 procAttacker = PROC_FLAG_DONE_PERIODIC;
uint32 procVictim = PROC_FLAG_TAKEN_PERIODIC;
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index fff69ae48df..166eff139f4 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -979,14 +979,22 @@ void Spell::SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTa
{
CallScriptObjectTargetSelectHandlers(target, effIndex, targetType);
if (target)
- m_targets.SetDst(*target);
+ {
+ SpellDestination dest(*target);
+ CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
+ m_targets.SetDst(dest);
+ }
}
else
TC_LOG_DEBUG("spells", "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
break;
case TARGET_DEST_CHANNEL_CASTER:
- m_targets.SetDst(*channeledSpell->GetCaster());
+ {
+ SpellDestination dest(*channeledSpell->GetCaster());
+ CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
+ m_targets.SetDst(dest);
break;
+ }
default:
ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target type");
break;
@@ -1042,7 +1050,11 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
if (m_spellInfo->RequiresSpellFocus)
{
if (focusObject)
- m_targets.SetDst(*focusObject);
+ {
+ SpellDestination dest(*focusObject);
+ CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
+ m_targets.SetDst(dest);
+ }
return;
}
break;
@@ -1068,7 +1080,6 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
switch (targetType.GetObjectType())
{
case TARGET_OBJECT_TYPE_UNIT:
- {
if (Unit* unit = target->ToUnit())
AddUnitTarget(unit, effMask, true, false);
else
@@ -1077,7 +1088,6 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
return;
}
break;
- }
case TARGET_OBJECT_TYPE_GOBJ:
if (GameObject* gobjTarget = target->ToGameObject())
AddGOTarget(gobjTarget, effMask);
@@ -1088,8 +1098,12 @@ void Spell::SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTar
}
break;
case TARGET_OBJECT_TYPE_DEST:
- m_targets.SetDst(*target);
+ {
+ SpellDestination dest(*target);
+ CallScriptDestinationTargetSelectHandlers(dest, effIndex, targetType);
+ m_targets.SetDst(dest);
break;
+ }
default:
ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target object type");
break;
@@ -5310,6 +5324,9 @@ SpellCastResult Spell::CheckCast(bool strict)
if (!target || m_caster->ToPlayer() == target || (!target->IsInSameRaidWith(m_caster->ToPlayer()) && m_spellInfo->Id != 48955)) // refer-a-friend spell
return SPELL_FAILED_BAD_TARGETS;
+ if (target->HasSummonPending())
+ return SPELL_FAILED_SUMMON_PENDING;
+
// check if our map is dungeon
MapEntry const* map = sMapStore.LookupEntry(m_caster->GetMapId());
if (map->IsDungeon())
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index 3f0ff9a0f19..51b6db197db 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -217,7 +217,7 @@ pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
&Spell::EffectCreateItem2, //157 SPELL_EFFECT_CREATE_ITEM_2 create item or create item template and replace by some randon spell loot item
&Spell::EffectMilling, //158 SPELL_EFFECT_MILLING milling
&Spell::EffectRenamePet, //159 SPELL_EFFECT_ALLOW_RENAME_PET allow rename pet once again
- &Spell::EffectNULL, //160 SPELL_EFFECT_160 1 spell - 45534
+ &Spell::EffectForceCast, //160 SPELL_EFFECT_FORCE_CAST_2
&Spell::EffectSpecCount, //161 SPELL_EFFECT_TALENT_SPEC_COUNT second talent spec (learn/revert)
&Spell::EffectActivateSpec, //162 SPELL_EFFECT_TALENT_SPEC_SELECT activate primary/secondary spec
&Spell::EffectNULL, //163 unused
@@ -3661,16 +3661,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
m_caster->CastSpell(unitTarget, 22682, true);
return;
}
- // Decimate
- case 28374:
- case 54426:
- if (unitTarget)
- {
- int32 decimateDamage = int32(unitTarget->GetHealth()) - int32(unitTarget->CountPctFromMaxHealth(5));
- if (decimateDamage > 0)
- m_caster->CastCustomSpell(28375, SPELLVALUE_BASE_POINT0, decimateDamage, unitTarget);
- }
- return;
// Mirren's Drinking Hat
case 29830:
{
@@ -3781,28 +3771,6 @@ void Spell::EffectScriptEffect(SpellEffIndex effIndex)
break;
}
- // Roll Dice - Decahedral Dwarven Dice
- case 47770:
- {
- char buf[128];
- const char *gender = "his";
- if (m_caster->getGender() > 0)
- gender = "her";
- sprintf(buf, "%s rubs %s [Decahedral Dwarven Dice] between %s hands and rolls. One %u and one %u.", m_caster->GetName().c_str(), gender, gender, urand(1, 10), urand(1, 10));
- m_caster->TextEmote(buf);
- break;
- }
- // Roll 'dem Bones - Worn Troll Dice
- case 47776:
- {
- char buf[128];
- const char *gender = "his";
- if (m_caster->getGender() > 0)
- gender = "her";
- sprintf(buf, "%s causually tosses %s [Worn Troll Dice]. One %u and one %u.", m_caster->GetName().c_str(), gender, urand(1, 6), urand(1, 6));
- m_caster->TextEmote(buf);
- break;
- }
// Death Knight Initiate Visual
case 51519:
{
@@ -4244,20 +4212,7 @@ void Spell::EffectSummonPlayer(SpellEffIndex /*effIndex*/)
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
return;
- // Evil Twin (ignore player summon, but hide this for summoner)
- if (unitTarget->HasAura(23445))
- return;
-
- float x, y, z;
- m_caster->GetPosition(x, y, z);
-
- unitTarget->ToPlayer()->SetSummonPoint(m_caster->GetMapId(), x, y, z);
-
- WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
- data << uint64(m_caster->GetGUID()); // summoner guid
- data << uint32(m_caster->GetZoneId()); // summoner zone
- data << uint32(MAX_PLAYER_SUMMON_DELAY*IN_MILLISECONDS); // auto decline after msecs
- unitTarget->ToPlayer()->GetSession()->SendPacket(&data);
+ unitTarget->ToPlayer()->SendSummonRequestFrom(m_caster);
}
void Spell::EffectActivateObject(SpellEffIndex /*effIndex*/)
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 069c794ca8b..f6078bd063f 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -418,7 +418,8 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster, int32 const* bp, Unit const
level = int32(_spellInfo->MaxLevel);
else if (level < int32(_spellInfo->BaseLevel))
level = int32(_spellInfo->BaseLevel);
- level -= int32(_spellInfo->SpellLevel);
+ if (!_spellInfo->IsPassive())
+ level -= int32(_spellInfo->SpellLevel);
basePoints += int32(level * basePointsPerLevel);
}
@@ -754,7 +755,7 @@ SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 157 SPELL_EFFECT_CREATE_ITEM_2
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_ITEM}, // 158 SPELL_EFFECT_MILLING
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 159 SPELL_EFFECT_ALLOW_RENAME_PET
- {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 160 SPELL_EFFECT_160
+ {EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 160 SPELL_EFFECT_FORCE_CAST_2
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 161 SPELL_EFFECT_TALENT_SPEC_COUNT
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 162 SPELL_EFFECT_TALENT_SPEC_SELECT
{EFFECT_IMPLICIT_TARGET_EXPLICIT, TARGET_OBJECT_TYPE_UNIT}, // 163 SPELL_EFFECT_163
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index 6876f8fa7ef..e2598386466 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -16,6 +16,7 @@
*/
#include "Spell.h"
+#include "ScriptMgr.h"
#include "SpellAuras.h"
#include "SpellScript.h"
#include "SpellMgr.h"
@@ -50,6 +51,12 @@ void _SpellScript::_Init(std::string const* scriptname, uint32 spellId)
m_currentScriptState = SPELL_SCRIPT_STATE_NONE;
m_scriptName = scriptname;
m_scriptSpellId = spellId;
+
+#ifdef TRINITY_API_USE_DYNAMIC_LINKING
+ // Acquire a strong reference to the binary code
+ // to keep it loaded until all spells are destroyed.
+ m_moduleReference = sScriptMgr->AcquireModuleReferenceOfScriptName(*scriptname);
+#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING
}
std::string const* _SpellScript::_GetScriptName() const
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 1d4efd8073d..539bc54cc94 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -22,6 +22,7 @@
#include "SharedDefines.h"
#include "SpellAuraDefines.h"
#include "Spell.h"
+#include "ScriptReloadMgr.h"
#include <stack>
class Unit;
@@ -105,6 +106,16 @@ class TC_GAME_API _SpellScript
uint8 m_currentScriptState;
std::string const* m_scriptName;
uint32 m_scriptSpellId;
+
+ private:
+
+#ifdef TRINITY_API_USE_DYNAMIC_LINKING
+
+ // Strong reference to keep the binary code loaded
+ std::shared_ptr<ModuleReference> m_moduleReference;
+
+#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING
+
public:
//
// SpellScript/AuraScript interface base
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 6380aece941..599c4a9886a 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -54,6 +54,7 @@
#include "PoolMgr.h"
#include "GitRevision.h"
#include "ScriptMgr.h"
+#include "ScriptReloadMgr.h"
#include "SkillDiscovery.h"
#include "SkillExtraItems.h"
#include "SmartAI.h"
@@ -1081,6 +1082,7 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN] = sConfigMgr->GetBoolDefault("OffhandCheckAtSpellUnlearn", true);
m_int_configs[CONFIG_CREATURE_PICKPOCKET_REFILL] = sConfigMgr->GetIntDefault("Creature.PickPocketRefillDelay", 10 * MINUTE);
+ m_int_configs[CONFIG_CREATURE_STOP_FOR_PLAYER] = sConfigMgr->GetIntDefault("Creature.MovingStopTimeForPlayer", 3 * MINUTE * IN_MILLISECONDS);
if (int32 clientCacheId = sConfigMgr->GetIntDefault("ClientCacheVersion", 0))
{
@@ -1319,6 +1321,14 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Creature.Zone.Area.Data", false);
m_bool_configs[CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Gameoject.Zone.Area.Data", false);
+ // HotSwap
+ m_bool_configs[CONFIG_HOTSWAP_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.Enabled", true);
+ m_bool_configs[CONFIG_HOTSWAP_RECOMPILER_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnableReCompiler", true);
+ m_bool_configs[CONFIG_HOTSWAP_EARLY_TERMINATION_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnableEarlyTermination", true);
+ m_bool_configs[CONFIG_HOTSWAP_BUILD_FILE_RECREATION_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnableBuildFileRecreation", true);
+ m_bool_configs[CONFIG_HOTSWAP_INSTALL_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnableInstall", true);
+ m_bool_configs[CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED] = sConfigMgr->GetBoolDefault("HotSwap.EnablePrefixCorrection", true);
+
// call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
@@ -1826,6 +1836,8 @@ void World::SetInitialWorldSettings()
m_timers[WUPDATE_PINGDB].SetInterval(getIntConfig(CONFIG_DB_PING_INTERVAL)*MINUTE*IN_MILLISECONDS); // Mysql ping time in minutes
+ m_timers[WUPDATE_CHECK_FILECHANGES].SetInterval(500);
+
//to set mailtimer to return mails every day between 4 and 5 am
//mailtimer is increased when updating auctions
//one second is 1000 -(tested on win system)
@@ -2109,6 +2121,13 @@ void World::Update(uint32 diff)
m_timers[WUPDATE_AHBOT].Reset();
}
+ /// <li> Handle file changes
+ if (m_timers[WUPDATE_CHECK_FILECHANGES].Passed())
+ {
+ sScriptReloadMgr->Update();
+ m_timers[WUPDATE_CHECK_FILECHANGES].Reset();
+ }
+
/// <li> Handle session updates when the timer has passed
ResetTimeDiffRecord();
UpdateSessions(diff);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index a59d9ef882a..99dd954560e 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -81,6 +81,7 @@ enum WorldTimers
WUPDATE_DELETECHARS,
WUPDATE_AHBOT,
WUPDATE_PINGDB,
+ WUPDATE_CHECK_FILECHANGES,
WUPDATE_COUNT
};
@@ -167,6 +168,12 @@ enum WorldBoolConfigs
CONFIG_RESET_DUEL_HEALTH_MANA,
CONFIG_BASEMAP_LOAD_GRIDS,
CONFIG_INSTANCEMAP_LOAD_GRIDS,
+ CONFIG_HOTSWAP_ENABLED,
+ CONFIG_HOTSWAP_RECOMPILER_ENABLED,
+ CONFIG_HOTSWAP_EARLY_TERMINATION_ENABLED,
+ CONFIG_HOTSWAP_BUILD_FILE_RECREATION_ENABLED,
+ CONFIG_HOTSWAP_INSTALL_ENABLED,
+ CONFIG_HOTSWAP_PREFIX_CORRECTION_ENABLED,
BOOL_CONFIG_VALUE_COUNT
};
@@ -350,6 +357,7 @@ enum WorldIntConfigs
CONFIG_BG_REWARD_LOSER_HONOR_LAST,
CONFIG_BIRTHDAY_TIME,
CONFIG_CREATURE_PICKPOCKET_REFILL,
+ CONFIG_CREATURE_STOP_FOR_PLAYER,
CONFIG_AHBOT_UPDATE_INTERVAL,
CONFIG_CHARTER_COST_GUILD,
CONFIG_CHARTER_COST_ARENA_2v2,
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index 8c0adc4c1e1..31ba073e77d 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -8,69 +8,232 @@
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# Enable precompiled headers when using the GCC compiler.
-
-message(STATUS "SCRIPT PREPARATIONS")
-
-macro(PrepareScripts name out)
- file(GLOB_RECURSE found
- ${name}/*.h
- ${name}/*.cpp
- )
- list(APPEND ${out} ${found})
- message(STATUS " -> Prepared: ${name}")
-endmacro(PrepareScripts)
-
-PrepareScripts(Spells PRIVATE_SOURCES)
-PrepareScripts(Commands PRIVATE_SOURCES)
-
-if(SCRIPTS)
- PrepareScripts(Custom PRIVATE_SOURCES)
- PrepareScripts(World PRIVATE_SOURCES)
- PrepareScripts(OutdoorPvP PRIVATE_SOURCES)
- PrepareScripts(EasternKingdoms PRIVATE_SOURCES)
- PrepareScripts(Kalimdor PRIVATE_SOURCES)
- PrepareScripts(Outland PRIVATE_SOURCES)
- PrepareScripts(Northrend PRIVATE_SOURCES)
- PrepareScripts(Events PRIVATE_SOURCES)
- PrepareScripts(Pet PRIVATE_SOURCES)
+message("")
+
+# Make the script module list available in the current scope
+GetScriptModuleList(SCRIPT_MODULE_LIST)
+
+# Make the native install offset available in this scope
+GetInstallOffset(INSTALL_OFFSET)
+
+# Sets the SCRIPTS_${SCRIPT_MODULE} variables
+# when using predefined templates for script building
+# like dynamic, static, minimal-static...
+# Sets SCRIPTS_DEFAULT_LINKAGE
+if (SCRIPTS MATCHES "dynamic")
+ set(SCRIPTS_DEFAULT_LINKAGE "dynamic")
+elseif(SCRIPTS MATCHES "static")
+ set(SCRIPTS_DEFAULT_LINKAGE "static")
+else()
+ set(SCRIPTS_DEFAULT_LINKAGE "disabled")
+endif()
+# Sets SCRIPTS_USE_WHITELIST
+# Sets SCRIPTS_WHITELIST
+if (SCRIPTS MATCHES "minimal")
+ set(SCRIPTS_USE_WHITELIST ON)
+ # Whitelist which is used when minimal is selected
+ list(APPEND SCRIPTS_WHITELIST Commands Spells)
endif()
-message(STATUS "SCRIPT PREPARATION COMPLETE")
-message("")
+# Set the SCRIPTS_${SCRIPT_MODULE} variables from the
+# variables set above
+foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST})
+ ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE)
+ if (${SCRIPT_MODULE_VARIABLE} STREQUAL "default")
+ if(SCRIPTS_USE_WHITELIST)
+ list(FIND SCRIPTS_WHITELIST "${SCRIPT_MODULE}" INDEX)
+ if (${INDEX} GREATER -1)
+ set(${SCRIPT_MODULE_VARIABLE} ${SCRIPTS_DEFAULT_LINKAGE})
+ else()
+ set(${SCRIPT_MODULE_VARIABLE} "disabled")
+ endif()
+ else()
+ set(${SCRIPT_MODULE_VARIABLE} ${SCRIPTS_DEFAULT_LINKAGE})
+ endif()
+ endif()
+ # Build the Graph values
+ if (${SCRIPT_MODULE_VARIABLE} MATCHES "dynamic")
+ GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME)
+ GetNativeSharedLibraryName(${SCRIPT_MODULE_PROJECT_NAME} SCRIPT_PROJECT_LIBRARY)
+ list(APPEND GRAPH_KEYS ${SCRIPT_MODULE_PROJECT_NAME})
+ set(GRAPH_VALUE_DISPLAY_${SCRIPT_MODULE_PROJECT_NAME} ${SCRIPT_PROJECT_LIBRARY})
+ list(APPEND GRAPH_VALUE_CONTAINS_MODULES_${SCRIPT_MODULE_PROJECT_NAME} ${SCRIPT_MODULE})
+ elseif(${SCRIPT_MODULE_VARIABLE} MATCHES "static")
+ list(APPEND GRAPH_KEYS worldserver)
+ set(GRAPH_VALUE_DISPLAY_worldserver worldserver)
+ list(APPEND GRAPH_VALUE_CONTAINS_MODULES_worldserver ${SCRIPT_MODULE})
+ else()
+ list(APPEND GRAPH_KEYS disabled)
+ set(GRAPH_VALUE_DISPLAY_disabled disabled)
+ list(APPEND GRAPH_VALUE_CONTAINS_MODULES_disabled ${SCRIPT_MODULE})
+ endif()
+endforeach()
-list(APPEND PRIVATE_SOURCES
- ${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.h
- ${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.cpp)
+list(SORT GRAPH_KEYS)
+list(REMOVE_DUPLICATES GRAPH_KEYS)
+# Display the script graph
+message("* Script configuration (${SCRIPTS}):
+ |")
+
+foreach(GRAPH_KEY ${GRAPH_KEYS})
+ if (NOT GRAPH_KEY STREQUAL "disabled")
+ message(" +- ${GRAPH_VALUE_DISPLAY_${GRAPH_KEY}}")
+ else()
+ message(" | ${GRAPH_VALUE_DISPLAY_${GRAPH_KEY}}")
+ endif()
+ foreach(GRAPH_PROJECT_ENTRY ${GRAPH_VALUE_CONTAINS_MODULES_${GRAPH_KEY}})
+ message(" | +- ${GRAPH_PROJECT_ENTRY}")
+ endforeach()
+ message(" |")
+endforeach()
+
+# Base sources which are used by every script project
if (USE_SCRIPTPCH)
- set(PRIVATE_PCH_HEADER PrecompiledHeaders/ScriptPCH.h)
- set(PRIVATE_PCH_SOURCE PrecompiledHeaders/ScriptPCH.cpp)
+ set(PRIVATE_PCH_HEADER ScriptPCH.h)
+ set(PRIVATE_PCH_SOURCE ScriptPCH.cpp)
endif ()
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+# Configures the scriptloader with the given name and stores the output in the LOADER_OUT variable.
+# It is possible to expose multiple subdirectories from the same scriptloader through passing
+# it to the variable arguments
+function(ConfigureScriptLoader SCRIPTLOADER_NAME LOADER_OUT IS_DYNAMIC_SCRIPTLOADER)
+ # Deduces following variables which are referenced by thge template:
+ # TRINITY_IS_DYNAMIC_SCRIPTLOADER
+ # TRINITY_SCRIPTS_FORWARD_DECL
+ # TRINITY_SCRIPTS_INVOKE
+ # TRINITY_CURRENT_SCRIPT_PROJECT
+
+ # To generate export macros
+ set(TRINITY_IS_DYNAMIC_SCRIPTLOADER ${IS_DYNAMIC_SCRIPTLOADER})
+ # To generate forward declarations of the loading functions
+ unset(TRINITY_SCRIPTS_FORWARD_DECL)
+ unset(TRINITY_SCRIPTS_INVOKE)
+ # The current script project which is built in
+ set(TRINITY_CURRENT_SCRIPT_PROJECT ${SCRIPTLOADER_NAME})
+ foreach(LOCALE_SCRIPT_MODULE ${ARGN})
+ # Determine the loader function ("Add##${NameOfDirectory}##Scripts()")
+ set(LOADER_FUNCTION
+ "Add${LOCALE_SCRIPT_MODULE}Scripts()")
+ # Generate the funciton call and the forward declarations
+ set(TRINITY_SCRIPTS_FORWARD_DECL
+ "${TRINITY_SCRIPTS_FORWARD_DECL}void ${LOADER_FUNCTION};\n")
+ set(TRINITY_SCRIPTS_INVOKE
+ "${TRINITY_SCRIPTS_INVOKE} ${LOADER_FUNCTION};\n")
+ endforeach()
+ set(GENERATED_LOADER ${CMAKE_CURRENT_BINARY_DIR}/gen_scriptloader/${SCRIPTLOADER_NAME}/ScriptLoader.cpp)
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/ScriptLoader.cpp.in.cmake ${GENERATED_LOADER})
+ set(${LOADER_OUT} ${GENERATED_LOADER} PARENT_SCOPE)
+endfunction()
+
+# Generates the actual script projects
+# Fills the STATIC_SCRIPT_MODULES and DYNAMIC_SCRIPT_MODULE_PROJECTS variables
+# which contain the names which scripts are linked statically/dynamically and
+# adds the sources of the static modules to the PRIVATE_SOURCES variable.
+foreach(SCRIPT_MODULE ${SCRIPT_MODULE_LIST})
+ GetPathToScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PATH)
+ ScriptModuleNameToVariable(${SCRIPT_MODULE} SCRIPT_MODULE_VARIABLE)
+
+ if ((${SCRIPT_MODULE_VARIABLE} STREQUAL "disabled") OR
+ (${SCRIPT_MODULE_VARIABLE} STREQUAL "static"))
+ # Uninstall disabled modules
+ GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME)
+ GetNativeSharedLibraryName(${SCRIPT_MODULE_PROJECT_NAME} SCRIPT_MODULE_OUTPUT_NAME)
+ list(APPEND DISABLED_SCRIPT_MODULE_PROJECTS ${INSTALL_OFFSET}/${SCRIPT_MODULE_OUTPUT_NAME})
+ if (${SCRIPT_MODULE_VARIABLE} STREQUAL "static")
+ # Add the module name to STATIC_SCRIPT_MODULES
+ list(APPEND STATIC_SCRIPT_MODULES ${SCRIPT_MODULE})
+ # Add the module content to the whole static module
+ CollectSourceFiles(${SCRIPT_MODULE_PATH} PRIVATE_SOURCES)
+ endif()
+ elseif(${SCRIPT_MODULE_VARIABLE} STREQUAL "dynamic")
+ # Generate an own dynamic module which is loadable on runtime
+ # Add the module content to the whole static module
+ unset(SCRIPT_MODULE_PRIVATE_SOURCES)
+ CollectSourceFiles(${SCRIPT_MODULE_PATH} SCRIPT_MODULE_PRIVATE_SOURCES)
+ # Configure the scriptloader
+ ConfigureScriptLoader(${SCRIPT_MODULE} SCRIPT_MODULE_PRIVATE_SCRIPTLOADER ON ${SCRIPT_MODULE})
+ GetProjectNameOfScriptModule(${SCRIPT_MODULE} SCRIPT_MODULE_PROJECT_NAME)
+ # Add the module name to DYNAMIC_SCRIPT_MODULES
+ list(APPEND DYNAMIC_SCRIPT_MODULE_PROJECTS ${SCRIPT_MODULE_PROJECT_NAME})
+ # Create the script module project
+ add_library(${SCRIPT_MODULE_PROJECT_NAME} SHARED
+ ${PRIVATE_PCH_SOURCE}
+ ${SCRIPT_MODULE_PRIVATE_SOURCES}
+ ${SCRIPT_MODULE_PRIVATE_SCRIPTLOADER})
+ target_link_libraries(${SCRIPT_MODULE_PROJECT_NAME}
+ PUBLIC
+ game)
+ set_target_properties(${SCRIPT_MODULE_PROJECT_NAME}
+ PROPERTIES
+ FOLDER
+ "scripts")
+
+ if(UNIX)
+ install(TARGETS ${SCRIPT_MODULE_PROJECT_NAME}
+ DESTINATION ${INSTALL_OFFSET}
+ COMPONENT ${SCRIPT_MODULE_PROJECT_NAME})
+ elseif(WIN32)
+ install(TARGETS ${SCRIPT_MODULE_PROJECT_NAME}
+ RUNTIME DESTINATION ${INSTALL_OFFSET}
+ COMPONENT ${SCRIPT_MODULE_PROJECT_NAME})
+ if(MSVC)
+ # Place the script modules in the script subdirectory
+ set_target_properties(${SCRIPT_MODULE_PROJECT_NAME} PROPERTIES
+ RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/bin/Debug/scripts
+ RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/bin/Release/scripts
+ RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO ${CMAKE_BINARY_DIR}/bin/RelWithDebInfo/scripts
+ RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL ${CMAKE_BINARY_DIR}/bin/MinSizeRel/scripts)
+ endif()
+ endif()
+ else()
+ message(FATAL_ERROR "Unknown value \"${${SCRIPT_MODULE_VARIABLE}}\"!")
+ endif()
+endforeach()
+
+# Add the dynamic script modules to the worldserver as dependency
+set(WORLDSERVER_DYNAMIC_SCRIPT_MODULES_DEPENDENCIES ${DYNAMIC_SCRIPT_MODULE_PROJECTS} PARENT_SCOPE)
+
+ConfigureScriptLoader("static" SCRIPT_MODULE_PRIVATE_SCRIPTLOADER OFF ${STATIC_SCRIPT_MODULES})
+
add_library(scripts STATIC
+ ScriptLoader.h
${PRIVATE_PCH_SOURCE}
- ${PRIVATE_SOURCES}
-)
+ ${SCRIPT_MODULE_PRIVATE_SCRIPTLOADER}
+ ${PRIVATE_SOURCES})
-target_include_directories(scripts
+target_link_libraries(scripts
PUBLIC
- ${CMAKE_CURRENT_SOURCE_DIR}
- PRIVATE
- ${CMAKE_CURRENT_BINARY_DIR})
+ game-interface)
-target_link_libraries(scripts
+target_include_directories(scripts
PUBLIC
- game)
+ ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(scripts
- PROPERTIES
- FOLDER
- "server")
+ PROPERTIES
+ FOLDER
+ "scripts")
# Generate precompiled header
if (USE_SCRIPTPCH)
- add_cxx_pch(scripts ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE})
+ list(APPEND ALL_SCRIPT_PROJECTS scripts ${DYNAMIC_SCRIPT_MODULE_PROJECTS})
+ add_cxx_pch("${ALL_SCRIPT_PROJECTS}" ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE})
+endif()
+
+# Remove all shared libraries in the installl directory which
+# are contained in the static library already.
+if (DISABLED_SCRIPT_MODULE_PROJECTS)
+ install(CODE "
+ foreach(SCRIPT_TO_UNINSTALL ${DISABLED_SCRIPT_MODULE_PROJECTS})
+ if (EXISTS \"\${SCRIPT_TO_UNINSTALL}\")
+ message(STATUS \"Uninstalling: \${SCRIPT_TO_UNINSTALL}\")
+ file(REMOVE \"\${SCRIPT_TO_UNINSTALL}\")
+ endif()
+ endforeach()
+ ")
endif()
+
+message("")
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 01a048c8795..1d8094885d4 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -124,6 +124,23 @@ public:
return false;
}
+ // Dump camera locations
+ if (CinematicSequencesEntry const* cineSeq = sCinematicSequencesStore.LookupEntry(id))
+ {
+ std::unordered_map<uint32, FlyByCameraCollection>::const_iterator itr = sFlyByCameraStore.find(cineSeq->cinematicCamera);
+ if (itr != sFlyByCameraStore.end())
+ {
+ handler->PSendSysMessage("Waypoints for sequence %u, camera %u", id, cineSeq->cinematicCamera);
+ uint32 count = 1 ;
+ for (FlyByCamera cam : itr->second)
+ {
+ handler->PSendSysMessage("%02u - %7ums [%f, %f, %f] Facing %f (%f degrees)", count, cam.timeStamp, cam.locations.x, cam.locations.y, cam.locations.z, cam.locations.w, cam.locations.w * (180 / M_PI));
+ count++;
+ }
+ handler->PSendSysMessage("%u waypoints dumped", itr->second.size());
+ }
+ }
+
handler->GetSession()->GetPlayer()->SendCinematicStart(id);
return true;
}
diff --git a/src/server/scripts/Commands/cs_misc.cpp b/src/server/scripts/Commands/cs_misc.cpp
index 3e35a721162..a98f9f4bf9c 100644
--- a/src/server/scripts/Commands/cs_misc.cpp
+++ b/src/server/scripts/Commands/cs_misc.cpp
@@ -796,7 +796,7 @@ public:
target->CleanupAfterTaxiFlight();
}
- target->TeleportTo(target->m_recallMap, target->m_recallX, target->m_recallY, target->m_recallZ, target->m_recallO);
+ target->Recall();
return true;
}
diff --git a/src/server/scripts/Commands/cs_modify.cpp b/src/server/scripts/Commands/cs_modify.cpp
index 3a062b21c3e..e25018cf1bd 100644
--- a/src/server/scripts/Commands/cs_modify.cpp
+++ b/src/server/scripts/Commands/cs_modify.cpp
@@ -80,23 +80,32 @@ public:
return commandTable;
}
- //Edit Player HP
- static bool HandleModifyHPCommand(ChatHandler* handler, const char* args)
+ template<typename... Args>
+ static void NotifyModification(ChatHandler* handler, Unit* target, TrinityStrings resourceMessage, TrinityStrings resourceReportMessage, Args&&... args)
+ {
+ if (Player* player = target->ToPlayer())
+ {
+ handler->PSendSysMessage(resourceMessage, handler->GetNameLink(player).c_str(), args...);
+ if (handler->needReportToTarget(player))
+ ChatHandler(player->GetSession()).PSendSysMessage(resourceReportMessage, handler->GetNameLink().c_str(), std::forward<Args>(args)...);
+ }
+ }
+
+ static bool CheckModifyResources(ChatHandler* handler, const char* args, Player* target, int32& res, int32& resmax, int8 const multiplier = 1)
{
if (!*args)
return false;
- int32 hp = atoi((char*)args);
- int32 hpm = atoi((char*)args);
+ res = atoi((char*)args) * multiplier;
+ resmax = atoi((char*)args) * multiplier;
- if (hp < 1 || hpm < 1 || hpm < hp)
+ if (res < 1 || resmax < 1 || resmax < res)
{
handler->SendSysMessage(LANG_BAD_VALUE);
handler->SetSentErrorMessage(true);
return false;
}
- Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -107,164 +116,87 @@ public:
if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
return false;
- handler->PSendSysMessage(LANG_YOU_CHANGE_HP, handler->GetNameLink(target).c_str(), hp, hpm);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_HP_CHANGED, handler->GetNameLink().c_str(), hp, hpm);
-
- target->SetMaxHealth(hpm);
- target->SetHealth(hp);
-
return true;
}
- //Edit Player Mana
- static bool HandleModifyManaCommand(ChatHandler* handler, const char* args)
+ //Edit Player HP
+ static bool HandleModifyHPCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- int32 mana = atoi((char*)args);
- int32 manam = atoi((char*)args);
-
- if (mana <= 0 || manam <= 0 || manam < mana)
+ int32 hp, hpmax;
+ Player* target = handler->getSelectedPlayerOrSelf();
+ if (CheckModifyResources(handler, args, target, hp, hpmax))
{
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_HP, LANG_YOURS_HP_CHANGED, hp, hpmax);
+ target->SetMaxHealth(hpmax);
+ target->SetHealth(hp);
+ return true;
}
+ return false;
+ }
+ //Edit Player Mana
+ static bool HandleModifyManaCommand(ChatHandler* handler, const char* args)
+ {
+ int32 mana, manamax;
Player* target = handler->getSelectedPlayerOrSelf();
- if (!target)
+
+ if (CheckModifyResources(handler, args, target, mana, manamax))
{
- handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_MANA, LANG_YOURS_MANA_CHANGED, mana, manamax);
+ target->SetMaxPower(POWER_MANA, manamax);
+ target->SetPower(POWER_MANA, mana);
+ return true;
}
-
- // check online security
- if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
- return false;
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_MANA, handler->GetNameLink(target).c_str(), mana, manam);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_MANA_CHANGED, handler->GetNameLink().c_str(), mana, manam);
-
- target->SetMaxPower(POWER_MANA, manam);
- target->SetPower(POWER_MANA, mana);
-
- return true;
+ return false;
}
//Edit Player Energy
static bool HandleModifyEnergyCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- int32 energy = atoi((char*)args)*10;
- int32 energym = atoi((char*)args)*10;
-
- if (energy <= 0 || energym <= 0 || energym < energy)
- {
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
+ int32 energy, energymax;
Player* target = handler->getSelectedPlayerOrSelf();
- if (!target)
+ int8 const energyMultiplier = 10;
+ if (CheckModifyResources(handler, args, target, energy, energymax, energyMultiplier))
{
- handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_ENERGY, LANG_YOURS_ENERGY_CHANGED, energy / energyMultiplier, energymax / energyMultiplier);
+ target->SetMaxPower(POWER_ENERGY, energymax);
+ target->SetPower(POWER_ENERGY, energy);
+ TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_ENERGY), target->GetMaxPower(POWER_ENERGY));
+ return true;
}
-
- // check online security
- if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
- return false;
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_ENERGY, handler->GetNameLink(target).c_str(), energy/10, energym/10);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ENERGY_CHANGED, handler->GetNameLink().c_str(), energy/10, energym/10);
-
- target->SetMaxPower(POWER_ENERGY, energym);
- target->SetPower(POWER_ENERGY, energy);
-
- TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_ENERGY), target->GetMaxPower(POWER_ENERGY));
-
- return true;
+ return false;
}
//Edit Player Rage
static bool HandleModifyRageCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- int32 rage = atoi((char*)args)*10;
- int32 ragem = atoi((char*)args)*10;
-
- if (rage <= 0 || ragem <= 0 || ragem < rage)
- {
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
+ int32 rage, ragemax;
Player* target = handler->getSelectedPlayerOrSelf();
- if (!target)
+ int8 const rageMultiplier = 10;
+ if (CheckModifyResources(handler, args, target, rage, ragemax, rageMultiplier))
{
- handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_RAGE, LANG_YOURS_RAGE_CHANGED, rage / rageMultiplier, ragemax / rageMultiplier);
+ target->SetMaxPower(POWER_RAGE, ragemax);
+ target->SetPower(POWER_RAGE, rage);
+ return true;
}
-
- // check online security
- if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
- return false;
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_RAGE, handler->GetNameLink(target).c_str(), rage/10, ragem/10);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_RAGE_CHANGED, handler->GetNameLink().c_str(), rage/10, ragem/10);
-
- target->SetMaxPower(POWER_RAGE, ragem);
- target->SetPower(POWER_RAGE, rage);
-
- return true;
+ return false;
}
// Edit Player Runic Power
static bool HandleModifyRunicPowerCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- int32 rune = atoi((char*)args)*10;
- int32 runem = atoi((char*)args)*10;
-
- if (rune <= 0 || runem <= 0 || runem < rune)
- {
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
+ int32 rune, runemax;
Player* target = handler->getSelectedPlayerOrSelf();
- if (!target)
+ int8 const runeMultiplier = 10;
+ if (CheckModifyResources(handler, args, target, rune, runemax, runeMultiplier))
{
- handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_RUNIC_POWER, LANG_YOURS_RUNIC_POWER_CHANGED, rune / runeMultiplier, runemax / runeMultiplier);
+ target->SetMaxPower(POWER_RUNIC_POWER, runemax);
+ target->SetPower(POWER_RUNIC_POWER, rune);
+ return true;
}
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_RUNIC_POWER, handler->GetNameLink(target).c_str(), rune/10, runem/10);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_RUNIC_POWER_CHANGED, handler->GetNameLink().c_str(), rune/10, runem/10);
-
- target->SetMaxPower(POWER_RUNIC_POWER, runem);
- target->SetPower(POWER_RUNIC_POWER, rune);
-
- return true;
+ return false;
}
//Edit Player Faction
@@ -437,22 +369,20 @@ public:
return false;
}
- //Edit Player Aspeed
- static bool HandleModifyASpeedCommand(ChatHandler* handler, const char* args)
+ static bool CheckModifySpeed(ChatHandler* handler, const char* args, Unit* target, float& speed, float minimumBound, float maximumBound, bool checkInFlight = true)
{
if (!*args)
return false;
- float ASpeed = (float)atof((char*)args);
+ speed = (float)atof((char*)args);
- if (ASpeed > 50.0f || ASpeed < 0.1f)
+ if (speed > maximumBound || speed < minimumBound)
{
handler->SendSysMessage(LANG_BAD_VALUE);
handler->SetSentErrorMessage(true);
return false;
}
- Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -460,238 +390,107 @@ public:
return false;
}
- // check online security
- if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
- return false;
-
- std::string targetNameLink = handler->GetNameLink(target);
-
- if (target->IsInFlight())
+ if (Player* player = target->ToPlayer())
{
- handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str());
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_ASPEED, targetNameLink.c_str(), ASpeed);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ASPEED_CHANGED, handler->GetNameLink().c_str(), ASpeed);
+ // check online security
+ if (handler->HasLowerSecurity(player, ObjectGuid::Empty))
+ return false;
- target->SetSpeed(MOVE_WALK, ASpeed, true);
- target->SetSpeed(MOVE_RUN, ASpeed, true);
- target->SetSpeed(MOVE_SWIM, ASpeed, true);
- //target->SetSpeed(MOVE_TURN, ASpeed, true);
- target->SetSpeed(MOVE_FLIGHT, ASpeed, true);
+ if (player->IsInFlight() && checkInFlight)
+ {
+ handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, handler->GetNameLink(player).c_str());
+ handler->SetSentErrorMessage(true);
+ return false;
+ }
+ }
return true;
}
- //Edit Player Speed
- static bool HandleModifySpeedCommand(ChatHandler* handler, const char* args)
+ //Edit Player Aspeed
+ static bool HandleModifyASpeedCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- float Speed = (float)atof((char*)args);
-
- if (Speed > 50.0f || Speed < 0.1f)
- {
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
+ float allSpeed;
Player* target = handler->getSelectedPlayerOrSelf();
- if (!target)
+ if (CheckModifySpeed(handler, args, target, allSpeed, 0.1f, 50.0f))
{
- handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_ASPEED, LANG_YOURS_ASPEED_CHANGED, allSpeed);
+ target->SetSpeedRate(MOVE_WALK, allSpeed);
+ target->SetSpeedRate(MOVE_RUN, allSpeed);
+ target->SetSpeedRate(MOVE_SWIM, allSpeed);
+ target->SetSpeedRate(MOVE_FLIGHT, allSpeed);
+ return true;
}
+ return false;
+ }
- // check online security
- if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
- return false;
-
- std::string targetNameLink = handler->GetNameLink(target);
-
- if (target->IsInFlight())
+ //Edit Player Speed
+ static bool HandleModifySpeedCommand(ChatHandler* handler, const char* args)
+ {
+ float Speed;
+ Player* target = handler->getSelectedPlayerOrSelf();
+ if (CheckModifySpeed(handler, args, target, Speed, 0.1f, 50.0f))
{
- handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str());
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_SPEED, LANG_YOURS_SPEED_CHANGED, Speed);
+ target->SetSpeedRate(MOVE_RUN, Speed);
+ return true;
}
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_SPEED, targetNameLink.c_str(), Speed);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_SPEED_CHANGED, handler->GetNameLink().c_str(), Speed);
-
- target->SetSpeed(MOVE_RUN, Speed, true);
-
- return true;
+ return false;
}
//Edit Player Swim Speed
static bool HandleModifySwimCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- float Swim = (float)atof((char*)args);
-
- if (Swim > 50.0f || Swim < 0.1f)
- {
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
+ float swimSpeed;
Player* target = handler->getSelectedPlayerOrSelf();
- if (!target)
+ if (CheckModifySpeed(handler, args, target, swimSpeed, 0.1f, 50.0f))
{
- handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- // check online security
- if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
- return false;
-
- std::string targetNameLink = handler->GetNameLink(target);
-
- if (target->IsInFlight())
- {
- handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str());
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_SWIM_SPEED, LANG_YOURS_SWIM_SPEED_CHANGED, swimSpeed);
+ target->SetSpeedRate(MOVE_SWIM, swimSpeed);
+ return true;
}
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_SWIM_SPEED, targetNameLink.c_str(), Swim);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_SWIM_SPEED_CHANGED, handler->GetNameLink().c_str(), Swim);
-
- target->SetSpeed(MOVE_SWIM, Swim, true);
-
- return true;
+ return false;
}
- //Edit Player Walk Speed
+ //Edit Player Backwards Walk Speed
static bool HandleModifyBWalkCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- float BSpeed = (float)atof((char*)args);
-
- if (BSpeed > 50.0f || BSpeed < 0.1f)
- {
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
+ float backSpeed;
Player* target = handler->getSelectedPlayerOrSelf();
- if (!target)
+ if (CheckModifySpeed(handler, args, target, backSpeed, 0.1f, 50.0f))
{
- handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- // check online security
- if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
- return false;
-
- std::string targetNameLink = handler->GetNameLink(target);
-
- if (target->IsInFlight())
- {
- handler->PSendSysMessage(LANG_CHAR_IN_FLIGHT, targetNameLink.c_str());
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_BACK_SPEED, LANG_YOURS_BACK_SPEED_CHANGED, backSpeed);
+ target->SetSpeedRate(MOVE_RUN_BACK, backSpeed);
+ return true;
}
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_BACK_SPEED, targetNameLink.c_str(), BSpeed);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_BACK_SPEED_CHANGED, handler->GetNameLink().c_str(), BSpeed);
-
- target->SetSpeed(MOVE_RUN_BACK, BSpeed, true);
-
- return true;
+ return false;
}
//Edit Player Fly
static bool HandleModifyFlyCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- float FSpeed = (float)atof((char*)args);
-
- if (FSpeed > 50.0f || FSpeed < 0.1f)
- {
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
+ float flySpeed;
Player* target = handler->getSelectedPlayerOrSelf();
- if (!target)
+ if (CheckModifySpeed(handler, args, target, flySpeed, 0.1f, 50.0f, false))
{
- handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
- handler->SetSentErrorMessage(true);
- return false;
+ NotifyModification(handler, target, LANG_YOU_CHANGE_FLY_SPEED, LANG_YOURS_FLY_SPEED_CHANGED, flySpeed);
+ target->SetSpeedRate(MOVE_FLIGHT, flySpeed);
+ return true;
}
-
- // check online security
- if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
- return false;
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_FLY_SPEED, handler->GetNameLink(target).c_str(), FSpeed);
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_FLY_SPEED_CHANGED, handler->GetNameLink().c_str(), FSpeed);
-
- target->SetSpeed(MOVE_FLIGHT, FSpeed, true);
-
- return true;
+ return false;
}
//Edit Player or Creature Scale
static bool HandleModifyScaleCommand(ChatHandler* handler, const char* args)
{
- if (!*args)
- return false;
-
- float Scale = (float)atof((char*)args);
- if (Scale > 10.0f || Scale < 0.1f)
- {
- handler->SendSysMessage(LANG_BAD_VALUE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
+ float Scale;
Unit* target = handler->getSelectedUnit();
- if (!target)
+ if (CheckModifySpeed(handler, args, target, Scale, 0.1f, 10.0f, false))
{
- handler->SendSysMessage(LANG_SELECT_CHAR_OR_CREATURE);
- handler->SetSentErrorMessage(true);
- return false;
- }
-
- if (Player* player = target->ToPlayer())
- {
- // check online security
- if (handler->HasLowerSecurity(player, ObjectGuid::Empty))
- return false;
-
- handler->PSendSysMessage(LANG_YOU_CHANGE_SIZE, handler->GetNameLink(player).c_str(), Scale);
- if (handler->needReportToTarget(player))
- ChatHandler(player->GetSession()).PSendSysMessage(LANG_YOURS_SIZE_CHANGED, handler->GetNameLink().c_str(), Scale);
+ NotifyModification(handler, target, LANG_YOU_CHANGE_SIZE, LANG_YOURS_SIZE_CHANGED, Scale);
+ target->SetObjectScale(Scale);
+ return true;
}
-
- target->SetObjectScale(Scale);
-
- return true;
+ return false;
}
//Enable Player mount
@@ -932,9 +731,7 @@ public:
if (handler->HasLowerSecurity(target, ObjectGuid::Empty))
return false;
- handler->PSendSysMessage(LANG_YOU_GIVE_MOUNT, handler->GetNameLink(target).c_str());
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_MOUNT_GIVED, handler->GetNameLink().c_str());
+ NotifyModification(handler, target, LANG_YOU_GIVE_MOUNT, LANG_MOUNT_GIVED);
target->SetUInt32Value(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP);
target->Mount(mId);
@@ -988,10 +785,7 @@ public:
TC_LOG_DEBUG("misc", handler->GetTrinityString(LANG_CURRENT_MONEY), targetMoney, moneyToAdd, newmoney);
if (newmoney <= 0)
{
- handler->PSendSysMessage(LANG_YOU_TAKE_ALL_MONEY, handler->GetNameLink(target).c_str());
- if (handler->needReportToTarget(target))
- ChatHandler(target->GetSession()).PSendSysMessage(LANG_YOURS_ALL_MONEY_GONE, handler->GetNameLink().c_str());
-
+ NotifyModification(handler, target, LANG_YOU_TAKE_ALL_MONEY, LANG_YOURS_ALL_MONEY_GONE);
target->SetMoney(0);
}
else
@@ -1339,8 +1133,8 @@ public:
}
// Set gender
- target->SetByteValue(UNIT_FIELD_BYTES_0, 2, gender);
- target->SetByteValue(PLAYER_BYTES_3, 0, gender);
+ target->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_GENDER, gender);
+ target->SetByteValue(PLAYER_BYTES_3, PLAYER_BYTES_3_OFFSET_GENDER, gender);
// Change display ID
target->InitDisplayIds();
diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp
index 56b0dbf43d0..eb28a8adae4 100644
--- a/src/server/scripts/Commands/cs_reload.cpp
+++ b/src/server/scripts/Commands/cs_reload.cpp
@@ -251,7 +251,7 @@ public:
static bool HandleReloadAllScriptsCommand(ChatHandler* handler, const char* /*args*/)
{
- if (sScriptMgr->IsScriptScheduled())
+ if (sMapMgr->IsScriptScheduled())
{
handler->PSendSysMessage("DB scripts used currently, please attempt reload later.");
handler->SetSentErrorMessage(true);
@@ -393,7 +393,7 @@ public:
static bool HandleReloadCommandCommand(ChatHandler* handler, const char* /*args*/)
{
- handler->SetLoadCommandTable(true);
+ ChatHandler::invalidateCommandTable();
handler->SendGlobalGMSysMessage("DB table `command` will be reloaded at next chat command use.");
return true;
}
@@ -893,7 +893,7 @@ public:
static bool HandleReloadEventScriptsCommand(ChatHandler* handler, const char* args)
{
- if (sScriptMgr->IsScriptScheduled())
+ if (sMapMgr->IsScriptScheduled())
{
handler->SendSysMessage("DB scripts used currently, please attempt reload later.");
handler->SetSentErrorMessage(true);
@@ -913,7 +913,7 @@ public:
static bool HandleReloadWpScriptsCommand(ChatHandler* handler, const char* args)
{
- if (sScriptMgr->IsScriptScheduled())
+ if (sMapMgr->IsScriptScheduled())
{
handler->SendSysMessage("DB scripts used currently, please attempt reload later.");
handler->SetSentErrorMessage(true);
@@ -946,7 +946,7 @@ public:
static bool HandleReloadSpellScriptsCommand(ChatHandler* handler, const char* args)
{
- if (sScriptMgr->IsScriptScheduled())
+ if (sMapMgr->IsScriptScheduled())
{
handler->SendSysMessage("DB scripts used currently, please attempt reload later.");
handler->SetSentErrorMessage(true);
diff --git a/src/server/scripts/Commands/cs_reset.cpp b/src/server/scripts/Commands/cs_reset.cpp
index 05941120423..ba1dab28350 100644
--- a/src/server/scripts/Commands/cs_reset.cpp
+++ b/src/server/scripts/Commands/cs_reset.cpp
@@ -102,7 +102,7 @@ public:
player->setFactionForRace(player->getRace());
- player->SetUInt32Value(UNIT_FIELD_BYTES_0, ((player->getRace()) | (player->getClass() << 8) | (player->getGender() << 16) | (powerType << 24)));
+ player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_POWER_TYPE, powerType);
// reset only if player not in some form;
if (player->GetShapeshiftForm() == FORM_NONE)
diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp
index 51bb314968d..ffec32c0619 100644
--- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp
+++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp
@@ -27,6 +27,8 @@ EndScriptData */
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "molten_core.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
enum Emotes
{
@@ -36,9 +38,10 @@ enum Emotes
enum Spells
{
SPELL_INFERNO = 19695,
+ SPELL_INFERNO_DMG = 19698,
SPELL_IGNITE_MANA = 19659,
SPELL_LIVING_BOMB = 20475,
- SPELL_ARMAGEDDON = 20479,
+ SPELL_ARMAGEDDON = 20478,
};
enum Events
@@ -119,7 +122,36 @@ class boss_baron_geddon : public CreatureScript
}
};
+class spell_baron_geddon_inferno : public SpellScriptLoader
+{
+ public:
+ spell_baron_geddon_inferno() : SpellScriptLoader("spell_baron_geddon_inferno") { }
+
+ class spell_baron_geddon_inferno_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_baron_geddon_inferno_AuraScript);
+
+ void OnPeriodic(AuraEffect const* aurEff)
+ {
+ PreventDefaultAction();
+ int32 damageForTick[8] = { 500, 500, 1000, 1000, 2000, 2000, 3000, 5000 };
+ GetTarget()->CastCustomSpell(SPELL_INFERNO_DMG, SPELLVALUE_BASE_POINT0, damageForTick[aurEff->GetTickNumber() - 1], (Unit*)nullptr, TRIGGERED_FULL_MASK, nullptr, aurEff);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_baron_geddon_inferno_AuraScript::OnPeriodic, EFFECT_0, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_baron_geddon_inferno_AuraScript();
+ }
+};
+
void AddSC_boss_baron_geddon()
{
new boss_baron_geddon();
+ new spell_baron_geddon_inferno();
}
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp
index 7d7c60ac419..6ff20e66f7f 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp
@@ -138,7 +138,7 @@ public:
{
Initialize();
- me->SetSpeed(MOVE_RUN, 2.0f);
+ me->SetSpeedRate(MOVE_RUN, 2.0f);
me->SetDisableGravity(true);
me->SetWalk(false);
me->setActive(true);
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
index 4aef3c8d4a3..ace15cc2a7e 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/karazhan.cpp
@@ -562,7 +562,7 @@ public:
arca->GetMotionMaster()->MovePoint(0, -11010.82f, -1761.18f, 156.47f);
arca->setActive(true);
arca->InterruptNonMeleeSpells(true);
- arca->SetSpeed(MOVE_FLIGHT, 2.0f);
+ arca->SetSpeedRate(MOVE_FLIGHT, 2.0f);
}
return 10000;
case 13:
diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
index b809128e731..ebe406c8909 100644
--- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
+++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp
@@ -405,7 +405,7 @@ public:
Creature* Orb = DoSpawnCreature(CREATURE_ARCANE_SPHERE, 5, 5, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 30000);
if (Orb && target)
{
- Orb->SetSpeed(MOVE_RUN, 0.5f);
+ Orb->SetSpeedRate(MOVE_RUN, 0.5f);
Orb->AddThreat(target, 1000000.0f);
Orb->AI()->AttackStart(target);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index 81044a0dbb1..3cf78b79f67 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -396,7 +396,7 @@ class npc_eye_of_acherus : public CreatureScript
if (Player* owner = me->GetCharmerOrOwner()->ToPlayer())
{
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
- me->SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true);
+ me->SetSpeedRate(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)));
Talk(TALK_MOVE_START, owner);
}
me->GetMotionMaster()->MovePath(me->GetEntry() * 100, false);
@@ -419,7 +419,7 @@ class npc_eye_of_acherus : public CreatureScript
{
owner->RemoveAura(SPELL_EYE_FLIGHT_BOOST);
for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i)
- me->SetSpeed(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)), true);
+ me->SetSpeedRate(UnitMoveType(i), owner->GetSpeedRate(UnitMoveType(i)));
Talk(TALK_CONTROL, owner);
}
@@ -703,7 +703,7 @@ class npc_dark_rider_of_acherus : public CreatureScript
TargetGUID = who->GetGUID();
me->SetWalk(true);
- me->SetSpeed(MOVE_RUN, 0.4f);
+ me->SetSpeedRate(MOVE_RUN, 0.4f);
me->GetMotionMaster()->MoveChase(who);
me->SetTarget(TargetGUID);
Intro = true;
@@ -1050,7 +1050,7 @@ class npc_scarlet_miner_cart : public CreatureScript
// Not 100% correct, but movement is smooth. Sometimes miner walks faster
// than normal, this speed is fast enough to keep up at those times.
- me->SetSpeed(MOVE_RUN, 1.25f);
+ me->SetSpeedRate(MOVE_RUN, 1.25f);
me->GetMotionMaster()->MoveFollow(miner, 1.0f, 0);
}
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
index e336ff24382..d25a225717a 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp
@@ -923,7 +923,7 @@ public:
if (ObjectAccessor::GetCreature(*me, uiLichKingGUID))
DoCast(me, SPELL_MOGRAINE_CHARGE); // jumping charge
// doesn't make it looks well, so workarounds, Darion charges, looks better
- me->SetSpeed(MOVE_RUN, 3.0f);
+ me->SetSpeedRate(MOVE_RUN, 3.0f);
me->SetWalk(false);
SetHoldState(false);
JumpToNextStep(0);
@@ -935,7 +935,7 @@ public:
temp->HandleEmoteCommand(EMOTE_ONESHOT_KICK);
temp->AI()->Talk(SAY_LIGHT_OF_DAWN46);
}
- me->SetSpeed(MOVE_RUN, 6.0f);
+ me->SetSpeedRate(MOVE_RUN, 6.0f);
me->SetStandState(UNIT_STAND_STATE_DEAD);
SetHoldState(false); // Darion got kicked by lich king
JumpToNextStep(0);
@@ -997,7 +997,7 @@ public:
Unit* temp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000);
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
temp->SetWalk(false);
- temp->SetSpeed(MOVE_RUN, 2.0f);
+ temp->SetSpeedRate(MOVE_RUN, 2.0f);
temp->setFaction(me->getFaction());
temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
uiDefenderGUID[0] = temp->GetGUID();
@@ -1005,7 +1005,7 @@ public:
temp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 10000);
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
temp->SetWalk(false);
- temp->SetSpeed(MOVE_RUN, 2.0f);
+ temp->SetSpeedRate(MOVE_RUN, 2.0f);
temp->setFaction(me->getFaction());
temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
uiEarthshatterGUID[0] = temp->GetGUID();
@@ -1014,7 +1014,7 @@ public:
{
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
temp->SetWalk(false);
- temp->SetSpeed(MOVE_RUN, 2.0f);
+ temp->SetSpeedRate(MOVE_RUN, 2.0f);
temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
temp->AI()->Talk(SAY_LIGHT_OF_DAWN50);
}
@@ -1022,7 +1022,7 @@ public:
{
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
temp->SetWalk(false);
- temp->SetSpeed(MOVE_RUN, 2.0f);
+ temp->SetSpeedRate(MOVE_RUN, 2.0f);
temp->HandleEmoteCommand(EMOTE_STATE_ATTACK_UNARMED);
temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
}
@@ -1030,7 +1030,7 @@ public:
{
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_ATTACK_UNARMED);
temp->SetWalk(false);
- temp->SetSpeed(MOVE_RUN, 2.0f);
+ temp->SetSpeedRate(MOVE_RUN, 2.0f);
temp->GetMotionMaster()->MovePoint(0, fLichPositionX, fLichPositionY, fLichPositionZ);
}
}
@@ -1044,33 +1044,33 @@ public:
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiMaxwellGUID))
{
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
- temp->SetSpeed(MOVE_RUN, 6.0f);
+ temp->SetSpeedRate(MOVE_RUN, 6.0f);
temp->SetStandState(UNIT_STAND_STATE_DEAD);
temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[14]);
}
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiKorfaxGUID))
{
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
- temp->SetSpeed(MOVE_RUN, 6.0f);
+ temp->SetSpeedRate(MOVE_RUN, 6.0f);
temp->SetStandState(UNIT_STAND_STATE_DEAD);
temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[11]);
}
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiEligorGUID))
{
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
- temp->SetSpeed(MOVE_RUN, 6.0f);
+ temp->SetSpeedRate(MOVE_RUN, 6.0f);
temp->SetStandState(UNIT_STAND_STATE_DEAD);
temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[17]);
}
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiDefenderGUID[0]))
{
- temp->SetSpeed(MOVE_RUN, 6.0f);
+ temp->SetSpeedRate(MOVE_RUN, 6.0f);
temp->SetStandState(UNIT_STAND_STATE_DEAD);
temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f }));
}
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiEarthshatterGUID[0]))
{
- temp->SetSpeed(MOVE_RUN, 6.0f);
+ temp->SetSpeedRate(MOVE_RUN, 6.0f);
temp->SetStandState(UNIT_STAND_STATE_DEAD);
temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 10), float(rand32() % 10), 0.0f, 0.0f }));
}
@@ -1093,7 +1093,7 @@ public:
break;
case 46: // Darion stand up, "not today"
- me->SetSpeed(MOVE_RUN, 1.0f);
+ me->SetSpeedRate(MOVE_RUN, 1.0f);
me->SetWalk(true);
me->SetStandState(UNIT_STAND_STATE_STAND);
Talk(SAY_LIGHT_OF_DAWN53);
@@ -1153,7 +1153,7 @@ public:
temp->AI()->Talk(EMOTE_LIGHT_OF_DAWN16);
temp->CastSpell(temp, SPELL_TIRION_CHARGE, false); // jumping charge
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_READY2H);
- temp->SetSpeed(MOVE_RUN, 3.0f); // workarounds, make Tirion still running
+ temp->SetSpeedRate(MOVE_RUN, 3.0f); // workarounds, make Tirion still running
temp->SetWalk(false);
temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[2]);
if (Creature* lktemp = ObjectAccessor::GetCreature(*me, uiLichKingGUID))
@@ -1171,7 +1171,7 @@ public:
case 54:
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiLichKingGUID))
{
- temp->SetSpeed(MOVE_RUN, 1.0f);
+ temp->SetSpeedRate(MOVE_RUN, 1.0f);
me->SetWalk(true);
temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[29]); // 26
}
@@ -1208,7 +1208,7 @@ public:
if (Creature* temp = ObjectAccessor::GetCreature(*me, uiTirionGUID)) // Tirion runs to Darion
{
temp->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_ONESHOT_NONE);
- temp->SetSpeed(MOVE_RUN, 1.0f);
+ temp->SetSpeedRate(MOVE_RUN, 1.0f);
temp->GetMotionMaster()->MovePoint(0, LightofDawnLoc[6]);
}
JumpToNextStep(2500);
diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
index 74b300919d8..734b70933aa 100644
--- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp
@@ -450,7 +450,7 @@ public:
me->SetVisible(false);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->SetDisableGravity(true);
- me->SetSpeed(MOVE_WALK, 5.0f, true);
+ me->SetSpeedRate(MOVE_WALK, 5.0f);
wp_reached = false;
count = 0;
say_timer = 3000;
@@ -894,12 +894,12 @@ public:
if (instance->GetBossState(DATA_HORSEMAN_EVENT) == IN_PROGRESS)
return false;
- player->AreaExploredOrEventHappens(11405);
- if (Creature* horseman = go->SummonCreature(HH_MOUNTED, FlightPoint[20].x, FlightPoint[20].y, FlightPoint[20].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 0))
- {
- ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->PlayerGUID = player->GetGUID();
- ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->FlyMode();
- }
+ player->AreaExploredOrEventHappens(11405);
+ if (Creature* horseman = go->SummonCreature(HH_MOUNTED, FlightPoint[20].x, FlightPoint[20].y, FlightPoint[20].z, 0, TEMPSUMMON_MANUAL_DESPAWN, 0))
+ {
+ ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->PlayerGUID = player->GetGUID();
+ ENSURE_AI(boss_headless_horseman::boss_headless_horsemanAI, horseman->AI())->FlyMode();
+ }
return true;
}
};
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
index d9b481d7b6d..fded249f9ca 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp
@@ -249,7 +249,7 @@ public:
me->CastStop(SPELL_FOG_BREATH);
me->RemoveAurasDueToSpell(SPELL_FOG_BREATH);
me->StopMoving();
- me->SetSpeed(MOVE_RUN, 2.0f);
+ me->SetSpeedRate(MOVE_RUN, 2.0f);
events.ScheduleEvent(EVENT_CLEAVE, urand(5000, 10000));
events.ScheduleEvent(EVENT_CORROSION, urand(10000, 20000));
@@ -530,7 +530,7 @@ public:
npc_felmyst_vaporAI(Creature* creature) : ScriptedAI(creature)
{
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetSpeed(MOVE_RUN, 0.8f);
+ me->SetSpeedRate(MOVE_RUN, 0.8f);
}
void Reset() override { }
diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp
index d86b3707606..7563a880f0a 100644
--- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp
+++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp
@@ -143,11 +143,7 @@ enum Spells
SPELL_RING_OF_BLUE_FLAMES = 45825 //Cast this spell when the go is activated
};
-/*** Error messages ***/
-#define ERROR_KJ_NOT_SUMMONED "TSCR ERROR: Unable to summon Kil'Jaeden for some reason"
-
/*** Others ***/
-#define FLOOR_Z 28.050388f
#define SHIELD_ORB_Z 45.000f
enum Phase
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
index 791f68bae31..72e76ba52bf 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp
@@ -425,7 +425,7 @@ class npc_akilzon_eagle : public CreatureScript
if (Unit* target = ObjectAccessor::GetUnit(*me, TargetGUID))
DoCast(target, SPELL_EAGLE_SWOOP, true);
TargetGUID.Clear();
- me->SetSpeed(MOVE_RUN, 1.2f);
+ me->SetSpeedRate(MOVE_RUN, 1.2f);
EagleSwoop_Timer = urand(5000, 10000);
}
}
@@ -454,7 +454,7 @@ class npc_akilzon_eagle : public CreatureScript
{
target->GetContactPoint(me, x, y, z);
z += 2;
- me->SetSpeed(MOVE_RUN, 5.0f);
+ me->SetSpeedRate(MOVE_RUN, 5.0f);
TargetGUID = target->GetGUID();
}
me->GetMotionMaster()->MovePoint(0, x, y, z);
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp
index 0407cb6cd7c..188f9d0cc03 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp
@@ -142,7 +142,7 @@ class boss_nalorakk : public CreatureScript
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
inMove = false;
waitTimer = 0;
- me->SetSpeed(MOVE_RUN, 2);
+ me->SetSpeedRate(MOVE_RUN, 2);
me->SetWalk(false);
}else
{
diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp
index 96c0798ae05..a1c2369cf66 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp
@@ -347,7 +347,7 @@ class boss_zuljin : public CreatureScript
Vortex->CastSpell(Vortex, SPELL_CYCLONE_PASSIVE, true);
Vortex->CastSpell(Vortex, SPELL_CYCLONE_VISUAL, true);
Vortex->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- Vortex->SetSpeed(MOVE_RUN, 1.0f);
+ Vortex->SetSpeedRate(MOVE_RUN, 1.0f);
Vortex->AI()->AttackStart(SelectTarget(SELECT_TARGET_RANDOM, 0));
DoZoneInCombat(Vortex);
}
@@ -438,7 +438,7 @@ class boss_zuljin : public CreatureScript
{
if (me->GetVictim())
TankGUID = me->EnsureVictim()->GetGUID();
- me->SetSpeed(MOVE_RUN, 5.0f);
+ me->SetSpeedRate(MOVE_RUN, 5.0f);
AttackStart(target); // change victim
Claw_Rage_Timer = 0;
Claw_Loop_Timer = 500;
@@ -462,7 +462,7 @@ class boss_zuljin : public CreatureScript
if (Claw_Counter == 12)
{
Claw_Rage_Timer = urand(15000, 20000);
- me->SetSpeed(MOVE_RUN, 1.2f);
+ me->SetSpeedRate(MOVE_RUN, 1.2f);
AttackStart(ObjectAccessor::GetUnit(*me, TankGUID));
TankGUID.Clear();
return;
@@ -487,7 +487,7 @@ class boss_zuljin : public CreatureScript
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0))
{
TankGUID = me->EnsureVictim()->GetGUID();
- me->SetSpeed(MOVE_RUN, 5.0f);
+ me->SetSpeedRate(MOVE_RUN, 5.0f);
AttackStart(target); // change victim
Lynx_Rush_Timer = 0;
Claw_Counter = 0;
@@ -510,7 +510,7 @@ class boss_zuljin : public CreatureScript
if (Claw_Counter == 9)
{
Lynx_Rush_Timer = urand(15000, 20000);
- me->SetSpeed(MOVE_RUN, 1.2f);
+ me->SetSpeedRate(MOVE_RUN, 1.2f);
AttackStart(ObjectAccessor::GetUnit(*me, TankGUID));
TankGUID.Clear();
}
diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
index 8c179af2adf..3697b0876c8 100644
--- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_mandokir.cpp
@@ -148,6 +148,11 @@ class boss_mandokir : public CreatureScript
instance->SaveToDB();
}
+ void JustReachedHome() override
+ {
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_IMMUNE_TO_NPC);
+ }
+
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
@@ -194,9 +199,9 @@ class boss_mandokir : public CreatureScript
me->SetWalk(false);
if (id == POINT_MANDOKIR_END)
{
- me->SetHomePosition(PosMandokir[0]);
+ me->SetHomePosition(PosMandokir[1]);
+ me->GetMotionMaster()->MoveTargetedHome();
instance->SetBossState(DATA_MANDOKIR, NOT_STARTED);
- me->DespawnOrUnsummon(6000); // No idea how to respawn on wipe.
}
}
}
diff --git a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
index 8c781bb9001..b794a653791 100644
--- a/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
+++ b/src/server/scripts/EasternKingdoms/eastern_kingdoms_script_loader.cpp
@@ -89,7 +89,6 @@ void AddSC_boss_sulfuron();
void AddSC_boss_majordomo();
void AddSC_boss_ragnaros();
void AddSC_instance_molten_core();
-void AddSC_instance_ragefire_chasm(); //Ragefire Chasm
void AddSC_the_scarlet_enclave(); //Scarlet Enclave
void AddSC_the_scarlet_enclave_c1();
void AddSC_the_scarlet_enclave_c2();
@@ -268,7 +267,6 @@ void AddEasternKingdomsScripts()
AddSC_boss_majordomo();
AddSC_boss_ragnaros();
AddSC_instance_molten_core();
- AddSC_instance_ragefire_chasm(); //Ragefire Chasm
AddSC_the_scarlet_enclave(); //Scarlet Enclave
AddSC_the_scarlet_enclave_c1();
AddSC_the_scarlet_enclave_c2();
diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp
index b0d6e782052..03c957fa221 100644
--- a/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp
+++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/instance_blackfathom_deeps.cpp
@@ -174,7 +174,7 @@ public:
if (state == DONE)
if (GameObject* go = instance->GetGameObject(shrineOfGelihastGUID))
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
- break;
+ break;
case DATA_AKU_MAI:
if (state == DONE)
if (GameObject* go = instance->GetGameObject(altarOfTheDeepsGUID))
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
index 44cbdec2cb5..8e53ab06ca5 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/EscapeFromDurnholdeKeep/old_hillsbrad.cpp
@@ -479,12 +479,12 @@ public:
void DoMount()
{
me->Mount(SKARLOC_MOUNT_MODEL);
- me->SetSpeed(MOVE_RUN, SPEED_MOUNT);
+ me->SetSpeedRate(MOVE_RUN, SPEED_MOUNT);
}
void DoUnmount()
{
me->Dismount();
- me->SetSpeed(MOVE_RUN, SPEED_RUN);
+ me->SetSpeedRate(MOVE_RUN, SPEED_RUN);
}
void EnterCombat(Unit* /*who*/) override
{
@@ -535,12 +535,12 @@ public:
if (!UpdateVictim())
return;
- /// @todo add his abilities'n-crap here
- if (!LowHp && HealthBelowPct(20))
- {
- Talk(SAY_TH_RANDOM_LOW_HP);
- LowHp = true;
- }
+ /// @todo add his abilities'n-crap here
+ if (!LowHp && HealthBelowPct(20))
+ {
+ Talk(SAY_TH_RANDOM_LOW_HP);
+ LowHp = true;
+ }
}
};
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp
index 8715f3ca0f6..4d0f80d502d 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_aeonus.cpp
@@ -106,33 +106,33 @@ public:
if (!UpdateVictim())
return;
- events.Update(diff);
+ events.Update(diff);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_SANDBREATH:
- DoCastVictim(SPELL_SAND_BREATH);
- events.ScheduleEvent(EVENT_SANDBREATH, urand(15000, 25000));
- break;
- case EVENT_TIMESTOP:
- DoCastVictim(SPELL_TIME_STOP);
- events.ScheduleEvent(EVENT_TIMESTOP, urand(20000, 35000));
- break;
- case EVENT_FRENZY:
- Talk(EMOTE_FRENZY);
- DoCast(me, SPELL_ENRAGE);
- events.ScheduleEvent(EVENT_FRENZY, urand(20000, 35000));
- break;
- default:
- break;
- }
+ case EVENT_SANDBREATH:
+ DoCastVictim(SPELL_SAND_BREATH);
+ events.ScheduleEvent(EVENT_SANDBREATH, urand(15000, 25000));
+ break;
+ case EVENT_TIMESTOP:
+ DoCastVictim(SPELL_TIME_STOP);
+ events.ScheduleEvent(EVENT_TIMESTOP, urand(20000, 35000));
+ break;
+ case EVENT_FRENZY:
+ Talk(EMOTE_FRENZY);
+ DoCast(me, SPELL_ENRAGE);
+ events.ScheduleEvent(EVENT_FRENZY, urand(20000, 35000));
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
+ }
+ DoMeleeAttackIfReady();
}
};
diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp
index 2befdabe550..844ce239bdf 100644
--- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp
+++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/boss_temporus.cpp
@@ -107,36 +107,36 @@ public:
if (!UpdateVictim())
return;
- events.Update(diff);
+ events.Update(diff);
- if (me->HasUnitState(UNIT_STATE_CASTING))
- return;
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
- while (uint32 eventId = events.ExecuteEvent())
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
{
- switch (eventId)
- {
- case EVENT_HASTE:
- DoCast(me, SPELL_HASTE);
- events.ScheduleEvent(EVENT_HASTE, urand(20000, 25000));
- break;
- case EVENT_MORTAL_WOUND:
- DoCast(me, SPELL_MORTAL_WOUND);
- events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 20000));
- break;
- case EVENT_WING_BUFFET:
- DoCast(me, SPELL_WING_BUFFET);
- events.ScheduleEvent(EVENT_WING_BUFFET, urand(20000, 30000));
- break;
- case EVENT_SPELL_REFLECTION: // Only in Heroic
- DoCast(me, SPELL_REFLECT);
- events.ScheduleEvent(EVENT_SPELL_REFLECTION, urand(25000, 35000));
- break;
- default:
- break;
- }
+ case EVENT_HASTE:
+ DoCast(me, SPELL_HASTE);
+ events.ScheduleEvent(EVENT_HASTE, urand(20000, 25000));
+ break;
+ case EVENT_MORTAL_WOUND:
+ DoCast(me, SPELL_MORTAL_WOUND);
+ events.ScheduleEvent(EVENT_MORTAL_WOUND, urand(10000, 20000));
+ break;
+ case EVENT_WING_BUFFET:
+ DoCast(me, SPELL_WING_BUFFET);
+ events.ScheduleEvent(EVENT_WING_BUFFET, urand(20000, 30000));
+ break;
+ case EVENT_SPELL_REFLECTION: // Only in Heroic
+ DoCast(me, SPELL_REFLECT);
+ events.ScheduleEvent(EVENT_SPELL_REFLECTION, urand(25000, 35000));
+ break;
+ default:
+ break;
}
- DoMeleeAttackIfReady();
+ }
+ DoMeleeAttackIfReady();
}
};
diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
index 7da15b1fdce..71ebe870e3d 100644
--- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
+++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp
@@ -205,7 +205,7 @@ public:
PointData = GetMoveData();
MovePoint = PointData->LocIdEnd;
- me->SetSpeed(MOVE_FLIGHT, 1.5f);
+ me->SetSpeedRate(MOVE_FLIGHT, 1.5f);
me->GetMotionMaster()->MovePoint(8, MiddleRoomLocation);
}
}
@@ -220,7 +220,7 @@ public:
PointData = GetMoveData();
if (PointData)
{
- me->SetSpeed(MOVE_FLIGHT, 1.0f);
+ me->SetSpeedRate(MOVE_FLIGHT, 1.0f);
me->GetMotionMaster()->MovePoint(PointData->LocId, PointData->fX, PointData->fY, PointData->fZ);
}
break;
@@ -250,7 +250,7 @@ public:
if (Creature * trigger = me->SummonCreature(NPC_TRIGGER, MiddleRoomLocation, TEMPSUMMON_CORPSE_DESPAWN))
triggerGUID = trigger->GetGUID();
me->GetMotionMaster()->MoveTakeoff(11, Phase2Floating);
- me->SetSpeed(MOVE_FLIGHT, 1.0f);
+ me->SetSpeedRate(MOVE_FLIGHT, 1.0f);
Talk(SAY_PHASE_2_TRANS);
instance->SetData(DATA_ONYXIA_PHASE, Phase);
events.ScheduleEvent(EVENT_WHELP_SPAWN, 5000);
diff --git a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
index f1969a063d6..87edf4781d4 100644
--- a/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
+++ b/src/server/scripts/Kalimdor/kalimdor_script_loader.cpp
@@ -47,6 +47,7 @@ void AddSC_boss_meathook();
void AddSC_culling_of_stratholme();
void AddSC_instance_culling_of_stratholme();
void AddSC_instance_dire_maul(); //Dire Maul
+void AddSC_instance_ragefire_chasm(); //Ragefire Chasm
void AddSC_boss_celebras_the_cursed(); //Maraudon
void AddSC_boss_landslide();
void AddSC_boss_noxxion();
@@ -143,6 +144,7 @@ void AddKalimdorScripts()
AddSC_culling_of_stratholme();
AddSC_instance_culling_of_stratholme();
AddSC_instance_dire_maul(); //Dire Maul
+ AddSC_instance_ragefire_chasm(); //Ragefire Chasm
AddSC_boss_celebras_the_cursed(); //Maraudon
AddSC_boss_landslide();
AddSC_boss_noxxion();
diff --git a/src/server/scripts/Kalimdor/zone_azshara.cpp b/src/server/scripts/Kalimdor/zone_azshara.cpp
index 1ed95c16a0d..4847ac46542 100644
--- a/src/server/scripts/Kalimdor/zone_azshara.cpp
+++ b/src/server/scripts/Kalimdor/zone_azshara.cpp
@@ -404,7 +404,7 @@ public:
DoCast(me, SPELL_PERIODIC_DEPTH_CHARGE);
me->SetHover(true);
me->SetSwim(true);
- me->SetSpeed(MOVE_RUN, 0.85f, true);
+ me->SetSpeedRate(MOVE_RUN, 0.85f);
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->MovePoint(CurrWP, WPs[CurrWP]);
Escape = true;
diff --git a/src/server/scripts/Kalimdor/zone_desolace.cpp b/src/server/scripts/Kalimdor/zone_desolace.cpp
index 6880d8ee38f..3f4a905147f 100644
--- a/src/server/scripts/Kalimdor/zone_desolace.cpp
+++ b/src/server/scripts/Kalimdor/zone_desolace.cpp
@@ -89,7 +89,7 @@ public:
me->UpdateEntry(NPC_TAMED_KODO);
me->CombatStop();
me->DeleteThreatList();
- me->SetSpeed(MOVE_RUN, 0.6f, true);
+ me->SetSpeedRate(MOVE_RUN, 0.6f);
me->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, me->GetFollowAngle());
me->setActive(true);
}
diff --git a/src/server/scripts/Kalimdor/zone_durotar.cpp b/src/server/scripts/Kalimdor/zone_durotar.cpp
index 05caf9cca3a..62a041e7798 100644
--- a/src/server/scripts/Kalimdor/zone_durotar.cpp
+++ b/src/server/scripts/Kalimdor/zone_durotar.cpp
@@ -483,8 +483,8 @@ class spell_mount_check : public SpellScriptLoader
else if (!owner->IsMounted() && target->IsMounted())
target->Dismount();
- target->SetSpeed(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN));
- target->SetSpeed(MOVE_WALK, owner->GetSpeedRate(MOVE_WALK));
+ target->SetSpeedRate(MOVE_RUN, owner->GetSpeedRate(MOVE_RUN));
+ target->SetSpeedRate(MOVE_WALK, owner->GetSpeedRate(MOVE_WALK));
}
void Register() override
diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp
index b113615ca50..7a963d066b6 100644
--- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp
+++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp
@@ -43,38 +43,37 @@ EndContentData */
## npc_beaten_corpse
######*/
-#define GOSSIP_CORPSE "Examine corpse in detail..."
-
enum BeatenCorpse
{
- QUEST_LOST_IN_BATTLE = 4921
+ GOSSIP_OPTION_ID_BEATEN_CORPSE = 0,
+ GOSSIP_MENU_OPTION_INSPECT_BODY = 2871
};
class npc_beaten_corpse : public CreatureScript
{
-public:
- npc_beaten_corpse() : CreatureScript("npc_beaten_corpse") { }
+ public:
+ npc_beaten_corpse() : CreatureScript("npc_beaten_corpse") { }
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF +1)
+ struct npc_beaten_corpseAI : public ScriptedAI
{
- player->SEND_GOSSIP_MENU(3558, creature->GetGUID());
- player->TalkedToCreature(creature->GetEntry(), creature->GetGUID());
- }
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- if (player->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_INCOMPLETE || player->GetQuestStatus(QUEST_LOST_IN_BATTLE) == QUEST_STATUS_COMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_CORPSE, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ npc_beaten_corpseAI(Creature* creature) : ScriptedAI(creature)
+ {
+ }
- player->SEND_GOSSIP_MENU(3557, creature->GetGUID());
- return true;
- }
+ void sGossipSelect(Player* player, uint32 menuId, uint32 gossipListId) override
+ {
+ if (menuId == GOSSIP_MENU_OPTION_INSPECT_BODY && gossipListId == GOSSIP_OPTION_ID_BEATEN_CORPSE)
+ {
+ player->CLOSE_GOSSIP_MENU();
+ player->TalkedToCreature(me->GetEntry(), me->GetGUID());
+ }
+ }
+ };
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return new npc_beaten_corpseAI(creature);
+ }
};
/*######
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
index ab09dd45710..3c11fd5d9a6 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp
@@ -454,11 +454,11 @@ public:
float distance = me->GetDistance(JedogaPosition[1]);
if (distance < 9.0f)
- me->SetSpeed(MOVE_WALK, 0.5f, true);
+ me->SetSpeedRate(MOVE_WALK, 0.5f);
else if (distance < 15.0f)
- me->SetSpeed(MOVE_WALK, 0.75f, true);
+ me->SetSpeedRate(MOVE_WALK, 0.75f);
else if (distance < 20.0f)
- me->SetSpeed(MOVE_WALK, 1.0f, true);
+ me->SetSpeedRate(MOVE_WALK, 1.0f);
me->GetMotionMaster()->Clear(false);
me->GetMotionMaster()->MovePoint(1, JedogaPosition[1]);
diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
index e25f64f61aa..04b62f77e9a 100644
--- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
+++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_prince_taldaram.cpp
@@ -178,7 +178,7 @@ class boss_prince_taldaram : public CreatureScript
if (Unit* embraceTarget = GetEmbraceTarget())
{
me->GetMotionMaster()->Clear();
- me->SetSpeed(MOVE_WALK, 2.0f, true);
+ me->SetSpeedRate(MOVE_WALK, 2.0f);
me->GetMotionMaster()->MoveChase(embraceTarget);
}
events.ScheduleEvent(EVENT_VANISHED, 1300);
@@ -188,7 +188,7 @@ class boss_prince_taldaram : public CreatureScript
DoCast(embraceTarget, SPELL_EMBRACE_OF_THE_VAMPYR);
Talk(SAY_FEED);
me->GetMotionMaster()->Clear();
- me->SetSpeed(MOVE_WALK, 1.0f, true);
+ me->SetSpeedRate(MOVE_WALK, 1.0f);
me->GetMotionMaster()->MoveChase(me->GetVictim());
events.ScheduleEvent(EVENT_FEEDING, 20000);
break;
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
index c89510211b9..7440984d7c5 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp
@@ -804,7 +804,7 @@ class npc_anubarak_spike : public CreatureScript
void StartChase(Unit* who)
{
DoCast(who, SPELL_MARK);
- me->SetSpeed(MOVE_RUN, 0.5f);
+ me->SetSpeedRate(MOVE_RUN, 0.5f);
// make sure the Spine will really follow the one he should
me->getThreatManager().clearReferences();
me->SetInCombatWithZone();
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 4c2b92da0ea..3ac85809fa2 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -2580,7 +2580,7 @@ class npc_quel_delar_sword : public CreatureScript
void Reset() override
{
_events.Reset();
- me->SetSpeed(MOVE_FLIGHT, 4.5f, true);
+ me->SetSpeedRate(MOVE_FLIGHT, 4.5f);
DoCast(SPELL_WHIRLWIND_VISUAL);
if (_intro)
_events.ScheduleEvent(EVENT_QUEL_DELAR_INIT, 0);
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp
index 03f12e46bc3..b24a36da3fb 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp
@@ -418,7 +418,7 @@ class boss_krick : public CreatureScript
case EVENT_OUTRO_6:
if (Creature* tyrannus = ObjectAccessor::GetCreature(*me, _instanceScript->GetGuidData(DATA_TYRANNUS_EVENT)))
{
- tyrannus->SetSpeed(MOVE_FLIGHT, 3.5f, true);
+ tyrannus->SetSpeedRate(MOVE_FLIGHT, 3.5f);
tyrannus->GetMotionMaster()->MovePoint(1, outroPos[4]);
_tyrannusGUID = tyrannus->GetGUID();
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
index 166e9739a95..51711f9ded5 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp
@@ -1069,7 +1069,7 @@ class npc_blood_queen_lana_thel : public CreatureScript
if (Creature* summon = DoSummon(NPC_FLOATING_TRIGGER, triggerPos, 15000, TEMPSUMMON_TIMED_DESPAWN))
{
summon->CastSpell(summon, SPELL_OOC_INVOCATION_VISUAL, true);
- summon->SetSpeed(MOVE_FLIGHT, 0.15f, true); // todo: creature is swimming, check if this is blizzlike or not.
+ summon->SetSpeedRate(MOVE_FLIGHT, 0.15f); // todo: creature is swimming, check if this is blizzlike or not.
summon->GetMotionMaster()->MovePoint(0, triggerEndPos);
}
}
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index 056231285e2..9f20799df82 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -142,7 +142,7 @@ class boss_lord_marrowgar : public CreatureScript
void Reset() override
{
_Reset();
- me->SetSpeed(MOVE_RUN, _baseSpeed, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed);
me->RemoveAurasDueToSpell(SPELL_BONE_STORM);
me->RemoveAurasDueToSpell(SPELL_BERSERK);
events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000);
@@ -224,7 +224,7 @@ class boss_lord_marrowgar : public CreatureScript
case EVENT_BONE_STORM_BEGIN:
if (Aura* pStorm = me->GetAura(SPELL_BONE_STORM))
pStorm->SetDuration(int32(_boneStormDuration));
- me->SetSpeed(MOVE_RUN, _baseSpeed*3.0f, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed*3.0f);
Talk(SAY_BONE_STORM);
events.ScheduleEvent(EVENT_BONE_STORM_END, _boneStormDuration+1);
// no break here
@@ -242,7 +242,7 @@ class boss_lord_marrowgar : public CreatureScript
if (me->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
me->GetMotionMaster()->MovementExpired();
me->GetMotionMaster()->MoveChase(me->GetVictim());
- me->SetSpeed(MOVE_RUN, _baseSpeed, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed);
events.CancelEvent(EVENT_BONE_STORM_MOVE);
events.ScheduleEvent(EVENT_ENABLE_BONE_SLICE, 10000);
if (!IsHeroic())
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
index 280a0aaa13a..fe6e4081326 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp
@@ -369,21 +369,21 @@ class boss_professor_putricide : public CreatureScript
{
case POINT_FESTERGUT:
instance->SetBossState(DATA_FESTERGUT, IN_PROGRESS); // needed here for delayed gate close
- me->SetSpeed(MOVE_RUN, _baseSpeed, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed);
DoAction(ACTION_FESTERGUT_GAS);
if (Creature* festergut = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FESTERGUT)))
festergut->CastSpell(festergut, SPELL_GASEOUS_BLIGHT_LARGE, false, NULL, NULL, festergut->GetGUID());
break;
case POINT_ROTFACE:
instance->SetBossState(DATA_ROTFACE, IN_PROGRESS); // needed here for delayed gate close
- me->SetSpeed(MOVE_RUN, _baseSpeed, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed);
DoAction(ACTION_ROTFACE_OOZE);
events.ScheduleEvent(EVENT_ROTFACE_OOZE_FLOOD, 25000, 0, PHASE_ROTFACE);
break;
case POINT_TABLE:
// stop attack
me->GetMotionMaster()->MoveIdle();
- me->SetSpeed(MOVE_RUN, _baseSpeed, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed);
if (GameObject* table = ObjectAccessor::GetGameObject(*me, instance->GetGuidData(DATA_PUTRICIDE_TABLE)))
me->SetFacingToObject(table);
// operating on new phase already
@@ -418,7 +418,7 @@ class boss_professor_putricide : public CreatureScript
{
case ACTION_FESTERGUT_COMBAT:
SetPhase(PHASE_FESTERGUT);
- me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f);
me->GetMotionMaster()->MovePoint(POINT_FESTERGUT, festergutWatchPos);
me->SetReactState(REACT_PASSIVE);
DoZoneInCombat(me);
@@ -435,7 +435,7 @@ class boss_professor_putricide : public CreatureScript
case ACTION_ROTFACE_COMBAT:
{
SetPhase(PHASE_ROTFACE);
- me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f);
me->GetMotionMaster()->MovePoint(POINT_ROTFACE, rotfaceWatchPos);
me->SetReactState(REACT_PASSIVE);
_oozeFloodStage = 0;
@@ -477,7 +477,7 @@ class boss_professor_putricide : public CreatureScript
events.ScheduleEvent(EVENT_ROTFACE_DIES, 4500, 0, PHASE_ROTFACE);
break;
case ACTION_CHANGE_PHASE:
- me->SetSpeed(MOVE_RUN, _baseSpeed*2.0f, true);
+ me->SetSpeedRate(MOVE_RUN, _baseSpeed*2.0f);
events.DelayEvents(30000);
me->AttackStop();
if (!IsHeroic())
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
index 0b129f3aa89..1a37d5238d2 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp
@@ -315,7 +315,7 @@ class boss_sindragosa : public CreatureScript
me->SetCanFly(true);
me->SetDisableGravity(true);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
- me->SetSpeed(MOVE_FLIGHT, 4.0f);
+ me->SetSpeedRate(MOVE_FLIGHT, 4.0f);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
float moveTime = me->GetExactDist(&SindragosaFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f);
me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SindragosaLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
@@ -351,7 +351,7 @@ class boss_sindragosa : public CreatureScript
me->RemoveByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
me->SetHomePosition(SindragosaLandPos);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->SetSpeed(MOVE_FLIGHT, 2.5f);
+ me->SetSpeedRate(MOVE_FLIGHT, 2.5f);
// Sindragosa enters combat as soon as she lands
DoZoneInCombat();
@@ -604,6 +604,7 @@ class npc_ice_tomb : public CreatureScript
_trappedPlayerGUID.Clear();
player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_DAMAGE);
player->RemoveAurasDueToSpell(SPELL_ASPHYXIATION);
+ player->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE);
}
}
@@ -697,7 +698,7 @@ class npc_spinestalker : public CreatureScript
return;
me->setActive(true);
- me->SetSpeed(MOVE_FLIGHT, 2.0f);
+ me->SetSpeedRate(MOVE_FLIGHT, 2.0f);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
float moveTime = me->GetExactDist(&SpinestalkerFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f);
me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, SpinestalkerLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
@@ -834,7 +835,7 @@ class npc_rimefang : public CreatureScript
return;
me->setActive(true);
- me->SetSpeed(MOVE_FLIGHT, 2.0f);
+ me->SetSpeedRate(MOVE_FLIGHT, 2.0f);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
float moveTime = me->GetExactDist(&RimefangFlyPos) / (me->GetSpeed(MOVE_FLIGHT) * 0.001f);
me->m_Events.AddEvent(new FrostwyrmLandEvent(*me, RimefangLandPos), me->m_Events.CalculateTime(uint64(moveTime) + 250));
@@ -1284,9 +1285,9 @@ class spell_sindragosa_ice_tomb : public SpellScriptLoader
public:
spell_sindragosa_ice_tomb() : SpellScriptLoader("spell_sindragosa_ice_tomb_trap") { }
- class spell_sindragosa_ice_tomb_SpellScript : public SpellScript
+ class spell_sindragosa_ice_tomb_AuraScript : public AuraScript
{
- PrepareSpellScript(spell_sindragosa_ice_tomb_SpellScript);
+ PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript);
bool Validate(SpellInfo const* /*spell*/) override
{
@@ -1297,46 +1298,42 @@ class spell_sindragosa_ice_tomb : public SpellScriptLoader
return true;
}
- void SummonTomb()
+ void PeriodicTick(AuraEffect const* aurEff)
{
- Position pos = GetHitUnit()->GetPosition();
- if (TempSummon* summon = GetCaster()->SummonCreature(NPC_ICE_TOMB, pos))
+ PreventDefaultAction();
+
+ if (aurEff->GetTickNumber() == 1)
{
- summon->AI()->SetGUID(GetHitUnit()->GetGUID(), DATA_TRAPPED_PLAYER);
- if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0))
+ if (Unit* caster = GetCaster())
{
- go->SetSpellId(SPELL_ICE_TOMB_DAMAGE);
- summon->AddGameObject(go);
+ Position pos = GetTarget()->GetPosition();
+
+ if (TempSummon* summon = caster->SummonCreature(NPC_ICE_TOMB, pos))
+ {
+ summon->AI()->SetGUID(GetTarget()->GetGUID(), DATA_TRAPPED_PLAYER);
+ GetTarget()->CastSpell(GetTarget(), SPELL_ICE_TOMB_UNTARGETABLE);
+ if (GameObject* go = summon->SummonGameObject(GO_ICE_BLOCK, pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), 0.0f, 0.0f, 0.0f, 0.0f, 0))
+ {
+ go->SetSpellId(SPELL_ICE_TOMB_DAMAGE);
+ summon->AddGameObject(go);
+ }
+ }
}
}
}
- void Register() override
- {
- AfterHit += SpellHitFn(spell_sindragosa_ice_tomb_SpellScript::SummonTomb);
- }
- };
-
- class spell_sindragosa_ice_tomb_AuraScript : public AuraScript
- {
- PrepareAuraScript(spell_sindragosa_ice_tomb_AuraScript);
-
- void PeriodicTick(AuraEffect const* /*aurEff*/)
+ void HandleRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
- PreventDefaultAction();
+ GetTarget()->RemoveAurasDueToSpell(SPELL_ICE_TOMB_UNTARGETABLE);
}
void Register() override
{
OnEffectPeriodic += AuraEffectPeriodicFn(spell_sindragosa_ice_tomb_AuraScript::PeriodicTick, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL);
+ AfterEffectRemove += AuraEffectRemoveFn(spell_sindragosa_ice_tomb_AuraScript::HandleRemove, EFFECT_2, SPELL_AURA_PERIODIC_TRIGGER_SPELL, AURA_EFFECT_HANDLE_REAL);
}
};
- SpellScript* GetSpellScript() const override
- {
- return new spell_sindragosa_ice_tomb_SpellScript();
- }
-
AuraScript* GetAuraScript() const override
{
return new spell_sindragosa_ice_tomb_AuraScript();
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
index 4675989228a..4a0a8217af8 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -763,7 +763,7 @@ class boss_the_lich_king : public CreatureScript
{
summons.Summon(summon);
summon->SetReactState(REACT_PASSIVE);
- summon->SetSpeed(MOVE_FLIGHT, 0.5f);
+ summon->SetSpeedRate(MOVE_FLIGHT, 0.5f);
summon->GetMotionMaster()->MoveRandom(10.0f);
if (!events.IsInPhase(PHASE_FROSTMOURNE))
summon->m_Events.AddEvent(new VileSpiritActivateEvent(summon), summon->m_Events.CalculateTime(15000));
@@ -1448,7 +1448,7 @@ class npc_valkyr_shadowguard : public CreatureScript
_events.Reset();
me->SetReactState(REACT_PASSIVE);
DoCast(me, SPELL_WINGS_OF_THE_DAMNED, false);
- me->SetSpeed(MOVE_FLIGHT, 0.642857f, true);
+ me->SetSpeedRate(MOVE_FLIGHT, 0.642857f);
}
void IsSummonedBy(Unit* /*summoner*/) override
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp
index ec47b0db101..ef6ccf5bf4b 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_gluth.cpp
@@ -18,38 +18,74 @@
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "naxxramas.h"
+#include "SpellScript.h"
+#include <math.h>
-enum Spells
+enum Texts
{
- SPELL_MORTAL_WOUND = 25646,
- SPELL_ENRAGE = 28371,
- SPELL_DECIMATE = 28374,
- SPELL_BERSERK = 26662,
- SPELL_INFECTED_WOUND = 29306
+ EMOTE_SPOTS_ONE = 0,
+ EMOTE_DECIMATE = 1,
+ EMOTE_ENRAGE = 2,
+ EMOTE_DEVOURS_ALL = 3,
+ EMOTE_BERSERKER = 4
};
-enum Creatures
+enum Spells
{
- NPC_ZOMBIE = 16360
+ // Gluth
+ SPELL_MORTAL_WOUND = 54378, // spell effect dummy unused. what its supposed to do is unkown.
+ SPELL_ENRAGE = 28371, // 54427 in 25 man.
+ SPELL_DECIMATE = 28374, // 54426 in 25 man. Effect0 is handled by SpellScript (see below) and 2 rows in conditions table. Effect2 is handled by SpellScript (see below).
+ SPELL_DECIMATE_DMG = 28375,
+ SPELL_BERSERK = 26662,
+ SPELL_ZOMBIE_CHOW_SEARCH_SINGLE = 28239, // Insta kill spell. Single target. See spell script below.
+ SPELL_ZOMBIE_CHOW_SEARCH_MULTI = 28404, // Insta kill spell. Affect all zombies 10 yards around Gluth's center. See one row conditions table + spell script below.
+
+ // Zombies
+ SPELL_INFECTED_WOUND = 29307 // Used by the zombies on self.
};
Position const PosSummon[3] =
{
- {3267.9f, -3172.1f, 297.42f, 0.94f},
- {3253.2f, -3132.3f, 297.42f, 0},
- {3308.3f, -3185.8f, 297.42f, 1.58f},
+ { 3270.132f, -3169.948f, 297.5891f, 5.88176f },
+ { 3307.298f, -3183.449f, 297.5891f, 5.742133f },
+ { 3255.708f, -3135.677f, 297.5891f, 1.867502f }
};
enum Events
{
- EVENT_WOUND = 1,
+ EVENT_WOUND = 1,
EVENT_ENRAGE,
EVENT_DECIMATE,
EVENT_BERSERK,
EVENT_SUMMON,
+ EVENT_SEARCH_ZOMBIE_SINGLE,
+ EVENT_KILL_ZOMBIE_SINGLE,
+ EVENT_SEARCH_ZOMBIE_MULTI
};
-#define EMOTE_NEARBY " spots a nearby zombie to devour!"
+enum States
+{
+ STATE_GLUTH_NORMAL = 1,
+ STATE_GLUTH_EATING = 2,
+
+ STATE_ZOMBIE_NORMAL = 1,
+ STATE_ZOMBIE_DECIMATED = 2,
+ STATE_ZOMBIE_TOBE_EATEN = 3
+};
+
+enum SummonGroups
+{
+ SUMMON_GROUP_CHOW_10MAN = 1,
+ SUMMON_GROUP_CHOW_25MAN = 2
+};
+
+enum Misc
+{
+ EVENT_GLUTH_ZOMBIE_BEHAVIOR = 10495, // unused. event handled by spell_gluth_decimate_SpellScript::HandleEvent
+ DATA_ZOMBIE_STATE = 1,
+ ACTION_DECIMATE_EVENT = 2,
+};
class boss_gluth : public CreatureScript
{
@@ -58,99 +94,388 @@ public:
CreatureAI* GetAI(Creature* creature) const override
{
- return new boss_gluthAI(creature);
+ return GetInstanceAI<boss_gluthAI>(creature);
}
struct boss_gluthAI : public BossAI
{
- boss_gluthAI(Creature* creature) : BossAI(creature, BOSS_GLUTH)
- {
- // Do not let Gluth be affected by zombies' debuff
- me->ApplySpellImmune(0, IMMUNITY_ID, SPELL_INFECTED_WOUND, true);
- }
- void MoveInLineOfSight(Unit* who) override
+ boss_gluthAI(Creature* creature) : BossAI(creature, BOSS_GLUTH), state(STATE_GLUTH_NORMAL) {}
+
+ void Reset() override
{
- if (who->GetEntry() == NPC_ZOMBIE && me->IsWithinDistInMap(who, 7))
- {
- SetGazeOn(who);
- /// @todo use a script text
- me->TextEmote(EMOTE_NEARBY, nullptr, true);
- }
- else
- BossAI::MoveInLineOfSight(who);
+ _Reset();
+ zombieToBeEatenGUID.Clear();
+ state = STATE_GLUTH_NORMAL;
+ me->SetReactState(REACT_AGGRESSIVE);
+ me->SetSpeed(UnitMoveType::MOVE_RUN, 12.0f);
}
void EnterCombat(Unit* /*who*/) override
{
_EnterCombat();
- events.ScheduleEvent(EVENT_WOUND, 10000);
- events.ScheduleEvent(EVENT_ENRAGE, 15000);
- events.ScheduleEvent(EVENT_DECIMATE, 105000);
- events.ScheduleEvent(EVENT_BERSERK, 8*60000);
- events.ScheduleEvent(EVENT_SUMMON, 15000);
+ events.ScheduleEvent(EVENT_WOUND, Seconds(10));
+ events.ScheduleEvent(EVENT_ENRAGE, randtime(Seconds(16), Seconds(22)));
+ events.ScheduleEvent(EVENT_DECIMATE, randtime(Minutes(1)+Seconds(50), Minutes(2)));
+ events.ScheduleEvent(EVENT_BERSERK, Minutes(8));
+ events.ScheduleEvent(EVENT_SUMMON, Seconds(15));
+ events.ScheduleEvent(EVENT_SEARCH_ZOMBIE_SINGLE, Seconds(12));
}
- void JustSummoned(Creature* summon) override
+ void SummonedCreatureDies(Creature* summoned, Unit* /* who */) override
{
- if (summon->GetEntry() == NPC_ZOMBIE)
- summon->AI()->AttackStart(me);
- summons.Summon(summon);
+ summons.Despawn(summoned); // needed or else dead zombies not despawned yet will still be in the list
}
void UpdateAI(uint32 diff) override
{
- if (!UpdateVictimWithGaze())
+ if (!UpdateVictim() || !CheckInRoom())
return;
events.Update(diff);
+ if (me->HasUnitState(UNIT_STATE_CASTING))
+ return;
+
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_WOUND:
+ if (state == STATE_GLUTH_EATING)
+ {
+ events.Repeat(Seconds(3));
+ break;
+ }
+
DoCastVictim(SPELL_MORTAL_WOUND);
- events.ScheduleEvent(EVENT_WOUND, 10000);
+ events.Repeat(Seconds(10));
break;
case EVENT_ENRAGE:
- /// @todo Add missing text
+ if (state == STATE_GLUTH_EATING)
+ {
+ events.Repeat(Seconds(5));
+ break;
+ }
+
+ Talk(EMOTE_ENRAGE);
DoCast(me, SPELL_ENRAGE);
- events.ScheduleEvent(EVENT_ENRAGE, 15000);
+ events.Repeat(randtime(Seconds(16), Seconds(22)));
break;
case EVENT_DECIMATE:
- /// @todo Add missing text
+ if (state == STATE_GLUTH_EATING)
+ {
+ events.Repeat(Seconds(4));
+ break;
+ }
+
+ Talk(EMOTE_DECIMATE);
DoCastAOE(SPELL_DECIMATE);
- events.ScheduleEvent(EVENT_DECIMATE, 105000);
+ for (int i = 1; i <= 20; i++)
+ events.ScheduleEvent(EVENT_SEARCH_ZOMBIE_MULTI, Seconds(3*i));
+ events.ScheduleEvent(EVENT_DECIMATE, randtime(Minutes(1)+Seconds(50), Minutes(2)));
break;
case EVENT_BERSERK:
+ Talk(EMOTE_BERSERKER);
DoCast(me, SPELL_BERSERK);
- events.ScheduleEvent(EVENT_BERSERK, 5*60000);
+ events.Repeat(Minutes(5)); //refresh the hard enrage buff
break;
case EVENT_SUMMON:
- for (int32 i = 0; i < RAID_MODE(1, 2); ++i)
- DoSummon(NPC_ZOMBIE, PosSummon[rand32() % RAID_MODE(1, 3)]);
- events.ScheduleEvent(EVENT_SUMMON, 10000);
+ if (Is25ManRaid()) // one wave each 10s. one wave=1 zombie in 10man and 2 zombies in 25man.
+ me->SummonCreatureGroup(SUMMON_GROUP_CHOW_25MAN);
+ else
+ me->SummonCreatureGroup(SUMMON_GROUP_CHOW_10MAN);
+ events.Repeat(Seconds(10));
+ break;
+ case EVENT_SEARCH_ZOMBIE_SINGLE:
+ {
+ Creature* zombie = nullptr;
+ for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr)
+ {
+ zombie=ObjectAccessor::GetCreature(*me, *itr);
+ if (!zombie || !zombie->IsAlive() || !zombie->IsWithinDistInMap(me, 10.0))
+ zombie = nullptr;
+ }
+
+ if (zombie)
+ {
+ zombieToBeEatenGUID = zombie->GetGUID(); // save for later use
+
+ // the soon-to-be-eaten zombie should stop moving and stop attacking
+ zombie->AI()->SetData(DATA_ZOMBIE_STATE, STATE_ZOMBIE_TOBE_EATEN);
+
+ // gluth should stop AAs on his primary target and turn toward the zombie (2 yards away). He then pauses for a few seconds.
+ me->SetSpeed(MOVE_RUN, 36.0f);
+
+ me->SetReactState(ReactStates::REACT_PASSIVE);
+ me->AttackStop();
+
+ Talk(EMOTE_SPOTS_ONE);
+
+ //me->SetTarget(ObjectGuid::Empty);
+
+ me->GetMotionMaster()->MoveCloserAndStop(1, zombie, 2.0f);
+
+ state = STATE_GLUTH_EATING;
+ }
+
+ events.Repeat(RAID_MODE(Seconds(7), Seconds(5)));
+ break;
+ }
+ case EVENT_KILL_ZOMBIE_SINGLE:
+ {
+ Creature* zombieToBeEaten = ObjectAccessor::GetCreature(*me, zombieToBeEatenGUID);
+ if (zombieToBeEaten && zombieToBeEaten->IsAlive() && zombieToBeEaten->IsWithinDistInMap(me, 10.0))
+ DoCast(zombieToBeEaten, SPELL_ZOMBIE_CHOW_SEARCH_SINGLE); // do the killing + healing in done inside by spell script see below.
+
+ zombieToBeEatenGUID = ObjectGuid::Empty;
+ state = STATE_GLUTH_NORMAL;
+ me->SetSpeed(UnitMoveType::MOVE_RUN, 12.0f);
+
+ // and then return on primary target
+ me->SetReactState(REACT_AGGRESSIVE);
+
+ break;
+ }
+ case EVENT_SEARCH_ZOMBIE_MULTI:
+ {
+ if (state == STATE_GLUTH_EATING) // skip and simply wait for the next occurence
+ break;
+
+ Creature* zombie = nullptr;
+ for (SummonList::const_iterator itr = summons.begin(); !zombie && itr != summons.end(); ++itr)
+ {
+ zombie = ObjectAccessor::GetCreature(*me, *itr);
+ if (zombie && zombie->IsAlive() && zombie->GetExactDist2d(me) > 18.0)
+ zombie = nullptr;
+ }
+
+ if (zombie) // cast the aoe spell only if at least one zombie is found nearby
+ {
+ Talk(EMOTE_DEVOURS_ALL);
+ DoCastAOE(SPELL_ZOMBIE_CHOW_SEARCH_MULTI);
+ }
break;
+ }
}
}
- if (me->GetVictim() && me->EnsureVictim()->GetEntry() == NPC_ZOMBIE)
+ DoMeleeAttackIfReady();
+ }
+
+ void MovementInform(uint32 /*type*/, uint32 id) override
+ {
+ if (id == 1){
+ me->GetMotionMaster()->MoveIdle();
+ events.ScheduleEvent(EVENT_KILL_ZOMBIE_SINGLE, Seconds(1));
+ }
+
+ }
+
+ void DoAction(int32 action) override
+ {
+ switch (action)
+ {
+ case ACTION_DECIMATE_EVENT:
+ for (ObjectGuid zombieGuid : summons)
+ {
+ Creature* zombie = ObjectAccessor::GetCreature(*me, zombieGuid);
+ if (zombie && zombie->IsAlive())
+ zombie->AI()->SetData(DATA_ZOMBIE_STATE, STATE_ZOMBIE_DECIMATED);
+ }
+ break;
+ }
+ }
+
+ private:
+ ObjectGuid zombieToBeEatenGUID;
+ uint8 state;
+ };
+
+};
+
+// spell 28374 (10man) / 54426 (25man) - Decimate
+class spell_gluth_decimate : public SpellScriptLoader
+{
+public:
+ spell_gluth_decimate() : SpellScriptLoader("spell_gluth_decimate") { }
+
+ class spell_gluth_decimate_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gluth_decimate_SpellScript);
+
+ // handles the damaging effect of the decimate spell.
+ void HandleScriptEffect(SpellEffIndex /* index */)
+ {
+ if (Unit *unit = GetHitUnit())
{
- if (me->IsWithinMeleeRange(me->GetVictim()))
+ int32 damage = int32(unit->GetHealth()) - int32(unit->CountPctFromMaxHealth(5));
+ if (damage > 0)
+ GetCaster()->CastCustomSpell(SPELL_DECIMATE_DMG, SPELLVALUE_BASE_POINT0, damage, unit);
+ }
+ }
+
+ // handles the change of zombies behavior after the decimate spell
+ void HandleEvent(SpellEffIndex /* index */)
+ {
+ GetCaster()->GetAI()->DoAction(ACTION_DECIMATE_EVENT);
+ }
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ return (sSpellMgr->GetSpellInfo(SPELL_DECIMATE_DMG) != nullptr);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gluth_decimate_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHit += SpellEffectFn(spell_gluth_decimate_SpellScript::HandleEvent, EFFECT_2, SPELL_EFFECT_SEND_EVENT);
+ }
+
+ bool Load() override
+ {
+ return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH;
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_gluth_decimate_SpellScript();
+ }
+
+};
+
+// used by both 28239 & 28404 (single target and aoe zombie-kill spell) to heal Gluth on each target hit.
+
+class spell_gluth_zombiechow_search : public SpellScriptLoader
+{
+public:
+ spell_gluth_zombiechow_search() : SpellScriptLoader("spell_gluth_zombiechow_search") { }
+
+ class spell_gluth_zombiechow_search_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gluth_zombiechow_search_SpellScript);
+
+ void HealForEachTargetHit()
+ {
+ GetCaster()->ModifyHealth(int32(GetCaster()->CountPctFromMaxHealth(5)));
+ }
+
+ void Register() override
+ {
+ AfterHit += SpellHitFn(spell_gluth_zombiechow_search_SpellScript::HealForEachTargetHit);
+ }
+
+ bool Load() override
+ {
+ return GetCaster() && GetCaster()->GetEntry() == NPC_GLUTH;
+ }
+ };
+
+ SpellScript* GetSpellScript() const
+ {
+ return new spell_gluth_zombiechow_search_SpellScript();
+ }
+
+};
+
+// creature 16360 (10man) / 30303 (25man)
+class npc_zombie_chow : public CreatureScript
+{
+public:
+
+ npc_zombie_chow() : CreatureScript("npc_zombie_chow") { }
+
+ struct npc_zombie_chowAI : public ScriptedAI
+ {
+ npc_zombie_chowAI(Creature* creature) : ScriptedAI(creature)
+ {
+ GluthGUID = creature->GetInstanceScript()->GetGuidData(DATA_GLUTH);
+
+ DoCast(me, SPELL_INFECTED_WOUND);
+ timer = 0;
+ state = STATE_ZOMBIE_NORMAL;
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ if (state == STATE_ZOMBIE_DECIMATED)
+ {
+ timer += diff;
+ Creature* gluth = ObjectAccessor::GetCreature(*me, GluthGUID);
+ // Putting this in the UpdateAI loop fixes an issue where death gripping a decimated zombie would make the zombie stand still until the rest of the fight.
+ // Also fix the issue where if one or more zombie is rooted when decimates hits (and MovePoint() is called), the zombie teleport to the boss. pretty weird behavior.
+ if (gluth && timer>1600 && me->GetExactDist2d(gluth) > 10.0 && me->CanFreeMove()) // it takes about 1600 ms for the animation to cycle. This way, the animation looks relatively smooth.
{
- me->Kill(me->GetVictim());
- me->ModifyHealth(int32(me->CountPctFromMaxHealth(5)));
+ me->GetMotionMaster()->MovePoint(0, gluth->GetPosition()); // isn't dynamic. So, to take into account Gluth's movement, it must be called periodicly.
+ timer = 0;
}
+
+ if (me->GetExactDist2d(gluth) <= 10.0)
+ me->StopMoving();
}
- else
+ else if (state == STATE_ZOMBIE_NORMAL)
DoMeleeAttackIfReady();
}
+
+ void SetData(uint32 id, uint32 value) override
+ {
+ if (id == DATA_ZOMBIE_STATE) // change of state
+ {
+ state = value;
+ if (value == STATE_ZOMBIE_DECIMATED)
+ {
+ me->SetReactState(ReactStates::REACT_PASSIVE);
+ me->AttackStop();
+ me->SetTarget(ObjectGuid::Empty);
+ // at this point, the zombie should be non attacking and non moving.
+
+ me->SetWalk(true); // it doesnt seem to work with MoveFollow() (but it does work with MovePoint()).
+
+ timer = 1000;
+ }
+ else if (value == STATE_ZOMBIE_TOBE_EATEN)
+ {
+ // forced to stand still
+ me->GetMotionMaster()->Clear();
+ me->StopMoving();
+
+ // and loose aggro behavior
+ me->SetReactState(ReactStates::REACT_PASSIVE);
+ me->AttackStop();
+ me->SetTarget(ObjectGuid::Empty);
+
+ me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_GRIP, true); // not sure if this is blizz-like but this is very convenient
+ }
+ }
+ }
+
+ uint32 GetData(uint32 index) const override
+ {
+ if (index == DATA_ZOMBIE_STATE)
+ return state;
+ return 0;
+ }
+
+ private:
+ uint32 timer;
+ uint8 state;
+ ObjectGuid GluthGUID;
};
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_zombie_chowAI>(creature);
+ }
};
void AddSC_boss_gluth()
{
new boss_gluth();
+ new spell_gluth_decimate();
+ new spell_gluth_zombiechow_search();
+ new npc_zombie_chow();
}
diff --git a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
index 02b82d255cd..e3971248513 100644
--- a/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/instance_naxxramas.cpp
@@ -153,6 +153,9 @@ class instance_naxxramas : public InstanceMapScript
case NPC_SIR:
SirGUID = creature->GetGUID();
break;
+ case NPC_GLUTH:
+ GluthGUID = creature->GetGUID();
+ break;
case NPC_HEIGAN:
HeiganGUID = creature->GetGUID();
break;
@@ -327,6 +330,8 @@ class instance_naxxramas : public InstanceMapScript
return SirGUID;
case DATA_HEIGAN:
return HeiganGUID;
+ case DATA_GLUTH:
+ return GluthGUID;
case DATA_FEUGEN:
return FeugenGUID;
case DATA_STALAGG:
@@ -582,6 +587,8 @@ class instance_naxxramas : public InstanceMapScript
ObjectGuid HorsemenChestGUID;
/* The Construct Quarter */
+ // Gluth
+ ObjectGuid GluthGUID;
// Thaddius
ObjectGuid ThaddiusGUID;
ObjectGuid FeugenGUID;
diff --git a/src/server/scripts/Northrend/Naxxramas/naxxramas.h b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
index bece5a60bee..a3fedf5aa40 100644
--- a/src/server/scripts/Northrend/Naxxramas/naxxramas.h
+++ b/src/server/scripts/Northrend/Naxxramas/naxxramas.h
@@ -68,6 +68,7 @@ enum Data64
DATA_LADY,
DATA_BARON,
DATA_SIR,
+ DATA_GLUTH,
DATA_THADDIUS,
DATA_HEIGAN,
DATA_FEUGEN,
@@ -92,6 +93,7 @@ enum CreaturesIds
NPC_LADY = 16065,
NPC_BARON = 30549,
NPC_SIR = 16063,
+ NPC_GLUTH = 15932,
NPC_HEIGAN = 15936,
NPC_THADDIUS = 15928,
NPC_FEUGEN = 15930,
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index 277ca793a8f..3d5a6ee8dfb 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -377,7 +377,7 @@ public:
me->SetDisableGravity(true);
me->SetByteFlag(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_HOVER);
// TO DO: find what in core is making boss slower than in retail (when correct speed data) or find missing movement flag update or forced spline change
- me->SetSpeed(MOVE_FLIGHT, _flySpeed * 0.25f);
+ me->SetSpeedRate(MOVE_FLIGHT, _flySpeed * 0.25f);
if (_despawned)
DoAction(ACTION_HANDLE_RESPAWN);
@@ -603,7 +603,7 @@ public:
me->SetRespawnDelay(respawnDelay);
// Set speed to normal value
- me->SetSpeed(MOVE_FLIGHT, _flySpeed);
+ me->SetSpeedRate(MOVE_FLIGHT, _flySpeed);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
me->RemoveAllAuras();
@@ -1165,7 +1165,7 @@ public:
_instance = creature->GetInstanceScript();
me->SetReactState(REACT_PASSIVE);
// TO DO: These were a bit faster than what they should be. Not sure what is the reason.
- me->SetSpeed(MOVE_FLIGHT, 1.25f);
+ me->SetSpeedRate(MOVE_FLIGHT, 1.25f);
}
void Initialize()
@@ -1224,13 +1224,15 @@ public:
void DoAction(int32 /*action*/) override
{
if (Vehicle* vehicleTemp = me->GetVehicleKit())
+ {
if (vehicleTemp->GetPassenger(0) && vehicleTemp->GetPassenger(0)->GetTypeId() == TYPEID_PLAYER)
{
vehicleTemp->RemoveAllPassengers();
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
+ }
- me->DespawnOrUnsummon(3*IN_MILLISECONDS);
+ me->DespawnOrUnsummon(3*IN_MILLISECONDS);
}
void MovementInform(uint32 type, uint32 id) override
@@ -1274,7 +1276,7 @@ public:
me->SetReactState(REACT_PASSIVE);
// TO DO: Something is wrong with calculations for flying creatures that are on WP/Cyclic path.
// They should get the same difference as to when at ground from run creature switch to walk.
- me->SetSpeed(MOVE_FLIGHT, 0.45f);
+ me->SetSpeedRate(MOVE_FLIGHT, 0.45f);
}
void Reset() override
@@ -1566,7 +1568,7 @@ public:
{
me->DespawnOrUnsummon(2050);
me->SetOrientation(2.5f);
- me->SetSpeed(MOVE_FLIGHT, 1.0f, true);
+ me->SetSpeedRate(MOVE_FLIGHT, 1.0f);
Position pos = me->GetPosition();
pos.m_positionX += 10.0f;
pos.m_positionY += 10.0f;
diff --git a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
index e1a4a6ed7b8..3d9ea97b136 100644
--- a/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
+++ b/src/server/scripts/Northrend/Nexus/Oculus/oculus.cpp
@@ -375,7 +375,7 @@ class npc_ruby_emerald_amber_drake : public CreatureScript
{
me->DespawnOrUnsummon(2050);
me->SetOrientation(2.5f);
- me->SetSpeed(MOVE_FLIGHT, 1.0f, true);
+ me->SetSpeedRate(MOVE_FLIGHT, 1.0f);
Talk(SAY_DRAKES_TAKEOFF);
Position pos = me->GetPosition();
Position offset = { 10.0f, 10.0f, 12.0f, 0.0f };
diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
index a98da2c6e3d..8f7687d0fca 100644
--- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
+++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_ionar.cpp
@@ -174,7 +174,7 @@ public:
{
if (pSpark->IsAlive())
{
- pSpark->SetSpeed(MOVE_RUN, 2.0f);
+ pSpark->SetSpeedRate(MOVE_RUN, 2.0f);
pSpark->GetMotionMaster()->Clear();
pSpark->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos);
}
@@ -355,7 +355,7 @@ public:
{
Position pos = ionar->GetPosition();
- me->SetSpeed(MOVE_RUN, 2.0f);
+ me->SetSpeedRate(MOVE_RUN, 2.0f);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(DATA_POINT_CALLBACK, pos);
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
index 0714f2426bc..8aa443cba3f 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp
@@ -703,7 +703,7 @@ class boss_leviathan_mk_ii : public CreatureScript
if (Unit* turret = me->GetVehicleKit()->GetPassenger(3))
turret->KillSelf();
- me->SetSpeed(MOVE_RUN, 1.5f, true);
+ me->SetSpeedRate(MOVE_RUN, 1.5f);
me->GetMotionMaster()->MovePoint(WP_MKII_P1_IDLE, VehicleRelocation[WP_MKII_P1_IDLE]);
}
else if (events.IsInPhase(PHASE_VOL7RON))
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
index f5337b2dca5..363f5907048 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
@@ -366,7 +366,7 @@ class boss_razorscale : public CreatureScript
_EnterCombat();
if (Creature* controller = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_RAZORSCALE_CONTROL)))
controller->AI()->DoAction(ACTION_HARPOON_BUILD);
- me->SetSpeed(MOVE_FLIGHT, 3.0f, true);
+ me->SetSpeedRate(MOVE_FLIGHT, 3.0f);
me->SetReactState(REACT_PASSIVE);
phase = PHASE_GROUND;
events.SetPhase(PHASE_GROUND);
@@ -550,7 +550,7 @@ class boss_razorscale : public CreatureScript
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED);
me->SetReactState(REACT_AGGRESSIVE);
me->RemoveAurasDueToSpell(SPELL_HARPOON_TRIGGER);
- me->SetSpeed(MOVE_FLIGHT, 1.0f, true);
+ me->SetSpeedRate(MOVE_FLIGHT, 1.0f);
PermaGround = true;
DoCastAOE(SPELL_FLAMEBREATH);
events.ScheduleEvent(EVENT_FLAME, 15000, 0, PHASE_PERMAGROUND);
@@ -677,7 +677,7 @@ class npc_expedition_commander : public CreatureScript
if (Creature* summonedEngineer = me->SummonCreature(NPC_ENGINEER, PosEngSpawn, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 3000))
{
summonedEngineer->SetWalk(false);
- summonedEngineer->SetSpeed(MOVE_RUN, 0.5f);
+ summonedEngineer->SetSpeedRate(MOVE_RUN, 0.5f);
summonedEngineer->SetHomePosition(PosEngRepair[n]);
summonedEngineer->GetMotionMaster()->MoveTargetedHome();
Engineer[n] = summonedEngineer->GetGUID();
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp
index 1af45f3031a..3dec0c60991 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_palehoof.cpp
@@ -102,7 +102,7 @@ public:
Sequence[i] = Phase(i);
/// This ensures a random order and only executes each phase once.
- std::random_shuffle(Sequence, Sequence + PHASE_GORTOK_PALEHOOF);
+ Trinity::Containers::RandomShuffle(Sequence);
uiArcingSmashTimer = 15000;
uiImpaleTimer = 12000;
@@ -118,7 +118,7 @@ public:
uint32 uiWhiteringRoarTimer;
Phase currentPhase;
uint8 AddCount;
- Phase Sequence[4];
+ std::array<Phase, 4> Sequence;
void Reset() override
{
@@ -746,7 +746,7 @@ public:
//! HACK: Creature's can't have MOVEMENTFLAG_FLYING
me->AddUnitMovementFlag(MOVEMENTFLAG_FLYING);
me->RemoveAurasDueToSpell(SPELL_ORB_VISUAL);
- me->SetSpeed(MOVE_FLIGHT, 0.5f);
+ me->SetSpeedRate(MOVE_FLIGHT, 0.5f);
}
void UpdateAI(uint32 diff) override
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
index d7b65093898..7615217a794 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp
@@ -209,7 +209,7 @@ public:
Initialize();
Summons.DespawnAll();
- me->SetSpeed(MOVE_FLIGHT, 3.0f);
+ me->SetSpeedRate(MOVE_FLIGHT, 3.0f);
if ((ObjectAccessor::GetCreature(*me, m_uiGraufGUID) == NULL) && !me->IsMounted())
me->SummonCreature(NPC_GRAUF, Location[0].GetPositionX(), Location[0].GetPositionY(), Location[0].GetPositionZ(), 3.0f);
instance->SetBossState(DATA_SKADI_THE_RUTHLESS, NOT_STARTED);
diff --git a/src/server/scripts/Northrend/zone_icecrown.cpp b/src/server/scripts/Northrend/zone_icecrown.cpp
index 1e020edd10a..3d801cc2fbb 100644
--- a/src/server/scripts/Northrend/zone_icecrown.cpp
+++ b/src/server/scripts/Northrend/zone_icecrown.cpp
@@ -712,7 +712,7 @@ enum BorrowedTechnologyAndVolatility
SPELL_PING_BUNNY = 59375,
SPELL_IMMOLATION = 54690,
SPELL_EXPLOSION = 59335,
- SPELL_RIDE = 56687,
+ SPELL_RIDE = 59319,
// Points
POINT_GRAB_DECOY = 1,
diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
index 7902c585509..14aeda04a7e 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp
@@ -745,7 +745,7 @@ public:
if (!Trigger)
return;
- Trigger->SetSpeed(MOVE_WALK, 3);
+ Trigger->SetSpeedRate(MOVE_WALK, 3);
Trigger->SetWalk(true);
Trigger->GetMotionMaster()->MovePoint(0, final.x, final.y, final.z);
@@ -1301,15 +1301,17 @@ public:
EventMaiev Event = EVENT_MAIEV_NULL;
for (uint8 i = 1; i <= MaxTimer; ++i)
+ {
if (Timer[i])
{
if (Timer[i] <= diff)
Event = (EventMaiev)i;
else Timer[i] -= diff;
}
+ }
- switch (Event)
- {
+ switch (Event)
+ {
case EVENT_MAIEV_STEALTH:
{
me->SetFullHealth();
@@ -1345,21 +1347,21 @@ public:
break;
default:
break;
- }
+ }
- if (HealthBelowPct(50))
- {
- me->SetVisible(false);
- me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
- ENSURE_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID());
- me->AttackStop();
- Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute
- MaxTimer = 1;
- }
+ if (HealthBelowPct(50))
+ {
+ me->SetVisible(false);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
+ if (Creature* illidan = ObjectAccessor::GetCreature(*me, IllidanGUID))
+ ENSURE_AI(boss_illidan_stormrage::boss_illidan_stormrageAI, illidan->AI())->DeleteFromThreatList(me->GetGUID());
+ me->AttackStop();
+ Timer[EVENT_MAIEV_STEALTH] = 60000; // reappear after 1 minute
+ MaxTimer = 1;
+ }
- if (Phase == PHASE_NORMAL_MAIEV)
- DoMeleeAttackIfReady();
+ if (Phase == PHASE_NORMAL_MAIEV)
+ DoMeleeAttackIfReady();
}
private:
@@ -1524,7 +1526,7 @@ public:
void BeginWalk()
{
me->SetWalk(false);
- me->SetSpeed(MOVE_RUN, 1.0f);
+ me->SetSpeedRate(MOVE_RUN, 1.0f);
me->GetMotionMaster()->MovePoint(0, AkamaWP[WalkCount].x, AkamaWP[WalkCount].y, AkamaWP[WalkCount].z);
}
diff --git a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
index 7e1215488e1..1a9074c2464 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_shade_of_akama.cpp
@@ -238,8 +238,8 @@ public:
if (me->GetAuraCount(SPELL_SHADE_SOUL_CHANNEL_2) <= 3)
{
moveSpeed = (2.0f - (0.6f * me->GetAuraCount(SPELL_SHADE_SOUL_CHANNEL_2)));
- me->SetSpeed(MOVE_WALK, moveSpeed / 2.5f);
- me->SetSpeed(MOVE_RUN, (moveSpeed * 2) / 7);
+ me->SetSpeedRate(MOVE_WALK, moveSpeed / 2.5f);
+ me->SetSpeedRate(MOVE_RUN, (moveSpeed * 2) / 7);
me->ClearUnitState(UNIT_STATE_ROOT);
}
else
diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
index ae4d17bdad4..0999f1fcd6b 100644
--- a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
+++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp
@@ -117,7 +117,7 @@ public:
DummyEntryCheckPredicate pred;
summons.DoAction(EVENT_VOLCANO, pred);
events.ScheduleEvent(EVENT_HATEFUL_STRIKE, 5000, GCD_CAST, PHASE_STRIKE);
- me->SetSpeed(MOVE_RUN, 1.2f);
+ me->SetSpeedRate(MOVE_RUN, 1.2f);
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, false);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, false);
}
@@ -126,7 +126,7 @@ public:
phase = PHASE_CHASE;
events.ScheduleEvent(EVENT_VOLCANO, 5000, GCD_CAST, PHASE_CHASE);
events.ScheduleEvent(EVENT_SWITCH_TARGET, 10000, 0, PHASE_CHASE);
- me->SetSpeed(MOVE_RUN, 0.9f);
+ me->SetSpeedRate(MOVE_RUN, 0.9f);
me->ApplySpellImmune(0, IMMUNITY_STATE, SPELL_AURA_MOD_TAUNT, true);
me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true);
}
diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp
index e24499c3aee..3ddf0fec416 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp
@@ -585,8 +585,8 @@ public:
void Reset() override
{
- me->SetSpeed(MOVE_WALK, 0.6f); // walk
- me->SetSpeed(MOVE_RUN, 0.6f); // run
+ me->SetSpeedRate(MOVE_WALK, 0.6f); // walk
+ me->SetSpeedRate(MOVE_RUN, 0.6f); // run
Initialize();
//search for nearest waypoint (up on stairs)
diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
index 8d117f7c3ef..f72b9a8d2ca 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp
@@ -244,7 +244,7 @@ public:
CheckChannelers();
Initialize();
me->SetCanDualWield(true);
- me->SetSpeed(MOVE_RUN, 2.0f, true);
+ me->SetSpeedRate(MOVE_RUN, 2.0f);
me->SetDisplayId(MODEL_NIGHTELF);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID , 0);
me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID+1, 0);
diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp
new file mode 100644
index 00000000000..89b7a8cbd46
--- /dev/null
+++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/boss_ahune.cpp
@@ -0,0 +1,1052 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "CreatureTextMgr.h"
+#include "LFGMgr.h"
+#include "ScriptedGossip.h"
+#include "ScriptedCreature.h"
+#include "ScriptMgr.h"
+#include "SpellAuraEffects.h"
+#include "SpellScript.h"
+#include "the_slave_pens.h"
+
+enum Spells
+{
+ // Ahune
+ SPELL_SYNCH_HEALTH = 46430,
+ SPELL_AHUNES_SHIELD = 45954,
+ SPELL_STAY_SUBMERGED = 46981,
+ SPELL_AHUNE_SELF_STUN = 46416,
+ SPELL_AHUNE_ACHIEVEMENT = 62043,
+ SPELL_AHUNE_SPANKY_HANDS = 46146,
+ SPELL_COLD_SLAP = 46145,
+ SPELL_RESURFACE = 46402,
+ SPELL_SUBMERGED = 37751,
+ SPELL_STAND = 37752,
+
+ //Earther Ring Flamecaller
+ SPELL_FIND_OPENING_VISUAL = 45964,
+ SPELL_FIND_OPENING_BEAM_END = 46333,
+ SPELL_FIND_OPENING_TRIGGER = 46341,
+ SPELL_FIND_OPENING_CHANNEL = 46345,
+ SPELL_BONFIRE_VISUAL = 46339,
+ SPELL_FOUND_OPENING = 46421,
+
+ //Ahune Bunny
+ SPELL_SUMMON_COLDWEAVE = 46143,
+ SPELL_SUMMON_FROSTWIND = 46382,
+ SPELL_SUMMON_HAILSTONE = 46176,
+ SPELL_SUMMONING_VISUAL_1 = 45937,
+ SPELL_SUMMONING_RHYME_AURA = 45926,
+ SPELL_SUMMONING_RHYME_BONFIRE = 45930,
+ SPELL_FORCE_WHISP_FLIGHT = 46603,
+ SPELL_SHAMANS_LOOK_FOR_OPENING = 46422,
+ SPELL_CLOSE_OPENING_VISUAL = 46236,
+ SPELL_ICE_BOMBARD = 46397,
+ SPELL_ICE_BOMBARDMENT_DEST_PICKER = 46398,
+ SPELL_ICE_BOMBARDMENT = 46396,
+
+ // Ice Spear
+ SPELL_SUMMON_ICE_SPEAR_BUNNY = 46359,
+ SPELL_ICE_SPEAR_KNOCKBACK = 46360,
+ SPELL_SUMMON_ICE_SPEAR_GO = 46369,
+ SPELL_ICE_SPEAR_AURA = 46371,
+ SPELL_ICE_SPEAR_TARGET_PICKER = 46372,
+ SPELL_ICE_SPEAR_DELAY = 46878,
+ SPELL_ICE_SPEAR_VISUAL = 75498,
+
+ // Slippery Floor
+ SPELL_SLIPPERY_FLOOR_AMBIENT = 46314,
+ SPELL_SLIPPERY_FLOOR_PERIODIC = 46320,
+ SPELL_SLIPPERY_FLOOR_SLIP = 45947,
+
+ // Frozen Core
+ SPELL_SUICIDE = 45254,
+ SPELL_SUMMON_LOOT_MISSILE = 45941,
+ SPELL_FROZEN_CORE_GETS_HIT = 46810,
+ SPELL_MINION_DESPAWNER = 46843,
+ SPELL_GHOST_DISGUISE = 46786
+};
+
+enum Emotes
+{
+ EMOTE_EARTHEN_ASSAULT = 0,
+ EMOTE_RETREAT = 0,
+ EMOTE_RESURFACE = 1
+};
+
+enum Says
+{
+ SAY_PLAYER_TEXT_1 = 0,
+ SAY_PLAYER_TEXT_2 = 1,
+ SAY_PLAYER_TEXT_3 = 2
+};
+
+enum Events
+{
+ EVENT_EMERGE = 1,
+ EVENT_INITIAL_EMERGE = 2,
+ EVENT_SYNCH_HEALTH = 3,
+ EVENT_FOUND_OPENING = 4,
+ EVENT_LOOKFOROPENING_0 = 5,
+ EVENT_LOOKFOROPENING_1 = 6,
+ EVENT_LOOKFOROPENING_2 = 7,
+ EVENT_SUMMON_HAILSTONE = 8,
+ EVENT_SUMMON_COLDWEAVE = 9,
+ EVENT_SUMMON_FROSTWIND = 10,
+ EVENT_SUMMON_AHUNE = 11,
+ EVENT_CLOSE_OPENING = 12,
+ EVENT_AHUNE_PHASE_ONE = 13,
+ EVENT_AHUNE_PHASE_TWO = 14,
+ EVENT_START_LOOKING_FOR_OPENING = 15,
+ EVENT_STOP_LOOKING_FOR_OPENING = 16
+};
+
+enum Actions
+{
+ ACTION_START_EVENT = -2574500,
+ ACTION_AHUNE_RETREAT = -2586500,
+ ACTION_AHUNE_RESURFACE = -2586501,
+ ACTION_EMOTE_RESURFACE = -2575400
+};
+
+enum Phases
+{
+ PHASE_ONE = 0,
+ PHASE_TWO = 1
+};
+
+enum Points
+{
+ POINT_FLAMECALLER_000,
+ POINT_FLAMECALLER_001,
+ POINT_FLAMECALLER_002
+};
+
+enum Misc
+{
+ MAX_FLAMECALLERS = 3
+};
+
+Position const SummonPositions[] =
+{
+ { -99.1021f, -233.7526f, -1.22307f, 1.588250f }, // Ahune
+ { -98.0151f, -230.4555f, -1.21089f, 1.797689f }, // Frozen Core
+ { -143.172f, -147.6801f, -3.16113f, 4.852015f }, // Bonfire Bunny 000
+ { -134.304f, -145.7803f, -1.70332f, 4.677482f }, // Bonfire Bunny 001
+ { -125.036f, -144.2065f, -1.91660f, 4.991642f }, // Bonfire Bunny 002
+ { -69.8121f, -162.4954f, -2.30451f, 1.710423f }, // Wisp Source Bunny
+ { -98.1029f, -230.7864f, -10.8085f, 1.448623f } // Wisp Dest Bunny
+};
+
+Position const FlameCallerSpots[] =
+{
+ { -145.2233f, -137.5543f, -1.59056f, 5.427049f },
+ { -137.4383f, -136.4050f, -1.72384f, 5.336747f },
+ { -129.0413f, -132.1494f, -2.09285f, 5.460842f }
+};
+
+class boss_ahune : public CreatureScript
+{
+public:
+ boss_ahune() : CreatureScript("boss_ahune") { }
+
+ struct boss_ahuneAI : public BossAI
+ {
+ boss_ahuneAI(Creature* creature) : BossAI(creature, DATA_AHUNE)
+ {
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISABLE_MOVE);
+ }
+
+ void EnterCombat(Unit* /*who*/) override
+ {
+ _EnterCombat();
+ events.ScheduleEvent(EVENT_INITIAL_EMERGE, 4);
+ events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AHUNE_BUNNY)))
+ ahuneBunny->AI()->EnterEvadeMode();
+ summons.DespawnAll();
+ me->DespawnOrUnsummon();
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _JustDied();
+ instance->DoCastSpellOnPlayers(SPELL_AHUNE_ACHIEVEMENT);
+
+ if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_AHUNE_BUNNY)))
+ me->Kill(ahuneBunny);
+ if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE)))
+ me->Kill(frozenCore);
+
+ Map::PlayerList const& players = me->GetMap()->GetPlayers();
+ if (!players.isEmpty())
+ {
+ if (Group* group = players.begin()->GetSource()->GetGroup())
+ if (group->isLFGGroup())
+ sLFGMgr->FinishDungeon(group->GetGUID(), 286);
+ }
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ BossAI::JustSummoned(summon);
+ }
+
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_AHUNE_RETREAT)
+ {
+ Submerge();
+ events.ScheduleEvent(EVENT_EMERGE, 35000);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ events.Update(diff);
+
+ while (uint32 eventId = events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_INITIAL_EMERGE:
+ DoCast(me, SPELL_STAND);
+ DoCast(me, SPELL_AHUNE_SPANKY_HANDS);
+ DoCast(me, SPELL_AHUNES_SHIELD);
+ break;
+ case EVENT_EMERGE:
+ Emerge();
+ break;
+ case EVENT_SYNCH_HEALTH:
+ if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE)))
+ DoCast(frozenCore, SPELL_SYNCH_HEALTH);
+ else
+ DoCast(me, SPELL_SUICIDE);
+ events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000);
+ break;
+ default:
+ break;
+ }
+ }
+ DoMeleeAttackIfReady();
+ }
+
+ void Emerge()
+ {
+ if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE)))
+ frozenCore->AI()->DoAction(ACTION_AHUNE_RESURFACE);
+
+ DoCast(me, SPELL_AHUNES_SHIELD);
+ me->RemoveAurasDueToSpell(SPELL_AHUNE_SELF_STUN);
+ me->RemoveAurasDueToSpell(SPELL_STAY_SUBMERGED);
+ DoCast(me, SPELL_STAND);
+ DoCast(me, SPELL_RESURFACE, true);
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000);
+ }
+
+ void Submerge()
+ {
+ if (Creature* frozenCore = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FROZEN_CORE)))
+ frozenCore->AI()->DoAction(ACTION_AHUNE_RETREAT);
+ me->RemoveAurasDueToSpell(SPELL_AHUNES_SHIELD);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
+ DoCast(me, SPELL_SUBMERGED, true);
+ DoCast(me, SPELL_AHUNE_SELF_STUN, true);
+ DoCast(me, SPELL_STAY_SUBMERGED, true);
+ me->HandleEmoteCommand(EMOTE_ONESHOT_SUBMERGE);
+ events.Reset();
+ }
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<boss_ahuneAI>(creature);
+ }
+};
+
+class npc_frozen_core : public CreatureScript
+{
+public:
+ npc_frozen_core() : CreatureScript("npc_frozen_core") { }
+
+ struct npc_frozen_coreAI : public ScriptedAI
+ {
+ npc_frozen_coreAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = me->GetInstanceScript();
+ Initialize();
+ }
+
+ void Initialize()
+ {
+ me->SetReactState(REACT_PASSIVE);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_DISABLE_MOVE);
+ DoCast(me, SPELL_FROZEN_CORE_GETS_HIT);
+ DoCast(me, SPELL_ICE_SPEAR_AURA);
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ DoCast(SPELL_MINION_DESPAWNER);
+ if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE)))
+ ahune->AI()->EnterEvadeMode();
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE)))
+ me->Kill(ahune);
+
+ DoCast(SPELL_SUMMON_LOOT_MISSILE);
+ DoCast(SPELL_MINION_DESPAWNER);
+ }
+
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_AHUNE_RETREAT)
+ {
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC);
+ me->RemoveAurasDueToSpell(SPELL_ICE_SPEAR_AURA);
+ _events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000, 0, PHASE_TWO);
+ }
+ else if (action == ACTION_AHUNE_RESURFACE)
+ {
+ _events.Reset();
+ DoCast(me, SPELL_ICE_SPEAR_AURA);
+ me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_DISABLE_MOVE);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_SYNCH_HEALTH:
+ if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE)))
+ DoCast(ahune, SPELL_SYNCH_HEALTH);
+ else
+ DoCast(me, SPELL_SUICIDE);
+ _events.ScheduleEvent(EVENT_SYNCH_HEALTH, 3000);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_frozen_coreAI>(creature);
+ }
+};
+
+class npc_ahune_bunny : public CreatureScript
+{
+public:
+ npc_ahune_bunny() : CreatureScript("npc_ahune_bunny") { }
+
+ struct npc_ahune_bunnyAI : public ScriptedAI
+ {
+ npc_ahune_bunnyAI(Creature* creature) : ScriptedAI(creature), _summons(me)
+ {
+ _instance = me->GetInstanceScript();
+ _submerged = false;
+ }
+
+ void JustSummoned(Creature* summon) override
+ {
+ if (summon->GetEntry() == NPC_AHUNE)
+ return;
+
+ summon->SetInCombatWithZone();
+ _summons.Summon(summon);
+ }
+
+ void JustDied(Unit* /*killer*/) override
+ {
+ _summons.DespawnAll();
+ ResetFlameCallers();
+ }
+
+ void EnterEvadeMode(EvadeReason /*why*/) override
+ {
+ _EnterEvadeMode();
+ _summons.DespawnAll();
+ ResetFlameCallers();
+
+ me->SummonGameObject(GO_ICE_STONE, -69.90455f, -162.2449f, -2.366563f, 2.426008f, 0.0f, 0.0f, 0.9366722f, 0.3502074f, 0);
+ }
+
+ void DoAction(int32 action) override
+ {
+ if (action == ACTION_START_EVENT)
+ {
+ DoCast(me, SPELL_SUMMONING_VISUAL_1);
+ me->SummonCreature(NPC_WHISP_SOURCE_BUNNY, SummonPositions[5], TEMPSUMMON_MANUAL_DESPAWN);
+ me->SummonCreature(NPC_WHISP_DEST_BUNNY, SummonPositions[6], TEMPSUMMON_MANUAL_DESPAWN);
+ me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_000, SummonPositions[2], TEMPSUMMON_MANUAL_DESPAWN);
+ me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_001, SummonPositions[3], TEMPSUMMON_MANUAL_DESPAWN);
+ me->SummonCreature(NPC_SHAMAN_BONFIRE_BUNNY_002, SummonPositions[4], TEMPSUMMON_MANUAL_DESPAWN);
+
+ for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter)
+ if (Creature* flameCaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter)))
+ flameCaller->GetMotionMaster()->MovePoint(counter, FlameCallerSpots[counter].GetPosition());
+
+ _submerged = false;
+ _events.Reset();
+ _events.SetPhase(PHASE_ONE);
+ _events.ScheduleEvent(EVENT_SUMMON_AHUNE, 10000);
+ _events.ScheduleEvent(EVENT_START_LOOKING_FOR_OPENING, 14000, 0, PHASE_ONE);
+ _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, 22000, 0, PHASE_ONE);
+ _events.ScheduleEvent(EVENT_SUMMON_HAILSTONE, 14000, 0, PHASE_ONE);
+ _events.ScheduleEvent(EVENT_AHUNE_PHASE_TWO, 108000, 0, PHASE_ONE);
+ }
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ if (!UpdateVictim())
+ return;
+
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_START_LOOKING_FOR_OPENING:
+ Talk(EMOTE_EARTHEN_ASSAULT);
+ for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter)
+ if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter)))
+ DoCast(flamecaller, SPELL_SHAMANS_LOOK_FOR_OPENING, true);
+ break;
+ case EVENT_SUMMON_HAILSTONE:
+ DoCast(SPELL_SUMMON_HAILSTONE);
+ break;
+ case EVENT_SUMMON_COLDWEAVE:
+ DoCast(SPELL_SUMMON_COLDWEAVE);
+ DoCast(SPELL_SUMMON_COLDWEAVE);
+ _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, 8000, 0, PHASE_ONE);
+ if (_submerged)
+ _events.ScheduleEvent(EVENT_SUMMON_FROSTWIND, 4000, 0, PHASE_ONE);
+ break;
+ case EVENT_SUMMON_FROSTWIND:
+ DoCast(SPELL_SUMMON_FROSTWIND);
+ break;
+ case EVENT_SUMMON_AHUNE:
+ if (TempSummon* ahune = me->SummonCreature(NPC_AHUNE, SummonPositions[0], TEMPSUMMON_DEAD_DESPAWN))
+ {
+ ahune->SummonCreature(NPC_FROZEN_CORE, SummonPositions[1], TEMPSUMMON_CORPSE_DESPAWN);
+ ahune->SetInCombatWithZone();
+ DoCast(ahune, SPELL_RESURFACE);
+ }
+ break;
+ case EVENT_CLOSE_OPENING:
+ if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000)))
+ flamecaller->AI()->DoAction(ACTION_EMOTE_RESURFACE);
+ DoCast(SPELL_CLOSE_OPENING_VISUAL);
+ DoCast(me, SPELL_ICE_BOMBARD);
+ break;
+ case EVENT_AHUNE_PHASE_TWO:
+ if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000)))
+ DoCast(flamecaller, SPELL_FOUND_OPENING);
+ if (Creature* ahune = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_AHUNE)))
+ ahune->AI()->DoAction(ACTION_AHUNE_RETREAT);
+ _events.Reset();
+ _events.SetPhase(PHASE_TWO);
+ _events.ScheduleEvent(EVENT_CLOSE_OPENING, 25000, 0, PHASE_TWO);
+ _events.ScheduleEvent(EVENT_AHUNE_PHASE_ONE, 35000, 0, PHASE_TWO);
+ break;
+ case EVENT_AHUNE_PHASE_ONE:
+ _submerged = true;
+ _events.Reset();
+ _events.SetPhase(PHASE_ONE);
+ _events.ScheduleEvent(EVENT_SUMMON_COLDWEAVE, 8000, 0, PHASE_ONE);
+ _events.ScheduleEvent(EVENT_SUMMON_HAILSTONE, 5000, 0, PHASE_ONE);
+ _events.ScheduleEvent(EVENT_START_LOOKING_FOR_OPENING, 5000, 0, PHASE_ONE);
+ _events.ScheduleEvent(EVENT_AHUNE_PHASE_TWO, 100000, 0, PHASE_ONE);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ void ResetFlameCallers()
+ {
+ for (uint8 counter = 0; counter < MAX_FLAMECALLERS; ++counter)
+ if (Creature* flamecaller = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_FLAMECALLER_000 + counter)))
+ flamecaller->AI()->EnterEvadeMode();
+ }
+
+ private:
+ InstanceScript* _instance;
+ EventMap _events;
+ SummonList _summons;
+ bool _submerged;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_ahune_bunnyAI>(creature);
+ }
+};
+
+class npc_earthen_ring_flamecaller : public CreatureScript
+{
+public:
+ npc_earthen_ring_flamecaller() : CreatureScript("npc_earthen_ring_flamecaller") { }
+
+ struct npc_earthen_ring_flamecallerAI : public ScriptedAI
+ {
+ npc_earthen_ring_flamecallerAI(Creature* creature) : ScriptedAI(creature)
+ {
+ _instance = me->GetInstanceScript();
+ _mySpot = 0;
+ }
+
+ void Reset() override
+ {
+ _events.Reset();
+ }
+
+ void MovementInform(uint32 motionType, uint32 pointId) override
+ {
+ if (motionType != POINT_MOTION_TYPE)
+ return;
+
+ switch (pointId)
+ {
+ case POINT_FLAMECALLER_000:
+ _mySpot = POINT_FLAMECALLER_000;
+ me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation());
+ break;
+ case POINT_FLAMECALLER_001:
+ _mySpot = POINT_FLAMECALLER_001;
+ me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation());
+ break;
+ case POINT_FLAMECALLER_002:
+ _mySpot = POINT_FLAMECALLER_002;
+ me->SetOrientation(FlameCallerSpots[_mySpot].GetOrientation());
+ break;
+ default:
+ break;
+ }
+
+ DoCast(me, SPELL_FIND_OPENING_CHANNEL);
+ }
+
+ void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override
+ {
+ switch (spellInfo->Id)
+ {
+ case SPELL_SHAMANS_LOOK_FOR_OPENING:
+ _events.ScheduleEvent(EVENT_LOOKFOROPENING_0, 17000);
+ break;
+ case SPELL_FOUND_OPENING:
+ _events.ScheduleEvent(EVENT_FOUND_OPENING, 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ void DoAction(int action) override
+ {
+ if (action == ACTION_EMOTE_RESURFACE)
+ Talk(EMOTE_RESURFACE);
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_LOOKFOROPENING_0:
+ LookOpening(true, 0);
+ _events.ScheduleEvent(EVENT_LOOKFOROPENING_1, 26000);
+ break;
+ case EVENT_LOOKFOROPENING_1:
+ LookOpening(true, 1);
+ _events.ScheduleEvent(EVENT_LOOKFOROPENING_2, 25000);
+ break;
+ case EVENT_LOOKFOROPENING_2:
+ LookOpening(true, 2);
+ _events.ScheduleEvent(EVENT_STOP_LOOKING_FOR_OPENING, 27000);
+ break;
+ case EVENT_STOP_LOOKING_FOR_OPENING:
+ LookOpening(false, _mySpot);
+ break;
+ case EVENT_FOUND_OPENING:
+ Talk(EMOTE_RETREAT);
+ default:
+ break;
+ }
+ }
+ }
+
+ void LookOpening(bool activate, uint8 spot)
+ {
+ if (_mySpot != spot)
+ return;
+
+ if (Creature* bonfireBunny = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BONFIRE_BUNNY_000 + spot)))
+ if (Creature* beamBunny = ObjectAccessor::GetCreature(*me, _instance->GetGuidData(DATA_BEAM_BUNNY_000 + spot)))
+ {
+ if (activate)
+ {
+ DoCast(bonfireBunny, SPELL_FIND_OPENING_TRIGGER);
+ bonfireBunny->CastSpell(beamBunny, SPELL_FIND_OPENING_VISUAL, true);
+ }
+ else
+ {
+ DoCast(me, SPELL_FIND_OPENING_CHANNEL);
+ bonfireBunny->CastStop();
+ beamBunny->RemoveAurasDueToSpell(SPELL_FIND_OPENING_BEAM_END);
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ InstanceScript* _instance;
+ uint8 _mySpot;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const override
+ {
+ return GetInstanceAI<npc_earthen_ring_flamecallerAI>(creature);
+ }
+};
+
+class go_ahune_ice_stone : public GameObjectScript
+{
+public:
+ go_ahune_ice_stone() : GameObjectScript("go_ahune_ice_stone") { }
+
+ bool OnGossipSelect(Player* player, GameObject* go, uint32 /*sender*/, uint32 /*action*/)
+ {
+ InstanceScript* instance = go->GetInstanceScript();
+ if (!instance)
+ return false;
+
+ player->PlayerTalkClass->ClearMenus();
+
+ if (Creature* ahuneBunny = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_AHUNE_BUNNY)))
+ {
+ ahuneBunny->AI()->DoAction(ACTION_START_EVENT);
+ ahuneBunny->SetInCombatWithZone();
+ }
+ if (Creature* luma = ObjectAccessor::GetCreature(*go, instance->GetGuidData(DATA_LUMA_SKYMOTHER)))
+ luma->CastSpell(player, SPELL_SUMMONING_RHYME_AURA, true);
+ player->CLOSE_GOSSIP_MENU();
+ go->Delete();
+
+ return true;
+ }
+};
+
+// 46430 - Synch Health
+class spell_ahune_synch_health : public SpellScriptLoader
+{
+public:
+ spell_ahune_synch_health() : SpellScriptLoader("spell_ahune_synch_health") { }
+
+ class spell_ahune_synch_health_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_ahune_synch_health_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SYNCH_HEALTH))
+ return false;
+ return true;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ if (Unit* caster = GetCaster())
+ target->SetHealth(caster->GetHealth());
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_ahune_synch_health_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_ahune_synch_health_SpellScript();
+ }
+};
+
+// 45926 - Summoning Rhyme Aura
+class spell_summoning_rhyme_aura : public SpellScriptLoader
+{
+public:
+ spell_summoning_rhyme_aura() : SpellScriptLoader("spell_summoning_rhyme_aura") { }
+
+ class spell_summoning_rhyme_aura_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_summoning_rhyme_aura_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_FORCE_WHISP_FLIGHT) || !sSpellMgr->GetSpellInfo(SPELL_SUMMONING_RHYME_BONFIRE))
+ return false;
+ return true;
+ }
+
+ void PeriodicTick(AuraEffect const* aurEff)
+ {
+ Creature* caster = GetCaster()->ToCreature();
+ Player* player = GetTarget()->ToPlayer();
+
+ if (!caster || !player)
+ return;
+
+ player->CastSpell(player, SPELL_FORCE_WHISP_FLIGHT);
+
+ switch (aurEff->GetTickNumber())
+ {
+ case 1:
+ sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_1, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player);
+ player->CastSpell(player, SPELL_SUMMONING_RHYME_BONFIRE, true);
+ break;
+ case 2:
+ sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_2, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player);
+ break;
+ case 3:
+ sCreatureTextMgr->SendChat(caster, SAY_PLAYER_TEXT_3, NULL, CHAT_MSG_SAY, LANG_UNIVERSAL, TEXT_RANGE_NORMAL, 0, TEAM_OTHER, false, player);
+ Remove();
+ break;
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_summoning_rhyme_aura_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_summoning_rhyme_aura_AuraScript();
+ }
+};
+
+// 46878 - Summon Ice Spear Delayer
+class spell_summon_ice_spear_delayer : public SpellScriptLoader
+{
+public:
+ spell_summon_ice_spear_delayer() : SpellScriptLoader("spell_summon_ice_spear_delayer") { }
+
+ class spell_summon_ice_spear_delayer_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_summon_ice_spear_delayer_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ICE_SPEAR_GO) || !sSpellMgr->GetSpellInfo(SPELL_ICE_SPEAR_KNOCKBACK))
+ return false;
+ return true;
+ }
+
+ void PeriodicTick(AuraEffect const* aurEff)
+ {
+ if (Creature* caster = GetCaster()->ToCreature())
+ switch (aurEff->GetTickNumber())
+ {
+ case 1:
+ caster->CastSpell(caster, SPELL_SUMMON_ICE_SPEAR_GO);
+ break;
+ case 3:
+ if (GameObject* spike = caster->FindNearestGameObject(GO_ICE_SPEAR, 3.0f))
+ spike->UseDoorOrButton();
+ caster->AI()->DoCastAOE(SPELL_ICE_SPEAR_KNOCKBACK, true);
+ break;
+ case 5:
+ if (GameObject* spike = caster->FindNearestGameObject(GO_ICE_SPEAR, 3.0f))
+ spike->Delete();
+ caster->DespawnOrUnsummon();
+ break;
+ default:
+ break;
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_summon_ice_spear_delayer_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_summon_ice_spear_delayer_AuraScript();
+ }
+};
+
+// 46371 - Ice Spear Control Aura
+class spell_ice_spear_control_aura : public SpellScriptLoader
+{
+public:
+ spell_ice_spear_control_aura() : SpellScriptLoader("spell_ice_spear_control_aura") { }
+
+ class spell_ice_spear_control_aura_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_ice_spear_control_aura_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_ICE_SPEAR_TARGET_PICKER))
+ return false;
+ return true;
+ }
+
+ void PeriodicTick(AuraEffect const* /*aurEff*/)
+ {
+ if (Unit* caster = GetCaster())
+ caster->CastSpell(caster, SPELL_ICE_SPEAR_TARGET_PICKER);
+ }
+
+ void Register() override
+ {
+ OnEffectPeriodic += AuraEffectPeriodicFn(spell_ice_spear_control_aura_AuraScript::PeriodicTick, EFFECT_0, SPELL_AURA_PERIODIC_DUMMY);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_ice_spear_control_aura_AuraScript();
+ }
+};
+
+// 46372 - Ice Spear Target Picker
+class spell_ice_spear_target_picker : public SpellScriptLoader
+{
+public:
+ spell_ice_spear_target_picker() : SpellScriptLoader("spell_ice_spear_target_picker") { }
+
+ class spell_ice_spear_target_picker_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_ice_spear_target_picker_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SUMMON_ICE_SPEAR_BUNNY))
+ return false;
+ return true;
+ }
+
+ void HandleDummy(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitUnit(), SPELL_SUMMON_ICE_SPEAR_BUNNY, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_ice_spear_target_picker_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_ice_spear_target_picker_SpellScript();
+ }
+};
+
+// 46320 - Spell Slippery Floor Periodic
+class spell_slippery_floor_periodic : public SpellScriptLoader
+{
+public:
+ spell_slippery_floor_periodic() : SpellScriptLoader("spell_slippery_floor_periodic") { }
+
+ class spell_slippery_floor_periodic_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_slippery_floor_periodic_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_SLIPPERY_FLOOR_SLIP))
+ return false;
+ return true;
+ }
+
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ if (target->isMoving())
+ target->CastSpell(target, SPELL_SLIPPERY_FLOOR_SLIP, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_slippery_floor_periodic_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_slippery_floor_periodic_SpellScript();
+ }
+};
+
+// 46146 - Ahune Spanky Hands
+class spell_ahune_spanky_hands : public SpellScriptLoader
+{
+public:
+ spell_ahune_spanky_hands() : SpellScriptLoader("spell_ahune_spanky_hands") { }
+
+ class spell_ahune_spanky_hands_AuraScript : public AuraScript
+ {
+ PrepareAuraScript(spell_ahune_spanky_hands_AuraScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_COLD_SLAP))
+ return false;
+ return true;
+ }
+
+ void HandleProc(AuraEffect const* /*aurEff*/, ProcEventInfo& eventInfo)
+ {
+ PreventDefaultAction();
+ GetTarget()->CastSpell(eventInfo.GetProcTarget(), SPELL_COLD_SLAP, true);
+ }
+
+ void Register() override
+ {
+ OnEffectProc += AuraEffectProcFn(spell_ahune_spanky_hands_AuraScript::HandleProc, EFFECT_0, SPELL_AURA_PROC_TRIGGER_SPELL);
+ }
+ };
+
+ AuraScript* GetAuraScript() const override
+ {
+ return new spell_ahune_spanky_hands_AuraScript();
+ }
+};
+
+class spell_ahune_minion_despawner : public SpellScriptLoader
+{
+public:
+ spell_ahune_minion_despawner() : SpellScriptLoader("spell_ahune_minion_despawner") { }
+
+ class spell_ahune_minion_despawner_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_ahune_minion_despawner_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (GetHitCreature())
+ GetHitCreature()->DespawnOrUnsummon();
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_ahune_minion_despawner_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_ahune_minion_despawner_SpellScript();
+ }
+};
+
+// 46398 - Spell Ice Bombardment Dest Picker
+class spell_ice_bombardment_dest_picker : public SpellScriptLoader
+{
+public:
+ spell_ice_bombardment_dest_picker() : SpellScriptLoader("spell_ice_bombardment_dest_picker") { }
+
+ class spell_ice_bombardment_dest_picker_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_ice_bombardment_dest_picker_SpellScript);
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sSpellMgr->GetSpellInfo(SPELL_ICE_BOMBARDMENT))
+ return false;
+ return true;
+ }
+
+ void HandleScriptEffect(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->CastSpell(GetHitDest()->GetPositionX(), GetHitDest()->GetPositionY(), GetHitDest()->GetPositionZ(), SPELL_ICE_BOMBARDMENT, true);
+ }
+
+ void Register() override
+ {
+ OnEffectHit += SpellEffectFn(spell_ice_bombardment_dest_picker_SpellScript::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_DUMMY);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_ice_bombardment_dest_picker_SpellScript();
+ }
+};
+
+void AddSC_boss_ahune()
+{
+ new boss_ahune();
+ new npc_frozen_core();
+ new npc_earthen_ring_flamecaller();
+ new npc_ahune_bunny();
+ new go_ahune_ice_stone();
+ new spell_ahune_synch_health();
+ new spell_summoning_rhyme_aura();
+ new spell_summon_ice_spear_delayer();
+ new spell_ice_spear_control_aura();
+ new spell_slippery_floor_periodic();
+ new spell_ahune_spanky_hands();
+ new spell_ahune_minion_despawner();
+ new spell_ice_spear_target_picker();
+ new spell_ice_bombardment_dest_picker();
+}
diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp
index 87a07cd1e5e..0fac7b5a39d 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp
+++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/instance_the_slave_pens.cpp
@@ -31,15 +31,125 @@ class instance_the_slave_pens : public InstanceMapScript
public:
instance_the_slave_pens() : InstanceMapScript(SPScriptName, 547) { }
+ struct instance_the_slave_pens_InstanceMapScript : public InstanceScript
+ {
+ instance_the_slave_pens_InstanceMapScript(Map* map) : InstanceScript(map)
+ {
+ counter = DATA_FLAMECALLER_000;
+ }
+
+ void OnCreatureCreate(Creature* creature) override
+ {
+ switch (creature->GetEntry())
+ {
+ case NPC_AHUNE:
+ AhuneGUID = creature->GetGUID();
+ break;
+ case NPC_FROZEN_CORE:
+ FrozenCoreGUID = creature->GetGUID();
+ break;
+ case NPC_AHUNE_LOC_BUNNY:
+ AhuneBunnyGUID = creature->GetGUID();
+ break;
+ case NPC_SHAMAN_BONFIRE_BUNNY_000:
+ BonfireBunnyGUIDs[0] = creature->GetGUID();
+ break;
+ case NPC_SHAMAN_BONFIRE_BUNNY_001:
+ BonfireBunnyGUIDs[1] = creature->GetGUID();
+ break;
+ case NPC_SHAMAN_BONFIRE_BUNNY_002:
+ BonfireBunnyGUIDs[2] = creature->GetGUID();
+ break;
+ case NPC_SHAMAN_BEAM_BUNNY_000:
+ BeamBunnyGUIDs[0] = creature->GetGUID();
+ break;
+ case NPC_SHAMAN_BEAM_BUNNY_001:
+ BeamBunnyGUIDs[1] = creature->GetGUID();
+ break;
+ case NPC_SHAMAN_BEAM_BUNNY_002:
+ BeamBunnyGUIDs[2] = creature->GetGUID();
+ break;
+ case NPC_LUMA_SKYMOTHER:
+ LumaGUID = creature->GetGUID();
+ break;
+ case NPC_EARTHEN_RING_FLAMECALLER:
+ SetGuidData(counter, creature->GetGUID());
+ ++counter;
+ break;
+ default:
+ break;
+ }
+ }
+
+ void SetGuidData(uint32 data, ObjectGuid guid) override
+ {
+ switch (data)
+ {
+ case DATA_FLAMECALLER_000:
+ FlameCallerGUIDs[0] = guid;
+ break;
+ case DATA_FLAMECALLER_001:
+ FlameCallerGUIDs[1] = guid;
+ break;
+ case DATA_FLAMECALLER_002:
+ FlameCallerGUIDs[2] = guid;
+ break;
+ default:
+ break;
+ }
+ }
+
+ ObjectGuid GetGuidData(uint32 type) const override
+ {
+ switch (type)
+ {
+ case DATA_AHUNE:
+ return AhuneGUID;
+ case DATA_AHUNE_BUNNY:
+ return AhuneBunnyGUID;
+ case DATA_FROZEN_CORE:
+ return FrozenCoreGUID;
+ case DATA_FLAMECALLER_000:
+ return FlameCallerGUIDs[0];
+ case DATA_FLAMECALLER_001:
+ return FlameCallerGUIDs[1];
+ case DATA_FLAMECALLER_002:
+ return FlameCallerGUIDs[2];
+ case DATA_BONFIRE_BUNNY_000:
+ return BonfireBunnyGUIDs[0];
+ case DATA_BONFIRE_BUNNY_001:
+ return BonfireBunnyGUIDs[1];
+ case DATA_BONFIRE_BUNNY_002:
+ return BonfireBunnyGUIDs[2];
+ case DATA_BEAM_BUNNY_000:
+ return BeamBunnyGUIDs[0];
+ case DATA_BEAM_BUNNY_001:
+ return BeamBunnyGUIDs[1];
+ case DATA_BEAM_BUNNY_002:
+ return BeamBunnyGUIDs[2];
+ case DATA_LUMA_SKYMOTHER:
+ return LumaGUID;
+ default:
+ break;
+ }
+ return ObjectGuid::Empty;
+ }
+
+ protected:
+ ObjectGuid AhuneGUID;
+ ObjectGuid AhuneBunnyGUID;
+ ObjectGuid FrozenCoreGUID;
+ ObjectGuid LumaGUID;
+ ObjectGuid FlameCallerGUIDs[3];
+ ObjectGuid BonfireBunnyGUIDs[3];
+ ObjectGuid BeamBunnyGUIDs[3];
+ uint8 counter;
+ };
+
InstanceScript* GetInstanceScript(InstanceMap* map) const override
{
return new instance_the_slave_pens_InstanceMapScript(map);
}
-
- struct instance_the_slave_pens_InstanceMapScript : public InstanceScript
- {
- instance_the_slave_pens_InstanceMapScript(Map* map) : InstanceScript(map) { }
- };
};
void AddSC_instance_the_slave_pens()
diff --git a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h
index 95e6e44121e..544e98fd206 100644
--- a/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h
+++ b/src/server/scripts/Outland/CoilfangReservoir/TheSlavePens/the_slave_pens.h
@@ -27,7 +27,43 @@ enum DataTypes
{
DATA_MENNU_THE_BETRAYER = 1,
DATA_ROKMAR_THE_CRACKLER = 2,
- DATA_QUAGMIRRAN = 3
+ DATA_QUAGMIRRAN = 3,
+ DATA_AHUNE = 4,
+ DATA_AHUNE_BUNNY = 5,
+ DATA_FROZEN_CORE = 6,
+ DATA_FLAMECALLER_000 = 7,
+ DATA_FLAMECALLER_001 = 8,
+ DATA_FLAMECALLER_002 = 9,
+ DATA_BONFIRE_BUNNY_000 = 10,
+ DATA_BONFIRE_BUNNY_001 = 11,
+ DATA_BONFIRE_BUNNY_002 = 12,
+ DATA_BEAM_BUNNY_000 = 13,
+ DATA_BEAM_BUNNY_001 = 14,
+ DATA_BEAM_BUNNY_002 = 15,
+ DATA_LUMA_SKYMOTHER = 16
+};
+
+enum CreaturesIds
+{
+ NPC_AHUNE = 25740,
+ NPC_FROZEN_CORE = 25865,
+ NPC_LUMA_SKYMOTHER = 25697,
+ NPC_AHUNE_LOC_BUNNY = 25745,
+ NPC_EARTHEN_RING_FLAMECALLER = 25754,
+ NPC_SHAMAN_BONFIRE_BUNNY_000 = 25971,
+ NPC_SHAMAN_BONFIRE_BUNNY_001 = 25972,
+ NPC_SHAMAN_BONFIRE_BUNNY_002 = 25973,
+ NPC_SHAMAN_BEAM_BUNNY_000 = 25964,
+ NPC_SHAMAN_BEAM_BUNNY_001 = 25965,
+ NPC_SHAMAN_BEAM_BUNNY_002 = 25966,
+ NPC_WHISP_DEST_BUNNY = 26120,
+ NPC_WHISP_SOURCE_BUNNY = 26121
+};
+
+enum GameObjectIds
+{
+ GO_ICE_SPEAR = 188077,
+ GO_ICE_STONE = 187882
};
#endif // SLAVE_PENS_H
diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp
index 4e20e6b0953..9b8220596c9 100644
--- a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp
@@ -372,7 +372,7 @@ class boss_vazruden_the_herald : public CreatureScript
if (summon->GetEntry() == NPC_NAZAN)
{
summon->SetDisableGravity(true);
- summon->SetSpeed(MOVE_FLIGHT, 2.5f);
+ summon->SetSpeedRate(MOVE_FLIGHT, 2.5f);
if (victim)
AttackStartNoMove(victim);
}
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
index 499550945c6..2592ed3b262 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
@@ -180,24 +180,23 @@ class boss_grand_warlock_nethekurse : public CreatureScript
}
void MoveInLineOfSight(Unit* who) override
-
{
if (!IntroOnce && me->IsWithinDistInMap(who, 30.0f))
- {
+ {
if (who->GetTypeId() != TYPEID_PLAYER)
return;
- Talk(SAY_INTRO);
- IntroOnce = true;
- IsIntroEvent = true;
+ Talk(SAY_INTRO);
+ IntroOnce = true;
+ IsIntroEvent = true;
- instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
- }
+ instance->SetBossState(DATA_NETHEKURSE, IN_PROGRESS);
+ }
- if (IsIntroEvent || !IsMainEvent)
- return;
+ if (IsIntroEvent || !IsMainEvent)
+ return;
- ScriptedAI::MoveInLineOfSight(who);
+ ScriptedAI::MoveInLineOfSight(who);
}
void EnterCombat(Unit* /*who*/) override
diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
index 4faab709e16..c29d560529d 100644
--- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
+++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
@@ -109,7 +109,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript
{
removeAdds();
_Reset();
- me->SetSpeed(MOVE_RUN, 2);
+ me->SetSpeedRate(MOVE_RUN, 2);
me->SetWalk(false);
Initialize();
@@ -231,7 +231,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript
{
// stop bladedance
InBlade = false;
- me->SetSpeed(MOVE_RUN, 2);
+ me->SetSpeedRate(MOVE_RUN, 2);
me->GetMotionMaster()->MoveChase(me->GetVictim());
Blade_Dance_Timer = 30000;
Wait_Timer = 0;
@@ -264,7 +264,7 @@ class boss_warchief_kargath_bladefist : public CreatureScript
Wait_Timer = 1;
InBlade = true;
Blade_Dance_Timer = 0;
- me->SetSpeed(MOVE_RUN, 4);
+ me->SetSpeedRate(MOVE_RUN, 4);
return;
}
else
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
index 56010c09897..20d96ecd29c 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp
@@ -130,7 +130,7 @@ class boss_alar : public CreatureScript
_Reset();
me->SetDisplayId(me->GetNativeDisplayId());
- me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate);
+ me->SetSpeedRate(MOVE_RUN, DefaultMoveSpeedRate);
//me->SetFloatValue(UNIT_FIELD_BOUNDINGRADIUS, 10);
//me->SetFloatValue(UNIT_FIELD_COMBATREACH, 10);
me->ApplySpellImmune(0, IMMUNITY_SCHOOL, SPELL_SCHOOL_MASK_FIRE, true);
@@ -178,7 +178,7 @@ class boss_alar : public CreatureScript
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
me->AttackStop();
me->SetTarget(ObjectGuid::Empty);
- me->SetSpeed(MOVE_RUN, 5.0f);
+ me->SetSpeedRate(MOVE_RUN, 5.0f);
me->GetMotionMaster()->Clear();
me->GetMotionMaster()->MovePoint(0, waypoint[5][0], waypoint[5][1], waypoint[5][2]);
}
@@ -261,7 +261,7 @@ class boss_alar : public CreatureScript
case WE_REVIVE:
me->SetUInt32Value(UNIT_FIELD_BYTES_1, UNIT_STAND_STATE_STAND);
me->SetFullHealth();
- me->SetSpeed(MOVE_RUN, DefaultMoveSpeedRate);
+ me->SetSpeedRate(MOVE_RUN, DefaultMoveSpeedRate);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
DoZoneInCombat();
DoCast(me, SPELL_REBIRTH, true);
diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp
index 9fd1c5c7388..30b3fd67687 100644
--- a/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_astromancer.cpp
@@ -325,86 +325,85 @@ class boss_high_astromancer_solarian : public CreatureScript
else
Phase1_Timer-=diff;
}
- else
- if (Phase == 2)
+ else if (Phase == 2)
+ {
+ //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals.
+ me->AttackStop();
+ me->StopMoving();
+ if (Phase2_Timer <= diff)
{
- //10 seconds after Solarian disappears, 12 mobs spawn out of the three portals.
- me->AttackStop();
- me->StopMoving();
- if (Phase2_Timer <= diff)
- {
- Phase = 3;
- for (int i=0; i <= 2; ++i)
- for (int j=1; j <= 4; j++)
- SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]);
+ Phase = 3;
+ for (int i=0; i <= 2; ++i)
+ for (int j=1; j <= 4; j++)
+ SummonMinion(NPC_SOLARIUM_AGENT, Portals[i][0], Portals[i][1], Portals[i][2]);
- Talk(SAY_SUMMON1);
- Phase2_Timer = 10000;
- }
- else
- Phase2_Timer -= diff;
+ Talk(SAY_SUMMON1);
+ Phase2_Timer = 10000;
}
else
- if (Phase == 3)
- {
- me->AttackStop();
- me->StopMoving();
- //Check Phase3_Timer
- if (Phase3_Timer <= diff)
- {
- Phase = 1;
- //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals.
- int i = rand32() % 3;
- me->GetMotionMaster()->Clear();
- me->SetPosition(Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O);
-
- for (int j=0; j <= 2; j++)
- if (j != i)
- SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]);
-
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetVisible(true);
-
- Talk(SAY_SUMMON2);
- AppearDelay = true;
- Phase3_Timer = 15000;
- }
- else
- Phase3_Timer -= diff;
- }
- else
- if (Phase == 4)
- {
- //Fear_Timer
- if (Fear_Timer <= diff)
- {
- DoCast(me, SPELL_FEAR);
- Fear_Timer = 20000;
- }
- else
- Fear_Timer -= diff;
- //VoidBolt_Timer
- if (VoidBolt_Timer <= diff)
- {
- DoCastVictim(SPELL_VOID_BOLT);
- VoidBolt_Timer = 10000;
- }
- else
- VoidBolt_Timer -= diff;
- }
- //When Solarian reaches 20% she will transform into a huge void walker.
- if (Phase != 4 && me->HealthBelowPct(20))
- {
- Phase = 4;
- //To make sure she wont be invisible or not selecatble
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
- me->SetVisible(true);
- Talk(SAY_VOIDA);
- Talk(SAY_VOIDB);
- me->SetArmor(WV_ARMOR);
- me->SetDisplayId(MODEL_VOIDWALKER);
- me->SetObjectScale(defaultsize*2.5f);
- }
+ Phase2_Timer -= diff;
+ }
+ else if (Phase == 3)
+ {
+ me->AttackStop();
+ me->StopMoving();
+ //Check Phase3_Timer
+ if (Phase3_Timer <= diff)
+ {
+ Phase = 1;
+ //15 seconds later Solarian reappears out of one of the 3 portals. Simultaneously, 2 healers appear in the two other portals.
+ int i = rand32() % 3;
+ me->GetMotionMaster()->Clear();
+ me->SetPosition(Portals[i][0], Portals[i][1], Portals[i][2], CENTER_O);
+
+ for (int j=0; j <= 2; j++)
+ if (j != i)
+ SummonMinion(NPC_SOLARIUM_PRIEST, Portals[j][0], Portals[j][1], Portals[j][2]);
+
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetVisible(true);
+
+ Talk(SAY_SUMMON2);
+ AppearDelay = true;
+ Phase3_Timer = 15000;
+ }
+ else
+ Phase3_Timer -= diff;
+ }
+ else if (Phase == 4)
+ {
+ //Fear_Timer
+ if (Fear_Timer <= diff)
+ {
+ DoCast(me, SPELL_FEAR);
+ Fear_Timer = 20000;
+ }
+ else
+ Fear_Timer -= diff;
+ //VoidBolt_Timer
+ if (VoidBolt_Timer <= diff)
+ {
+ DoCastVictim(SPELL_VOID_BOLT);
+ VoidBolt_Timer = 10000;
+ }
+ else
+ VoidBolt_Timer -= diff;
+ }
+
+ //When Solarian reaches 20% she will transform into a huge void walker.
+ if (Phase != 4 && me->HealthBelowPct(20))
+ {
+ Phase = 4;
+ //To make sure she wont be invisible or not selecatble
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
+ me->SetVisible(true);
+ Talk(SAY_VOIDA);
+ Talk(SAY_VOIDB);
+ me->SetArmor(WV_ARMOR);
+ me->SetDisplayId(MODEL_VOIDWALKER);
+ me->SetObjectScale(defaultsize*2.5f);
+ }
+
DoMeleeAttackIfReady();
}
};
diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp
index 3aa2674aec6..d45e17bd28d 100644
--- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp
+++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp
@@ -176,7 +176,7 @@ class npc_ragin_flames : public CreatureScript
Initialize();
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_MAGIC, true);
me->ApplySpellImmune(0, IMMUNITY_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, true);
- me->SetSpeed(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f));
+ me->SetSpeedRate(MOVE_RUN, DUNGEON_MODE(0.5f, 0.7f));
}
void EnterCombat(Unit* /*who*/) override
diff --git a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
index 856649c6c5e..e64c0fe9f5e 100644
--- a/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
+++ b/src/server/scripts/Outland/TempestKeep/botanica/boss_warp_splinter.cpp
@@ -167,7 +167,7 @@ class boss_warp_splinter : public CreatureScript
{
Initialize();
- me->SetSpeed(MOVE_RUN, 0.7f, true);
+ me->SetSpeedRate(MOVE_RUN, 0.7f);
}
void EnterCombat(Unit* /*who*/) override
diff --git a/src/server/scripts/Outland/outland_script_loader.cpp b/src/server/scripts/Outland/outland_script_loader.cpp
index 91ba4e5689f..ed2c21da6c3 100644
--- a/src/server/scripts/Outland/outland_script_loader.cpp
+++ b/src/server/scripts/Outland/outland_script_loader.cpp
@@ -72,6 +72,7 @@ void AddSC_instance_the_slave_pens();
void AddSC_boss_mennu_the_betrayer();
void AddSC_boss_rokmar_the_crackler();
void AddSC_boss_quagmirran();
+void AddSC_boss_ahune();
// Coilfang Reservoir - The Underbog
void AddSC_instance_the_underbog();
@@ -193,6 +194,7 @@ void AddOutlandScripts()
AddSC_boss_mennu_the_betrayer();
AddSC_boss_rokmar_the_crackler();
AddSC_boss_quagmirran();
+ AddSC_boss_ahune();
// Coilfang Reservoir - The Underbog
AddSC_instance_the_underbog();
diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
index 404cdc7ceb2..668c484dd63 100644
--- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
+++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp
@@ -159,7 +159,7 @@ public:
else
TC_LOG_ERROR("scripts", "TRINITY: npc_ancestral_wolf can not obtain owner or owner is not a player.");
- creature->SetSpeed(MOVE_WALK, 1.5f);
+ creature->SetSpeedRate(MOVE_WALK, 1.5f);
Reset();
}
@@ -192,7 +192,7 @@ public:
if (ryga->IsAlive() && !ryga->IsInCombat())
{
ryga->SetWalk(true);
- ryga->SetSpeed(MOVE_WALK, 1.5f);
+ ryga->SetSpeedRate(MOVE_WALK, 1.5f);
ryga->GetMotionMaster()->MovePoint(0, 517.340698f, 3885.03975f, 190.455978f, true);
Reset();
}
@@ -778,7 +778,7 @@ public:
me->AddAura(SPELL_JULES_THREATENS_AURA, me);
me->SetCanFly(true);
- me->SetSpeed(MOVE_RUN, 0.2f);
+ me->SetSpeedRate(MOVE_RUN, 0.2f);
me->SetFacingTo(3.207566f);
me->GetMotionMaster()->MoveJump(exorcismPos[2], 2.0f, 2.0f);
@@ -798,7 +798,7 @@ public:
break;
case ACTION_JULES_MOVE_HOME:
wpreached = false;
- me->SetSpeed(MOVE_RUN, 1.0f);
+ me->SetSpeedRate(MOVE_RUN, 1.0f);
me->GetMotionMaster()->MovePoint(11, exorcismPos[2]);
events.CancelEvent(EVENT_SUMMON_SKULL);
diff --git a/src/server/scripts/Outland/zone_shattrath_city.cpp b/src/server/scripts/Outland/zone_shattrath_city.cpp
index c734d000077..e4e51a98348 100644
--- a/src/server/scripts/Outland/zone_shattrath_city.cpp
+++ b/src/server/scripts/Outland/zone_shattrath_city.cpp
@@ -29,7 +29,6 @@ npc_salsalabim
npc_shattrathflaskvendors
npc_zephyr
npc_kservant
-npc_ishanah
EndContentData */
#include "ScriptMgr.h"
@@ -43,13 +42,15 @@ EndContentData */
## npc_raliq_the_drunk
######*/
-#define GOSSIP_RALIQ "You owe Sim'salabim money. Hand them over or die!"
-
-enum Raliq
+enum RaliqTheDrunk
{
- SPELL_UPPERCUT = 10966,
- QUEST_CRACK_SKULLS = 10009,
- FACTION_HOSTILE_RD = 45
+ SAY_RALIQ_ATTACK = 0,
+ OPTION_ID_COLLECT_A_DEBT = 0,
+ FACTION_OGRE_HOSTILE = 45,
+ MENU_ID_COLLECT_A_DEBT = 7729,
+ NPC_TEXT_WUT_YOU_WANT = 9440,
+ CRACKIN_SOME_SKULLS = 10009,
+ SPELL_UPPERCUT = 10966
};
class npc_raliq_the_drunk : public CreatureScript
@@ -63,7 +64,8 @@ public:
if (action == GOSSIP_ACTION_INFO_DEF+1)
{
player->CLOSE_GOSSIP_MENU();
- creature->setFaction(FACTION_HOSTILE_RD);
+ creature->setFaction(FACTION_OGRE_HOSTILE);
+ creature->AI()->Talk(SAY_RALIQ_ATTACK, player);
creature->AI()->AttackStart(player);
}
return true;
@@ -71,10 +73,16 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
- if (player->GetQuestStatus(QUEST_CRACK_SKULLS) == QUEST_STATUS_INCOMPLETE)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_RALIQ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
-
- player->SEND_GOSSIP_MENU(9440, creature->GetGUID());
+ if (player->GetQuestStatus(CRACKIN_SOME_SKULLS) == QUEST_STATUS_INCOMPLETE)
+ {
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_COLLECT_A_DEBT, OPTION_ID_COLLECT_A_DEBT, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ player->SEND_GOSSIP_MENU(NPC_TEXT_WUT_YOU_WANT, creature->GetGUID());
+ }
+ else
+ {
+ player->PlayerTalkClass->ClearMenus();
+ player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
+ }
return true;
}
@@ -125,16 +133,14 @@ public:
enum Salsalabim
{
- // Factions
- FACTION_HOSTILE_SA = 90,
- FACTION_FRIENDLY_SA = 35,
-
- // Quests
- QUEST_10004 = 10004,
-
- // Spells
- SPELL_MAGNETIC_PULL = 31705
-
+ SAY_DEMONIC_AGGRO = 0,
+ OPTION_ID_ALTRUIS_SENT_ME = 0,
+ FACTION_FRIENDLY = 35,
+ FACTION_DEMON_HOSTILE = 90,
+ MENU_ID_ALTRUIS_SENT_ME = 7725,
+ NPC_TEXT_SAL_GROWLS_AT_YOU = 9435,
+ PATIENCE_AND_UNDERSTANDING = 10004,
+ SPELL_MAGNETIC_PULL = 31705
};
class npc_salsalabim : public CreatureScript
@@ -142,13 +148,26 @@ class npc_salsalabim : public CreatureScript
public:
npc_salsalabim() : CreatureScript("npc_salsalabim") { }
- bool OnGossipHello(Player* player, Creature* creature) override
+ bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
{
- if (player->GetQuestStatus(QUEST_10004) == QUEST_STATUS_INCOMPLETE)
+ player->PlayerTalkClass->ClearMenus();
+ if (action == GOSSIP_ACTION_INFO_DEF+1)
{
- creature->setFaction(FACTION_HOSTILE_SA);
+ player->CLOSE_GOSSIP_MENU();
+ creature->setFaction(FACTION_DEMON_HOSTILE);
+ creature->AI()->Talk(SAY_DEMONIC_AGGRO, player);
creature->AI()->AttackStart(player);
}
+ return true;
+ }
+
+ bool OnGossipHello(Player* player, Creature* creature) override
+ {
+ if (player->GetQuestStatus(PATIENCE_AND_UNDERSTANDING) == QUEST_STATUS_INCOMPLETE)
+ {
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_ALTRUIS_SENT_ME, OPTION_ID_ALTRUIS_SENT_ME, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ player->SEND_GOSSIP_MENU(NPC_TEXT_SAL_GROWLS_AT_YOU, creature->GetGUID());
+ }
else
{
if (creature->IsQuestGiver())
@@ -187,7 +206,7 @@ public:
{
if (done_by->GetTypeId() == TYPEID_PLAYER && me->HealthBelowPctDamaged(20, damage))
{
- done_by->ToPlayer()->GroupEventHappens(QUEST_10004, me);
+ done_by->ToPlayer()->GroupEventHappens(PATIENCE_AND_UNDERSTANDING, me);
damage = 0;
EnterEvadeMode();
}
@@ -220,6 +239,19 @@ Purchase requires exalted reputation with Scryers/Aldor, Cenarion Expedition and
##################################################
*/
+enum FlaskVendors
+{
+ ALDOR_REPUTATION = 932,
+ SCRYERS_REPUTATION = 934,
+ THE_SHA_TAR_REPUTATION = 935,
+ CENARION_EXPEDITION_REP = 942,
+ NPC_TEXT_EXALTED_ALDOR = 11083, // (need to be exalted with Sha'tar, Cenarion Expedition and the Aldor)
+ NPC_TEXT_EXALTED_SCRYERS = 11084, // (need to be exalted with Sha'tar, Cenarion Expedition and the Scryers)
+ NPC_TEXT_WELCOME_NAME = 11085, // Access granted
+ ARCANIST_XORITH = 23483, // Scryer Apothecary
+ HALDOR_THE_COMPULSIVE = 23484 // Aldor Apothecary
+};
+
class npc_shattrathflaskvendors : public CreatureScript
{
public:
@@ -236,31 +268,31 @@ public:
bool OnGossipHello(Player* player, Creature* creature) override
{
- if (creature->GetEntry() == 23484)
+ if (creature->GetEntry() == HALDOR_THE_COMPULSIVE)
{
// Aldor vendor
- if (creature->IsVendor() && (player->GetReputationRank(932) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED))
+ if (creature->IsVendor() && (player->GetReputationRank(ALDOR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(THE_SHA_TAR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(CENARION_EXPEDITION_REP) == REP_EXALTED))
{
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
- player->SEND_GOSSIP_MENU(11085, creature->GetGUID());
+ player->SEND_GOSSIP_MENU(NPC_TEXT_WELCOME_NAME, creature->GetGUID());
}
else
{
- player->SEND_GOSSIP_MENU(11083, creature->GetGUID());
+ player->SEND_GOSSIP_MENU(NPC_TEXT_EXALTED_ALDOR, creature->GetGUID());
}
}
- if (creature->GetEntry() == 23483)
+ if (creature->GetEntry() == ARCANIST_XORITH)
{
// Scryers vendor
- if (creature->IsVendor() && (player->GetReputationRank(934) == REP_EXALTED) && (player->GetReputationRank(935) == REP_EXALTED) && (player->GetReputationRank(942) == REP_EXALTED))
+ if (creature->IsVendor() && (player->GetReputationRank(SCRYERS_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(THE_SHA_TAR_REPUTATION) == REP_EXALTED) && (player->GetReputationRank(CENARION_EXPEDITION_REP) == REP_EXALTED))
{
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_VENDOR, GOSSIP_TEXT_BROWSE_GOODS, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_TRADE);
- player->SEND_GOSSIP_MENU(11085, creature->GetGUID());
+ player->SEND_GOSSIP_MENU(NPC_TEXT_WELCOME_NAME, creature->GetGUID());
}
else
{
- player->SEND_GOSSIP_MENU(11084, creature->GetGUID());
+ player->SEND_GOSSIP_MENU(NPC_TEXT_EXALTED_SCRYERS, creature->GetGUID());
}
}
@@ -272,7 +304,13 @@ public:
# npc_zephyr
######*/
-#define GOSSIP_HZ "Take me to the Caverns of Time."
+enum Zephyr
+{
+ OPTION_ID_TAKE_ME_TO_C_O_T = 0,
+ KEEPERS_OF_TIME_REPUTATION = 989,
+ MENU_ID_TAKE_ME_TO_C_O_T = 9205,
+ TELEPORT_CAVERNS_OF_TIME = 37778
+};
class npc_zephyr : public CreatureScript
{
@@ -283,15 +321,15 @@ public:
{
player->PlayerTalkClass->ClearMenus();
if (action == GOSSIP_ACTION_INFO_DEF+1)
- player->CastSpell(player, 37778, false);
+ player->CastSpell(player, TELEPORT_CAVERNS_OF_TIME, false);
return true;
}
bool OnGossipHello(Player* player, Creature* creature) override
{
- if (player->GetReputationRank(989) >= REP_REVERED)
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_HZ, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
+ if (player->GetReputationRank(KEEPERS_OF_TIME_REPUTATION) >= REP_REVERED)
+ player->ADD_GOSSIP_ITEM_DB(MENU_ID_TAKE_ME_TO_C_O_T, OPTION_ID_TAKE_ME_TO_C_O_T, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
@@ -305,28 +343,29 @@ public:
enum KServant
{
- SAY1 = 0,
- WHISP1 = 1,
- WHISP2 = 2,
- WHISP3 = 3,
- WHISP4 = 4,
- WHISP5 = 5,
- WHISP6 = 6,
- WHISP7 = 7,
- WHISP8 = 8,
- WHISP9 = 9,
- WHISP10 = 10,
- WHISP11 = 11,
- WHISP12 = 12,
- WHISP13 = 13,
- WHISP14 = 14,
- WHISP15 = 15,
- WHISP16 = 16,
- WHISP17 = 17,
- WHISP18 = 18,
- WHISP19 = 19,
- WHISP20 = 20,
- WHISP21 = 21
+ SAY1 = 0,
+ WHISP1 = 1,
+ WHISP2 = 2,
+ WHISP3 = 3,
+ WHISP4 = 4,
+ WHISP5 = 5,
+ WHISP6 = 6,
+ WHISP7 = 7,
+ WHISP8 = 8,
+ WHISP9 = 9,
+ WHISP10 = 10,
+ WHISP11 = 11,
+ WHISP12 = 12,
+ WHISP13 = 13,
+ WHISP14 = 14,
+ WHISP15 = 15,
+ WHISP16 = 16,
+ WHISP17 = 17,
+ WHISP18 = 18,
+ WHISP19 = 19,
+ WHISP20 = 20,
+ WHISP21 = 21,
+ CITY_OF_LIGHT = 10211
};
class npc_kservant : public CreatureScript
@@ -417,7 +456,7 @@ public:
break;
case 56:
Talk(WHISP21, player);
- player->GroupEventHappens(10211, me);
+ player->GroupEventHappens(CITY_OF_LIGHT, me);
break;
}
}
@@ -429,7 +468,7 @@ public:
return;
Player* player = who->ToPlayer();
- if (player && player->GetQuestStatus(10211) == QUEST_STATUS_INCOMPLETE)
+ if (player && player->GetQuestStatus(CITY_OF_LIGHT) == QUEST_STATUS_INCOMPLETE)
{
float Radius = 10.0f;
if (me->IsWithinDistInMap(who, Radius))
@@ -443,43 +482,6 @@ public:
};
};
-/*######
-# npc_ishanah
-######*/
-
-#define ISANAH_GOSSIP_1 "Who are the Sha'tar?"
-#define ISANAH_GOSSIP_2 "Isn't Shattrath a draenei city? Why do you allow others here?"
-
-class npc_ishanah : public CreatureScript
-{
-public:
- npc_ishanah() : CreatureScript("npc_ishanah") { }
-
- bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
- {
- player->PlayerTalkClass->ClearMenus();
- if (action == GOSSIP_ACTION_INFO_DEF+1)
- player->SEND_GOSSIP_MENU(9458, creature->GetGUID());
- else if (action == GOSSIP_ACTION_INFO_DEF+2)
- player->SEND_GOSSIP_MENU(9459, creature->GetGUID());
-
- return true;
- }
-
- bool OnGossipHello(Player* player, Creature* creature) override
- {
- if (creature->IsQuestGiver())
- player->PrepareQuestMenu(creature->GetGUID());
-
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
- player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, ISANAH_GOSSIP_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
-
- player->SEND_GOSSIP_MENU(player->GetGossipTextId(creature), creature->GetGUID());
-
- return true;
- }
-};
-
void AddSC_shattrath_city()
{
new npc_raliq_the_drunk();
@@ -487,5 +489,4 @@ void AddSC_shattrath_city()
new npc_shattrathflaskvendors();
new npc_zephyr();
new npc_kservant();
- new npc_ishanah();
}
diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp
index 80b3a00774b..113b14a0d54 100644
--- a/src/server/scripts/Pet/pet_dk.cpp
+++ b/src/server/scripts/Pet/pet_dk.cpp
@@ -103,8 +103,8 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript
//! HACK: Creature's can't have MOVEMENTFLAG_FLYING
// Fly Away
me->SetCanFly(true);
- me->SetSpeed(MOVE_FLIGHT, 0.75f, true);
- me->SetSpeed(MOVE_RUN, 0.75f, true);
+ me->SetSpeedRate(MOVE_FLIGHT, 0.75f);
+ me->SetSpeedRate(MOVE_RUN, 0.75f);
float x = me->GetPositionX() + 20 * std::cos(me->GetOrientation());
float y = me->GetPositionY() + 20 * std::sin(me->GetOrientation());
float z = me->GetPositionZ() + 40;
diff --git a/src/server/scripts/ScriptLoader.cpp b/src/server/scripts/ScriptLoader.cpp
deleted file mode 100644
index 57c848d5981..00000000000
--- a/src/server/scripts/ScriptLoader.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "ScriptLoader.h"
-#include "World.h"
-
-void AddSpellsScripts();
-void AddCommandsScripts();
-
-#ifdef SCRIPTS
-void AddWorldScripts();
-void AddEasternKingdomsScripts();
-void AddKalimdorScripts();
-void AddOutlandScripts();
-void AddNorthrendScripts();
-void AddEventsScripts();
-void AddPetScripts();
-void AddOutdoorPvPScripts();
-void AddCustomScripts();
-#endif
-
-void AddScripts()
-{
- AddSpellsScripts();
- AddCommandsScripts();
-#ifdef SCRIPTS
- AddWorldScripts();
- AddEasternKingdomsScripts();
- AddKalimdorScripts();
- AddOutlandScripts();
- AddNorthrendScripts();
- AddEventsScripts();
- AddPetScripts();
- AddOutdoorPvPScripts();
- AddCustomScripts();
-#endif
-}
diff --git a/src/server/scripts/ScriptLoader.cpp.in.cmake b/src/server/scripts/ScriptLoader.cpp.in.cmake
new file mode 100644
index 00000000000..33c336a9a93
--- /dev/null
+++ b/src/server/scripts/ScriptLoader.cpp.in.cmake
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008-2016 TrinityCore <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+// This file was created automatically from your script configuration!
+// Use CMake to reconfigure this file, never change it on your own!
+
+#cmakedefine TRINITY_IS_DYNAMIC_SCRIPTLOADER
+
+#include "Define.h"
+#include <vector>
+#include <string>
+
+@TRINITY_SCRIPTS_FORWARD_DECL@
+#ifdef TRINITY_IS_DYNAMIC_SCRIPTLOADER
+# include "revision_data.h"
+# define TC_SCRIPT_API TC_API_EXPORT
+extern "C" {
+
+/// Exposed in script modules to return the script module revision hash.
+TC_SCRIPT_API char const* GetScriptModuleRevisionHash()
+{
+ return _HASH;
+}
+
+/// Exposed in script module to return the name of the script module
+/// contained in this shared library.
+TC_SCRIPT_API char const* GetScriptModule()
+{
+ return "@TRINITY_CURRENT_SCRIPT_PROJECT@";
+}
+
+#else
+# include "ScriptLoader.h"
+# define TC_SCRIPT_API
+#endif
+
+/// Exposed in script modules to register all scripts to the ScriptMgr.
+TC_SCRIPT_API void AddScripts()
+{
+@TRINITY_SCRIPTS_INVOKE@}
+
+/// Exposed in script modules to get the build directive of the module.
+TC_SCRIPT_API char const* GetBuildDirective()
+{
+ return _BUILD_DIRECTIVE;
+}
+
+#ifdef TRINITY_IS_DYNAMIC_SCRIPTLOADER
+} // extern "C"
+#endif
diff --git a/src/server/scripts/PrecompiledHeaders/ScriptPCH.cpp b/src/server/scripts/ScriptPCH.cpp
index 41fecf3c60d..41fecf3c60d 100644
--- a/src/server/scripts/PrecompiledHeaders/ScriptPCH.cpp
+++ b/src/server/scripts/ScriptPCH.cpp
diff --git a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h b/src/server/scripts/ScriptPCH.h
index 1cd25309055..1cd25309055 100644
--- a/src/server/scripts/PrecompiledHeaders/ScriptPCH.h
+++ b/src/server/scripts/ScriptPCH.h
diff --git a/src/server/scripts/Spells/spell_item.cpp b/src/server/scripts/Spells/spell_item.cpp
index 0abff255e4b..84c67bad63b 100644
--- a/src/server/scripts/Spells/spell_item.cpp
+++ b/src/server/scripts/Spells/spell_item.cpp
@@ -201,6 +201,55 @@ class spell_item_blessing_of_ancient_kings : public SpellScriptLoader
}
};
+// 47770 - Roll Dice
+class spell_item_decahedral_dwarven_dice : public SpellScriptLoader
+{
+ public:
+ spell_item_decahedral_dwarven_dice() : SpellScriptLoader("spell_item_decahedral_dwarven_dice") { }
+
+ class spell_item_decahedral_dwarven_dice_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_item_decahedral_dwarven_dice_SpellScript);
+
+ enum
+ {
+ TEXT_DECAHEDRAL_DWARVEN_DICE = 26147
+ };
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sObjectMgr->GetBroadcastText(TEXT_DECAHEDRAL_DWARVEN_DICE))
+ return false;
+ return true;
+ }
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->TextEmote(TEXT_DECAHEDRAL_DWARVEN_DICE, GetHitUnit());
+
+ static uint32 const minimum = 1;
+ static uint32 const maximum = 100;
+
+ GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_decahedral_dwarven_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_item_decahedral_dwarven_dice_SpellScript();
+ }
+};
+
// 8342 - Defibrillate (Goblin Jumper Cables) have 33% chance on success
// 22999 - Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
// 54732 - Defibrillate (Gnomish Army Knife) have 67% chance on success
@@ -1319,6 +1368,57 @@ class spell_item_underbelly_elixir : public SpellScriptLoader
}
};
+// 47776 - Roll 'dem Bones
+class spell_item_worn_troll_dice : public SpellScriptLoader
+{
+ public:
+ spell_item_worn_troll_dice() : SpellScriptLoader("spell_item_worn_troll_dice") { }
+
+ class spell_item_worn_troll_dice_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_item_worn_troll_dice_SpellScript);
+
+ enum
+ {
+ TEXT_WORN_TROLL_DICE = 26152
+ };
+
+ bool Validate(SpellInfo const* /*spellInfo*/) override
+ {
+ if (!sObjectMgr->GetBroadcastText(TEXT_WORN_TROLL_DICE))
+ return false;
+ return true;
+ }
+
+ bool Load() override
+ {
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ GetCaster()->TextEmote(TEXT_WORN_TROLL_DICE, GetHitUnit());
+
+ static uint32 const minimum = 1;
+ static uint32 const maximum = 6;
+
+ // roll twice
+ GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
+ GetCaster()->ToPlayer()->DoRandomRoll(minimum, maximum);
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_item_worn_troll_dice_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_item_worn_troll_dice_SpellScript();
+ }
+};
+
enum AirRifleSpells
{
SPELL_AIR_RIFLE_HOLD_VISUAL = 65582,
@@ -2682,6 +2782,7 @@ void AddSC_item_spell_scripts()
new spell_item_aegis_of_preservation();
new spell_item_arcane_shroud();
new spell_item_blessing_of_ancient_kings();
+ new spell_item_decahedral_dwarven_dice();
new spell_item_defibrillate("spell_item_goblin_jumper_cables", 67, SPELL_GOBLIN_JUMPER_CABLES_FAIL);
new spell_item_defibrillate("spell_item_goblin_jumper_cables_xl", 50, SPELL_GOBLIN_JUMPER_CABLES_XL_FAIL);
new spell_item_defibrillate("spell_item_gnomish_army_knife", 33);
@@ -2706,6 +2807,7 @@ void AddSC_item_spell_scripts()
new spell_item_six_demon_bag();
new spell_item_the_eye_of_diminution();
new spell_item_underbelly_elixir();
+ new spell_item_worn_troll_dice();
new spell_item_red_rider_air_rifle();
new spell_item_create_heart_candy();
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 3121a18734d..ae761413ca5 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -1707,7 +1707,7 @@ enum Quest13291_13292_13239_13261Data
NPC_SKYTALON = 31583,
NPC_DECOY = 31578,
// Spells
- SPELL_RIDE = 56687
+ SPELL_RIDE = 59319
};
class spell_q13291_q13292_q13239_q13261_frostbrood_skytalon_grab_decoy : public SpellScriptLoader
diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp
index 1f89720803d..65dec74414b 100644
--- a/src/server/scripts/World/boss_emerald_dragons.cpp
+++ b/src/server/scripts/World/boss_emerald_dragons.cpp
@@ -205,7 +205,7 @@ class npc_dream_fog : public CreatureScript
}
// Seeping fog movement is slow enough for a player to be able to walk backwards and still outpace it
me->SetWalk(true);
- me->SetSpeed(MOVE_WALK, 0.75f);
+ me->SetSpeedRate(MOVE_WALK, 0.75f);
}
else
_roamTimer -= diff;
diff --git a/src/server/scripts/World/go_scripts.cpp b/src/server/scripts/World/go_scripts.cpp
index 3094ecd660a..8f2ea5887d2 100644
--- a/src/server/scripts/World/go_scripts.cpp
+++ b/src/server/scripts/World/go_scripts.cpp
@@ -1171,7 +1171,7 @@ public:
player->CastSpell(player, SPELL_CLEANSING_SOUL);
player->SetStandState(UNIT_STAND_STATE_SIT);
}
- return true;
+ return true;
}
};
diff --git a/src/server/scripts/World/item_scripts.cpp b/src/server/scripts/World/item_scripts.cpp
index f4241ba0819..52174e1b012 100644
--- a/src/server/scripts/World/item_scripts.cpp
+++ b/src/server/scripts/World/item_scripts.cpp
@@ -57,18 +57,18 @@ public:
//for special scripts
switch (itemId)
{
- case 24538:
+ case 24538:
if (player->GetAreaId() != 3628)
disabled = true;
- break;
- case 34489:
+ break;
+ case 34489:
if (player->GetZoneId() != 4080)
disabled = true;
- break;
- case 34475:
- if (const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(SPELL_ARCANE_CHARGES))
+ break;
+ case 34475:
+ if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(SPELL_ARCANE_CHARGES))
Spell::SendCastResult(player, spellInfo, 1, SPELL_FAILED_NOT_ON_GROUND);
- break;
+ break;
}
// allow use in flight only
diff --git a/src/server/shared/DataStores/DBCStore.h b/src/server/shared/DataStores/DBCStore.h
index b93bbdaea12..7c2cab1e36a 100644
--- a/src/server/shared/DataStores/DBCStore.h
+++ b/src/server/shared/DataStores/DBCStore.h
@@ -25,6 +25,121 @@
#include "DatabaseWorkerPool.h"
#include "Implementation/WorldDatabase.h"
#include "DatabaseEnv.h"
+#include <G3D/Vector3.h>
+#include <G3D/AABox.h>
+
+ // Structures for M4 file. Source: https://wowdev.wiki
+template<typename T>
+struct M2SplineKey
+{
+ T p0;
+ T p1;
+ T p2;
+};
+
+struct M2Header
+{
+ char Magic[4]; // "MD20"
+ uint32 Version; // The version of the format.
+ uint32 lName; // Length of the model's name including the trailing \0
+ uint32 ofsName; // Offset to the name, it seems like models can get reloaded by this name.should be unique, i guess.
+ uint32 GlobalModelFlags; // 0x0001: tilt x, 0x0002: tilt y, 0x0008: add 2 fields in header, 0x0020: load .phys data (MoP+), 0x0080: has _lod .skin files (MoP?+), 0x0100: is camera related.
+ uint32 nGlobalSequences;
+ uint32 ofsGlobalSequences; // A list of timestamps.
+ uint32 nAnimations;
+ uint32 ofsAnimations; // Information about the animations in the model.
+ uint32 nAnimationLookup;
+ uint32 ofsAnimationLookup; // Mapping of global IDs to the entries in the Animation sequences block.
+ uint32 nBones; // MAX_BONES = 0x100
+ uint32 ofsBones; // Information about the bones in this model.
+ uint32 nKeyBoneLookup;
+ uint32 ofsKeyBoneLookup; // Lookup table for key skeletal bones.
+ uint32 nVertices;
+ uint32 ofsVertices; // Vertices of the model.
+ uint32 nViews; // Views (LOD) are now in .skins.
+ uint32 nSubmeshAnimations;
+ uint32 ofsSubmeshAnimations; // Submesh color and alpha animations definitions.
+ uint32 nTextures;
+ uint32 ofsTextures; // Textures of this model.
+ uint32 nTransparency;
+ uint32 ofsTransparency; // Transparency of textures.
+ uint32 nUVAnimation;
+ uint32 ofsUVAnimation;
+ uint32 nTexReplace;
+ uint32 ofsTexReplace; // Replaceable Textures.
+ uint32 nRenderFlags;
+ uint32 ofsRenderFlags; // Blending modes / render flags.
+ uint32 nBoneLookupTable;
+ uint32 ofsBoneLookupTable; // A bone lookup table.
+ uint32 nTexLookup;
+ uint32 ofsTexLookup; // The same for textures.
+ uint32 nTexUnits; // possibly removed with cata?!
+ uint32 ofsTexUnits; // And texture units. Somewhere they have to be too.
+ uint32 nTransLookup;
+ uint32 ofsTransLookup; // Everything needs its lookup. Here are the transparencies.
+ uint32 nUVAnimLookup;
+ uint32 ofsUVAnimLookup;
+ G3D::AABox BoundingBox; // min/max( [1].z, 2.0277779f ) - 0.16f seems to be the maximum camera height
+ float BoundingSphereRadius;
+ G3D::AABox CollisionBox;
+ float CollisionSphereRadius;
+ uint32 nBoundingTriangles;
+ uint32 ofsBoundingTriangles; // Our bounding volumes. Similar structure like in the old ofsViews.
+ uint32 nBoundingVertices;
+ uint32 ofsBoundingVertices;
+ uint32 nBoundingNormals;
+ uint32 ofsBoundingNormals;
+ uint32 nAttachments;
+ uint32 ofsAttachments; // Attachments are for weapons etc.
+ uint32 nAttachLookup;
+ uint32 ofsAttachLookup; // Of course with a lookup.
+ uint32 nEvents;
+ uint32 ofsEvents; // Used for playing sounds when dying and a lot else.
+ uint32 nLights;
+ uint32 ofsLights; // Lights are mainly used in loginscreens but in wands and some doodads too.
+ uint32 nCameras; // Format of Cameras changed with version 271!
+ uint32 ofsCameras; // The cameras are present in most models for having a model in the Character-Tab.
+ uint32 nCameraLookup;
+ uint32 ofsCameraLookup; // And lookup-time again.
+ uint32 nRibbonEmitters;
+ uint32 ofsRibbonEmitters; // Things swirling around. See the CoT-entrance for light-trails.
+ uint32 nParticleEmitters;
+ uint32 ofsParticleEmitters; // Spells and weapons, doodads and loginscreens use them. Blood dripping of a blade? Particles.
+ uint32 nBlendMaps; // This has to deal with blending. Exists IFF (flags & 0x8) != 0. When set, textures blending is overriden by the associated array. See M2/WotLK#Blend_mode_overrides
+ uint32 ofsBlendMaps; // Same as above. Points to an array of uint16 of nBlendMaps entries -- From WoD information.};
+};
+
+struct M2Array
+{
+ uint32_t number;
+ uint32 offset_elements;
+};
+struct M2Track
+{
+ uint16_t interpolation_type;
+ uint16_t global_sequence;
+ M2Array timestamps;
+ M2Array values;
+};
+
+struct M2Camera
+{
+ uint32_t type; // 0: portrait, 1: characterinfo; -1: else (flyby etc.); referenced backwards in the lookup table.
+ float fov; // No radians, no degrees. Multiply by 35 to get degrees.
+ float far_clip;
+ float near_clip;
+ M2Track positions; // How the camera's position moves. Should be 3*3 floats.
+ G3D::Vector3 position_base;
+ M2Track target_positions; // How the target moves. Should be 3*3 floats.
+ G3D::Vector3 target_position_base;
+ M2Track rolldata; // The camera can have some roll-effect. Its 0 to 2*Pi.
+};
+
+struct FlyByCamera
+{
+ uint32 timeStamp;
+ G3D::Vector4 locations;
+};
struct SqlDbc
{
diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt
index 7923b239854..0de8d6054f3 100644
--- a/src/server/worldserver/CMakeLists.txt
+++ b/src/server/worldserver/CMakeLists.txt
@@ -48,6 +48,7 @@ set_target_properties(worldserver PROPERTIES LINK_FLAGS "${worldserver_LINK_FLAG
target_link_libraries(worldserver
PUBLIC
scripts
+ game
gsoap
readline)
@@ -68,6 +69,11 @@ set_target_properties(worldserver
FOLDER
"server")
+# Add all dynamic projects as dependency to the worldserver
+if (WORLDSERVER_DYNAMIC_SCRIPT_MODULES_DEPENDENCIES)
+ add_dependencies(worldserver ${WORLDSERVER_DYNAMIC_SCRIPT_MODULES_DEPENDENCIES})
+endif()
+
if( WIN32 )
if ( MSVC )
add_custom_command(TARGET worldserver
diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp
index c047c1fafc3..f4d736ac675 100644
--- a/src/server/worldserver/Main.cpp
+++ b/src/server/worldserver/Main.cpp
@@ -24,6 +24,7 @@
#include <openssl/crypto.h>
#include <boost/asio/io_service.hpp>
#include <boost/asio/deadline_timer.hpp>
+#include <boost/filesystem/path.hpp>
#include <boost/program_options.hpp>
#include "Common.h"
@@ -39,6 +40,7 @@
#include "InstanceSaveMgr.h"
#include "ObjectAccessor.h"
#include "ScriptMgr.h"
+#include "ScriptReloadMgr.h"
#include "ScriptLoader.h"
#include "OutdoorPvP/OutdoorPvPMgr.h"
#include "BattlegroundMgr.h"
@@ -52,6 +54,7 @@
#include "AppenderDB.h"
using namespace boost::program_options;
+namespace fs = boost::filesystem;
#ifndef _TRINITY_CORE_CONFIG
#define _TRINITY_CORE_CONFIG "worldserver.conf"
@@ -89,14 +92,14 @@ void ClearOnlineAccounts();
void ShutdownCLIThread(std::thread* cliThread);
void ShutdownThreadPool(std::vector<std::thread>& threadPool);
bool LoadRealmInfo();
-variables_map GetConsoleArguments(int argc, char** argv, std::string& cfg_file, std::string& cfg_service);
+variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& cfg_service);
/// Launch the Trinity server
extern int main(int argc, char** argv)
{
signal(SIGABRT, &Trinity::AbortHandler);
- std::string configFile = _TRINITY_CORE_CONFIG;
+ auto configFile = fs::absolute(_TRINITY_CORE_CONFIG);
std::string configService;
auto vm = GetConsoleArguments(argc, argv, configFile, configService);
@@ -114,7 +117,9 @@ extern int main(int argc, char** argv)
#endif
std::string configError;
- if (!sConfigMgr->LoadInitial(configFile, configError))
+ if (!sConfigMgr->LoadInitial(configFile.generic_string(),
+ std::vector<std::string>(argv, argv + argc),
+ configError))
{
printf("Error in config file: %s\n", configError.c_str());
return 1;
@@ -135,7 +140,7 @@ extern int main(int argc, char** argv)
TC_LOG_INFO("server.worldserver", " \\/_/\\/_/ \\/_/\\/_/\\/_/\\/_/\\/__/ `/___/> \\");
TC_LOG_INFO("server.worldserver", " C O R E /\\___/");
TC_LOG_INFO("server.worldserver", "http://TrinityCore.org \\/__/\n");
- TC_LOG_INFO("server.worldserver", "Using configuration file %s.", configFile.c_str());
+ TC_LOG_INFO("server.worldserver", "Using configuration file %s.", sConfigMgr->GetFilename().c_str());
TC_LOG_INFO("server.worldserver", "Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
TC_LOG_INFO("server.worldserver", "Using Boost version: %i.%i.%i", BOOST_VERSION / 100000, BOOST_VERSION / 100 % 1000, BOOST_VERSION % 100);
@@ -271,6 +276,7 @@ extern int main(int argc, char** argv)
sOutdoorPvPMgr->Die();
sMapMgr->UnloadAll(); // unload all grids (including locked in memory)
sScriptMgr->Unload();
+ sScriptReloadMgr->Unload();
// set server offline
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag | %u WHERE id = '%d'", REALM_FLAG_OFFLINE, realm.Id.Realm);
@@ -569,7 +575,7 @@ void ClearOnlineAccounts()
/// @}
-variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService)
+variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, std::string& configService)
{
// Silences warning about configService not be used if the OS is not Windows
(void)configService;
@@ -578,7 +584,8 @@ variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile
all.add_options()
("help,h", "print usage message")
("version,v", "print version build info")
- ("config,c", value<std::string>(&configFile)->default_value(_TRINITY_CORE_CONFIG), "use <arg> as configuration file")
+ ("config,c", value<fs::path>(&configFile)->default_value(fs::absolute(_TRINITY_CORE_CONFIG)),
+ "use <arg> as configuration file")
;
#ifdef _WIN32
options_description win("Windows platform specific options");
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 7c512d8ae6e..519a3dfb7e3 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -12,6 +12,7 @@
# SERVER LOGGING
# SERVER SETTINGS
# UPDATE SETTINGS
+# HOTSWAP SETTINGS
# WARDEN SETTINGS
# PLAYER INTERACTION
# CREATURE SETTINGS
@@ -724,7 +725,7 @@ CharacterCreating.Disabled.RaceMask = 0
# 2 - (Disabled, Paladin)
# 4 - (Disabled, Hunter)
# 8 - (Disabled, Rogue)
-# 16 - (Disabled, Undead)
+# 16 - (Disabled, Priest)
# 32 - (Disabled, Death Knight)
# 64 - (Disabled, Shaman)
# 128 - (Disabled, Mage)
@@ -1280,6 +1281,78 @@ Updates.CleanDeadRefMaxCount = 3
###################################################################################################
###################################################################################################
+# HOTSWAP SETTINGS
+#
+# HotSwap.Enabled (Requires compilation with DYNAMIC_LINKING=1)
+# Description: Enables dynamic script hotswapping.
+# Reloads scripts on changes.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+HotSwap.Enabled = 1
+
+#
+# HotSwap.ScriptDir
+# Description: Directory containing the script shared libraries (.dll/.so).
+# Example: "/usr/local/scripts"
+# Default: "scripts"
+
+HotSwap.ScriptDir = "scripts"
+
+# HotSwap.EnableReCompiler
+# Description: Enables the dynamic script recompiler.
+# Watches your script source directories and recompiles the
+# script modules on changes.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+HotSwap.EnableReCompiler = 1
+
+# HotSwap.EnableEarlyTermination
+# Description: Terminate the build of a module when an associated
+# source file was changed meanwhile.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+HotSwap.EnableEarlyTermination = 1
+
+# HotSwap.EnableBuildFileRecreation
+# Description: Recreate build files when sources to a module
+# were added or removed.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+HotSwap.EnableBuildFileRecreation = 1
+
+#
+# HotSwap.EnableInstall
+# Description: Enables cmake install after automatic builds have finished
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+HotSwap.EnableInstall = 1
+
+#
+# HotSwap.EnablePrefixCorrection
+# Description: Allows the core to automatic set the CMAKE_INSTALL_PREFIX
+# to it's current location in the filesystem.
+# Default: 1 - (Enabled)
+# 0 - (Disabled)
+
+HotSwap.EnablePrefixCorrection = 1
+
+# HotSwap.ReCompilerBuildType
+# Description: Defines the build type of the builds invoked by the recompiler.
+# Default: "" - Built-in build type of the module is used.
+# "Release" - Release builds only
+# "Debug" - Debug builds only
+
+HotSwap.ReCompilerBuildType = ""
+
+#
+###################################################################################################
+
+###################################################################################################
# WARDEN SETTINGS
#
# Warden.Enabled
@@ -1585,6 +1658,14 @@ ListenRange.TextEmote = 40
ListenRange.Yell = 300
#
+# Creature.MovingStopTimeForPlayer
+# Description: Time (in milliseconds) during which creature will not move after
+# interaction with player.
+# Default: 180000
+
+Creature.MovingStopTimeForPlayer = 180000
+
+#
###################################################################################################
###################################################################################################
@@ -3220,7 +3301,6 @@ AuctionHouseBot.Class.Key = 1
AuctionHouseBot.Class.Misc = 5
AuctionHouseBot.Class.Glyph = 3
-
#
###################################################################################################
@@ -3509,6 +3589,7 @@ Appender.DBErrors=2,2,0,DBErrors.log
Logger.root=5,Console Server
Logger.server=3,Console Server
Logger.commands.gm=3,Console GM
+Logger.scripts.hotswap=3,Console Server
Logger.sql.sql=5,Console DBErrors
Logger.sql.updates=3,Console Server
Logger.mmaps=3,Server
diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp
index f3a761fd437..1d84fc75d27 100644
--- a/src/tools/map_extractor/System.cpp
+++ b/src/tools/map_extractor/System.cpp
@@ -53,12 +53,13 @@ char input_path[MAX_PATH_LENGTH] = ".";
// **************************************************
enum Extract
{
- EXTRACT_MAP = 1,
- EXTRACT_DBC = 2
+ EXTRACT_MAP = 1,
+ EXTRACT_DBC = 2,
+ EXTRACT_CAMERA = 4
};
// Select data for extract
-int CONF_extract = EXTRACT_MAP | EXTRACT_DBC;
+int CONF_extract = EXTRACT_MAP | EXTRACT_DBC | EXTRACT_CAMERA;
// This option allow limit minimum height to some value (Allow save some memory)
bool CONF_allow_height_limit = true;
float CONF_use_minHeight = -500.0f;
@@ -103,7 +104,7 @@ void Usage(char* prg)
"%s -[var] [value]\n"\
"-i set input path (max %d characters)\n"\
"-o set output path (max %d characters)\n"\
- "-e extract only MAP(1)/DBC(2) - standard: both(3)\n"\
+ "-e extract only MAP(1)/DBC(2)/Camera(4) - standard: all(7)\n"\
"-f height stored as int (less map size but lost some accuracy) 1 by default\n"\
"Example: %s -f 0 -i \"c:\\games\\game\"", prg, MAX_PATH_LENGTH - 1, MAX_PATH_LENGTH - 1, prg);
exit(1);
@@ -151,7 +152,7 @@ void HandleArgs(int argc, char * arg[])
if(c + 1 < argc) // all ok
{
CONF_extract=atoi(arg[(c++) + 1]);
- if(!(CONF_extract > 0 && CONF_extract < 4))
+ if(!(CONF_extract > 0 && CONF_extract < 8))
Usage(arg[0]);
}
else
@@ -1025,6 +1026,56 @@ void ExtractDBCFiles(int locale, bool basicLocale)
printf("Extracted %u DBC files\n\n", count);
}
+void ExtractCameraFiles(int locale, bool basicLocale)
+{
+ printf("Extracting camera files...\n");
+ DBCFile camdbc("DBFilesClient\\CinematicCamera.dbc");
+
+ if (!camdbc.open())
+ {
+ printf("Unable to open CinematicCamera.dbc. Camera extract aborted.\n");
+ return;
+ }
+
+ // get camera file list from DBC
+ std::vector<std::string> camerafiles;
+ size_t cam_count = camdbc.getRecordCount();
+
+ for (uint32 i = 0; i < cam_count; ++i)
+ {
+ std::string camFile(camdbc.getRecord(i).getString(1));
+ size_t loc = camFile.find(".mdx");
+ if (loc != std::string::npos)
+ camFile.replace(loc, 4, ".m2");
+ camerafiles.push_back(std::string(camFile));
+ }
+
+ std::string path = output_path;
+ path += "/Cameras/";
+ CreateDir(path);
+ if (!basicLocale)
+ {
+ path += langs[locale];
+ path += "/";
+ CreateDir(path);
+ }
+
+ // extract M2s
+ uint32 count = 0;
+ for (std::string thisFile : camerafiles)
+ {
+ std::string filename = path;
+ filename += (thisFile.c_str() + strlen("Cameras\\"));
+
+ if (boost::filesystem::exists(filename))
+ continue;
+
+ if (ExtractFile(thisFile.c_str(), filename))
+ ++count;
+ }
+ printf("Extracted %u camera files\n", count);
+}
+
void LoadLocaleMPQFiles(int const locale)
{
std::string fileName = Trinity::StringFormat("%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]);
@@ -1111,6 +1162,19 @@ int main(int argc, char * arg[])
return 0;
}
+ if (CONF_extract & EXTRACT_CAMERA)
+ {
+ printf("Using locale: %s\n", langs[FirstLocale]);
+
+ // Open MPQs
+ LoadLocaleMPQFiles(FirstLocale);
+ LoadCommonMPQFiles();
+
+ ExtractCameraFiles(FirstLocale, true);
+ // Close MPQs
+ CloseMPQFiles();
+ }
+
if (CONF_extract & EXTRACT_MAP)
{
printf("Using locale: %s\n", langs[FirstLocale]);