diff options
84 files changed, 1540 insertions, 689 deletions
diff --git a/.gitignore b/.gitignore index 489df1c251..f243cc106e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,24 @@ +# +# AzerothCore +# + +conf/* +!conf/*.dist +modules/* -*/compiler/config.sh +# +# Allow modules to control git ignoring +# +!modules/* +modules/*/* +!modules/*/.gitignore build*/ + +# +#Generic +# + .directory .mailmap *.orig @@ -27,6 +44,7 @@ CMakeLists.txt.user # exclude in all levels nbproject/ .sync.ffs_db +*.kate-swp .browse.VC* .vscode diff --git a/CMakeLists.txt b/CMakeLists.txt index a57662fd1b..e0be328721 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,11 +28,6 @@ set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1) # set macro-directory set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/src/cmake/macros") -# build in Release-mode by default if not explicitly set -if( NOT CMAKE_BUILD_TYPE ) - set(CMAKE_BUILD_TYPE "Release") -endif() - include(CheckCXXSourceRuns) include(CheckIncludeFiles) @@ -40,7 +35,19 @@ include(CheckIncludeFiles) include(src/cmake/utils.cmake) # set default buildoptions and print them -include(src/cmake/options.cmake) +include(conf/config.cmake.dist) + +# load custom configurations for cmake if exists +if(EXISTS "conf/config.cmake") + include(conf/config.cmake) +endif() + +RUN_HOOK("AFTER_LOAD_CONF") + +# build in Release-mode by default if not explicitly set +if( NOT CMAKE_BUILD_TYPE ) + set(CMAKE_BUILD_TYPE "Release") +endif() # turn off PCH totally if enabled (hidden setting, mainly for devs) if( NOPCH ) @@ -79,9 +86,11 @@ include(src/cmake/showoptions.cmake) # add modules and dependencies AZTH_SUBDIRLIST(sub_DIRS "${CMAKE_SOURCE_DIR}/modules" FALSE FALSE) FOREACH(subdir ${sub_DIRS}) - STRING(REGEX REPLACE "^${CMAKE_SOURCE_DIR}/" "" subdir ${subdir}) - message("Loading module: ${subdir}") - add_subdirectory("${subdir}") + STRING(REGEX REPLACE "^${CMAKE_SOURCE_DIR}/" "" subdir_rel ${subdir}) + if(EXISTS "${subdir}/CMakeLists.txt") + message("Loading module: ${subdir_rel}") + add_subdirectory("${subdir_rel}") + endif() ENDFOREACH() RUN_HOOK("BEFORE_SRC_LOAD") diff --git a/bin/bash_shared/defines.sh b/bin/bash_shared/defines.sh index 67cde98ef9..6020ca871d 100644 --- a/bin/bash_shared/defines.sh +++ b/bin/bash_shared/defines.sh @@ -2,4 +2,6 @@ AZTH_PATH_ROOT=$(readlink -f "$AZTH_PATH_BIN/../") AZTH_PATH_CONF="$AZTH_PATH_ROOT/conf" +AZTH_PATH_MODULES="$AZTH_PATH_ROOT/modules" + AZTH_PATH_CUSTOM=$(readlink -f "$AZTH_PATH_ROOT/../azth_custom") diff --git a/bin/bash_shared/includes.sh b/bin/bash_shared/includes.sh index 3e53937a2b..966e622970 100644 --- a/bin/bash_shared/includes.sh +++ b/bin/bash_shared/includes.sh @@ -5,3 +5,20 @@ AZTH_PATH_SHARED="$AZTH_PATH_BIN/bash_shared" source "$AZTH_PATH_SHARED/defines.sh" source "$AZTH_PATH_SHARED/functions.sh" + +source "$AZTH_PATH_CONF/config.sh.dist" # "hack" to avoid missing conf variables + +if [ -f "$AZTH_PATH_CONF/config.sh" ]; then + source "$AZTH_PATH_CONF/config.sh" # should overwrite previous +fi + +# +# Load modules +# + +for entry in "$AZTH_PATH_MODULES/"*/include.sh +do + if [ -e $entry ]; then + source $entry + fi +done diff --git a/bin/compiler/.gitignore b/bin/compiler/.gitignore new file mode 100644 index 0000000000..ba57f2bccf --- /dev/null +++ b/bin/compiler/.gitignore @@ -0,0 +1,2 @@ +config.sh + diff --git a/bin/compiler/1-clean.sh b/bin/compiler/1-clean.sh index 7fbe9a84b5..fc27e2bedb 100755 --- a/bin/compiler/1-clean.sh +++ b/bin/compiler/1-clean.sh @@ -1,8 +1,5 @@ #!/bin/bash -CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -source "$CURRENT_PATH/includes/common.sh" -source "$CURRENT_PATH/includes/includes.sh" +CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -clean +bash "$CURRENT_PATH/compiler.sh" 1 diff --git a/bin/compiler/2-configure.sh b/bin/compiler/2-configure.sh index 6acc934686..9c610576c0 100755 --- a/bin/compiler/2-configure.sh +++ b/bin/compiler/2-configure.sh @@ -1,8 +1,5 @@ #!/bin/bash -CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -source "$CURRENT_PATH/includes/common.sh" -source "$CURRENT_PATH/includes/includes.sh" +CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -configure +bash "$CURRENT_PATH/compiler.sh" 2 diff --git a/bin/compiler/3-build.sh b/bin/compiler/3-build.sh index 20b77ecb44..126da69cfa 100755 --- a/bin/compiler/3-build.sh +++ b/bin/compiler/3-build.sh @@ -1,8 +1,5 @@ #!/bin/bash -CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" - -source "$CURRENT_PATH/includes/common.sh" -source "$CURRENT_PATH/includes/includes.sh" +CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -build +bash "$CURRENT_PATH/compiler.sh" 3 diff --git a/bin/compiler/README.md b/bin/compiler/README.md index f423501669..c50dae2ec2 100644 --- a/bin/compiler/README.md +++ b/bin/compiler/README.md @@ -1,7 +1,7 @@ ## How to compile: first of all, if you need some custom configuration you have to copy and rename -config.sh.dist in config.sh and configure it +/conf/config.sh.dist in /conf/config.sh and configure it * for a "clean" compilation you must run all scripts in their order: @@ -21,4 +21,4 @@ config.sh.dist in config.sh and configure it ## Note: -For an optimal development process and **really faster** compilation time, is suggested to use clang instead of gcc
\ No newline at end of file +For an optimal development process and **really faster** compilation time, is suggested to use clang instead of gcc diff --git a/bin/compiler/compiler.sh b/bin/compiler/compiler.sh new file mode 100755 index 0000000000..187a16ed14 --- /dev/null +++ b/bin/compiler/compiler.sh @@ -0,0 +1,43 @@ +#!/bin/bash +CURRENT_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +source "$CURRENT_PATH/includes/includes.sh" + +function all() { + clean + configure + build +} + +function run_option() { + if test "${comp_functions[$1-1]+'test'}"; then + ${comp_functions[$1-1]} + else + echo "invalid option" + fi +} + +comp_options=("Clean" "Configure" "Build" "All") +comp_functions=("clean" "configure" "build" "all") + +runHooks "ON_AFTER_OPTIONS" #you can create your custom options + +# push exit after custom options +comp_options+=('Exit') +comp_functions+=('exit 0') + +# run option directly if specified in argument +[ ! -z $1 ] && run_option $1 && exit 0 + +PS3='[ Please enter your choice ]: ' +select opt in "${comp_options[@]}" +do + case $opt in + 'Exit') + break + ;; + *) + run_option $REPLY + ;; + esac +done diff --git a/bin/compiler/config.sh.dist b/bin/compiler/config.sh.dist deleted file mode 100644 index e0b9ba3205..0000000000 --- a/bin/compiler/config.sh.dist +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - - -# set preferred compilers -#CCOMPILERC="/usr/bin/clang-3.6" -#CCOMPILERCC="/usr/bin/clang-3.6" -#CCOMPILERCXX="/usr/bin/clang++-3.6" -CCOMPILERC="/usr/bin/gcc" -CCOMPILERCC="/usr/bin/gcc" -CCOMPILERCXX="/usr/bin/g++" - -# how many thread must be used for compilation ( leave zero to use all available ) -MTHREADS=0 -# enable/disable warnings during compilation -CWARNINGS=1 -# enable/disable some debug informations ( it's not a debug compilation ) -CDEBUG=0 -# specify compilation type -CCTYPE=Release -# compile scripts -CSCRIPTS=1 -# compile server -CSERVERS=1 -# compile tools -CTOOLS=0 -# use precompiled headers ( fatest compilation but not optimized if you change headers often ) -CSCRIPTPCH=1 -CCOREPCH=1 - -# absolute root path of your azerothshard repository -SRCPATH= -# absolute path where binary files must be stored -BINPATH= -# absolute path where config. files must be stored -CONFDIR= - - - diff --git a/bin/compiler/includes/common.sh b/bin/compiler/includes/common.sh deleted file mode 100644 index 61a73ca130..0000000000 --- a/bin/compiler/includes/common.sh +++ /dev/null @@ -1,5 +0,0 @@ -source "./config.sh.dist" # "hack" to avoid missing conf variables - -if [ -f "./config.sh" ]; then - source "./config.sh" # should overwrite previous -fi diff --git a/bin/compiler/includes/defines.sh b/bin/compiler/includes/defines.sh index e6b37f4eae..e8324e92c4 100644 --- a/bin/compiler/includes/defines.sh +++ b/bin/compiler/includes/defines.sh @@ -11,6 +11,6 @@ BUILDPATH=$BINPATH INSTALL_PATH=$(readlink -f "$BINPATH/../") -[ $CCTYPE == "Debug" ] && BUILDPATH="$BUILDPATH/debug/build/" || BUILDPATH="$BUILDPATH/release/build/" +[ $CTYPE == "Debug" ] && BUILDPATH="$BUILDPATH/debug/build/" || BUILDPATH="$BUILDPATH/release/build/" -[ $CCTYPE == "Debug" ] && BINPATH="$BINPATH/debug" || BINPATH="$BINPATH/release" +[ $CTYPE == "Debug" ] && BINPATH="$BINPATH/debug" || BINPATH="$BINPATH/release" diff --git a/bin/compiler/includes/functions.sh b/bin/compiler/includes/functions.sh index ba268173fb..d8fe078b99 100644 --- a/bin/compiler/includes/functions.sh +++ b/bin/compiler/includes/functions.sh @@ -20,7 +20,7 @@ function configure() { echo "Build path: $BUILDPATH" echo "DEBUG info: $CDEBUG" - echo "Compilation type: $CCTYPE" + echo "Compilation type: $CTYPE" # -DCMAKE_BUILD_TYPE=$CCTYPE disable optimization "slow and huge amount of ram" # -DWITH_COREDEBUG=$CDEBUG compiled with debug information @@ -30,8 +30,8 @@ function configure() { cmake $SRCPATH -DCMAKE_INSTALL_PREFIX=$BINPATH -DCONF_DIR=$CONFDIR -DSERVERS=$CSERVERS \ -DSCRIPTS=$CSCRIPTS \ - -DTOOLS=$CTOOLS -DUSE_SCRIPTPCH=$CSCRIPTPCH -DUSE_COREPCH=$CCOREPCH -DWITH_COREDEBUG=$CDEBUG -DCMAKE_BUILD_TYPE=$CCTYPE -DWITH_WARNINGS=$CWARNINGS \ - -DCMAKE_C_COMPILER=$CCOMPILERC -DCMAKE_CXX_COMPILER=$CCOMPILERCXX + -DTOOLS=$CTOOLS -DUSE_SCRIPTPCH=$CSCRIPTPCH -DUSE_COREPCH=$CCOREPCH -DWITH_COREDEBUG=$CDEBUG -DCMAKE_BUILD_TYPE=$CTYPE -DWITH_WARNINGS=$CWARNINGS \ + -DCMAKE_C_COMPILER=$CCOMPILERC -DCMAKE_CXX_COMPILER=$CCOMPILERCXX $CCUSTOMOPTIONS cd $CWD diff --git a/bin/compiler/includes/includes.sh b/bin/compiler/includes/includes.sh index 4150841891..1396accb1f 100644 --- a/bin/compiler/includes/includes.sh +++ b/bin/compiler/includes/includes.sh @@ -4,6 +4,10 @@ source "$CURRENT_PATH/../../bash_shared/includes.sh" AZTH_PATH_COMPILER="$AZTH_PATH_BIN/compiler" +if [ -f "$AZTH_PATH_COMPILER/config.sh" ]; then + source "$AZTH_PATH_COMPILER/config.sh" # should overwrite previous +fi + function azth_on_after_build() { # move the run engine cp -rvf "$AZTH_PATH_BIN/runners/"* "$INSTALL_PATH/bin/" diff --git a/bin/db_assembler/config.sh.dist b/bin/db_assembler/config.sh.dist deleted file mode 100644 index 87f6cbabf6..0000000000 --- a/bin/db_assembler/config.sh.dist +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash - -# 0 if you want create an sql for each kind of following categories -# 1 to create a single big file to import ( suggested for new installations ) -ALL_IN_ONE=0 - -DATABASES=( - "AUTH" - "CHARACTERS" - "WORLD" -) - -OUTPUT_FOLDER="output/" - -# FULL DB -DB_CHARACTERS_PATHS=( - $SRCPATH"/data/sql/databases/characters.sql" -) - -DB_AUTH_PATHS=( - $SRCPATH"/data/sql/databases/auth.sql" -) - -DB_WORLD_PATHS=( - $SRCPATH"/data/sql/databases/world.sql" -) - -# UPDATES -DB_CHARACTERS_UPDATE_PATHS=( - $SRCPATH"/data/sql/updates/characters/" -) - -DB_AUTH_UPDATE_PATHS=( - $SRCPATH"/data/sql/updates/auth/" -) - -DB_WORLD_UPDATE_PATHS=( - $SRCPATH"/data/sql/updates/world/" -) - -# CUSTOM -DB_CHARACTERS_CUSTOM_PATHS=( -) - -DB_AUTH_CUSTOM_PATHS=( -) - -DB_WORLD_CUSTOM_PATHS=( -) diff --git a/bin/db_assembler/db_assembler.sh b/bin/db_assembler/db_assembler.sh index 2a29e2f3f6..1716b71eb9 100755 --- a/bin/db_assembler/db_assembler.sh +++ b/bin/db_assembler/db_assembler.sh @@ -2,128 +2,148 @@ SRCPATH=$(readlink -f "../../") -# -# You can pass latest version as first argument of this script -# -if [ -z "$1" ]; then - read -p "Enter latest sql version ( leave blank to use : 0000_00_00_00 )" $version - version=${version:-0000_00_00_00} +source $SRCPATH"/bin/bash_shared/includes.sh" + +if [ -f "./config.sh" ]; then + source "./config.sh" # should overwrite previous +fi + +unamestr=`uname` +if [[ "$unamestr" == 'Darwin' ]]; then + MD5_CMD="md5" else - version=$1 + MD5_CMD="md5sum" fi -source "./config.sh.dist" # "hack" to avoid missing conf variables +reg_file="$OUTPUT_FOLDER/.zzz_db_assembler_registry.sh" -if [ -f "./config.sh" ]; then - source "./config.sh" # should overwrite previous +declare -A registry + +if [ -f "$reg_file" ]; then + source "$reg_file" fi echo "===== STARTING PROCESS =====" -gtversion="" function assemble() { - database=$1 - start_sql=$2 - - var_full="DB_"$database"_PATHS" - full=${!var_full} - - var_updates="DB_"$database"_UPDATE_PATHS" - updates=${!var_updates} - - var_custom="DB_"$database"_CUSTOM_PATHS" - custom=${!var_custom} - - - suffix_base="" - suffix_upd="" - suffix_custom="" - - if (( $ALL_IN_ONE == 0 )); then - suffix_base="_base" - fi; - - echo "" > $OUTPUT_FOLDER$database$suffix_base".sql" - - - if [ ! ${#full[@]} -eq 0 ]; then - echo "Generating $OUTPUT_FOLDER$database$suffix_based ..." - - for entry in "${full[@]}" - do - if [ ! -z $entry ]; then - if [ -e $entry ]; then - cat "$entry" >> $OUTPUT_FOLDER$database$suffix_base".sql" - fi - fi - done - fi - - if (( $ALL_IN_ONE == 0 )); then - suffix_upd="_updates" - - echo "" > $OUTPUT_FOLDER$database$suffix_upd".sql" - fi; - - if [ ! ${#updates[@]} -eq 0 ]; then - echo "Generating $OUTPUT_FOLDER$database$suffix_upd ..." - - for d in "${updates[@]}" - do - for entry in "$d"/*.sql "$d"/**/*.sql - do - if [ ! -z $d ]; then - file=$(basename $entry) - if [[ "$file" > "$start_sql" ]] - then - if [ -e $entry ]; then - if [[ "$gtversion" < "$file" ]]; then - gtversion=$file - fi - - cat "$entry" >> $OUTPUT_FOLDER$database$suffix_upd".sql" - fi - fi - fi - done - done - fi - - if (( $ALL_IN_ONE == 0 )); then - suffix_custom="_custom" - - echo "" > $OUTPUT_FOLDER$database$suffix_custom".sql" - fi; - - - - if [ ! ${#custom[@]} -eq 0 ]; then - echo "Generating $OUTPUT_FOLDER$database$suffix_custom ..." - - for d in "${custom[@]}" - do - if [ ! -z $d ]; then - for entry in "$d"/*.sql "$d"/**/*.sql - do - if [ -e $entry ]; then - cat "$entry" >> $OUTPUT_FOLDER$database$suffix_custom".sql" - fi - done - fi - done - fi + database=$1 + start_sql=$2 + + var_base="DB_"$database"_PATHS" + base=${!var_base} + + var_updates="DB_"$database"_UPDATE_PATHS" + updates=${!var_updates} + + var_custom="DB_"$database"_CUSTOM_PATHS" + custom=${!var_custom} + + + suffix_base="" + suffix_upd="" + suffix_custom="" + + if (( $ALL_IN_ONE == 0 )); then + suffix_base="_base" + fi; + + echo "" > $OUTPUT_FOLDER$database$suffix_base".sql" + + + if [ ! ${#base[@]} -eq 0 ]; then + echo "Generating $OUTPUT_FOLDER$database$suffix_base ..." + + for d in "${base[@]}" + do + if [ ! -z $d ]; then + for entry in "$d"/*.sql "$d"/**/*.sql + do + if [[ -e $entry ]]; then + cat "$entry" >> $OUTPUT_FOLDER$database$suffix_base".sql" + fi + done + fi + done + fi + + if (( $ALL_IN_ONE == 0 )); then + suffix_upd="_updates" + + echo "" > $OUTPUT_FOLDER$database$suffix_upd".sql" + fi; + + if [ ! ${#updates[@]} -eq 0 ]; then + echo "Generating $OUTPUT_FOLDER$database$suffix_upd ..." + + for d in "${updates[@]}" + do + if [ ! -z $d ]; then + for entry in "$d"/*.sql "$d"/**/*.sql + do + if [[ ! -e $entry ]]; then + continue + fi + + file=$(basename "$entry") + hash=$($MD5_CMD "$entry") + hash="${hash%% *}" #remove file path + if [[ -z ${registry[$hash]} ]]; then + registry["$hash"]="$file" + echo "-- New update sql: "$file + cat "$entry" >> $OUTPUT_FOLDER$database$suffix_upd".sql" + fi + done + fi + done + fi + + if (( $ALL_IN_ONE == 0 )); then + suffix_custom="_custom" + + echo "" > $OUTPUT_FOLDER$database$suffix_custom".sql" + fi; + + + + if [ ! ${#custom[@]} -eq 0 ]; then + echo "Generating $OUTPUT_FOLDER$database$suffix_custom ..." + + for d in "${custom[@]}" + do + if [ ! -z $d ]; then + for entry in "$d"/*.sql "$d"/**/*.sql + do + if [[ ! -e $entry ]]; then + continue + fi + + file=$(basename "$entry") + hash=$($MD5_CMD "$entry") + hash="${hash%% *}" #remove file path + if [[ -z ${registry[$hash]} ]]; then + registry["$hash"]="$file" + echo "-- New custom sql: "$file + cat "$entry" >> $OUTPUT_FOLDER$database$suffix_custom".sql" + fi + done + fi + done + fi } mkdir -p $OUTPUT_FOLDER for db in ${DATABASES[@]} do - assemble "$db" $version".sql" + assemble "$db" $version".sql" done -rm $OUTPUT_FOLDER"ZZZ_latest_version_"* -echo $gtversion > $OUTPUT_FOLDER"ZZZ_latest_version_"${gtversion%.*} +echo "" > $reg_file -echo "===== DONE =====" +for i in "${!registry[@]}" +do + echo "registry['"$i"']='"${registry[$i]}"'" >> "$reg_file" +done +echo "===== DONE =====" diff --git a/bin/runners/config.dist b/bin/runners/config.dist deleted file mode 100644 index 6b5b275544..0000000000 --- a/bin/runners/config.dist +++ /dev/null @@ -1,31 +0,0 @@ -#!/bin/bash - -###################### - -# enable/disable GDB execution -export GDB_ENABLED=0 - -# gdb file -export GDB="" - -# directory where binary are stored -exoirt BINPATH="" - - ### Put here the pid you configured on your worldserver.conf file ### -export SERVERPID="" - -# path to conf file -export CONFIG="" - -# path of log files -export LOGS_PATH=""; - -# exec name -export SERVERBIN="" - -# name of screen service ( for restarter ) -export SCREEN_NAME="" - -###################### - - diff --git a/bin/runners/starter b/bin/runners/starter index 4cd6dd2411..675bb13fb8 100755 --- a/bin/runners/starter +++ b/bin/runners/starter @@ -7,11 +7,10 @@ SYSERR="$5" GBD_ENABLED="$6" if [ $GBD_ENABLED -eq 1 ]; then - echo "run -c $3" > "$GDB_FILE" + echo "set logging on" > "$GDB_FILE" + echo "set debug timestamp" >> "$GDB_FILE" + echo "run -c $3" >> "$GDB_FILE" echo "bt" >> "$GDB_FILE" - echo "bt full" >> "$GDB_FILE" - echo "info threads" >> "$GDB_FILE" - echo "thread apply all bt full" >> "$GDB_FILE" [ ! -f "$SYSLOG" ] && touch "$SYSLOG" [ ! -f "$SYSERR" ] && touch "$SYSERR" @@ -19,4 +18,4 @@ if [ $GBD_ENABLED -eq 1 ]; then gdb -x $GDB_FILE --batch $1 >> "$SYSLOG" 2>> "$SYSERR" elif [ $GBD_ENABLED -eq 0 ]; then "./$1" -c "$CONFIG" -fi
\ No newline at end of file +fi diff --git a/src/cmake/options.cmake b/conf/config.cmake.dist index f8db7e9081..f51b4d8834 100644 --- a/src/cmake/options.cmake +++ b/conf/config.cmake.dist @@ -1,13 +1,3 @@ -# Copyright (C) -# -# 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. - option(SERVERS "Build worldserver and authserver" 1) option(SCRIPTS "Build core with scripts included" 1) option(TOOLS "Build map/vmap/mmap extraction/assembler tools" 0) diff --git a/conf/config.sh.dist b/conf/config.sh.dist new file mode 100644 index 0000000000..f14fe78878 --- /dev/null +++ b/conf/config.sh.dist @@ -0,0 +1,132 @@ +#!/bin/bash + +#!/bin/bash + + +# absolute root path of your azerothshard repository +SRCPATH="$AZTH_PATH_ROOT" +# absolute path where binary files must be stored +BINPATH="$AZTH_PATH_ROOT/build/" +# absolute path where config. files must be stored +CONFDIR="$AZTH_PATH_ROOT/build/etc/" + +############################################## +# +# COMPILER_CONFIGURATIONS +# +############################################## + + +# set preferred compilers +#CCOMPILERC="/usr/bin/clang-3.6" +#CCOMPILERCC="/usr/bin/clang-3.6" +#CCOMPILERCXX="/usr/bin/clang++-3.6" +CCOMPILERC="/usr/bin/gcc" +CCOMPILERCC="/usr/bin/gcc" +CCOMPILERCXX="/usr/bin/g++" + +# how many thread must be used for compilation ( leave zero to use all available ) +MTHREADS=0 +# enable/disable warnings during compilation +CWARNINGS=1 +# enable/disable some debug informations ( it's not a debug compilation ) +CDEBUG=0 +# specify compilation type +CTYPE=Release +# compile scripts +CSCRIPTS=1 +# compile server +CSERVERS=1 +# compile tools +CTOOLS=0 +# use precompiled headers ( fatest compilation but not optimized if you change headers often ) +CSCRIPTPCH=1 +CCOREPCH=1 +# you can add your custom definitions here ( -D ) +CCUSTOMOPTIONS="" + +############################################## +# +# RUNNER CONFIGURATION +# +############################################## + +# enable/disable GDB execution +export GDB_ENABLED=0 + +# gdb file +export GDB="" + +# directory where binary are stored +export BINPATH="" + + ### Put here the pid you configured on your worldserver.conf file ### +export SERVERPID="" + +# path to conf file +export CONFIG="" + +# path of log files +export LOGS_PATH=""; + +# exec name +export SERVERBIN="" + +# name of screen service ( for restarter ) +export SCREEN_NAME="" + + +############################################## +# +# DB ASSEMBLER CONFIGURATIONS +# +############################################## + + +# 0 if you want create an sql for each kind of following categories +# 1 to create a single big file to import ( suggested for new installations ) +ALL_IN_ONE=0 + +DATABASES=( + "AUTH" + "CHARACTERS" + "WORLD" +) + +OUTPUT_FOLDER="output/" + +# FULL DB +DB_CHARACTERS_PATHS=( + $SRCPATH"/data/sql/base/characters" +) + +DB_AUTH_PATHS=( + $SRCPATH"/data/sql/base/auth/" +) + +DB_WORLD_PATHS=( + $SRCPATH"/data/sql/base/world/" +) + +# UPDATES +DB_CHARACTERS_UPDATE_PATHS=( + $SRCPATH"/data/sql/updates/characters/" +) + +DB_AUTH_UPDATE_PATHS=( + $SRCPATH"/data/sql/updates/auth/" +) + +DB_WORLD_UPDATE_PATHS=( + $SRCPATH"/data/sql/updates/world/" +) + +# CUSTOM +DB_CHARACTERS_CUSTOM_PATHS=( +) + +DB_AUTH_CUSTOM_PATHS=( +) + +DB_WORLD_CUSTOM_PATHS=( +) diff --git a/data/doc b/data/doc -Subproject 46489f483fc41a7f1eac208f0c66dc3f4182a3e +Subproject 352f3c6a77c8c455b53b997589f0838afe22b95 diff --git a/data/sql/databases/auth.sql b/data/sql/base/auth/auth.sql index 63f7ea9938..63f7ea9938 100644 --- a/data/sql/databases/auth.sql +++ b/data/sql/base/auth/auth.sql diff --git a/data/sql/databases/characters.sql b/data/sql/base/characters/characters.sql index 84342a891f..84342a891f 100644 --- a/data/sql/databases/characters.sql +++ b/data/sql/base/characters/characters.sql diff --git a/data/sql/databases/world.sql b/data/sql/base/world/world.sql index c036e84061..c036e84061 100644 --- a/data/sql/databases/world.sql +++ b/data/sql/base/world/world.sql diff --git a/data/sql/updates/characters/2016_07_30_00.sql b/data/sql/updates/characters/2016_07_30_00.sql new file mode 100644 index 0000000000..d55f10ae38 --- /dev/null +++ b/data/sql/updates/characters/2016_07_30_00.sql @@ -0,0 +1,25 @@ +ALTER TABLE characters_db_version CHANGE COLUMN 2016_07_10_00 2016_07_30_00 bit; + +CREATE TABLE IF NOT EXISTS `gm_ticket` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `type` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '0 open, 1 closed, 2 character deleted', + `playerGuid` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'Global Unique Identifier of ticket creator', + `name` varchar(12) NOT NULL COMMENT 'Name of ticket creator', + `description` text NOT NULL, + `createTime` int(10) unsigned NOT NULL DEFAULT '0', + `mapId` smallint(5) unsigned NOT NULL DEFAULT '0', + `posX` float NOT NULL DEFAULT '0', + `posY` float NOT NULL DEFAULT '0', + `posZ` float NOT NULL DEFAULT '0', + `lastModifiedTime` int(10) unsigned NOT NULL DEFAULT '0', + `closedBy` int(10) unsigned NOT NULL DEFAULT '0', + `assignedTo` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'GUID of admin to whom ticket is assigned', + `comment` text NOT NULL, + `response` text NOT NULL, + `completed` tinyint(3) unsigned NOT NULL DEFAULT '0', + `escalated` tinyint(3) unsigned NOT NULL DEFAULT '0', + `viewed` tinyint(3) unsigned NOT NULL DEFAULT '0', + `needMoreHelp` tinyint(3) unsigned NOT NULL DEFAULT '0', + `resolvedBy` int(10) unsigned NOT NULL DEFAULT '0' COMMENT 'GUID of GM who resolved the ticket', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=10572 DEFAULT CHARSET=utf8 COMMENT='Player System'; diff --git a/data/sql/updates/world/2016_07_28_00.sql b/data/sql/updates/world/2016_07_28_00.sql new file mode 100644 index 0000000000..90b69837cd --- /dev/null +++ b/data/sql/updates/world/2016_07_28_00.sql @@ -0,0 +1,15 @@ +-- loot for mindless servant 26536 in utgarde pinnacle +DELETE FROM `creature_loot_template` WHERE (Entry = 26536); +INSERT INTO `creature_loot_template` (`Entry`, `Item`, `ChanceOrQuestChance`, `LootMode`, `GroupId`, `mincountOrRef`, `maxcount`) VALUES +(26536, 33470, 10.7, 1, 0, 1, 7), +(26536, 26002, 3, 1, 1, -26002, 1), +(26536, 26011, 1, 1, 1, -26011, 1), +(26536, 26012, 1, 1, 1, -26012, 1), +(26536, 26040, 21.4, 1, 0, -26040, 1), +(26536, 33370, 3.6, 0, 1, 1, 1), +(26536, 33399, 3.6, 0, 1, 1, 1), +(26536, 33454, 35.5, 1, 0, 1, 1), +(26536, 37068, 0.69, 0, 1, 1, 1), +(26536, 37069, 0.69, 0, 1, 1, 1), +(26536, 37070, 0.69, 0, 1, 1, 1), +(26536, 45912, 0.1, 0, 1, 1, 1);
\ No newline at end of file diff --git a/data/sql/updates/world/2016_08_01_00.sql b/data/sql/updates/world/2016_08_01_00.sql new file mode 100644 index 0000000000..6adf2fc9d2 --- /dev/null +++ b/data/sql/updates/world/2016_08_01_00.sql @@ -0,0 +1,3 @@ +UPDATE creature_template SET faction = 14 WHERE faction != 35 and entry in ( +35572,35569,35571,35570,35617,34705,34702,34701,34657,34703,35329,35328,35331,35330, +35332,35314,35326,35325,35323,35327,35119,35518,34928,35517,35309,35305,35307,35451,35004,35005,35545,35564,33628,36085,36090,36084,35517,35490,36089,35518,36091,36087,36086,36083,36082,36088,35310,35308,35546,35568,35306);
\ No newline at end of file diff --git a/data/sql/updates/world/2016_08_03_00.sql b/data/sql/updates/world/2016_08_03_00.sql new file mode 100644 index 0000000000..b0e770ae5e --- /dev/null +++ b/data/sql/updates/world/2016_08_03_00.sql @@ -0,0 +1 @@ +DELETE from spell_area where spell = 60815 and area = 14;
\ No newline at end of file diff --git a/install.sh b/install.sh new file mode 100755 index 0000000000..36e2f97bb8 --- /dev/null +++ b/install.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +CUR_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +PATH_MODULES="$CUR_PATH/modules/" +[ ! -d $PATH_MODULES/udw/joiner ] && git clone https://github.com/udw/joiner $PATH_MODULES/udw/joiner -b master +source "$PATH_MODULES/udw/joiner/joiner.sh" + + + +if [[ $1 == "dev" ]]; then + git submodule update --init "$CUR_PATH/data/doc" +fi diff --git a/modules/dep/.gitignore b/modules/dep/.gitignore new file mode 100644 index 0000000000..c2e6c9cf29 --- /dev/null +++ b/modules/dep/.gitignore @@ -0,0 +1,49 @@ +!.gitignore + +!* + +# +#Generic +# + +.directory +.mailmap +*.orig +*.rej +*~ +.hg/ +*.kdev* +.DS_Store +CMakeLists.txt.user +*.bak +*.patch +*.diff +*.REMOTE.* +*.BACKUP.* +*.BASE.* +*.LOCAL.* + +# +# IDE & other softwares +# +/.settings/ +/.externalToolBuilders/* +# exclude in all levels +nbproject/ +.sync.ffs_db + +# +# Eclipse +# +*.pydevproject +.metadata +.gradle +tmp/ +*.tmp +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.project +.cproject diff --git a/src/cmake/utils.cmake b/src/cmake/utils.cmake index b3ab0f6b42..742c40d43b 100644 --- a/src/cmake/utils.cmake +++ b/src/cmake/utils.cmake @@ -37,8 +37,8 @@ MACRO(AZTH_ADD_GLOBAL name val) AZTH_GET_GLOBAL(${name}) set_property ( GLOBAL PROPERTY ${name} - ${val} ${${name}} + ${val} ) # after set , create the variable for current scope AZTH_GET_GLOBAL(${name}) @@ -69,6 +69,21 @@ MACRO(AZTH_SET_PATH name val) ENDMACRO() # +# AZTH_ADD_SCRIPTS +# +MACRO(AZTH_ADD_SCRIPTS script_def include) + AZTH_ADD_GLOBAL("AZTH_ADD_SCRIPTS_LIST" "Add${script_def}Scripts()\;") + + + if (NOT ${include} STREQUAL "") + AZTH_GET_GLOBAL("AZTH_ADD_SCRIPTS_INCLUDE") + if (NOT ";${AZTH_ADD_SCRIPTS_INCLUDE};" MATCHES ";${include};") + AZTH_ADD_GLOBAL("AZTH_ADD_SCRIPTS_INCLUDE" "${include}\;") + endif() + endif() +ENDMACRO() + +# # AZTH_ADD_INC_PATH # MACRO(AZTH_ADD_INC_PATH val) diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index 7fc158cdcc..cbf2fa186f 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -108,3 +108,5 @@ endif() if (USE_COREPCH) add_cxx_pch(authserver ${authserver_PCH_HDR} ${authserver_PCH_SRC}) endif() + +RUN_HOOK("AFTER_AUTHSERVER_CMAKE") diff --git a/src/server/authserver/Main.cpp b/src/server/authserver/Main.cpp index 4b891ec512..20a270ff00 100644 --- a/src/server/authserver/Main.cpp +++ b/src/server/authserver/Main.cpp @@ -104,7 +104,15 @@ extern int main(int argc, char** argv) ++count; } - if (!sConfigMgr->LoadInitial(configFile)) + std::string cfg_def_file=_TRINITY_REALM_CONFIG; + cfg_def_file += ".dist"; + + if (!sConfigMgr->LoadInitial(cfg_def_file.c_str())) { + printf("Invalid or missing default configuration file : %s\n", cfg_def_file.c_str()); + return 1; + } + + if (!sConfigMgr->LoadMore(configFile)) { printf("Invalid or missing configuration file : %s\n", configFile); printf("Verify that the file exists and has \'[authserver]\' written in the top of the file!\n"); diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp index 83ce0f9e61..c0274574ff 100644 --- a/src/server/game/AI/CoreAI/PetAI.cpp +++ b/src/server/game/AI/CoreAI/PetAI.cpp @@ -492,16 +492,18 @@ void PetAI::HandleReturnMovement() { if (!me->GetCharmInfo()->IsAtStay() && !me->GetCharmInfo()->IsReturning()) { - // Return to previous position where stay was clicked - if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE) + if (me->GetCharmInfo()->HasStayPosition()) { - float x, y, z; - - me->GetCharmInfo()->GetStayPosition(x, y, z); - ClearCharmInfoFlags(); - me->GetCharmInfo()->SetIsReturning(true); - me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MovePoint(me->GetGUIDLow(), x, y, z); + // Return to previous position where stay was clicked + if (me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE) + { + float x, y, z; + me->GetCharmInfo()->GetStayPosition(x, y, z); + ClearCharmInfoFlags(); + me->GetCharmInfo()->SetIsReturning(true); + me->GetMotionMaster()->Clear(); + me->GetMotionMaster()->MovePoint(me->GetUInt32Value(OBJECT_FIELD_GUID), x, y, z); + } } } } diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 29194632c1..04aefdec48 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -1196,7 +1196,7 @@ class SmartTrigger : public AreaTriggerScript } }; -void AddSC_SmartSCripts() +void AddSC_SmartScripts() { new SmartTrigger(); } diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp index 101ab5c95c..ceb125a74a 100644 --- a/src/server/game/Battlefield/Zones/BattlefieldWG.cpp +++ b/src/server/game/Battlefield/Zones/BattlefieldWG.cpp @@ -201,15 +201,13 @@ bool BattlefieldWG::Update(uint32 diff) else m_saveTimer -= diff; - // Update Tenacity + // Update Tenacity every 2,5 sec. if (IsWarTime()) { if (m_tenacityUpdateTimer <= diff) { - m_tenacityUpdateTimer = 10000; - if (!m_updateTenacityList.empty()) - UpdateTenacity(); - m_updateTenacityList.clear(); + m_tenacityUpdateTimer = 2500; + UpdateTenacity(); } else m_tenacityUpdateTimer -= diff; @@ -1087,42 +1085,7 @@ void BattlefieldWG::UpdateTenacity() newStack = int32((1.0f - ((float)alliancePlayers / hordePlayers)) * 4.0f); // negative, should cast on horde } - // Return if no change in stack and apply tenacity to new player - if (newStack == m_tenacityStack) - { - for (GuidSet::const_iterator itr = m_updateTenacityList.begin(); itr != m_updateTenacityList.end(); ++itr) - if (Player* newPlayer = ObjectAccessor::FindPlayer(*itr)) - if ((newPlayer->GetTeamId() == TEAM_ALLIANCE && m_tenacityStack > 0) || (newPlayer->GetTeamId() == TEAM_HORDE && m_tenacityStack < 0)) - { - newStack = std::min(abs(newStack), 20); - uint32 buff_honor = GetHonorBuff(newStack); - newPlayer->SetAuraStack(SPELL_TENACITY, newPlayer, newStack); - if (buff_honor) - newPlayer->CastSpell(newPlayer, buff_honor, true); - } - return; - } - - if (m_tenacityStack != 0) - { - if (m_tenacityStack > 0 && newStack <= 0) // old buff was on alliance - team = TEAM_ALLIANCE; - else if (m_tenacityStack < 0 && newStack >= 0) // old buff was on horde - team = TEAM_HORDE; - } - - m_tenacityStack = newStack; - // Remove old buff - if (team != TEAM_NEUTRAL) - { - for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) - if (Player* player = ObjectAccessor::FindPlayer(*itr)) - player->RemoveAurasDueToSpell(SPELL_TENACITY); - - for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) - if (Unit* unit = ObjectAccessor::FindUnit(*itr)) - unit->RemoveAurasDueToSpell(SPELL_TENACITY_VEHICLE); - } + // new way to check: always add stacks if they exist, to every one in the game // Apply new buff if (newStack) @@ -1147,6 +1110,28 @@ void BattlefieldWG::UpdateTenacity() unit->CastSpell(unit, buff_honor, true); } } + + if (m_tenacityStack != 0) + { + if (m_tenacityStack > 0 && newStack <= 0) // old buff was on alliance + team = TEAM_ALLIANCE; + else if (m_tenacityStack < 0 && newStack >= 0) // old buff was on horde + team = TEAM_HORDE; + } + + // Remove old buff + if (team != TEAM_NEUTRAL) + { + for (GuidSet::const_iterator itr = m_PlayersInWar[team].begin(); itr != m_PlayersInWar[team].end(); ++itr) + if (Player* player = ObjectAccessor::FindPlayer(*itr)) + player->RemoveAurasDueToSpell(SPELL_TENACITY); + + for (GuidSet::const_iterator itr = m_vehicles[team].begin(); itr != m_vehicles[team].end(); ++itr) + if (Unit* unit = ObjectAccessor::FindUnit(*itr)) + unit->RemoveAurasDueToSpell(SPELL_TENACITY_VEHICLE); + } + + m_tenacityStack = newStack; // Assign new tenacity value } WintergraspCapturePoint::WintergraspCapturePoint(BattlefieldWG* battlefield, TeamId teamInControl) : BfCapturePoint(battlefield) diff --git a/src/server/game/Battlegrounds/Battleground.cpp b/src/server/game/Battlegrounds/Battleground.cpp index 3300aab3ee..de41ed4433 100644 --- a/src/server/game/Battlegrounds/Battleground.cpp +++ b/src/server/game/Battlegrounds/Battleground.cpp @@ -665,17 +665,48 @@ void Battleground::RewardHonorToTeam(uint32 honor, TeamId teamId) void Battleground::RewardReputationToTeam(uint32 factionId, uint32 reputation, TeamId teamId) { - if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(factionId)) for (BattlegroundPlayerMap::const_iterator itr = m_Players.begin(); itr != m_Players.end(); ++itr) if (itr->second->GetBgTeamId() == teamId) { + uint32 realFactionId = GetRealRepFactionForPlayer(factionId, itr->second); + uint32 repGain = reputation; AddPct(repGain, itr->second->GetTotalAuraModifier(SPELL_AURA_MOD_REPUTATION_GAIN)); - AddPct(repGain, itr->second->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_FACTION_REPUTATION_GAIN, factionId)); - itr->second->GetReputationMgr().ModifyReputation(factionEntry, repGain); + AddPct(repGain, itr->second->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_FACTION_REPUTATION_GAIN, realFactionId)); + if (FactionEntry const* factionEntry = sFactionStore.LookupEntry(realFactionId)) + itr->second->GetReputationMgr().ModifyReputation(factionEntry, repGain); + } +} + +uint32 Battleground::GetRealRepFactionForPlayer(uint32 factionId, Player* player) +{ + if (player) + { + // if the bg team is not the original team, reverse reputation + if (player->GetBgTeamId() != player->GetTeamId(true)) + { + switch (factionId) + { + case BG_REP_AB_ALLIANCE: + return BG_REP_AB_HORDE; + case BG_REP_AB_HORDE: + return BG_REP_AB_ALLIANCE; + case BG_REP_AV_ALLIANCE: + return BG_REP_AV_HORDE; + case BG_REP_AV_HORDE: + return BG_REP_AV_ALLIANCE; + case BG_REP_WS_ALLIANCE: + return BG_REP_WS_HORDE; + case BG_REP_WS_HORDE: + return BG_REP_WS_ALLIANCE; } + } + } + + return factionId; } + void Battleground::UpdateWorldState(uint32 Field, uint32 Value) { WorldPacket data; diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h index 3aaa88fec1..9e86d69969 100644 --- a/src/server/game/Battlegrounds/Battleground.h +++ b/src/server/game/Battlegrounds/Battleground.h @@ -116,6 +116,16 @@ enum BattlegroundSpells SPELL_THE_LAST_STANDING = 26549, // Arena achievement related }; +enum BattlegroundReputations +{ + BG_REP_AV_HORDE = 729, + BG_REP_AV_ALLIANCE = 730, + BG_REP_AB_HORDE = 510, + BG_REP_AB_ALLIANCE = 509, + BG_REP_WS_HORDE = 889, + BG_REP_WS_ALLIANCE = 890, +}; + enum BattlegroundTimeIntervals { CHECK_PLAYER_POSITION_INVERVAL = 9000, // ms @@ -453,6 +463,7 @@ class Battleground void RemoveAuraOnTeam(uint32 spellId, TeamId teamId); void RewardHonorToTeam(uint32 honor, TeamId teamId); void RewardReputationToTeam(uint32 factionId, uint32 reputation, TeamId teamId); + uint32 GetRealRepFactionForPlayer(uint32 factionId, Player* player); void UpdateWorldState(uint32 Field, uint32 Value); void UpdateWorldStateForPlayer(uint32 Field, uint32 Value, Player* player); diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 8c87c6bd09..211549f0d6 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -205,6 +205,7 @@ include_directories( ${CMAKE_CURRENT_SOURCE_DIR}/World ${CMAKE_CURRENT_SOURCE_DIR}/ArenaSpectator ${CMAKE_CURRENT_SOURCE_DIR}/Misc + ${CMAKE_SOURCE_DIR}/src/server/scripts/ ${CMAKE_SOURCE_DIR}/src/server/scripts/PrecompiledHeaders ${ACE_INCLUDE_DIR} ${MYSQL_INCLUDE_DIR} diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp index 1c07c1ac59..6ee5f97cbc 100644 --- a/src/server/game/Entities/Pet/Pet.cpp +++ b/src/server/game/Entities/Pet/Pet.cpp @@ -40,7 +40,7 @@ Pet::Pet(Player* owner, PetType type) : Guardian(NULL, owner ? owner->GetGUID() : 0, true), m_usedTalentCount(0), m_removed(false), m_owner(owner), m_happinessTimer(PET_LOSE_HAPPINES_INTERVAL), m_petRegenTimer(PET_FOCUS_REGEN_INTERVAL), m_petType(type), m_duration(0), -m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL), asynchLoadType(PET_LOAD_DEFAULT) +m_auraRaidUpdateMask(0), m_loading(false), m_declinedname(NULL), m_tempspell(0), m_tempspellTarget(NULL), m_tempoldTarget(NULL), m_tempspellIsPositive(false), asynchLoadType(PET_LOAD_DEFAULT) { m_unitTypeMask |= UNIT_MASK_PET; if (type == HUNTER_PET) @@ -384,6 +384,115 @@ void Pet::Update(uint32 diff) } } + if (m_tempspell != 0) + { + Unit* tempspellTarget = m_tempspellTarget; + Unit* tempoldTarget = m_tempoldTarget; + bool tempspellIsPositive = m_tempspellIsPositive; + uint32 tempspell = m_tempspell; + Unit* charmer = GetCharmerOrOwner(); + if (!charmer) + return; + + if (!GetCharmInfo()) + return; + + if (tempspellTarget && tempspellTarget->IsAlive()) + { + SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(tempspell); + if (!spellInfo) + return; + float max_range = GetSpellMaxRangeForTarget(tempspellTarget, spellInfo); + + if (IsWithinLOSInMap(tempspellTarget) && GetDistance(tempspellTarget) < max_range) + { + if (tempspellTarget && !GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo) && !HasSpellCooldown(tempspell)) + { + StopMoving(); + GetMotionMaster()->Clear(false); + GetMotionMaster()->MoveIdle(); + + GetCharmInfo()->SetIsCommandAttack(false); + GetCharmInfo()->SetIsAtStay(true); + GetCharmInfo()->SetIsCommandFollow(false); + GetCharmInfo()->SetIsFollowing(false); + GetCharmInfo()->SetIsReturning(false); + GetCharmInfo()->SaveStayPosition(true); + + CastSpell(tempspellTarget, tempspell, true); + m_tempspell = 0; + m_tempspellTarget = NULL; + + if (tempspellIsPositive) + { + if (tempoldTarget && tempoldTarget->IsAlive()) + { + GetCharmInfo()->SetIsCommandAttack(true); + GetCharmInfo()->SetIsAtStay(false); + GetCharmInfo()->SetIsFollowing(false); + GetCharmInfo()->SetIsCommandFollow(false); + GetCharmInfo()->SetIsReturning(false); + + if (ToCreature() && ToCreature()->IsAIEnabled) + ToCreature()->AI()->AttackStart(tempoldTarget); + } + else + { + GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); + GetCharmInfo()->SetIsCommandAttack(false); + GetCharmInfo()->SetIsAtStay(false); + GetCharmInfo()->SetIsReturning(true); + GetCharmInfo()->SetIsCommandFollow(true); + GetCharmInfo()->SetIsFollowing(false); + GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, GetFollowAngle()); + } + + m_tempoldTarget = NULL; + m_tempspellIsPositive = false; + } + } + } + } + else + { + m_tempspell = 0; + m_tempspellTarget = NULL; + m_tempoldTarget = NULL; + m_tempspellIsPositive = false; + + Unit* victim = charmer->GetVictim(); + if (victim && victim->IsAlive()) + { + StopMoving(); + GetMotionMaster()->Clear(false); + GetMotionMaster()->MoveIdle(); + + GetCharmInfo()->SetIsCommandAttack(true); + GetCharmInfo()->SetIsAtStay(false); + GetCharmInfo()->SetIsFollowing(false); + GetCharmInfo()->SetIsCommandFollow(false); + GetCharmInfo()->SetIsReturning(false); + + if (ToCreature() && ToCreature()->IsAIEnabled) + ToCreature()->AI()->AttackStart(victim); + } + else + { + StopMoving(); + GetMotionMaster()->Clear(false); + GetMotionMaster()->MoveIdle(); + + GetCharmInfo()->SetCommandState(COMMAND_FOLLOW); + GetCharmInfo()->SetIsCommandAttack(false); + GetCharmInfo()->SetIsAtStay(false); + GetCharmInfo()->SetIsReturning(true); + GetCharmInfo()->SetIsCommandFollow(true); + GetCharmInfo()->SetIsFollowing(false); + GetMotionMaster()->MoveFollow(charmer, PET_FOLLOW_DIST, GetFollowAngle()); + } + } + } + if (getPetType() == HUNTER_PET) { m_happinessTimer -= diff; @@ -2103,3 +2212,44 @@ void Pet::SetDisplayId(uint32 modelId) if (player->GetGroup()) player->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_MODEL_ID); } + +void Pet::CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarget, bool spellIsPositive) +{ + if (!spellid) + return; + + if (!spellTarget) + return; + + m_tempspellTarget = spellTarget; + m_tempspell = spellid; + m_tempspellIsPositive = spellIsPositive; + + if (oldTarget) + m_tempoldTarget = oldTarget; +} + +void Pet::ClearCastWhenWillAvailable() +{ + m_tempspellIsPositive = false; + m_tempspell = 0; + m_tempspellTarget = NULL; + m_tempoldTarget = NULL; +} + +void Pet::RemoveSpellCooldown(uint32 spell_id, bool update /* = false */) +{ + m_CreatureSpellCooldowns.erase(spell_id); + + if (update) + { + + if (Player* playerOwner = GetCharmerOrOwnerPlayerOrPlayerItself()) + { + WorldPacket data(SMSG_CLEAR_COOLDOWN, 4 + 8); + data << uint32(spell_id); + data << uint64(GetGUID()); + playerOwner->SendDirectMessage(&data); + } + } +}
\ No newline at end of file diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h index 6315946922..8595a9d3b2 100644 --- a/src/server/game/Entities/Pet/Pet.h +++ b/src/server/game/Entities/Pet/Pet.h @@ -120,6 +120,10 @@ class Pet : public Guardian void LearnPetPassives(); void CastPetAuras(bool current); + void CastWhenWillAvailable(uint32 spellid, Unit* spellTarget, Unit* oldTarget, bool spellIsPositive = false); + void ClearCastWhenWillAvailable(); + void RemoveSpellCooldown(uint32 spell_id, bool update /* = false */); + void _SaveSpellCooldowns(SQLTransaction& trans, bool logout); void _SaveAuras(SQLTransaction& trans, bool logout); void _SaveSpells(SQLTransaction& trans); @@ -175,6 +179,12 @@ class Pet : public Guardian int32 m_petRegenTimer; // xinef: used for focus regeneration DeclinedName *m_declinedname; + + Unit* m_tempspellTarget; + Unit* m_tempoldTarget; + bool m_tempspellIsPositive; + uint32 m_tempspell; + uint8 asynchLoadType; private: diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 49bae4e57a..d707cc1478 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -84,6 +84,7 @@ #include "GameObjectAI.h" #include "PoolMgr.h" #include "SavingSystem.h" +#include "TicketMgr.h" #define ZONE_UPDATE_INTERVAL (2*IN_MILLISECONDS) @@ -678,6 +679,7 @@ Player::Player(WorldSession* session): Unit(true), m_mover(this) #pragma warning(default:4355) #endif + m_drwGUID = 0; m_speakTime = 0; m_speakCount = 0; @@ -1114,7 +1116,7 @@ bool Player::Create(uint32 guidlow, CharacterCreateInfo* createInfo) GetReputationMgr().SetReputation(sFactionStore.LookupEntry(1077), 42999); // Factions depending on team, like cities and some more stuff - switch (GetTeamId()) + switch (GetTeamId(true)) { case TEAM_ALLIANCE: GetReputationMgr().SetReputation(sFactionStore.LookupEntry(72), 42999); @@ -4729,6 +4731,11 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC // remove from arena teams LeaveAllArenaTeams(playerguid); + // close player ticket if any + GmTicket* ticket = sTicketMgr->GetTicketByPlayer(playerguid); + if (ticket) + ticket->SetClosedBy(playerguid); + // remove from group if (uint32 groupId = GetGroupIdFromStorage(guid)) if (Group* group = sGroupMgr->GetGroupByGUID(groupId)) @@ -4923,9 +4930,18 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC stmt->setUInt32(0, guid); trans->Append(stmt); - stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS); - stmt->setUInt32(0, guid); - trans->Append(stmt); + if (sWorld->getBoolConfig(CONFIG_DELETE_CHARACTER_TICKET_TRACE)) + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION); + stmt->setUInt32(0, guid); + trans->Append(stmt); + } + else + { + stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PLAYER_GM_TICKETS); + stmt->setUInt32(0, guid); + trans->Append(stmt); + } stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER); stmt->setUInt32(0, guid); @@ -7045,7 +7061,7 @@ void Player::RewardReputation(Unit* victim, float rate) ChampioningFaction = GetChampioningFaction(); } - TeamId teamId = GetTeamId(); + TeamId teamId = GetTeamId(true); // Always check player original reputation when rewarding if (Rep->RepFaction1 && (!Rep->TeamDependent || teamId == TEAM_ALLIANCE)) { @@ -7168,12 +7184,13 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar if (HasAura(SPELL_AURA_PLAYER_INACTIVE)) return false; - // check if player has same IP + /* check if player has same IP if (uVictim && uVictim->GetTypeId() == TYPEID_PLAYER) { if (GetSession()->GetRemoteAddress() == uVictim->ToPlayer()->GetSession()->GetRemoteAddress()) return false; } + */ uint64 victim_guid = 0; uint32 victim_rank = 0; @@ -7216,7 +7233,7 @@ bool Player::RewardHonor(Unit* uVictim, uint32 groupsize, int32 honor, bool awar // [29..38] Other title and player name // [39+] Nothing uint32 victim_title = victim->GetUInt32Value(PLAYER_CHOSEN_TITLE); - // Get Killer titles, CharTitlesEntry::bit_index + // Get Killer titles, CharTitlesEntry::bit_index // Ranks: // title[1..14] -> rank[5..18] // title[15..28] -> rank[5..18] @@ -7471,12 +7488,12 @@ void Player::UpdateArea(uint32 newArea) AreaTableEntry const* zone = GetAreaEntryByAreaID(area->zone); uint32 areaFlags = area->flags; bool isSanctuary = area->IsSanctuary(); - bool isInn = area->IsInn(GetTeamId()); + bool isInn = area->IsInn(GetTeamId(true)); if (zone) { areaFlags |= zone->flags; isSanctuary |= zone->IsSanctuary(); - isInn |= zone->IsInn(GetTeamId()); + isInn |= zone->IsInn(GetTeamId(true)); } // previously this was in UpdateZone (but after UpdateArea) so nothing will break @@ -7576,10 +7593,10 @@ void Player::UpdateZone(uint32 newZone, uint32 newArea) switch (zone->team) { case AREATEAM_ALLY: - pvpInfo.IsInHostileArea = GetTeamId() != TEAM_ALLIANCE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL); + pvpInfo.IsInHostileArea = GetTeamId(true) != TEAM_ALLIANCE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL); break; case AREATEAM_HORDE: - pvpInfo.IsInHostileArea = GetTeamId() != TEAM_HORDE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL); + pvpInfo.IsInHostileArea = GetTeamId(true) != TEAM_HORDE && (sWorld->IsPvPRealm() || zone->flags & AREA_FLAG_CAPITAL); break; case AREATEAM_NONE: // overwrite for battlegrounds, maybe batter some zone flags but current known not 100% fit to this @@ -17568,7 +17585,7 @@ bool Player::LoadFromDB(uint32 guid, SQLQueryHolder *holder) else if (!taxi_nodes.empty()) { instanceId = 0; - if (!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes, GetTeamId())) + if (!m_taxi.LoadTaxiDestinationsFromString(taxi_nodes, GetTeamId(true))) { // xinef: could no load valid data for taxi, relocate to homebind and clear m_taxi.ClearTaxiDestinations(); @@ -19030,9 +19047,9 @@ bool Player::Satisfy(AccessRequirement const* ar, uint32 target_map, bool report } uint32 missingQuest = 0; - if (GetTeamId() == TEAM_ALLIANCE && ar->quest_A && !GetQuestRewardStatus(ar->quest_A)) + if (GetTeamId(true) == TEAM_ALLIANCE && ar->quest_A && !GetQuestRewardStatus(ar->quest_A)) missingQuest = ar->quest_A; - else if (GetTeamId() == TEAM_HORDE && ar->quest_H && !GetQuestRewardStatus(ar->quest_H)) + else if (GetTeamId(true) == TEAM_HORDE && ar->quest_H && !GetQuestRewardStatus(ar->quest_H)) missingQuest = ar->quest_H; uint32 missingAchievement = 0; @@ -21196,7 +21213,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc // only one mount ID for both sides. Probably not good to use 315 in case DBC nodes // change but I couldn't find a suitable alternative. OK to use class because only DK // can use this taxi. - uint32 mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeamId(), npc == NULL || (sourcenode == 315 && getClass() == CLASS_DEATH_KNIGHT)); + uint32 mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeamId(true), npc == NULL || (sourcenode == 315 && getClass() == CLASS_DEATH_KNIGHT)); // in spell case allow 0 model if ((mount_display_id == 0 && spellid == 0) || sourcepath == 0) @@ -21273,7 +21290,7 @@ void Player::ContinueTaxiFlight() ;//sLog->outDebug(LOG_FILTER_UNITS, "WORLD: Restart character %u taxi flight", GetGUIDLow()); - uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourceNode, GetTeamId(), true); + uint32 mountDisplayId = sObjectMgr->GetTaxiMountDisplayId(sourceNode, GetTeamId(true), true); if (!mountDisplayId) return; @@ -21514,7 +21531,7 @@ bool Player::BuyItemFromVendorSlot(uint64 vendorguid, uint32 vendorslot, uint32 return false; } - if (!IsGameMaster() && ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeamId() == TEAM_ALLIANCE) || (pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeamId() == TEAM_HORDE))) + if (!IsGameMaster() && ((pProto->Flags2 & ITEM_FLAGS_EXTRA_HORDE_ONLY && GetTeamId(true) == TEAM_ALLIANCE) || (pProto->Flags2 == ITEM_FLAGS_EXTRA_ALLIANCE_ONLY && GetTeamId(true) == TEAM_HORDE))) return false; Creature* creature = GetNPCIfCanInteractWith(vendorguid, UNIT_NPC_FLAG_VENDOR); diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index e36a89030f..e285e374ee 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2074,7 +2074,7 @@ class Player : public Unit, public GridObject<Player> void CheckAreaExploreAndOutdoor(void); static TeamId TeamIdForRace(uint8 race); - TeamId GetTeamId() const { return m_team; } + TeamId GetTeamId(bool original = false) const { return original ? TeamIdForRace(getRace()) : m_team; }; void setFactionForRace(uint8 race); void InitDisplayIds(); @@ -2573,6 +2573,11 @@ class Player : public Unit, public GridObject<Player> uint32 m_pendingSpectatorInviteInstanceId; std::set<uint32> m_receivedSpectatorResetFor; + // Dancing Rune weapon + void setRuneWeaponGUID(uint64 guid) { m_drwGUID = guid; }; + uint64 getRuneWeaponGUID() { return m_drwGUID; }; + uint64 m_drwGUID; + bool CanSeeDKPet() const { return m_ExtraFlags & PLAYER_EXTRA_SHOW_DK_PET; } void SetShowDKPet(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_SHOW_DK_PET; else m_ExtraFlags &= ~PLAYER_EXTRA_SHOW_DK_PET; }; void PrepareCharmAISpells(); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 73eae5329b..4d27576628 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -2749,7 +2749,7 @@ SpellMissInfo Unit::MagicSpellHitResult(Unit* victim, SpellInfo const* spell) int32 tmp = 10000 - HitChance; - int32 rand = irand(0, 10000); + int32 rand = irand(1, 10000); // Needs to be 1 to 10000 to avoid the 1/10000 chance to miss on 100% hit rating if (rand < tmp) return SPELL_MISS_MISS; @@ -5047,6 +5047,11 @@ uint32 Unit::GetDiseasesByCaster(uint64 casterGUID, uint8 mode) SPELL_AURA_NONE }; + uint64 drwGUID = 0; + + if (Player* playerCaster = ObjectAccessor::GetPlayer(*this, casterGUID)) + drwGUID = playerCaster->getRuneWeaponGUID(); + uint32 diseases = 0; for (uint8 index = 0; diseaseAuraTypes[index] != SPELL_AURA_NONE; ++index) { @@ -5054,7 +5059,7 @@ uint32 Unit::GetDiseasesByCaster(uint64 casterGUID, uint8 mode) { // Get auras with disease dispel type by caster if ((*i)->GetSpellInfo()->Dispel == DISPEL_DISEASE - && (*i)->GetCasterGUID() == casterGUID) + && ((*i)->GetCasterGUID() == casterGUID || (*i)->GetCasterGUID() == drwGUID)) // if its caster or his dancing rune weapon { ++diseases; @@ -18618,6 +18623,18 @@ void CharmInfo::GetStayPosition(float &x, float &y, float &z) z = _stayZ; } +void CharmInfo::RemoveStayPosition() +{ + _stayX = 0.0f; + _stayY = 0.0f; + _stayZ = 0.0f; +} + +bool CharmInfo::HasStayPosition() +{ + return _stayX && _stayY && _stayZ; +} + void CharmInfo::SetIsAtStay(bool val) { _isAtStay = val; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 0447ac6fe2..c7cd3e746c 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1224,6 +1224,8 @@ struct CharmInfo bool IsReturning(); void SaveStayPosition(bool atCurrentPos); void GetStayPosition(float &x, float &y, float &z); + void RemoveStayPosition(); + bool HasStayPosition(); void SetForcedSpell(uint32 id) { _forcedSpellId = id; } int32 GetForcedSpell() { return _forcedSpellId; } diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp index 6ed0a24db2..c7fb4da794 100644 --- a/src/server/game/Handlers/CharacterHandler.cpp +++ b/src/server/game/Handlers/CharacterHandler.cpp @@ -2006,7 +2006,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recvData) if (recvData.GetOpcode() == CMSG_CHAR_FACTION_CHANGE) { // if player is in a guild - if (playerData->guildId) + if (playerData->guildId && !sWorld->getBoolConfig(CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD)) { WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1); data << (uint8)CHAR_CREATE_CHARACTER_IN_GUILD; diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp index cb9297c1be..b782b7b456 100644 --- a/src/server/game/Handlers/PetHandler.cpp +++ b/src/server/game/Handlers/PetHandler.cpp @@ -507,6 +507,9 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid charmInfo->SetIsReturning(false); charmInfo->SetIsAtStay(!controlledMotion); charmInfo->SaveStayPosition(controlledMotion); + if (pet->ToPet()) + pet->ToPet()->ClearCastWhenWillAvailable(); + charmInfo->SetForcedSpell(0); charmInfo->SetForcedTargetGUID(0); @@ -518,6 +521,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid pet->InterruptNonMeleeSpells(false); pet->ClearInPetCombat(); pet->GetMotionMaster()->MoveFollow(_player, PET_FOLLOW_DIST, pet->GetFollowAngle()); + if (pet->ToPet()) + pet->ToPet()->ClearCastWhenWillAvailable(); charmInfo->SetCommandState(COMMAND_FOLLOW); charmInfo->SetIsCommandAttack(false); @@ -525,7 +530,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid charmInfo->SetIsReturning(true); charmInfo->SetIsCommandFollow(true); charmInfo->SetIsFollowing(false); - + charmInfo->RemoveStayPosition(); charmInfo->SetForcedSpell(0); charmInfo->SetForcedTargetGUID(0); break; @@ -641,6 +646,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid { case REACT_PASSIVE: //passive pet->AttackStop(); + if (pet->ToPet()) + pet->ToPet()->ClearCastWhenWillAvailable(); pet->ClearInPetCombat(); case REACT_DEFENSIVE: //recovery @@ -658,9 +665,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid { Unit* unit_target = NULL; - if (guid2) - unit_target = ObjectAccessor::GetUnit(*_player, guid2); - // do not cast unknown spells SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid); if (!spellInfo) @@ -669,6 +673,11 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid return; } + if (guid2) + unit_target = ObjectAccessor::GetUnit(*_player, guid2); + else if (!spellInfo->IsPositive()) + return; + for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) { if (spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_SRC_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_DEST_AREA_ENEMY || spellInfo->Effects[i].TargetA.GetTarget() == TARGET_DEST_DYNOBJ_ENEMY) @@ -743,6 +752,131 @@ void WorldSession::HandlePetActionHelper(Unit* pet, uint64 guid1, uint16 spellid charmInfo->SetForcedSpell(0); charmInfo->SetForcedTargetGUID(0); } + else if (pet->ToPet() && (result == SPELL_FAILED_LINE_OF_SIGHT || result == SPELL_FAILED_OUT_OF_RANGE)) + { + unit_target = spell->m_targets.GetUnitTarget(); + bool haspositiveeffect = false; + + if (!unit_target) + return; + + // search positive effects for spell + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (spellInfo->_IsPositiveEffect(i, true)) + { + haspositiveeffect = true; + break; + } + } + + if (pet->isPossessed() || pet->IsVehicle()) + Spell::SendCastResult(GetPlayer(), spellInfo, 0, result); + else if (GetPlayer()->IsFriendlyTo(unit_target) && !haspositiveeffect) + spell->SendPetCastResult(SPELL_FAILED_TARGET_FRIENDLY); + else + spell->SendPetCastResult(SPELL_FAILED_DONT_REPORT); + + if (!pet->HasSpellCooldown(spellid)) + if(pet->ToPet()) + pet->ToPet()->RemoveSpellCooldown(spellid, true); + + spell->finish(false); + delete spell; + + if (_player->HasAuraType(SPELL_AURA_MOD_PACIFY)) + return; + + bool tempspellIsPositive = false; + + if (!GetPlayer()->IsFriendlyTo(unit_target)) + { + // only place where pet can be player + Unit* TargetUnit = ObjectAccessor::GetUnit(*_player, guid2); + if (!TargetUnit) + return; + + if (Unit* owner = pet->GetOwner()) + if (!owner->IsValidAttackTarget(TargetUnit)) + return; + + pet->ClearUnitState(UNIT_STATE_FOLLOW); + // This is true if pet has no target or has target but targets differs. + if (pet->GetVictim() != TargetUnit || (pet->GetVictim() == TargetUnit && !pet->GetCharmInfo()->IsCommandAttack())) + { + if (pet->GetVictim()) + pet->AttackStop(); + + if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature() && pet->ToCreature()->IsAIEnabled) + { + charmInfo->SetIsCommandAttack(true); + charmInfo->SetIsAtStay(false); + charmInfo->SetIsFollowing(false); + charmInfo->SetIsCommandFollow(false); + charmInfo->SetIsReturning(false); + + pet->ToCreature()->AI()->AttackStart(TargetUnit); + + if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != TargetUnit && urand(0, 100) < 10) + pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + else + pet->SendPetAIReaction(guid1); + } + else // charmed player + { + if (pet->GetVictim() && pet->GetVictim() != TargetUnit) + pet->AttackStop(); + + charmInfo->SetIsCommandAttack(true); + charmInfo->SetIsAtStay(false); + charmInfo->SetIsFollowing(false); + charmInfo->SetIsCommandFollow(false); + charmInfo->SetIsReturning(false); + + pet->Attack(TargetUnit, true); + pet->SendPetAIReaction(guid1); + } + + pet->ToPet()->CastWhenWillAvailable(spellid, unit_target, NULL, tempspellIsPositive); + } + } + else if (haspositiveeffect) + { + bool tempspellIsPositive = true; + pet->ClearUnitState(UNIT_STATE_FOLLOW); + // This is true if pet has no target or has target but targets differs. + Unit* victim = pet->GetVictim(); + if (victim) + { + pet->AttackStop(); + } + else + victim = NULL; + + if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature() && pet->ToCreature()->IsAIEnabled) + { + pet->StopMoving(); + pet->GetMotionMaster()->Clear(); + + charmInfo->SetIsCommandAttack(false); + charmInfo->SetIsAtStay(false); + charmInfo->SetIsFollowing(false); + charmInfo->SetIsCommandFollow(false); + charmInfo->SetIsReturning(false); + + pet->GetMotionMaster()->MoveChase(unit_target); + + if (pet->IsPet() && ((Pet*)pet)->getPetType() == SUMMON_PET && pet != unit_target && urand(0, 100) < 10) + pet->SendPetTalk((uint32)PET_TALK_SPECIAL_SPELL); + else + { + pet->SendPetAIReaction(guid1); + } + + pet->ToPet()->CastWhenWillAvailable(spellid, unit_target, victim, tempspellIsPositive); + } + } + } else { // dont spam alerts diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h index f22905cbd6..31563834b9 100644 --- a/src/server/game/Instances/InstanceSaveMgr.h +++ b/src/server/game/Instances/InstanceSaveMgr.h @@ -35,6 +35,7 @@ struct MapEntry; class Player; class Group; class InstanceSaveManager; +class InstanceSave; struct InstancePlayerBind { diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index 0623ed9f97..bc5be246c4 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -2682,10 +2682,12 @@ void InstanceMap::PermBindAllPlayers() { player = itr->GetSource(); group = player->GetGroup(); + // players inside an instance cannot be bound to other instances // some players may already be permanently bound, in this case nothing happens InstancePlayerBind* bind = sInstanceSaveMgr->PlayerGetBoundInstance(player->GetGUIDLow(), save->GetMapId(), save->GetDifficulty()); - if ((!group || !group->isLFGGroup() || !group->IsLfgRandomInstance()) && (!bind || !bind->perm)) + + if (!bind || !bind->perm) { WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4); data << uint32(0); diff --git a/src/server/game/Miscellaneous/Formulas.h b/src/server/game/Miscellaneous/Formulas.h index b0cea99c1b..e44076d2e7 100644 --- a/src/server/game/Miscellaneous/Formulas.h +++ b/src/server/game/Miscellaneous/Formulas.h @@ -160,27 +160,33 @@ namespace Trinity inline uint32 Gain(Player* player, Unit* u) { - uint32 gain; + Creature* creature = u->ToCreature(); + uint32 gain = 0; - if (u->GetTypeId() == TYPEID_UNIT && - (((Creature*)u)->IsTotem() || ((Creature*)u)->IsPet() || - (((Creature*)u)->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL) || - u->IsCritter())) - gain = 0; - else + if (!creature || (!creature->IsTotem() && !creature->IsPet() && !creature->IsCritter() && + !(creature->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL))) { + float xpMod = 1.0f; + gain = BaseGain(player->getLevel(), u->getLevel(), GetContentLevelsForMapAndZone(u->GetMapId(), u->GetZoneId())); - if (gain != 0 && u->GetTypeId() == TYPEID_UNIT && ((Creature*)u)->isElite()) + if (gain && creature) { - // Elites in instances have a 2.75x XP bonus instead of the regular 2x world bonus. - if (u->GetMap()->IsDungeon()) - gain = uint32(gain * 2.75); - else - gain *= 2; + if (creature->isElite()) + { + // Elites in instances have a 2.75x XP bonus instead of the regular 2x world bonus. + if (u->GetMap() && u->GetMap()->IsDungeon()) + xpMod *= 2.75f; + else + xpMod *= 2.0f; + } + + // This requires TrinityCore creature_template.ExperienceModifier feature + // xpMod *= creature->GetCreatureTemplate()->ModExperience; } - gain = uint32(gain * sWorld->getRate(RATE_XP_KILL)); + xpMod *= isBattleGround ? sWorld->getRate(RATE_XP_BG_KILL) : sWorld->getRate(RATE_XP_KILL); + gain = uint32(gain * xpMod); } //sScriptMgr->OnGainCalculation(gain, player, u); // pussywizard: optimization diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 4c744753ff..80bbaa9e0c 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -163,6 +163,7 @@ class ScriptRegistry ScriptMgr::ScriptMgr() : _scriptCount(0), _scheduledScripts(0) { + } ScriptMgr::~ScriptMgr() @@ -171,18 +172,8 @@ ScriptMgr::~ScriptMgr() void ScriptMgr::Initialize() { - uint32 oldMSTime = getMSTime(); - - LoadDatabase(); - - sLog->outString("Loading C++ scripts"); - - FillSpellSummary(); AddScripts(); - CheckIfScriptsInDatabaseExist(); - - sLog->outString(">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime)); - sLog->outString(); + sLog->outString("Loading C++ scripts"); } void ScriptMgr::Unload() @@ -223,7 +214,32 @@ void ScriptMgr::Unload() void ScriptMgr::LoadDatabase() { + uint32 oldMSTime = getMSTime(); + sScriptSystemMgr->LoadScriptWaypoints(); + + // Add all scripts that must be loaded after db/maps + ScriptRegistry<WorldMapScript>::AddALScripts(); + ScriptRegistry<BattlegroundMapScript>::AddALScripts(); + ScriptRegistry<InstanceMapScript>::AddALScripts(); + ScriptRegistry<SpellScriptLoader>::AddALScripts(); + ScriptRegistry<ItemScript>::AddALScripts(); + ScriptRegistry<CreatureScript>::AddALScripts(); + ScriptRegistry<GameObjectScript>::AddALScripts(); + ScriptRegistry<AreaTriggerScript>::AddALScripts(); + ScriptRegistry<BattlegroundScript>::AddALScripts(); + ScriptRegistry<OutdoorPvPScript>::AddALScripts(); + ScriptRegistry<WeatherScript>::AddALScripts(); + ScriptRegistry<ConditionScript>::AddALScripts(); + ScriptRegistry<TransportScript>::AddALScripts(); + ScriptRegistry<AchievementCriteriaScript>::AddALScripts(); + + FillSpellSummary(); + + CheckIfScriptsInDatabaseExist(); + + sLog->outString(">> Loaded %u C++ scripts in %u ms", GetScriptCount(), GetMSTimeDiffToNow(oldMSTime)); + sLog->outString(); } struct TSpellSummary @@ -232,6 +248,40 @@ struct TSpellSummary uint8 Effects; // set of enum SelectEffect } *SpellSummary; +void ScriptMgr::CheckIfScriptsInDatabaseExist() +{ + ObjectMgr::ScriptNameContainer& sn = sObjectMgr->GetScriptNames(); + for (ObjectMgr::ScriptNameContainer::iterator itr = sn.begin(); itr != sn.end(); ++itr) + if (uint32 sid = sObjectMgr->GetScriptId((*itr).c_str())) + { + if (!ScriptRegistry<SpellScriptLoader>::GetScriptById(sid) && + !ScriptRegistry<ServerScript>::GetScriptById(sid) && + !ScriptRegistry<WorldScript>::GetScriptById(sid) && + !ScriptRegistry<FormulaScript>::GetScriptById(sid) && + !ScriptRegistry<WorldMapScript>::GetScriptById(sid) && + !ScriptRegistry<InstanceMapScript>::GetScriptById(sid) && + !ScriptRegistry<BattlegroundMapScript>::GetScriptById(sid) && + !ScriptRegistry<ItemScript>::GetScriptById(sid) && + !ScriptRegistry<CreatureScript>::GetScriptById(sid) && + !ScriptRegistry<GameObjectScript>::GetScriptById(sid) && + !ScriptRegistry<AreaTriggerScript>::GetScriptById(sid) && + !ScriptRegistry<BattlegroundScript>::GetScriptById(sid) && + !ScriptRegistry<OutdoorPvPScript>::GetScriptById(sid) && + !ScriptRegistry<CommandScript>::GetScriptById(sid) && + !ScriptRegistry<WeatherScript>::GetScriptById(sid) && + !ScriptRegistry<AuctionHouseScript>::GetScriptById(sid) && + !ScriptRegistry<ConditionScript>::GetScriptById(sid) && + !ScriptRegistry<VehicleScript>::GetScriptById(sid) && + !ScriptRegistry<DynamicObjectScript>::GetScriptById(sid) && + !ScriptRegistry<TransportScript>::GetScriptById(sid) && + !ScriptRegistry<AchievementCriteriaScript>::GetScriptById(sid) && + !ScriptRegistry<PlayerScript>::GetScriptById(sid) && + !ScriptRegistry<GuildScript>::GetScriptById(sid) && + !ScriptRegistry<GroupScript>::GetScriptById(sid)) + sLog->outErrorDb("Script named '%s' is assigned in database, but has no code!", (*itr).c_str()); + } +} + void ScriptMgr::FillSpellSummary() { SpellSummary = new TSpellSummary[sSpellMgr->GetSpellInfoStoreSize()]; @@ -403,9 +453,14 @@ void ScriptMgr::OnOpenStateChange(bool open) FOREACH_SCRIPT(WorldScript)->OnOpenStateChange(open); } -void ScriptMgr::OnConfigLoad(bool reload) +void ScriptMgr::OnBeforeConfigLoad(bool reload) +{ + FOREACH_SCRIPT(WorldScript)->OnBeforeConfigLoad(reload); +} + +void ScriptMgr::OnAfterConfigLoad(bool reload) { - FOREACH_SCRIPT(WorldScript)->OnConfigLoad(reload); + FOREACH_SCRIPT(WorldScript)->OnAfterConfigLoad(reload); } void ScriptMgr::OnMotdChange(std::string& newMotd) @@ -1292,27 +1347,18 @@ FormulaScript::FormulaScript(const char* name) WorldMapScript::WorldMapScript(const char* name, uint32 mapId) : ScriptObject(name), MapScript<Map>(mapId) { - if (GetEntry() && !GetEntry()->IsWorldMap()) - sLog->outError("WorldMapScript for map %u is invalid.", mapId); - ScriptRegistry<WorldMapScript>::AddScript(this); } InstanceMapScript::InstanceMapScript(const char* name, uint32 mapId) : ScriptObject(name), MapScript<InstanceMap>(mapId) { - if (GetEntry() && !GetEntry()->IsDungeon()) - sLog->outError("InstanceMapScript for map %u is invalid.", mapId); - ScriptRegistry<InstanceMapScript>::AddScript(this); } BattlegroundMapScript::BattlegroundMapScript(const char* name, uint32 mapId) : ScriptObject(name), MapScript<BattlegroundMap>(mapId) { - if (GetEntry() && !GetEntry()->IsBattleground()) - sLog->outError("BattlegroundMapScript for map %u is invalid.", mapId); - ScriptRegistry<BattlegroundMapScript>::AddScript(this); } @@ -1420,6 +1466,7 @@ GroupScript::GroupScript(const char* name) // Instantiate static members of ScriptRegistry. template<class TScript> std::map<uint32, TScript*> ScriptRegistry<TScript>::ScriptPointerList; +template<class TScript> std::vector<TScript*> ScriptRegistry<TScript>::ALScripts; template<class TScript> uint32 ScriptRegistry<TScript>::_scriptIdCounter = 0; // Specialize for each script type class like so: diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index eff5254c68..b7dfec043f 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -159,6 +159,8 @@ class ScriptObject // Do not override this in scripts; it should be overridden by the various script type classes. It indicates // whether or not this script type must be assigned in the database. virtual bool IsDatabaseBound() const { return false; } + virtual bool isAfterLoadScript() const { return IsDatabaseBound(); } + virtual void checkValidity() { } const std::string& GetName() const { return _name; } @@ -242,7 +244,10 @@ class WorldScript : public ScriptObject virtual void OnOpenStateChange(bool /*open*/) { } // Called after the world configuration is (re)loaded. - virtual void OnConfigLoad(bool /*reload*/) { } + virtual void OnAfterConfigLoad(bool /*reload*/) { } + + // Called before the world configuration is (re)loaded. + virtual void OnBeforeConfigLoad(bool /*reload*/) { } // Called before the message of the day is changed. virtual void OnMotdChange(std::string& /*newMotd*/) { } @@ -296,17 +301,22 @@ class FormulaScript : public ScriptObject template<class TMap> class MapScript : public UpdatableScript<TMap> { MapEntry const* _mapEntry; + uint32 _mapId; protected: MapScript(uint32 mapId) - : _mapEntry(sMapStore.LookupEntry(mapId)) + : _mapId(mapId) { - if (!_mapEntry) - sLog->outError("Invalid MapScript for %u; no such map ID.", mapId); } public: + void checkMap() { + _mapEntry = sMapStore.LookupEntry(_mapId); + + if (!_mapEntry) + sLog->outError("Invalid MapScript for %u; no such map ID.", _mapId); + } // Gets the MapEntry structure associated with this script. Can return NULL. MapEntry const* GetEntry() { return _mapEntry; } @@ -338,6 +348,17 @@ class WorldMapScript : public ScriptObject, public MapScript<Map> protected: WorldMapScript(const char* name, uint32 mapId); + + public: + + bool isAfterLoadScript() const { return true; } + + void checkValidity() { + checkMap(); + + if (GetEntry() && !GetEntry()->IsWorldMap()) + sLog->outError("WorldMapScript for map %u is invalid.", GetEntry()->MapID); + } }; class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap> @@ -350,6 +371,13 @@ class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap> bool IsDatabaseBound() const { return true; } + void checkValidity() { + checkMap(); + + if (GetEntry() && !GetEntry()->IsDungeon()) + sLog->outError("InstanceMapScript for map %u is invalid.", GetEntry()->MapID); + } + // Gets an InstanceScript object for this instance. virtual InstanceScript* GetInstanceScript(InstanceMap* /*map*/) const { return NULL; } }; @@ -359,6 +387,17 @@ class BattlegroundMapScript : public ScriptObject, public MapScript<Battleground protected: BattlegroundMapScript(const char* name, uint32 mapId); + + public: + + bool isAfterLoadScript() const { return true; } + + void checkValidity() { + checkMap(); + + if (GetEntry() && !GetEntry()->IsBattleground()) + sLog->outError("BattlegroundMapScript for map %u is invalid.", GetEntry()->MapID); + } }; class ItemScript : public ScriptObject @@ -799,6 +838,7 @@ class ScriptMgr void Initialize(); void LoadDatabase(); void FillSpellSummary(); + void CheckIfScriptsInDatabaseExist(); const char* ScriptsVersion() const { return "Integrated Trinity Scripts"; } @@ -825,7 +865,8 @@ class ScriptMgr public: /* WorldScript */ void OnOpenStateChange(bool open); - void OnConfigLoad(bool reload); + void OnBeforeConfigLoad(bool reload); + void OnAfterConfigLoad(bool reload); void OnMotdChange(std::string& newMotd); void OnShutdownInitiate(ShutdownExitCode code, ShutdownMask mask); void OnShutdownCancel(); @@ -1023,75 +1064,92 @@ class ScriptRegistry typedef std::map<uint32, TScript*> ScriptMap; typedef typename ScriptMap::iterator ScriptMapIterator; + typedef std::vector<TScript*> ScriptVector; + typedef typename ScriptVector::iterator ScriptVectorIterator; + // The actual list of scripts. This will be accessed concurrently, so it must not be modified // after server startup. static ScriptMap ScriptPointerList; + // After database load scripts + static ScriptVector ALScripts; static void AddScript(TScript* const script) { ASSERT(script); - // 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) + if (!_checkMemory(script)) + return; + + if (script->isAfterLoadScript()) { - if (it->second == script) - { - sLog->outError("Script '%s' has same memory pointer as '%s'.", - script->GetName().c_str(), it->second->GetName().c_str()); + ALScripts.push_back(script); + } + else + { + script->checkValidity(); - return; - } + // We're dealing with a code-only script; just add it. + ScriptPointerList[_scriptIdCounter++] = script; + sScriptMgr->IncrementScriptCount(); } + } - if (script->IsDatabaseBound()) - { - // 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().c_str()); - if (id) - { - // Try to find an existing script. - bool existing = false; - for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it) + static void AddALScripts() { + for(ScriptVectorIterator it = ALScripts.begin(); it != ALScripts.end(); ++it) { + TScript* const script = *it; + + script->checkValidity(); + + if (script->IsDatabaseBound()) { + + if (!_checkMemory(script)) + return; + + // 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().c_str()); + if (id) { - // If the script names match... - if (it->second->GetName() == script->GetName()) + // Try to find an existing script. + bool existing = false; + for (ScriptMapIterator it = ScriptPointerList.begin(); it != ScriptPointerList.end(); ++it) { - // ... It exists. - existing = true; - break; + // 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(); + // If the script isn't assigned -> assign it! + if (!existing) + { + ScriptPointerList[id] = script; + sScriptMgr->IncrementScriptCount(); + } + else + { + // If the script is already assigned -> delete it! + sLog->outError("Script '%s' already assigned with the same script name, so the script can't work.", + script->GetName().c_str()); + + ASSERT(false); // Error that should be fixed ASAP. + } } else { - // If the script is already assigned -> delete it! - sLog->outError("Script '%s' already assigned with the same script name, so the script can't work.", - script->GetName().c_str()); - - ASSERT(false); // Error that should be fixed ASAP. + // The script uses a script name from database, but isn't assigned to anything. + if (script->GetName().find("Smart") == std::string::npos) + sLog->outErrorDb("Script named '%s' does not have a script name assigned in database.", + script->GetName().c_str()); } + } else { + // We're dealing with a code-only script; just add it. + ScriptPointerList[_scriptIdCounter++] = script; + sScriptMgr->IncrementScriptCount(); } - else - { - // The script uses a script name from database, but isn't assigned to anything. - if (script->GetName().find("Smart") == std::string::npos) - sLog->outErrorDb("Script named '%s' does not have a script name assigned in database.", - script->GetName().c_str()); - } - } - else - { - // We're dealing with a code-only script; just add it. - ScriptPointerList[_scriptIdCounter++] = script; - sScriptMgr->IncrementScriptCount(); } } @@ -1106,6 +1164,24 @@ class ScriptRegistry } private: + // 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. + static bool _checkMemory(TScript* const script) { + // 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) + { + if (it->second == script) + { + sLog->outError("Script '%s' has same memory pointer as '%s'.", + script->GetName().c_str(), it->second->GetName().c_str()); + + return false; + } + } + + return true; + } // Counter used for code-only scripts. static uint32 _scriptIdCounter; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index feecb53e59..1e53625f9d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -1930,39 +1930,22 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar // max dist which spell can reach float searchRadius = jumpRadius; - if (isBouncingFar && !isChainHeal) + if (isBouncingFar) searchRadius *= chainTargets; - // Xinef: the distance should be increased by caster size, it is neglected in latter calculations std::list<WorldObject*> tempTargets; - SearchAreaTargets(tempTargets, searchRadius, (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE ? m_caster : target), m_caster, objectType, selectType, condList); + SearchAreaTargets(tempTargets, searchRadius, target, m_caster, objectType, selectType, condList); tempTargets.remove(target); - // xinef: if we have select category nearby and checktype entry, select random of what we have, not by distance - if (selectCategory == TARGET_SELECT_CATEGORY_NEARBY && selectType == TARGET_CHECK_ENTRY) - { - Trinity::Containers::RandomResizeList(tempTargets, chainTargets); - targets = tempTargets; - return; - } - // remove targets which are always invalid for chain spells // for some spells allow only chain targets in front of caster (swipe for example) if (!isBouncingFar) { - float allowedArc = 0.0f; - if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE) - allowedArc = (M_PI*7.0f) / 18.0f; // 70 degrees - else if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED) - allowedArc = M_PI*0.5f; // 90 degrees - for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();) { std::list<WorldObject*>::iterator checkItr = itr++; if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr)) tempTargets.erase(checkItr); - else if (allowedArc > 0.0f && !m_caster->HasInArc(allowedArc, *checkItr, (*checkItr)->GetObjectSize())) - tempTargets.erase(checkItr); } } @@ -1976,14 +1959,10 @@ void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTar uint32 maxHPDeficit = 0; for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr) { - if (Unit* itrTarget = (*itr)->ToUnit()) + if (Unit* unit = (*itr)->ToUnit()) { - uint32 deficit = itrTarget->GetMaxHealth() - itrTarget->GetHealth(); - // xinef: chain should not heal targets with max health - if (deficit == 0) - continue; - - if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(itrTarget, jumpRadius) && target->IsWithinLOSInMap(itrTarget)) + uint32 deficit = unit->GetMaxHealth() - unit->GetHealth(); + if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unit, jumpRadius) && target->IsWithinLOSInMap(unit)) { foundItr = itr; maxHPDeficit = deficit; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 81113b5e5f..e9712a2a5d 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -3133,6 +3133,9 @@ void SpellMgr::LoadSpellCustomAttr() spellInfo->RecoveryTime = 1500; spellInfo->_requireCooldownInfo = true; break; + case 44535: // Spirit Heal, abilities also have no cost + spellInfo->Effects[EFFECT_0].MiscValue = 127; + break; } switch (spellInfo->SpellFamilyName) @@ -3558,12 +3561,12 @@ void SpellMgr::LoadDbcDataCorrections() spellInfo->EffectSpellClassMask[0][0] = 0; spellInfo->EffectSpellClassMask[0][2] = 0x8000000; break; - // Judgements Facing + /* Judgements Facing -- SCEICCO: not sure this is offylike case 20271: case 53407: case 53408: spellInfo->FacingCasterFlags |= SPELL_FACING_FLAG_INFRONT; - break; + break;*/ // Seal of Light trigger case 20167: spellInfo->spellLevel = 0; diff --git a/src/server/game/Tickets/TicketMgr.cpp b/src/server/game/Tickets/TicketMgr.cpp index be4b71f87e..6ce2ed07a1 100644 --- a/src/server/game/Tickets/TicketMgr.cpp +++ b/src/server/game/Tickets/TicketMgr.cpp @@ -32,11 +32,11 @@ inline float GetAge(uint64 t) { return float(time(NULL) - t) / DAY; } /////////////////////////////////////////////////////////////////////////////////////////////////// // GM ticket -GmTicket::GmTicket() : _id(0), _playerGuid(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0), - _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), +GmTicket::GmTicket() : _id(0), _type(TICKET_TYPE_OPEN), _playerGuid(0), _posX(0), _posY(0), _posZ(0), _mapId(0), _createTime(0), _lastModifiedTime(0), + _closedBy(0), _resolvedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needResponse(false), _needMoreHelp(false) { } -GmTicket::GmTicket(Player* player) : _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needMoreHelp(false) +GmTicket::GmTicket(Player* player) : _type(TICKET_TYPE_OPEN), _createTime(time(NULL)), _lastModifiedTime(time(NULL)), _closedBy(0), _resolvedBy(0), _assignedTo(0), _completed(false), _escalatedStatus(TICKET_UNASSIGNED), _viewed(false), _needMoreHelp(false) { _id = sTicketMgr->GenerateTicketId(); _playerName = player->GetName(); @@ -47,10 +47,11 @@ GmTicket::~GmTicket() { } bool GmTicket::LoadFromDB(Field* fields) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 - // ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + // id, type, playerGuid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket, resolvedBy uint8 index = 0; _id = fields[ index].GetUInt32(); + _type = TicketType(fields[++index].GetUInt8()); _playerGuid = MAKE_NEW_GUID(fields[++index].GetUInt32(), 0, HIGHGUID_PLAYER); _playerName = fields[++index].GetString(); _message = fields[++index].GetString(); @@ -68,16 +69,19 @@ bool GmTicket::LoadFromDB(Field* fields) _escalatedStatus = GMTicketEscalationStatus(fields[++index].GetUInt8()); _viewed = fields[++index].GetBool(); _needMoreHelp = fields[++index].GetBool(); + _resolvedBy = fields[++index].GetInt32(); + return true; } void GmTicket::SaveToDB(SQLTransaction& trans) const { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 - // ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, completed, escalated, viewed + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 + // id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy uint8 index = 0; PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GM_TICKET); stmt->setUInt32( index, _id); + stmt->setUInt8 (++index, uint8(_type)); stmt->setUInt32(++index, GUID_LOPART(_playerGuid)); stmt->setString(++index, _playerName); stmt->setString(++index, _message); @@ -95,6 +99,7 @@ void GmTicket::SaveToDB(SQLTransaction& trans) const stmt->setUInt8 (++index, uint8(_escalatedStatus)); stmt->setBool (++index, _viewed); stmt->setBool (++index, _needMoreHelp); + stmt->setInt32 (++index, GUID_LOPART(_resolvedBy)); CharacterDatabase.ExecuteOrAppend(trans, stmt); } @@ -363,6 +368,20 @@ void TicketMgr::RemoveTicket(uint32 ticketId) } } +void TicketMgr::ResolveAndCloseTicket(uint32 ticketId, int64 source) +{ + if (GmTicket* ticket = GetTicket(ticketId)) + { + SQLTransaction trans = SQLTransaction(NULL); + ticket->SetClosedBy(source); + ticket->SetResolvedBy(source); + if (source) + --_openTicketCount; + ticket->SaveToDB(trans); + } +} + + void TicketMgr::ShowList(ChatHandler& handler, bool onlineOnly) const { handler.SendSysMessage(onlineOnly ? LANG_COMMAND_TICKETSHOWONLINELIST : LANG_COMMAND_TICKETSHOWLIST); diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h index 86ebcd9993..2328278039 100644 --- a/src/server/game/Tickets/TicketMgr.h +++ b/src/server/game/Tickets/TicketMgr.h @@ -78,6 +78,13 @@ enum LagReportType LAG_REPORT_TYPE_SPELL = 6 }; +enum TicketType +{ + TICKET_TYPE_OPEN = 0, + TICKET_TYPE_CLOSED = 1, + TICKET_TYPE_CHARACTER_DELETED = 2, +}; + class GmTicket { public: @@ -85,7 +92,7 @@ public: GmTicket(Player* player); ~GmTicket(); - bool IsClosed() const { return _closedBy; } + bool IsClosed() const { return _type != TICKET_TYPE_OPEN; } bool IsCompleted() const { return _completed; } bool IsFromPlayer(uint64 guid) const { return guid == _playerGuid; } bool IsAssigned() const { return _assignedTo != 0; } @@ -119,7 +126,8 @@ public: else if (_escalatedStatus == TICKET_UNASSIGNED) _escalatedStatus = TICKET_ASSIGNED; } - void SetClosedBy(int64 value) { _closedBy = value; } + void SetClosedBy(int64 value) { _closedBy = value; _type = TICKET_TYPE_CLOSED; } + void SetResolvedBy(int64 value) { _resolvedBy = value; } void SetCompleted() { _completed = true; } void SetMessage(std::string const& message) { @@ -151,6 +159,7 @@ public: private: uint32 _id; uint64 _playerGuid; + TicketType _type; // 0 = Open, 1 = Closed, 2 = Character deleted std::string _playerName; float _posX; float _posY; @@ -159,7 +168,8 @@ private: std::string _message; uint64 _createTime; uint64 _lastModifiedTime; - int64 _closedBy; // 0 = Open, -1 = Console, playerGuid = player abandoned ticket, other = GM who closed it. + int64 _closedBy; // 0 = Open or Closed by Console (if type = 1), playerGuid = GM who closed it or player abandoned ticket or read the GM response message. + int64 _resolvedBy; // 0 = Open, -1 = Resolved by Console, GM who resolved it by closing or completing the ticket. uint64 _assignedTo; std::string _comment; bool _completed; @@ -213,6 +223,7 @@ public: void AddTicket(GmTicket* ticket); void CloseTicket(uint32 ticketId, int64 source = -1); + void ResolveAndCloseTicket(uint32 ticketId, int64 source); // used when GM resolves a ticket by simply closing it void RemoveTicket(uint32 ticketId); bool GetStatus() const { return _status; } diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 86b087a46c..79ed1906ff 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -429,13 +429,18 @@ void World::LoadConfigSettings(bool reload) { if (!sConfigMgr->Reload()) { - sLog->outError("World settings reload fail: can't read settings from %s.", sConfigMgr->GetFilename().c_str()); + sLog->outError("World settings reload fail: can't read settings."); return; } - - sLog->ReloadConfig(); // Reload log levels and filters } + sScriptMgr->OnBeforeConfigLoad(reload); + + // Reload log levels and filters + // doing it again to allow sScriptMgr + // to change log confs at start + sLog->ReloadConfig(); + ///- Read the player limit and the Message of the day from the config file if (!reload) SetPlayerAmountLimit(sConfigMgr->GetIntDefault("PlayerLimit", 100)); @@ -443,6 +448,7 @@ void World::LoadConfigSettings(bool reload) ///- Read ticket system setting from the config file m_bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetBoolDefault("AllowTickets", true); + m_bool_configs[CONFIG_DELETE_CHARACTER_TICKET_TRACE] = sConfigMgr->GetBoolDefault("DeletedCharacterTicketTrace", false); ///- Get string for new logins (newly created characters) SetNewCharString(sConfigMgr->GetStringDefault("PlayerStart.String", "")); @@ -1043,6 +1049,7 @@ void World::LoadConfigSettings(bool reload) m_float_configs[CONFIG_LISTEN_RANGE_YELL] = sConfigMgr->GetFloatDefault("ListenRange.Yell", 300.0f); m_bool_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfigMgr->GetBoolDefault("Battleground.CastDeserter", true); + m_bool_configs[CONFIG_BATTLEGROUND_RANDOM_CROSSFACTION] = sConfigMgr->GetBoolDefault("Battleground.RandomCrossFaction.Enable", true); // [AZTH] RBG Crossfaction m_bool_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Battleground.QueueAnnouncer.Enable", false); m_int_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfigMgr->GetIntDefault ("Battleground.PrematureFinishTimer", 5 * MINUTE * IN_MILLISECONDS); m_int_configs[CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH] = sConfigMgr->GetIntDefault ("Battleground.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILLISECONDS); @@ -1234,8 +1241,7 @@ void World::LoadConfigSettings(bool reload) m_int_configs[CONFIG_BIRTHDAY_TIME] = sConfigMgr->GetIntDefault("BirthdayTime", 1222964635); // call ScriptMgr if we're reloading the configuration - if (reload) - sScriptMgr->OnConfigLoad(reload); + sScriptMgr->OnAfterConfigLoad(reload); } extern void LoadGameObjectModelList(); @@ -1251,6 +1257,9 @@ void World::SetInitialWorldSettings() ///- Initialize detour memory management dtAllocSetCustom(dtCustomAlloc, dtCustomFree); + + sLog->outString("Initializing Scripts..."); + sScriptMgr->Initialize(); ///- Initialize config settings LoadConfigSettings(); @@ -1698,9 +1707,8 @@ void World::SetInitialWorldSettings() sLog->outString("Loading Creature Text Locales..."); sCreatureTextMgr->LoadCreatureTextLocales(); - sLog->outString("Initializing Scripts..."); - sScriptMgr->Initialize(); - sScriptMgr->OnConfigLoad(false); // must be done after the ScriptMgr has been properly initialized + sLog->outString("Loading Scripts..."); + sScriptMgr->LoadDatabase(); sLog->outString("Validating spell scripts..."); sObjectMgr->ValidateSpellScripts(); diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h index dfb5f7102b..cbe8d5577d 100644 --- a/src/server/game/World/World.h +++ b/src/server/game/World/World.h @@ -127,6 +127,7 @@ enum WorldBoolConfigs CONFIG_DIE_COMMAND_MODE, CONFIG_DECLINED_NAMES_USED, CONFIG_BATTLEGROUND_CAST_DESERTER, + CONFIG_BATTLEGROUND_RANDOM_CROSSFACTION, // [AZTH] RBG Crossfaction CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE, CONFIG_BG_XP_FOR_KILL, CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, @@ -143,6 +144,7 @@ enum WorldBoolConfigs CONFIG_SHOW_KICK_IN_WORLD, CONFIG_AUTOBROADCAST, CONFIG_ALLOW_TICKETS, + CONFIG_DELETE_CHARACTER_TICKET_TRACE, CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES, CONFIG_PRESERVE_CUSTOM_CHANNELS, CONFIG_WINTERGRASP_ENABLE, diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 44ceb35eb2..9d5261e666 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -22,13 +22,19 @@ include(Commands/CMakeLists.txt) set(scripts_STAT_SRCS ${scripts_STAT_SRCS} + ScriptLoader.cpp + ScriptLoader.h + ${BUILDDIR}/GenLoader.cpp ../game/AI/ScriptedAI/ScriptedEscortAI.cpp ../game/AI/ScriptedAI/ScriptedCreature.cpp ../game/AI/ScriptedAI/ScriptedFollowerAI.cpp ) +AZTH_ADD_SCRIPTS("Spell" "ScriptLoader.h") +AZTH_ADD_SCRIPTS("SC_Smart" "ScriptLoader.h") +AZTH_ADD_SCRIPTS("Command" "ScriptLoader.h") + if(SCRIPTS) - include(Custom/CMakeLists.txt) include(World/CMakeLists.txt) include(OutdoorPvP/CMakeLists.txt) include(EasternKingdoms/CMakeLists.txt) @@ -39,6 +45,18 @@ if(SCRIPTS) include(Pet/CMakeLists.txt) endif() + +AZTH_GET_GLOBAL("AZTH_ADD_SCRIPTS_LIST") +AZTH_GET_GLOBAL("AZTH_ADD_SCRIPTS_INCLUDE") + +set("AZTH_SCRIPTS_INCLUDES" "") + +FOREACH (include ${AZTH_ADD_SCRIPTS_INCLUDE}) + set("AZTH_SCRIPTS_INCLUDES" "#include \"${include}\"\n${AZTH_SCRIPTS_INCLUDES}") +ENDFOREACH() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/GenLoader.cpp.cmake ${BUILDDIR}/GenLoader.cpp) + message(STATUS "SCRIPT PREPARATION COMPLETE") message("") @@ -140,6 +158,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/World ${CMAKE_SOURCE_DIR}/src/server/game/ArenaSpectator ${CMAKE_SOURCE_DIR}/src/server/game/Misc + ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/PrecompiledHeaders ${ACE_INCLUDE_DIR} ${MYSQL_INCLUDE_DIR} diff --git a/src/server/scripts/Commands/cs_ticket.cpp b/src/server/scripts/Commands/cs_ticket.cpp index 24a7e9c00e..d36ae4902c 100644 --- a/src/server/scripts/Commands/cs_ticket.cpp +++ b/src/server/scripts/Commands/cs_ticket.cpp @@ -156,7 +156,7 @@ public: return true; } - sTicketMgr->CloseTicket(ticket->GetId(), player ? player->GetGUID() : -1); + sTicketMgr->ResolveAndCloseTicket(ticket->GetId(), player ? player->GetGUID() : -1); sTicketMgr->UpdateLastChange(); std::string msg = ticket->FormatMessageString(*handler, player ? player->GetName().c_str() : "Console", NULL, NULL, NULL); @@ -234,8 +234,12 @@ public: if (Player* player = ticket->GetPlayer()) ticket->SendResponse(player->GetSession()); + Player* gm = handler->GetSession() ? handler->GetSession()->GetPlayer() : NULL; + + SQLTransaction trans = SQLTransaction(NULL); ticket->SetCompleted(); + ticket->SetResolvedBy(gm ? gm->GetGUID() : -1); ticket->SaveToDB(trans); sTicketMgr->UpdateLastChange(); diff --git a/src/server/scripts/Custom/CMakeLists.txt b/src/server/scripts/Custom/CMakeLists.txt deleted file mode 100644 index 26b9eb6ccb..0000000000 --- a/src/server/scripts/Custom/CMakeLists.txt +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (C) -# -# 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. - -set(scripts_STAT_SRCS - ${scripts_STAT_SRCS} -) - -message(" -> Prepared: Custom") diff --git a/src/server/scripts/EasternKingdoms/CMakeLists.txt b/src/server/scripts/EasternKingdoms/CMakeLists.txt index cf5a49ed8f..2ccc1001a8 100644 --- a/src/server/scripts/EasternKingdoms/CMakeLists.txt +++ b/src/server/scripts/EasternKingdoms/CMakeLists.txt @@ -164,4 +164,6 @@ set(scripts_STAT_SRCS EasternKingdoms/TheStockade/instance_the_stockade.cpp ) +AZTH_ADD_SCRIPTS("EasternKingdoms" "ScriptLoader.h") + message(" -> Prepared: Eastern Kingdoms") diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp index 08f3cf3fbf..91777b9941 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_nalorakk.cpp @@ -143,7 +143,9 @@ class boss_nalorakk : public CreatureScript waitTimer = 0; me->SetSpeed(MOVE_RUN, 2); me->SetWalk(false); - }else + ResetMobs(); + } + else { (*me).GetMotionMaster()->MovePoint(0, NalorakkWay[7][0], NalorakkWay[7][1], NalorakkWay[7][2]); } @@ -160,6 +162,33 @@ class boss_nalorakk : public CreatureScript // me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + 1, 5122); /// @todo find the correct equipment id } + void ResetMobs() + { + std::list<Creature*> templist; + float x, y, z; + me->GetPosition(x, y, z); + + { + CellCoord pair(Trinity::ComputeCellCoord(x, y)); + Cell cell(pair); + cell.SetNoCreate(); + + Trinity::AllFriendlyCreaturesInGrid check(me); + Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid> searcher(me, templist, check); + + TypeContainerVisitor<Trinity::CreatureListSearcher<Trinity::AllFriendlyCreaturesInGrid>, GridTypeMapContainer> cSearcher(searcher); + + cell.Visit(pair, cSearcher, *(me->GetMap()), *me, me->GetGridActivationRange()); + } + + if (templist.empty()) + return; + + for (std::list<Creature*>::const_iterator i = templist.begin(); i != templist.end(); ++i) + if ((*i) && me->IsWithinDistInMap((*i), 25)) + (*i)->AI()->Reset(); + } + void SendAttacker(Unit* target) { std::list<Creature*> templist; @@ -283,6 +312,7 @@ class boss_nalorakk : public CreatureScript void JustDied(Unit* /*killer*/) { + ResetMobs(); instance->SetData(DATA_NALORAKKEVENT, DONE); me->MonsterYell(YELL_DEATH, LANG_UNIVERSAL, NULL); diff --git a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp index 9b2d9be46b..084c87fbe9 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp @@ -235,69 +235,75 @@ class instance_zulaman : public InstanceMapScript { switch (type) { - case DATA_GONGEVENT: - m_auiEncounter[DATA_GONGEVENT] = data; - if (data == IN_PROGRESS) - SaveToDB(); - else if (data == DONE) - QuestMinute = 21; - break; - case DATA_NALORAKKEVENT: - m_auiEncounter[DATA_NALORAKKEVENT] = data; - if (data == DONE) - { - if (QuestMinute) + case DATA_GONGEVENT: + m_auiEncounter[DATA_GONGEVENT] = data; + if (data == IN_PROGRESS) + SaveToDB(); + else if (data == DONE) + QuestMinute = 21; + break; + case DATA_NALORAKKEVENT: + m_auiEncounter[DATA_NALORAKKEVENT] = data; + if (data == DONE) { - QuestMinute += 15; - DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute); + if (QuestMinute) + { + QuestMinute += 15; + DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute); + } + SummonHostage(0); + SaveToDB(); } - SummonHostage(0); - } - break; - case DATA_AKILZONEVENT: - m_auiEncounter[DATA_AKILZONEVENT] = data; - HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS); - if (data == DONE) - { - if (QuestMinute) + break; + case DATA_AKILZONEVENT: + m_auiEncounter[DATA_AKILZONEVENT] = data; + HandleGameObject(AkilzonDoorGUID, data != IN_PROGRESS); + if (data == DONE) { - QuestMinute += 10; - DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute); + if (QuestMinute) + { + QuestMinute += 10; + DoUpdateWorldState(WORLDSTATE_TIME_TO_SACRIFICE, QuestMinute); + } + SummonHostage(1); + SaveToDB(); } - SummonHostage(1); - } - break; - case DATA_JANALAIEVENT: - m_auiEncounter[DATA_JANALAIEVENT] = data; - if (data == DONE) - SummonHostage(2); - break; - case DATA_HALAZZIEVENT: - m_auiEncounter[DATA_HALAZZIEVENT] = data; - HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS); - if (data == DONE) SummonHostage(3); - break; - case DATA_HEXLORDEVENT: - m_auiEncounter[DATA_HEXLORDEVENT] = data; - if (data == IN_PROGRESS) - HandleGameObject(HexLordGateGUID, false); - else if (data == NOT_STARTED) - CheckInstanceStatus(); - break; - case DATA_ZULJINEVENT: - m_auiEncounter[DATA_ZULJINEVENT] = data; - HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS); - break; - case DATA_CHESTLOOTED: - ++ChestLooted; - SaveToDB(); - break; - case TYPE_RAND_VENDOR_1: - RandVendor[0] = data; - break; - case TYPE_RAND_VENDOR_2: - RandVendor[1] = data; - break; + break; + case DATA_JANALAIEVENT: + m_auiEncounter[DATA_JANALAIEVENT] = data; + if (data == DONE) + SummonHostage(2); + SaveToDB(); + break; + case DATA_HALAZZIEVENT: + m_auiEncounter[DATA_HALAZZIEVENT] = data; + HandleGameObject(HalazziDoorGUID, data != IN_PROGRESS); + if (data == DONE) SummonHostage(3); + SaveToDB(); + break; + case DATA_HEXLORDEVENT: + m_auiEncounter[DATA_HEXLORDEVENT] = data; + if (data == IN_PROGRESS) + HandleGameObject(HexLordGateGUID, false); + else if (data == NOT_STARTED) + CheckInstanceStatus(); + SaveToDB(); + break; + case DATA_ZULJINEVENT: + m_auiEncounter[DATA_ZULJINEVENT] = data; + HandleGameObject(ZulJinDoorGUID, data != IN_PROGRESS); + SaveToDB(); + break; + case DATA_CHESTLOOTED: + ++ChestLooted; + SaveToDB(); + break; + case TYPE_RAND_VENDOR_1: + RandVendor[0] = data; + break; + case TYPE_RAND_VENDOR_2: + RandVendor[1] = data; + break; } if (data == DONE) @@ -317,17 +323,17 @@ class instance_zulaman : public InstanceMapScript { switch (type) { - case DATA_GONGEVENT: return m_auiEncounter[DATA_GONGEVENT]; - case DATA_NALORAKKEVENT: return m_auiEncounter[DATA_NALORAKKEVENT]; - case DATA_AKILZONEVENT: return m_auiEncounter[DATA_AKILZONEVENT]; - case DATA_JANALAIEVENT: return m_auiEncounter[DATA_JANALAIEVENT]; - case DATA_HALAZZIEVENT: return m_auiEncounter[DATA_HALAZZIEVENT]; - case DATA_HEXLORDEVENT: return m_auiEncounter[DATA_HEXLORDEVENT]; - case DATA_ZULJINEVENT: return m_auiEncounter[DATA_ZULJINEVENT]; - case DATA_CHESTLOOTED: return ChestLooted; - case TYPE_RAND_VENDOR_1: return RandVendor[0]; - case TYPE_RAND_VENDOR_2: return RandVendor[1]; - default: return 0; + case DATA_GONGEVENT: return m_auiEncounter[DATA_GONGEVENT]; + case DATA_NALORAKKEVENT: return m_auiEncounter[DATA_NALORAKKEVENT]; + case DATA_AKILZONEVENT: return m_auiEncounter[DATA_AKILZONEVENT]; + case DATA_JANALAIEVENT: return m_auiEncounter[DATA_JANALAIEVENT]; + case DATA_HALAZZIEVENT: return m_auiEncounter[DATA_HALAZZIEVENT]; + case DATA_HEXLORDEVENT: return m_auiEncounter[DATA_HEXLORDEVENT]; + case DATA_ZULJINEVENT: return m_auiEncounter[DATA_ZULJINEVENT]; + case DATA_CHESTLOOTED: return ChestLooted; + case TYPE_RAND_VENDOR_1: return RandVendor[0]; + case TYPE_RAND_VENDOR_2: return RandVendor[1]; + default: return 0; } } diff --git a/src/server/scripts/Events/CMakeLists.txt b/src/server/scripts/Events/CMakeLists.txt index c14891c9e8..5f9c9aba2e 100644 --- a/src/server/scripts/Events/CMakeLists.txt +++ b/src/server/scripts/Events/CMakeLists.txt @@ -9,4 +9,6 @@ set(scripts_STAT_SRCS Events/midsummer.cpp ) -message(" -> Prepared: Events")
\ No newline at end of file +AZTH_ADD_SCRIPTS("Event" "ScriptLoader.h") + +message(" -> Prepared: Events") diff --git a/src/server/scripts/GenLoader.cpp.cmake b/src/server/scripts/GenLoader.cpp.cmake new file mode 100644 index 0000000000..7e656f099b --- /dev/null +++ b/src/server/scripts/GenLoader.cpp.cmake @@ -0,0 +1,7 @@ +// This file is autogenerated, please do not modify directly! + +@AZTH_SCRIPTS_INCLUDES@ + +void AddScripts() { + @AZTH_ADD_SCRIPTS_LIST@ +} diff --git a/src/server/scripts/Kalimdor/CMakeLists.txt b/src/server/scripts/Kalimdor/CMakeLists.txt index 674f7cee51..cd987796dd 100644 --- a/src/server/scripts/Kalimdor/CMakeLists.txt +++ b/src/server/scripts/Kalimdor/CMakeLists.txt @@ -105,4 +105,6 @@ set(scripts_STAT_SRCS Kalimdor/DireMaul/dire_maul.h ) +AZTH_ADD_SCRIPTS("Kalimdor" "ScriptLoader.h") + message(" -> Prepared: Kalimdor") diff --git a/src/server/scripts/Northrend/CMakeLists.txt b/src/server/scripts/Northrend/CMakeLists.txt index 3805aad11f..62d2f083b9 100644 --- a/src/server/scripts/Northrend/CMakeLists.txt +++ b/src/server/scripts/Northrend/CMakeLists.txt @@ -196,4 +196,6 @@ set(scripts_STAT_SRCS Northrend/DraktharonKeep/boss_dred.cpp ) +AZTH_ADD_SCRIPTS("Northrend" "ScriptLoader.h") + message(" -> Prepared: Northrend") diff --git a/src/server/scripts/OutdoorPvP/CMakeLists.txt b/src/server/scripts/OutdoorPvP/CMakeLists.txt index 728a5f88e7..dcdd6b30c0 100644 --- a/src/server/scripts/OutdoorPvP/CMakeLists.txt +++ b/src/server/scripts/OutdoorPvP/CMakeLists.txt @@ -26,4 +26,6 @@ set(scripts_STAT_SRCS OutdoorPvP/OutdoorPvPGH.h ) +AZTH_ADD_SCRIPTS("OutdoorPvP" "ScriptLoader.h") + message(" -> Prepared: Outdoor PVP Zones") diff --git a/src/server/scripts/Outland/CMakeLists.txt b/src/server/scripts/Outland/CMakeLists.txt index 606a4f42a1..660aae1bb0 100644 --- a/src/server/scripts/Outland/CMakeLists.txt +++ b/src/server/scripts/Outland/CMakeLists.txt @@ -109,4 +109,6 @@ set(scripts_STAT_SRCS Outland/zone_zangarmarsh.cpp ) +AZTH_ADD_SCRIPTS("Outland" "ScriptLoader.h") + message(" -> Prepared: Outland") diff --git a/src/server/scripts/Pet/CMakeLists.txt b/src/server/scripts/Pet/CMakeLists.txt index 47ccd38c79..b91af24a77 100644 --- a/src/server/scripts/Pet/CMakeLists.txt +++ b/src/server/scripts/Pet/CMakeLists.txt @@ -18,4 +18,6 @@ set(scripts_STAT_SRCS Pet/pet_shaman.cpp ) +AZTH_ADD_SCRIPTS("Pet" "ScriptLoader.h") + message(" -> Prepared: Pet") diff --git a/src/server/scripts/Pet/pet_dk.cpp b/src/server/scripts/Pet/pet_dk.cpp index 0a2f02f43f..5265c91f01 100644 --- a/src/server/scripts/Pet/pet_dk.cpp +++ b/src/server/scripts/Pet/pet_dk.cpp @@ -50,7 +50,11 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript _despawnTimer = 36000; // 30 secs + 4 fly out + 2 initial attack timer _despawning = false; _initialSelection = true; + _ghoulSelection = true; + _targetGUID = 0; + _markedTargetGUID = 0; + _ghoulTargetGUID = 0; } void MovementInform(uint32 type, uint32 point) @@ -90,8 +94,17 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript Unit* owner = me->GetOwner(); if (owner && owner->GetTypeId() == TYPEID_PLAYER && (!me->GetVictim() || me->GetVictim()->IsImmunedToSpell(sSpellMgr->GetSpellInfo(51963)) || !me->IsValidAttackTarget(me->GetVictim()) || !owner->CanSeeOrDetect(me->GetVictim()))) { - Unit* selection = owner->ToPlayer()->GetSelectedUnit(); - if (selection && selection != me->GetVictim() && me->IsValidAttackTarget(selection)) + Unit* ghoulTarget = ObjectAccessor::GetUnit(*me, GetGhoulTargetGUID()); + Unit* dkTarget = owner->ToPlayer()->GetSelectedUnit(); + + if (ghoulTarget && ghoulTarget != me->GetVictim() && me->IsValidAttackTarget(ghoulTarget)) + { + me->GetMotionMaster()->Clear(false); + SwitchTargetAndAttack(ghoulTarget); + return; + } + + if (dkTarget && dkTarget != me->GetVictim() && me->IsValidAttackTarget(dkTarget)) { me->GetMotionMaster()->Clear(false); SetGazeOn(selection); @@ -171,9 +184,52 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript (*iter)->RemoveAura(SPELL_DK_SUMMON_GARGOYLE_1, me->GetOwnerGUID()); SetGazeOn(*iter); _targetGUID = (*iter)->GetGUID(); + _markedTargetGUID = _targetGUID; break; } } + + if (_ghoulSelection) //find pet ghoul target + { + std::list<Unit*> targets; + Trinity::AnyFriendlyUnitInObjectRangeCheck ghoul_check(me, me, 50); + Trinity::UnitListSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(me, targets, ghoul_check); + me->VisitNearbyObject(50, searcher); + for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) + { + if ((*iter)->GetEntry() == 26125) // ghoul entry + { + if ((*iter)->GetOwnerGUID() == me->GetOwnerGUID()) // same owner + { + _ghoulTargetGUID = (*iter)->GetTarget(); + break; + } + } + } + } + + + + if (Unit* ghoulTarget = ObjectAccessor::GetUnit(*me, _ghoulTargetGUID)) + { + if(ghoulTarget->IsAlive()) + { + AttackStart(ghoulTarget); + } + } + else + { + _ghoulSelection = false; // check for ghoul at next update. + + if (Unit* markedTarget = ObjectAccessor::GetUnit(*me, _markedTargetGUID)) + { + if (markedTarget->IsAlive()) + { + AttackStart(markedTarget); + } + } + } + if (_despawnTimer > 4000) { _despawnTimer -= diff; @@ -190,8 +246,11 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript MySelectNextTarget(); _selectionTimer = 0; } - if (_initialCastTimer >= 2000 && !me->HasUnitState(UNIT_STATE_CASTING|UNIT_STATE_LOST_CONTROL) && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE) - me->CastSpell(me->GetVictim(), 51963, false); + // check start timer and if not casting + if(_initialCastTimer >= 2000 && !me->HasUnitState(UNIT_STATE_CASTING)) + if (!(me->HasAuraType(SPELL_AURA_MOD_FEAR) || me->HasAuraType(SPELL_AURA_MOD_ROOT) || me->HasAuraType(SPELL_AURA_MOD_CONFUSE) || me->HasAuraType(SPELL_AURA_MOD_STUN))) + if (_initialCastTimer >= 2000 && !me->HasUnitState(UNIT_STATE_LOST_CONTROL) && me->GetMotionMaster()->GetMotionSlotType(MOTION_SLOT_CONTROLLED) == NULL_MOTION_TYPE) + me->CastSpell(me->GetVictim(), 51963, false); } else { @@ -207,11 +266,14 @@ class npc_pet_dk_ebon_gargoyle : public CreatureScript private: uint64 _targetGUID; + uint64 _ghoulTargetGUID; + uint64 _markedTargetGUID; uint32 _despawnTimer; uint32 _selectionTimer; uint32 _initialCastTimer; bool _despawning; bool _initialSelection; + bool _ghoulSelection; }; CreatureAI* GetAI(Creature* creature) const @@ -282,7 +344,12 @@ class npc_pet_dk_dancing_rune_weapon : public CreatureScript // Xinef: Hit / Expertise scaling me->AddAura(61017, me); if (Unit* owner = me->GetOwner()) + { me->GetMotionMaster()->MoveFollow(owner, 0.01f, me->GetFollowAngle(), MOTION_SLOT_CONTROLLED); + if (Player* player = owner->ToPlayer()) + player->setRuneWeaponGUID(me->GetGUID()); + } + NullCreatureAI::InitializeAI(); } }; diff --git a/src/server/scripts/Pet/pet_generic.cpp b/src/server/scripts/Pet/pet_generic.cpp index e9456d3e44..fd214985e8 100644 --- a/src/server/scripts/Pet/pet_generic.cpp +++ b/src/server/scripts/Pet/pet_generic.cpp @@ -60,7 +60,7 @@ class npc_pet_gen_mojo : public CreatureScript me->HandleEmoteCommand(emote); Unit* owner = me->GetOwner(); if (emote != TEXT_EMOTE_KISS || !owner || owner->GetTypeId() != TYPEID_PLAYER || - owner->ToPlayer()->GetTeamId() != player->GetTeamId()) + owner->ToPlayer()->GetTeamId(true) != player->GetTeamId(true)) { return; } @@ -255,13 +255,13 @@ public: { _state = ARGENT_PONY_STATE_ENCH; - aura = (player->GetTeamId() == TEAM_ALLIANCE ? SPELL_AURA_TIRED_S : SPELL_AURA_TIRED_G); + aura = (player->GetTeamId(true) == TEAM_ALLIANCE ? SPELL_AURA_TIRED_S : SPELL_AURA_TIRED_G); duration = player->GetSpellCooldownDelay(aura); me->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); for (uint8 i = 0; i < 3; ++i) { - if (player->GetTeamId() == TEAM_ALLIANCE) + if (player->GetTeamId(true) == TEAM_ALLIANCE) { if (uint32 cooldown = player->GetSpellCooldownDelay(SPELL_AURA_POSTMAN_S+i)) { @@ -286,7 +286,7 @@ public: } // Generate Banners - uint32 mask = player->GetTeamId() ? RACEMASK_HORDE : RACEMASK_ALLIANCE; + uint32 mask = player->GetTeamId(true) ? RACEMASK_HORDE : RACEMASK_ALLIANCE; for (uint8 i = 1; i < MAX_RACES; ++i) if (mask & (1 << (i-1)) && player->HasAchieved(argentBanners[i].achievement)) _banners[i] = true; @@ -351,7 +351,7 @@ public: if (player->GetGUID() != creature->GetOwnerGUID()) return true; - if (!creature->HasAura(player->GetTeamId() ? SPELL_AURA_TIRED_G : SPELL_AURA_TIRED_S)) + if (!creature->HasAura(player->GetTeamId(true) ? SPELL_AURA_TIRED_G : SPELL_AURA_TIRED_S)) { uint8 _state = creature->AI()->GetData(0 /*GET_DATA_STATE*/); if (_state == ARGENT_PONY_STATE_ENCH || _state == ARGENT_PONY_STATE_VENDOR) @@ -379,20 +379,20 @@ public: case GOSSIP_ACTION_TRADE: creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_VENDOR); player->GetSession()->SendListInventory(creature->GetGUID()); - spellId = player->GetTeamId() ? SPELL_AURA_SHOP_G : SPELL_AURA_SHOP_S; + spellId = player->GetTeamId(true) ? SPELL_AURA_SHOP_G : SPELL_AURA_SHOP_S; creature->AI()->DoAction(ARGENT_PONY_STATE_VENDOR); break; case GOSSIP_ACTION_BANK: creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_BANKER); player->GetSession()->SendShowBank(player->GetGUID()); - spellId = player->GetTeamId() ? SPELL_AURA_BANK_G : SPELL_AURA_BANK_S; + spellId = player->GetTeamId(true) ? SPELL_AURA_BANK_G : SPELL_AURA_BANK_S; creature->AI()->DoAction(ARGENT_PONY_STATE_BANK); break; case GOSSIP_ACTION_MAILBOX: { creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP|UNIT_NPC_FLAG_MAILBOX); player->GetSession()->SendShowMailBox(creature->GetGUID()); - spellId = player->GetTeamId() ? SPELL_AURA_POSTMAN_G : SPELL_AURA_POSTMAN_S; + spellId = player->GetTeamId(true) ? SPELL_AURA_POSTMAN_G : SPELL_AURA_POSTMAN_S; creature->AI()->DoAction(ARGENT_PONY_STATE_MAILBOX); break; } @@ -409,7 +409,7 @@ public: { creature->CastSpell(creature, spellId, true); player->AddSpellCooldown(spellId, 0, 3*MINUTE*IN_MILLISECONDS); - player->AddSpellCooldown(player->GetTeamId() ? SPELL_AURA_TIRED_G : SPELL_AURA_TIRED_S, 0, 3*MINUTE*IN_MILLISECONDS + 4*HOUR*IN_MILLISECONDS); + player->AddSpellCooldown(player->GetTeamId(true) ? SPELL_AURA_TIRED_G : SPELL_AURA_TIRED_S, 0, 3*MINUTE*IN_MILLISECONDS + 4*HOUR*IN_MILLISECONDS); creature->DespawnOrUnsummon(3*MINUTE*IN_MILLISECONDS); } return true; diff --git a/src/server/game/Scripting/ScriptLoader.cpp b/src/server/scripts/ScriptLoader.cpp index 3b13eff925..89ac21bb38 100644 --- a/src/server/game/Scripting/ScriptLoader.cpp +++ b/src/server/scripts/ScriptLoader.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) + * Copyright (C) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -40,7 +40,7 @@ void AddSC_warrior_spell_scripts(); void AddSC_quest_spell_scripts(); void AddSC_item_spell_scripts(); -void AddSC_SmartSCripts(); +void AddSC_SmartScripts(); //Commands void AddSC_account_commandscript(); @@ -237,7 +237,7 @@ void AddSC_western_plaguelands(); void AddSC_westfall(); void AddSC_wetlands(); -//kalimdor +//kalimdor void AddSC_instance_blackfathom_deeps(); //Blackfathom Depths void AddSC_hyjal(); //CoT Battle for Mt. Hyjal void AddSC_boss_archimonde(); @@ -588,59 +588,6 @@ void AddSC_outdoorpvp_gh(); #endif -void AddScripts() -{ - AddSpellScripts(); - AddSC_SmartSCripts(); - AddCommandScripts(); -#ifdef SCRIPTS - AddWorldScripts(); - AddEventScripts(); - AddEasternKingdomsScripts(); - AddKalimdorScripts(); - AddOutlandScripts(); - AddNorthrendScripts(); - AddPetScripts(); - AddBattlegroundScripts(); - AddOutdoorPvPScripts(); - AddCustomScripts(); -#endif -} - -void CheckIfScriptsInDatabaseExist() -{ - ObjectMgr::ScriptNameContainer& sn = sObjectMgr->GetScriptNames(); - for (ObjectMgr::ScriptNameContainer::iterator itr = sn.begin(); itr != sn.end(); ++itr) - if (uint32 sid = sObjectMgr->GetScriptId((*itr).c_str())) - { - if (!ScriptRegistry<SpellScriptLoader>::GetScriptById(sid) && - !ScriptRegistry<ServerScript>::GetScriptById(sid) && - !ScriptRegistry<WorldScript>::GetScriptById(sid) && - !ScriptRegistry<FormulaScript>::GetScriptById(sid) && - !ScriptRegistry<WorldMapScript>::GetScriptById(sid) && - !ScriptRegistry<InstanceMapScript>::GetScriptById(sid) && - !ScriptRegistry<BattlegroundMapScript>::GetScriptById(sid) && - !ScriptRegistry<ItemScript>::GetScriptById(sid) && - !ScriptRegistry<CreatureScript>::GetScriptById(sid) && - !ScriptRegistry<GameObjectScript>::GetScriptById(sid) && - !ScriptRegistry<AreaTriggerScript>::GetScriptById(sid) && - !ScriptRegistry<BattlegroundScript>::GetScriptById(sid) && - !ScriptRegistry<OutdoorPvPScript>::GetScriptById(sid) && - !ScriptRegistry<CommandScript>::GetScriptById(sid) && - !ScriptRegistry<WeatherScript>::GetScriptById(sid) && - !ScriptRegistry<AuctionHouseScript>::GetScriptById(sid) && - !ScriptRegistry<ConditionScript>::GetScriptById(sid) && - !ScriptRegistry<VehicleScript>::GetScriptById(sid) && - !ScriptRegistry<DynamicObjectScript>::GetScriptById(sid) && - !ScriptRegistry<TransportScript>::GetScriptById(sid) && - !ScriptRegistry<AchievementCriteriaScript>::GetScriptById(sid) && - !ScriptRegistry<PlayerScript>::GetScriptById(sid) && - !ScriptRegistry<GuildScript>::GetScriptById(sid) && - !ScriptRegistry<GroupScript>::GetScriptById(sid)) - sLog->outErrorDb("Script named '%s' is assigned in database, but has no code!", (*itr).c_str()); - } -} - void AddSpellScripts() { AddSC_deathknight_spell_scripts(); @@ -1233,21 +1180,3 @@ void AddOutdoorPvPScripts() #endif } -void AddBattlegroundScripts() -{ -#ifdef SCRIPTS -#endif -} - -#ifdef SCRIPTS -/* This is where custom scripts' loading functions should be declared. */ - -#endif - -void AddCustomScripts() -{ -#ifdef SCRIPTS - /* This is where custom scripts should be added. */ - -#endif -} diff --git a/src/server/game/Scripting/ScriptLoader.h b/src/server/scripts/ScriptLoader.h index 301b0e736b..2ca37df35d 100644 --- a/src/server/game/Scripting/ScriptLoader.h +++ b/src/server/scripts/ScriptLoader.h @@ -19,18 +19,16 @@ #define SC_SCRIPTLOADER_H void AddScripts(); -void CheckIfScriptsInDatabaseExist(); void AddSpellScripts(); void AddCommandScripts(); +void AddSC_SmartScripts(); void AddWorldScripts(); void AddEventScripts(); void AddEasternKingdomsScripts(); void AddKalimdorScripts(); void AddOutlandScripts(); void AddNorthrendScripts(); -void AddBattlegroundScripts(); void AddPetScripts(); void AddOutdoorPvPScripts(); -void AddCustomScripts(); #endif diff --git a/src/server/scripts/World/CMakeLists.txt b/src/server/scripts/World/CMakeLists.txt index 84bcb1e6c0..192a8f1564 100644 --- a/src/server/scripts/World/CMakeLists.txt +++ b/src/server/scripts/World/CMakeLists.txt @@ -23,4 +23,6 @@ set(scripts_STAT_SRCS World/npcs_special.cpp ) +AZTH_ADD_SCRIPTS("World" "ScriptLoader.h") + message(" -> Prepared: World") diff --git a/src/server/shared/Configuration/Config.cpp b/src/server/shared/Configuration/Config.cpp index 43b50b49e0..2dce7a7482 100644 --- a/src/server/shared/Configuration/Config.cpp +++ b/src/server/shared/Configuration/Config.cpp @@ -49,10 +49,9 @@ bool ConfigMgr::LoadInitial(char const* file) GuardType guard(_configLock); - _filename = file; _config.reset(new ACE_Configuration_Heap()); if (_config->open() == 0) - if (LoadData(_filename.c_str())) + if (LoadData(file)) return true; _config.reset(); @@ -71,11 +70,25 @@ bool ConfigMgr::LoadMore(char const* file) bool ConfigMgr::Reload() { - return LoadInitial(_filename.c_str()); + for(std::vector<std::string>::iterator it = _confFiles.begin(); it != _confFiles.end(); ++it) { + if (it==_confFiles.begin()) { + if (!LoadInitial((*it).c_str())) + return false; + } else { + if (!LoadMore((*it).c_str())) + return false; + } + } + + return true; } bool ConfigMgr::LoadData(char const* file) { + if(std::find(_confFiles.begin(), _confFiles.end(), file) == _confFiles.end()) { + _confFiles.push_back(file); + } + ACE_Ini_ImpExp config_importer(*_config.get()); if (config_importer.import_config(file) == 0) return true; @@ -112,12 +125,6 @@ float ConfigMgr::GetFloatDefault(const char* name, float def) return GetValueHelper(name, val) ? (float)atof(val.c_str()) : def; } -std::string const& ConfigMgr::GetFilename() -{ - GuardType guard(_configLock); - return _filename; -} - std::list<std::string> ConfigMgr::GetKeysByString(std::string const& name) { GuardType guard(_configLock); diff --git a/src/server/shared/Configuration/Config.h b/src/server/shared/Configuration/Config.h index c640bcfbbf..cb51293b30 100644 --- a/src/server/shared/Configuration/Config.h +++ b/src/server/shared/Configuration/Config.h @@ -21,6 +21,7 @@ #include <string> #include <list> +#include <vector> #include <ace/Singleton.h> #include <ace/Configuration_Import_Export.h> #include <ace/Thread_Mutex.h> @@ -55,7 +56,6 @@ public: int GetIntDefault(const char* name, int def); float GetFloatDefault(const char* name, float def); - std::string const& GetFilename(); std::list<std::string> GetKeysByString(std::string const& name); private: @@ -65,7 +65,7 @@ private: typedef ACE_Thread_Mutex LockType; typedef ACE_Guard<LockType> GuardType; - std::string _filename; + std::vector<std::string> _confFiles; Config _config; LockType _configLock; diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp index 80ef19aea0..b117fbfb95 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp @@ -302,10 +302,11 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_GO_RESPAWN_BY_INSTANCE, "DELETE FROM gameobject_respawn WHERE mapId = ? AND instanceId = ?", CONNECTION_ASYNC); // GM Tickets - PrepareStatement(CHAR_SEL_GM_TICKETS, "SELECT ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket FROM gm_tickets", CONNECTION_SYNCH); - PrepareStatement(CHAR_REP_GM_TICKET, "REPLACE INTO gm_tickets (ticketId, guid, name, message, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, haveTicket) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); - PrepareStatement(CHAR_DEL_GM_TICKET, "DELETE FROM gm_tickets WHERE ticketId = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_tickets WHERE guid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_GM_TICKETS, "SELECT id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy FROM gm_ticket", CONNECTION_SYNCH); + PrepareStatement(CHAR_REP_GM_TICKET, "REPLACE INTO gm_ticket (id, type, playerGuid, name, description, createTime, mapId, posX, posY, posZ, lastModifiedTime, closedBy, assignedTo, comment, response, completed, escalated, viewed, needMoreHelp, resolvedBy) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_GM_TICKET, "DELETE FROM gm_ticket WHERE id = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_PLAYER_GM_TICKETS, "DELETE FROM gm_ticket WHERE playerGuid = ?", CONNECTION_ASYNC); + PrepareStatement(CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION, "UPDATE gm_ticket SET type = 2 WHERE playerGuid = ?", CONNECTION_ASYNC); // GM Survey/subsurvey/lag report PrepareStatement(CHAR_INS_GM_SURVEY, "INSERT INTO gm_surveys (guid, surveyId, mainSurvey, overallComment, createTime) VALUES (?, ?, ?, ?, UNIX_TIMESTAMP(NOW()))", CONNECTION_ASYNC); @@ -349,7 +350,7 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_UPD_GROUP_MEMBER_FLAG, "UPDATE group_member SET memberFlags = ? WHERE memberGuid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_GROUP_DIFFICULTY, "UPDATE groups SET difficulty = ? WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_GROUP_RAID_DIFFICULTY, "UPDATE groups SET raiddifficulty = ? WHERE guid = ?", CONNECTION_ASYNC); - PrepareStatement(CHAR_DEL_ALL_GM_TICKETS, "TRUNCATE TABLE gm_tickets", CONNECTION_ASYNC); + PrepareStatement(CHAR_DEL_ALL_GM_TICKETS, "TRUNCATE TABLE gm_ticket", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_INVALID_SPELL_TALENTS, "DELETE FROM character_talent WHERE spell = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_INVALID_SPELL_SPELLS, "DELETE FROM character_spell WHERE spell = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_UPD_DELETE_INFO, "UPDATE characters SET deleteInfos_Name = name, deleteInfos_Account = account, deleteDate = UNIX_TIMESTAMP(), name = '', account = 0 WHERE guid = ?", CONNECTION_ASYNC); diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h index da9598e964..0a25b7751e 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/shared/Database/Implementation/CharacterDatabase.h @@ -268,6 +268,7 @@ enum CharacterDatabaseStatements CHAR_DEL_GM_TICKET, CHAR_DEL_ALL_GM_TICKETS, CHAR_DEL_PLAYER_GM_TICKETS, + CHAR_UPD_PLAYER_GM_TICKETS_ON_CHAR_DELETION, CHAR_INS_GM_SURVEY, CHAR_INS_GM_SUBSURVEY, diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index 5bd1dd2212..1b6b3ae2b7 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -208,3 +208,5 @@ endif() if( USE_COREPCH ) add_cxx_pch(worldserver ${worldserver_PCH_HDR} ${worldserver_PCH_SRC}) endif() + +RUN_HOOK("AFTER_WORLDSERVER_CMAKE") diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp index aeb6547819..588e25565f 100644 --- a/src/server/worldserver/Main.cpp +++ b/src/server/worldserver/Main.cpp @@ -125,12 +125,21 @@ extern int main(int argc, char** argv) ++c; } - if (!sConfigMgr->LoadInitial(cfg_file)) + std::string cfg_def_file=_TRINITY_CORE_CONFIG; + cfg_def_file += ".dist"; + + if (!sConfigMgr->LoadInitial(cfg_def_file.c_str())) { + printf("Invalid or missing default configuration file : %s\n", cfg_def_file.c_str()); + return 1; + } + + if (!sConfigMgr->LoadMore(cfg_file)) { printf("Invalid or missing configuration file : %s\n", cfg_file); printf("Verify that the file exists and has \'[worldserver]' written in the top of the file!\n"); return 1; } + sLog->outString("Using configuration file %s.", cfg_file); sLog->outString("Using SSL version: %s (library: %s)", OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION)); diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist index 31fb37e757..d27373de10 100644 --- a/src/server/worldserver/worldserver.conf.dist +++ b/src/server/worldserver/worldserver.conf.dist @@ -1407,6 +1407,15 @@ Command.LookupMaxResults = 0 AllowTickets = 1 +# DeletedCharacterTicketTrace +# Description: Keep trace of tickets opened by deleted characters +# gm_ticket.playerGuid will be 0, old GUID and character name +# will be included in gm_ticket.comment +# Default: 0 - (Disabled) +# 1 - (Enabled) + +DeletedCharacterTicketTrace = 0 + # # DungeonFinder.OptionsMask # Description: Dungeon and raid finder system. @@ -2440,6 +2449,14 @@ AutoBroadcast.Timer = 60000 Battleground.CastDeserter = 1 # +# Battleground.RandomCrossFaction.Enable +# Description: Enable random battleground crossfaction randomizing system +# Default: 0 - (Disabled) +# 1 - (Enabled) + +Battleground.RandomCrossFaction.Enable = 1 + +# # Battleground.QueueAnnouncer.Enable # Description: Announce battleground queue status to chat. # Default: 0 - (Disabled) |