mirror of
https://github.com/azerothcore/azerothcore-wotlk.git
synced 2025-11-10 21:04:26 +08:00
Merge branch 'master' into fix/raise-ally-target-check
This commit is contained in:
commit
05a27d11c8
19
.github/workflows/dashboard-ci.yml
vendored
19
.github/workflows/dashboard-ci.yml
vendored
@ -74,11 +74,16 @@ jobs:
|
||||
|
||||
- name: Configure AzerothCore settings
|
||||
run: |
|
||||
# Create basic configuration
|
||||
cp conf/dist/config.sh conf/config.sh
|
||||
# Configure dashboard
|
||||
sed -i 's/MTHREADS=.*/MTHREADS="4"/' conf/config.sh
|
||||
sed -i 's/CBUILD_TESTING=.*/CBUILD_TESTING="ON"/' conf/config.sh
|
||||
touch conf/config.sh
|
||||
echo 'MTHREADS=4' >> conf/config.sh
|
||||
echo 'CBUILD_TESTING=ON' >> conf/config.sh
|
||||
echo 'AC_ENABLE_ROOT_CMAKE_INSTALL=1' >> conf/config.sh
|
||||
echo 'export AC_CONFIG_POLICY=$AC_CONFIG_POLICY_PRESET_ZERO_CONF' >> conf/config.sh
|
||||
echo 'AC_ENABLE_CONF_COPY_ON_INSTALL=0' >> conf/config.sh
|
||||
cat conf/config.sh
|
||||
|
||||
# debug content of AC_CONFIG_POLICY
|
||||
./acore.sh config show AC_CONFIG_POLICY
|
||||
|
||||
- name: Test module commands
|
||||
run: |
|
||||
@ -92,8 +97,6 @@ jobs:
|
||||
./acore.sh module update --all
|
||||
|
||||
- name: Run complete installation (deps, compile, database, client-data)
|
||||
env:
|
||||
AC_ENABLE_ROOT_CMAKE_INSTALL: 1
|
||||
run: |
|
||||
# This runs: install-deps, compile, database setup, client-data download
|
||||
./acore.sh init
|
||||
@ -113,12 +116,14 @@ jobs:
|
||||
|
||||
- name: Test authserver dry-run
|
||||
run: |
|
||||
source ./acore.sh config load
|
||||
cd env/dist/bin
|
||||
timeout 5m ./authserver -dry-run
|
||||
continue-on-error: false
|
||||
|
||||
- name: Test worldserver dry-run
|
||||
run: |
|
||||
source ./acore.sh config load
|
||||
cd env/dist/bin
|
||||
timeout 5m ./worldserver -dry-run
|
||||
continue-on-error: false
|
||||
|
||||
@ -1,17 +1,19 @@
|
||||
function registerHooks() { acore_event_registerHooks "$@"; }
|
||||
function runHooks() { acore_event_runHooks "$@"; }
|
||||
|
||||
#shellcheck source=../../conf/dist/config.sh
|
||||
source "$AC_PATH_CONF/dist/config.sh" # include dist to avoid missing conf variables
|
||||
function acore_common_loadConfig() {
|
||||
#shellcheck source=../../conf/dist/config.sh
|
||||
source "$AC_PATH_CONF/dist/config.sh" # include dist to avoid missing conf variables
|
||||
|
||||
# first check if it's defined in env, otherwise use the default
|
||||
USER_CONF_PATH=${USER_CONF_PATH:-"$AC_PATH_CONF/config.sh"}
|
||||
# first check if it's defined in env, otherwise use the default
|
||||
USER_CONF_PATH=${USER_CONF_PATH:-"$AC_PATH_CONF/config.sh"}
|
||||
|
||||
if [ -f "$USER_CONF_PATH" ]; then
|
||||
source "$USER_CONF_PATH" # should overwrite previous
|
||||
else
|
||||
echo "NOTICE: file <$USER_CONF_PATH> not found, we use default configuration only."
|
||||
fi
|
||||
if [ -f "$USER_CONF_PATH" ]; then
|
||||
source "$USER_CONF_PATH" # should overwrite previous
|
||||
else
|
||||
echo "NOTICE: file <$USER_CONF_PATH> not found, we use default configuration only."
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# Load modules
|
||||
|
||||
@ -25,4 +25,6 @@ export AC_PATH_MODULES="$AC_PATH_ROOT/modules"
|
||||
|
||||
export AC_PATH_DEPS="$AC_PATH_ROOT/deps"
|
||||
|
||||
export AC_BASH_LIB_PATH="$AC_PATH_DEPS/acore/bash-lib/src"
|
||||
|
||||
export AC_PATH_VAR="$AC_PATH_ROOT/var"
|
||||
|
||||
@ -16,6 +16,8 @@ source "$AC_PATH_DEPS/acore/bash-lib/src/event/hooks.sh"
|
||||
# shellcheck source=./common.sh
|
||||
source "$AC_PATH_SHARED/common.sh"
|
||||
|
||||
acore_common_loadConfig
|
||||
|
||||
if [[ "$OSTYPE" = "msys" ]]; then
|
||||
AC_BINPATH_FULL="$BINPATH"
|
||||
else
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# shellcheck source=../../../deps/acore/bash-lib/src/common/boolean.sh
|
||||
source "$AC_BASH_LIB_PATH/common/boolean.sh"
|
||||
|
||||
# Set SUDO variable - one liner
|
||||
SUDO=""
|
||||
|
||||
@ -135,7 +138,8 @@ function comp_compile() {
|
||||
echo "Done"
|
||||
;;
|
||||
linux*|darwin*)
|
||||
local confDir=${CONFDIR:-"$AC_BINPATH_FULL/../etc"}
|
||||
local confDir
|
||||
confDir=${CONFDIR:-"$AC_BINPATH_FULL/../etc"}
|
||||
|
||||
# create the folders before installing to
|
||||
# set the current user and permissions
|
||||
@ -145,6 +149,8 @@ function comp_compile() {
|
||||
mkdir -p "$confDir"
|
||||
mkdir -p "$confDir/modules"
|
||||
|
||||
confDir=$(realpath "$confDir")
|
||||
|
||||
echo "Cmake install..."
|
||||
$SUDO cmake --install . --config $CTYPE
|
||||
|
||||
@ -161,18 +167,25 @@ function comp_compile() {
|
||||
$SUDO setcap cap_sys_nice=eip "$AC_BINPATH_FULL/authserver"
|
||||
fi
|
||||
|
||||
[[ -f "$confDir/worldserver.conf.dist" ]] && \
|
||||
cp -v --no-clobber "$confDir/worldserver.conf.dist" "$confDir/worldserver.conf"
|
||||
[[ -f "$confDir/authserver.conf.dist" ]] && \
|
||||
cp -v --no-clobber "$confDir/authserver.conf.dist" "$confDir/authserver.conf"
|
||||
[[ -f "$confDir/dbimport.conf.dist" ]] && \
|
||||
cp -v --no-clobber "$confDir/dbimport.conf.dist" "$confDir/dbimport.conf"
|
||||
|
||||
for f in "$confDir/modules/"*.dist
|
||||
do
|
||||
[[ -e $f ]] || break # handle the case of no *.dist files
|
||||
cp -v --no-clobber "$f" "${f%.dist}";
|
||||
done
|
||||
if ( isTrue "$AC_ENABLE_CONF_COPY_ON_INSTALL" ) then
|
||||
echo "Copying default configuration files to $confDir ..."
|
||||
[[ -f "$confDir/worldserver.conf.dist" && ! -f "$confDir/worldserver.conf" ]] && \
|
||||
cp -v "$confDir/worldserver.conf.dist" "$confDir/worldserver.conf"
|
||||
[[ -f "$confDir/authserver.conf.dist" && ! -f "$confDir/authserver.conf" ]] && \
|
||||
cp -v "$confDir/authserver.conf.dist" "$confDir/authserver.conf"
|
||||
[[ -f "$confDir/dbimport.conf.dist" && ! -f "$confDir/dbimport.conf" ]] && \
|
||||
cp -v "$confDir/dbimport.conf.dist" "$confDir/dbimport.conf"
|
||||
|
||||
for f in "$confDir/modules/"*.dist
|
||||
do
|
||||
[[ -e $f ]] || break # handle the case of no *.dist files
|
||||
if [[ ! -f "${f%.dist}" ]]; then
|
||||
echo "Copying module config $(basename "${f%.dist}")"
|
||||
cp -v "$f" "${f%.dist}";
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
echo "Done"
|
||||
;;
|
||||
|
||||
9
apps/installer/includes/config/config-main.sh
Normal file
9
apps/installer/includes/config/config-main.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd )
|
||||
|
||||
# shellcheck source=./config.sh
|
||||
source "$CURRENT_PATH/config.sh"
|
||||
|
||||
acore_dash_config "$@"
|
||||
|
||||
60
apps/installer/includes/config/config.sh
Normal file
60
apps/installer/includes/config/config.sh
Normal file
@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
CURRENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd )
|
||||
|
||||
# shellcheck source=../../../bash_shared/includes.sh
|
||||
source "$CURRENT_PATH/../../../bash_shared/includes.sh"
|
||||
# shellcheck source=../includes.sh
|
||||
source "$CURRENT_PATH/../includes.sh"
|
||||
# shellcheck source=../../../bash_shared/menu_system.sh
|
||||
source "$AC_PATH_APPS/bash_shared/menu_system.sh"
|
||||
|
||||
function acore_dash_configShowValue() {
|
||||
if [ $# -ne 1 ]; then
|
||||
echo "Usage: show <VAR_NAME>"
|
||||
return 1
|
||||
fi
|
||||
|
||||
local varName="$1"
|
||||
local varValue="${!varName}"
|
||||
if [ -z "$varValue" ]; then
|
||||
echo "$varName is not set."
|
||||
else
|
||||
echo "$varName=$varValue"
|
||||
fi
|
||||
}
|
||||
|
||||
function acore_dash_configLoad() {
|
||||
acore_common_loadConfig
|
||||
echo "Configuration loaded into the current shell session."
|
||||
}
|
||||
|
||||
# Configuration management menu definition
|
||||
# Format: "key|short|description"
|
||||
config_menu_items=(
|
||||
"show|s|Show configuration variable value"
|
||||
"load|l|Load configurations variables within the current shell session"
|
||||
"help|h|Show detailed help"
|
||||
"quit|q|Close this menu"
|
||||
)
|
||||
|
||||
# Menu command handler for configuration operations
|
||||
function handle_config_command() {
|
||||
local key="$1"
|
||||
shift
|
||||
|
||||
case "$key" in
|
||||
"show")
|
||||
acore_dash_configShowValue "$@"
|
||||
;;
|
||||
"load")
|
||||
acore_dash_configLoad
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
function acore_dash_config() {
|
||||
menu_run_with_items "CONFIG MANAGER" handle_config_command -- "${config_menu_items[@]}" -- "$@"
|
||||
return $?
|
||||
}
|
||||
|
||||
@ -183,3 +183,5 @@ function inst_download_client_data {
|
||||
&& echo "Remove downloaded file" && rm "$zipPath" \
|
||||
&& echo "INSTALLED_VERSION=$VERSION" > "$dataVersionFile"
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
CURRENT_PATH=$( cd "$(dirname "${BASH_SOURCE[0]}")" ; pwd )
|
||||
|
||||
# shellcheck source=../../bash_shared/includes.sh
|
||||
source "$CURRENT_PATH/../../bash_shared/includes.sh"
|
||||
|
||||
AC_PATH_INSTALLER="$AC_PATH_APPS/installer"
|
||||
@ -9,14 +10,14 @@ AC_PATH_INSTALLER="$AC_PATH_APPS/installer"
|
||||
J_PATH="$AC_PATH_DEPS/acore/joiner"
|
||||
J_PATH_MODULES="$AC_PATH_MODULES"
|
||||
|
||||
# shellcheck source=../../../deps/acore/joiner/joiner.sh
|
||||
source "$J_PATH/joiner.sh"
|
||||
|
||||
if [ -f "$AC_PATH_INSTALLER/config.sh" ]; then
|
||||
source "$AC_PATH_INSTALLER/config.sh" # should overwrite previous
|
||||
fi
|
||||
|
||||
# shellcheck source=../../compiler/includes/includes.sh
|
||||
source "$AC_PATH_APPS/compiler/includes/includes.sh"
|
||||
|
||||
# shellcheck source=../../../deps/semver_bash/semver.sh
|
||||
source "$AC_PATH_DEPS/semver_bash/semver.sh"
|
||||
|
||||
# shellcheck source=../includes/functions.sh
|
||||
source "$AC_PATH_INSTALLER/includes/functions.sh"
|
||||
|
||||
@ -59,7 +59,6 @@ else
|
||||
C_GREEN=''
|
||||
C_YELLOW=''
|
||||
C_BLUE=''
|
||||
C_MAGENTA=''
|
||||
C_CYAN=''
|
||||
fi
|
||||
|
||||
@ -174,42 +173,8 @@ function inst_module_list() {
|
||||
# Usage: ./acore.sh module <search|install|update|remove> [args...]
|
||||
# ./acore.sh module # Interactive menu
|
||||
function inst_module() {
|
||||
# If no arguments provided, start interactive menu
|
||||
if [[ $# -eq 0 ]]; then
|
||||
menu_run_with_items "MODULE MANAGER" handle_module_command -- "${module_menu_items[@]}" --
|
||||
return $?
|
||||
fi
|
||||
|
||||
# Normalize arguments into an array
|
||||
local tokens=()
|
||||
read -r -a tokens <<< "$*"
|
||||
local cmd="${tokens[0]}"
|
||||
local args=("${tokens[@]:1}")
|
||||
|
||||
case "$cmd" in
|
||||
""|"help"|"-h"|"--help")
|
||||
inst_module_help
|
||||
;;
|
||||
"search"|"s")
|
||||
inst_module_search "${args[@]}"
|
||||
;;
|
||||
"install"|"i")
|
||||
inst_module_install "${args[@]}"
|
||||
;;
|
||||
"update"|"u")
|
||||
inst_module_update "${args[@]}"
|
||||
;;
|
||||
"remove"|"r")
|
||||
inst_module_remove "${args[@]}"
|
||||
;;
|
||||
"list"|"l")
|
||||
inst_module_list "${args[@]}"
|
||||
;;
|
||||
*)
|
||||
print_error "Unknown module command: $cmd. Use 'help' to see available commands."
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
menu_run_with_items "MODULE MANAGER" handle_module_command -- "${module_menu_items[@]}" -- "$@"
|
||||
return $?
|
||||
}
|
||||
|
||||
# =============================================================================
|
||||
@ -683,7 +648,7 @@ function inst_getVersionBranch() {
|
||||
res="none"
|
||||
# since we've the pair version,branch alternated in not associative and one-dimensional
|
||||
# array, we've to simulate the association with length/2 trick
|
||||
for idx in `seq 0 $((${#vers[*]}/2-1))`; do
|
||||
for idx in $(seq 0 $((${#vers[*]}/2-1))); do
|
||||
semverParseInto "${vers[idx*2]}" MODULE_MAJOR MODULE_MINOR MODULE_PATCH MODULE_SPECIAL
|
||||
if [[ $MODULE_MAJOR -eq $ACV_MAJOR && $MODULE_MINOR -le $ACV_MINOR ]]; then
|
||||
res="${vers[idx*2+1]}"
|
||||
|
||||
@ -45,6 +45,7 @@ menu_items=(
|
||||
"docker|dr|Run docker tools"
|
||||
"version|v|Show AzerothCore version"
|
||||
"service-manager|sm|Run service manager to run authserver and worldserver in background"
|
||||
"config|cf|Configuration manager"
|
||||
"quit|q|Exit from this menu"
|
||||
)
|
||||
|
||||
@ -100,6 +101,9 @@ function handle_menu_command() {
|
||||
bash "$AC_PATH_APPS/startup-scripts/src/service-manager.sh" "$@"
|
||||
exit
|
||||
;;
|
||||
"config")
|
||||
bash "$AC_PATH_APPS/installer/includes/config/config-main.sh" "$@"
|
||||
;;
|
||||
"quit")
|
||||
echo "Goodbye!"
|
||||
exit
|
||||
|
||||
@ -751,5 +751,5 @@ EOF
|
||||
|
||||
run inst_module "unknown-command"
|
||||
[ "$status" -eq 1 ]
|
||||
[[ "$output" =~ "Unknown module command" ]]
|
||||
[[ "$output" =~ "Invalid option" ]]
|
||||
}
|
||||
@ -50,6 +50,8 @@ fi
|
||||
# Main restart loop
|
||||
while true; do
|
||||
STARTING_TIME=$(date +%s)
|
||||
|
||||
echo "AC_CONFIG_POLICY: $AC_CONFIG_POLICY"
|
||||
|
||||
# Use starter script to launch the binary with all parameters
|
||||
"$STARTER_SCRIPT" "$BINPATH" "$BINFILE" "$GDB_FILE" "$CONFIG" "$SYSLOG" "$SYSERR" "$GDB_ENABLED" "$CRASHES_PATH"
|
||||
|
||||
36
conf/dist/config.sh
vendored
36
conf/dist/config.sh
vendored
@ -118,6 +118,12 @@ export CCACHE_DIR=${CCACHE_DIR:-"$AC_PATH_VAR/ccache"}
|
||||
#
|
||||
export AC_ENABLE_ROOT_CMAKE_INSTALL=${AC_ENABLE_ROOT_CMAKE_INSTALL:-0}
|
||||
|
||||
#
|
||||
# Enable copying configuration files on install
|
||||
# Default: 1 (true)
|
||||
#
|
||||
export AC_ENABLE_CONF_COPY_ON_INSTALL=${AC_ENABLE_CONF_COPY_ON_INSTALL:-1}
|
||||
|
||||
##############################################
|
||||
#
|
||||
# GOOGLE PERF TOOLS
|
||||
@ -182,4 +188,34 @@ export MODULES_EXCLUDE_LIST=""
|
||||
NO_COLOR=${NO_COLOR:-}
|
||||
FORCE_COLOR=${FORCE_COLOR:-}
|
||||
|
||||
##############################################
|
||||
#
|
||||
# CONFIGURATION SEVERITY POLICY
|
||||
#
|
||||
# Controls how the core reacts to missing configuration files,
|
||||
# missing/unknown options and invalid values.
|
||||
# The policy string follows the format "key=severity" separated by commas.
|
||||
# Supported severities: skip, warn, error, fatal.
|
||||
# Possible keys: default, missing_file, missing_option, critical_option,
|
||||
# unknown_option, value_error.
|
||||
#
|
||||
# Examples:
|
||||
# export AC_CONFIG_POLICY="$AC_CONFIG_POLICY_PRESET_DEFAULT"
|
||||
# export AC_CONFIG_POLICY="default=skip,critical_option=fatal,unknown_option=warn"
|
||||
# export AC_CONFIG_POLICY="missing_file=fatal,missing_option=error"
|
||||
#
|
||||
# Presets:
|
||||
# AC_CONFIG_POLICY_PRESET_DEFAULT -> mirrors the core default behaviour
|
||||
# (errors on missing files, fatal on critical)
|
||||
# AC_CONFIG_POLICY_PRESET_ZERO_CONF -> skips non-critical gaps so the core
|
||||
# can boot from environment defaults
|
||||
# AC_CONFIG_POLICY_PRESET_STRICT -> escalates everything to errors/fatals
|
||||
#
|
||||
|
||||
export AC_CONFIG_POLICY_PRESET_ZERO_CONF='default=skip'
|
||||
export AC_CONFIG_POLICY_PRESET_DEFAULT='missing_file=error,missing_option=warn,critical_option=fatal,unknown_option=error,value_error=error'
|
||||
export AC_CONFIG_POLICY_PRESET_STRICT='default=error,missing_file=fatal,missing_option=error,critical_option=fatal,unknown_option=error,value_error=error'
|
||||
|
||||
export AC_CONFIG_POLICY=$AC_CONFIG_POLICY_PRESET_DEFAULT
|
||||
|
||||
|
||||
|
||||
87
data/sql/updates/db_world/2025_10_25_00.sql
Normal file
87
data/sql/updates/db_world/2025_10_25_00.sql
Normal file
@ -0,0 +1,87 @@
|
||||
-- DB update 2025_10_24_05 -> 2025_10_25_00
|
||||
|
||||
-- Delete old Waypoint and add new ones
|
||||
DELETE FROM `waypoints` WHERE (`entry` IN (28948));
|
||||
|
||||
DELETE FROM `waypoint_data` WHERE (`id` IN (2894800, 2894801, 2894802, 2894803, 2894804, 2894805));
|
||||
INSERT INTO `waypoint_data` (`id`, `point`, `position_x`, `position_y`, `position_z`, `orientation`, `delay`, `move_type`, `action`, `action_chance`, `wpguid`) VALUES
|
||||
(2894800, 1, 6232.341, -1965.3967, 484.76993, NULL, 0, 0, 0, 100, 0),
|
||||
(2894800, 2, 6218.6577, -1962.0309, 484.85934, NULL, 0, 0, 0, 100, 0),
|
||||
(2894801, 1, 6191.6187, -1930.0017, 485.06897, NULL, 0, 0, 0, 100, 0),
|
||||
(2894801, 2, 6175.131, -1934.6721, 484.8741, NULL, 0, 0, 0, 100, 0),
|
||||
(2894801, 3, 6156.749, -1953.0284, 484.90906, NULL, 0, 0, 0, 100, 0),
|
||||
(2894802, 1, 6119.237, -1976.635, 484.8796, NULL, 0, 0, 0, 100, 0),
|
||||
(2894802, 2, 6093.954, -1990.4447, 484.8646, NULL, 0, 0, 0, 100, 0),
|
||||
(2894802, 3, 6089.3467, -2014.2975, 484.85828, NULL, 0, 0, 0, 100, 0),
|
||||
(2894802, 4, 6113.093, -2041.1102, 484.8815, NULL, 0, 0, 0, 100, 0),
|
||||
(2894802, 5, 6108.405, -2060.9314, 484.76993, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 1, 6136.712, -2078.5974, 484.86215, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 2, 6157.7085, -2107.486, 485.07727, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 3, 6156.6816, -2122.8438, 485.18344, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 4, 6141.0166, -2128.8904, 485.348, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 5, 6143.3594, -2127.986, 485.39215, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 6, 6118.48, -2123.0764, 473.51685, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 7, 6121.2275, -2108.0781, 473.54965, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 8, 6146.223, -2111.0583, 461.30115, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 9, 6156.9985, -2110.611, 461.30157, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 10, 6160.259, -2087.5088, 461.30212, NULL, 0, 0, 0, 100, 0),
|
||||
(2894803, 11, 6148.678, -2072.7812, 461.303, NULL, 0, 0, 0, 100, 0),
|
||||
(2894804, 1, 6144.377, -2044.998, 460.9487, NULL, 0, 0, 0, 100, 0),
|
||||
(2894804, 2, 6139.7783, -2046.457, 461.30005, NULL, 0, 0, 0, 100, 0),
|
||||
(2894805, 1, 6161.379, -2028.9777, 458.94113, NULL, 0, 0, 0, 100, 0),
|
||||
(2894805, 2, 6172.3604, -2019.7084, 455.11356, NULL, 0, 0, 0, 100, 0);
|
||||
|
||||
-- Change Emotes
|
||||
UPDATE `creature_text` SET `Emote` = 4 WHERE (`CreatureID` = 28948) AND (`GroupID` IN (0));
|
||||
UPDATE `creature_text` SET `Emote` = 396 WHERE (`CreatureID` = 28948) AND (`GroupID` IN (1));
|
||||
UPDATE `creature_text` SET `Emote` = 5 WHERE (`CreatureID` = 28948) AND (`GroupID` IN (3, 12));
|
||||
UPDATE `creature_text` SET `Emote` = 2 WHERE (`CreatureID` = 28948) AND (`GroupID` IN (14));
|
||||
|
||||
-- Set SmartAI
|
||||
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 28948;
|
||||
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 28948);
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(28948, 0, 0, 1, 54, 0, 100, 0, 0, 0, 0, 0, 0, 0, 64, 25, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - On Just Summoned - Store Targetlist'),
|
||||
(28948, 0, 1, 0, 61, 0, 100, 0, 0, 0, 0, 0, 0, 0, 80, 2894800, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - On Just Summoned - Run Script'),
|
||||
(28948, 0, 2, 0, 109, 0, 100, 0, 0, 2894800, 0, 0, 0, 0, 80, 2894801, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - On Path 2894800 Finished - Run Script'),
|
||||
(28948, 0, 3, 0, 109, 0, 100, 0, 0, 2894801, 0, 0, 0, 0, 80, 2894802, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - On Path 2894801 Finished - Run Script'),
|
||||
(28948, 0, 4, 0, 109, 0, 100, 0, 0, 2894802, 0, 0, 0, 0, 80, 2894803, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - On Path 2894802 Finished - Run Script'),
|
||||
(28948, 0, 5, 0, 109, 0, 100, 0, 0, 2894803, 0, 0, 0, 0, 80, 2894804, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - On Path 2894803 Finished - Run Script'),
|
||||
(28948, 0, 6, 0, 109, 0, 100, 0, 0, 2894804, 0, 0, 0, 0, 80, 2894805, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - On Path 2894804 Finished - Run Script'),
|
||||
(28948, 0, 7, 0, 109, 0, 100, 0, 0, 2894805, 0, 0, 0, 0, 80, 2894806, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - On Path 2894805 Finished - Run Script');
|
||||
|
||||
-- Set Action Lists
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 9) AND (`entryorguid` IN (2894800, 2894801, 2894802, 2894803, 2894804, 2894805, 2894806));
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(2894800, 9, 0, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Set Orientation Stored'),
|
||||
(2894800, 9, 1, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 0'),
|
||||
(2894800, 9, 2, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 1'),
|
||||
(2894800, 9, 3, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 232, 2894800, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Start Path 2894800'),
|
||||
(2894801, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Set Orientation Stored'),
|
||||
(2894801, 9, 1, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 2'),
|
||||
(2894801, 9, 2, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 0, 232, 2894801, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Start Path 2894801'),
|
||||
(2894802, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Set Orientation Stored'),
|
||||
(2894802, 9, 1, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 3'),
|
||||
(2894802, 9, 2, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 232, 2894802, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Start Path 2894802'),
|
||||
(2894803, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 4'),
|
||||
(2894803, 9, 1, 0, 0, 0, 100, 0, 8000, 8000, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Set Orientation Stored'),
|
||||
(2894803, 9, 2, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 1, 5, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 5'),
|
||||
(2894803, 9, 3, 0, 0, 0, 100, 0, 3000, 3000, 0, 0, 0, 0, 232, 2894803, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Start Path 2894803'),
|
||||
(2894804, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 6, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 6'),
|
||||
(2894804, 9, 1, 0, 0, 0, 100, 0, 8000, 8000, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Set Orientation Stored'),
|
||||
(2894804, 9, 2, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 1, 7, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 7'),
|
||||
(2894804, 9, 3, 0, 0, 0, 100, 0, 4000, 4000, 0, 0, 0, 0, 232, 2894804, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Start Path 2894804'),
|
||||
(2894805, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 1, 8, 0, 0, 0, 0, 0, 12, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 8'),
|
||||
(2894805, 9, 1, 0, 0, 0, 100, 0, 6000, 6000, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Set Orientation Stored'),
|
||||
(2894805, 9, 2, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 1, 9, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 9'),
|
||||
(2894805, 9, 3, 0, 0, 0, 100, 0, 9000, 9000, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 19, 28931, 30, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Set Orientation Closest Creature \'Blightblood Troll\''),
|
||||
(2894805, 9, 4, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 1, 10, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 10'),
|
||||
(2894805, 9, 5, 0, 0, 0, 100, 0, 7000, 7000, 0, 0, 0, 0, 1, 11, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 11'),
|
||||
(2894805, 9, 6, 0, 0, 0, 100, 0, 8000, 8000, 0, 0, 0, 0, 232, 2894805, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Start Path 2894805'),
|
||||
(2894806, 9, 0, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 66, 0, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Set Orientation Stored'),
|
||||
(2894806, 9, 1, 0, 0, 0, 100, 0, 500, 500, 0, 0, 0, 0, 1, 12, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 12'),
|
||||
(2894806, 9, 2, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 0, 1, 13, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 13'),
|
||||
(2894806, 9, 3, 0, 0, 0, 100, 0, 5000, 5000, 0, 0, 0, 0, 1, 14, 0, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Say Line 14'),
|
||||
(2894806, 9, 4, 0, 0, 0, 100, 0, 2000, 2000, 0, 0, 0, 0, 11, 53101, 2, 0, 0, 0, 0, 12, 25, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Cast \'Kill Credit\''),
|
||||
(2894806, 9, 5, 0, 0, 0, 100, 0, 0, 0, 0, 0, 0, 0, 41, 2000, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Malmortis - Actionlist - Despawn In 2000 ms');
|
||||
8
data/sql/updates/db_world/2025_10_25_01.sql
Normal file
8
data/sql/updates/db_world/2025_10_25_01.sql
Normal file
@ -0,0 +1,8 @@
|
||||
-- DB update 2025_10_25_00 -> 2025_10_25_01
|
||||
--
|
||||
UPDATE `creature_template` SET `AIName` = 'SmartAI' WHERE `entry` = 27970;
|
||||
DELETE FROM `smart_scripts` WHERE (`source_type` = 0 AND `entryorguid` = 27970);
|
||||
INSERT INTO `smart_scripts` (`entryorguid`, `source_type`, `id`, `link`, `event_type`, `event_phase_mask`, `event_chance`, `event_flags`, `event_param1`, `event_param2`, `event_param3`, `event_param4`, `event_param5`, `event_param6`, `action_type`, `action_param1`, `action_param2`, `action_param3`, `action_param4`, `action_param5`, `action_param6`, `target_type`, `target_param1`, `target_param2`, `target_param3`, `target_param4`, `target_x`, `target_y`, `target_z`, `target_o`, `comment`) VALUES
|
||||
(27970, 0, 0, 0, 0, 0, 100, 2, 3000, 9000, 16000, 16000, 0, 0, 11, 51819, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Raging Construct - In Combat - Cast \'Potent Jolt\' (Normal Dungeon)'),
|
||||
(27970, 0, 1, 0, 0, 0, 100, 4, 3000, 9000, 16000, 16000, 0, 0, 11, 61514, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 'Raging Construct - In Combat - Cast \'Potent Jolt\' (Heroic Dungeon)'),
|
||||
(27970, 0, 2, 0, 0, 0, 100, 6, 4000, 7000, 9000, 12000, 0, 0, 11, 28168, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 'Raging Construct - In Combat - Cast \'Arcing Smash\' (Dungeon)');
|
||||
5
deps/acore/bash-lib/src/common/boolean.sh
vendored
Normal file
5
deps/acore/bash-lib/src/common/boolean.sh
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
function isTrue() {
|
||||
local val
|
||||
val=$(echo "$1" | tr '[:upper:]' '[:lower:]')
|
||||
[[ "$val" == "1" || "$val" == "true" || "$val" == "yes" || "$val" == "on" ]]
|
||||
}
|
||||
101
doc/ConfigPolicy.md
Normal file
101
doc/ConfigPolicy.md
Normal file
@ -0,0 +1,101 @@
|
||||
# Configuration Severity Policy
|
||||
|
||||
The configuration loader can decide how strictly it should react when it
|
||||
encounters missing files, undefined options or invalid values. This document
|
||||
describes the available knobs and provides ready-to-use presets.
|
||||
|
||||
## Severity Levels
|
||||
|
||||
Each policy entry maps a **key** to one of the following severities:
|
||||
|
||||
| Severity | Description |
|
||||
|----------|-----------------------------------------------------------------------------|
|
||||
| `skip` | Ignore the problem and continue silently. |
|
||||
| `warn` | Log a warning and continue. |
|
||||
| `error` | Log an error and continue (useful to surface issues without aborting). |
|
||||
| `fatal` | Log a fatal message and abort the process immediately. |
|
||||
|
||||
## Policy Keys
|
||||
|
||||
The following keys can be customised:
|
||||
|
||||
| Key | Applies to |
|
||||
|--------------------|----------------------------------------------------------------------|
|
||||
| `default` | Fallback severity for any key that is not explicitly overridden. |
|
||||
| `missing_file` | Missing or empty configuration files (worldserver.conf, modules, …). |
|
||||
| `missing_option` | Options looked up in code but not present in any config file. |
|
||||
| `critical_option` | Required options (`RealmID`, `*DatabaseInfo`, …). |
|
||||
| `unknown_option` | Options found in optional configs that the core does not recognise. |
|
||||
| `value_error` | Options that cannot be converted to the expected type. |
|
||||
|
||||
> Critical options remain fatal by default to prevent the core from booting with
|
||||
> incomplete database details; you can relax them if required.
|
||||
|
||||
## Configuration Channels
|
||||
|
||||
### `config.sh`
|
||||
|
||||
`conf/dist/config.sh` exposes the `AC_CONFIG_POLICY` variable alongside a few
|
||||
presets:
|
||||
|
||||
```bash
|
||||
# Mirrors the default behaviour (errors, with fatal criticals)
|
||||
export AC_CONFIG_POLICY="$AC_CONFIG_POLICY_PRESET_DEFAULT"
|
||||
|
||||
# Skip anything non-critical so the core can bootstrap from defaults + env vars
|
||||
export AC_CONFIG_POLICY="$AC_CONFIG_POLICY_PRESET_ZERO_CONF"
|
||||
|
||||
# Treat everything strictly (useful for CI)
|
||||
export AC_CONFIG_POLICY="$AC_CONFIG_POLICY_PRESET_STRICT"
|
||||
```
|
||||
|
||||
The presets are defined as:
|
||||
|
||||
```bash
|
||||
AC_CONFIG_POLICY_PRESET_DEFAULT='missing_file=error,missing_option=warn,critical_option=fatal,unknown_option=error,value_error=error'
|
||||
AC_CONFIG_POLICY_PRESET_ZERO_CONF='default=skip,critical_option=fatal,unknown_option=warn,value_error=warn'
|
||||
AC_CONFIG_POLICY_PRESET_STRICT='default=error,missing_file=fatal,missing_option=error,critical_option=fatal,unknown_option=error,value_error=error'
|
||||
```
|
||||
|
||||
Modify or extend these entries to suit your deployment.
|
||||
|
||||
### Environment Variable
|
||||
|
||||
The runtime honours the `AC_CONFIG_POLICY` environment variable, so you can
|
||||
override the policy without editing `config.sh`:
|
||||
|
||||
```bash
|
||||
export AC_CONFIG_POLICY="default=skip,critical_option=fatal"
|
||||
./acore.sh run-worldserver
|
||||
```
|
||||
|
||||
### CLI Override
|
||||
|
||||
Every server/tool executable accepts `--config-policy`:
|
||||
|
||||
```bash
|
||||
./bin/worldserver --config-policy="missing_file=fatal,unknown_option=warn"
|
||||
./bin/authserver --config-policy "$AC_CONFIG_POLICY_PRESET_STRICT"
|
||||
```
|
||||
|
||||
The CLI flag takes precedence over the environment and `config.sh`.
|
||||
|
||||
## Quick Presets
|
||||
|
||||
| Preset | Intended use |
|
||||
|---------------|---------------------------------------------------------------------------|
|
||||
| `legacy` | Default behaviour before this feature (errors for missing files/options). |
|
||||
| `zero-conf` | Zero-touch deployments; rely on defaults/env vars where possible. |
|
||||
| `strict` | Fail-fast in CI or controlled environments. |
|
||||
|
||||
Feel free to clone these presets and store your own variants inside
|
||||
`config.sh` or deployment scripts.
|
||||
|
||||
## Tips
|
||||
|
||||
- Pair `fatal` severities with monitoring so regressions in configuration
|
||||
surface quickly.
|
||||
- When experimenting locally, start with `zero-conf` and elevate specific keys
|
||||
to `error`/`fatal` as you validate your setup.
|
||||
- Remember that number parsing errors (`value_error`) often indicate typos;
|
||||
keep them at least `error` unless you have a very good reason.
|
||||
@ -21,10 +21,14 @@
|
||||
#include "StringFormat.h"
|
||||
#include "Tokenize.h"
|
||||
#include "Util.h"
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <locale>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -34,13 +38,14 @@ namespace
|
||||
std::unordered_map<std::string /*name*/, std::string /*value*/> _configOptions;
|
||||
std::unordered_map<std::string /*name*/, std::string /*value*/> _envVarCache;
|
||||
std::mutex _configLock;
|
||||
ConfigPolicy _policy;
|
||||
|
||||
std::vector<std::string> _fatalConfigOptions =
|
||||
std::unordered_set<std::string> _criticalConfigOptions =
|
||||
{
|
||||
{ "RealmID" },
|
||||
{ "LoginDatabaseInfo" },
|
||||
{ "WorldDatabaseInfo" },
|
||||
{ "CharacterDatabaseInfo" },
|
||||
"RealmID",
|
||||
"LoginDatabaseInfo",
|
||||
"WorldDatabaseInfo",
|
||||
"CharacterDatabaseInfo",
|
||||
};
|
||||
|
||||
// Check system configs like *server.conf*
|
||||
@ -62,6 +67,29 @@ namespace
|
||||
return foundAppender != std::string_view::npos || foundLogger != std::string_view::npos;
|
||||
}
|
||||
|
||||
Optional<ConfigSeverity> ParseSeverity(std::string_view value)
|
||||
{
|
||||
if (value.empty())
|
||||
return std::nullopt;
|
||||
|
||||
std::string lowered(value);
|
||||
std::transform(lowered.begin(), lowered.end(), lowered.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
if (lowered == "skip")
|
||||
return ConfigSeverity::Skip;
|
||||
|
||||
if (lowered == "warn" || lowered == "warning")
|
||||
return ConfigSeverity::Warn;
|
||||
|
||||
if (lowered == "error")
|
||||
return ConfigSeverity::Error;
|
||||
|
||||
if (lowered == "fatal" || lowered == "abort" || lowered == "panic")
|
||||
return ConfigSeverity::Fatal;
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
inline void PrintError(std::string_view filename, Format&& fmt, Args&& ... args)
|
||||
{
|
||||
@ -77,6 +105,138 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Format, typename... Args>
|
||||
inline void LogWithSeverity(ConfigSeverity severity, std::string_view filename, Format&& fmt, Args&&... args)
|
||||
{
|
||||
std::string message = Acore::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...);
|
||||
|
||||
switch (severity)
|
||||
{
|
||||
case ConfigSeverity::Skip:
|
||||
return;
|
||||
case ConfigSeverity::Warn:
|
||||
{
|
||||
if (IsAppConfig(filename))
|
||||
fmt::print("{}\n", message);
|
||||
|
||||
LOG_WARN("server.loading", message);
|
||||
return;
|
||||
}
|
||||
case ConfigSeverity::Error:
|
||||
{
|
||||
if (IsAppConfig(filename))
|
||||
fmt::print("{}\n", message);
|
||||
|
||||
LOG_ERROR("server.loading", message);
|
||||
return;
|
||||
}
|
||||
case ConfigSeverity::Fatal:
|
||||
{
|
||||
if (IsAppConfig(filename))
|
||||
fmt::print("{}\n", message);
|
||||
|
||||
LOG_FATAL("server.loading", message);
|
||||
ABORT(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ConfigPolicy ApplyPolicyString(ConfigPolicy policy, std::string_view input)
|
||||
{
|
||||
if (input.empty())
|
||||
return policy;
|
||||
|
||||
std::vector<std::pair<std::string, ConfigSeverity>> overrides;
|
||||
Optional<ConfigSeverity> defaultOverride;
|
||||
|
||||
std::string tokenBuffer(input);
|
||||
for (std::string_view rawToken : Acore::Tokenize(tokenBuffer, ',', false))
|
||||
{
|
||||
std::string token = Acore::String::Trim(std::string(rawToken), std::locale());
|
||||
if (token.empty())
|
||||
continue;
|
||||
|
||||
auto separator = token.find('=');
|
||||
if (separator == std::string::npos)
|
||||
continue;
|
||||
|
||||
std::string key = Acore::String::Trim(token.substr(0, separator), std::locale());
|
||||
std::string value = Acore::String::Trim(token.substr(separator + 1), std::locale());
|
||||
|
||||
if (key.empty() || value.empty())
|
||||
continue;
|
||||
|
||||
auto severity = ParseSeverity(value);
|
||||
if (!severity)
|
||||
continue;
|
||||
|
||||
std::transform(key.begin(), key.end(), key.begin(), [](unsigned char c) { return std::tolower(c); });
|
||||
|
||||
if (key == "default")
|
||||
{
|
||||
defaultOverride = severity;
|
||||
continue;
|
||||
}
|
||||
|
||||
overrides.emplace_back(std::move(key), *severity);
|
||||
}
|
||||
|
||||
if (defaultOverride)
|
||||
{
|
||||
policy.defaultSeverity = *defaultOverride;
|
||||
policy.missingFileSeverity = *defaultOverride;
|
||||
policy.missingOptionSeverity = *defaultOverride;
|
||||
policy.criticalOptionSeverity = *defaultOverride;
|
||||
policy.unknownOptionSeverity = *defaultOverride;
|
||||
policy.valueErrorSeverity = *defaultOverride;
|
||||
}
|
||||
|
||||
for (auto const& [key, severity] : overrides)
|
||||
{
|
||||
if (key == "missing_file" || key == "file")
|
||||
policy.missingFileSeverity = severity;
|
||||
else if (key == "missing_option" || key == "option")
|
||||
policy.missingOptionSeverity = severity;
|
||||
else if (key == "critical_option" || key == "critical")
|
||||
policy.criticalOptionSeverity = severity;
|
||||
else if (key == "unknown_option" || key == "unknown")
|
||||
policy.unknownOptionSeverity = severity;
|
||||
else if (key == "value_error" || key == "value")
|
||||
policy.valueErrorSeverity = severity;
|
||||
}
|
||||
|
||||
return policy;
|
||||
}
|
||||
|
||||
ConfigPolicy ApplyPolicyFromArgs(ConfigPolicy policy, std::vector<std::string> const& args)
|
||||
{
|
||||
for (std::size_t i = 0; i < args.size(); ++i)
|
||||
{
|
||||
std::string const& arg = args[i];
|
||||
std::string_view value;
|
||||
|
||||
constexpr std::string_view shortOpt = "--config-policy";
|
||||
|
||||
if (arg.rfind(shortOpt, 0) == 0)
|
||||
{
|
||||
if (arg.size() == shortOpt.size() && (i + 1) < args.size())
|
||||
{
|
||||
value = args[i + 1];
|
||||
++i;
|
||||
}
|
||||
else if (arg.size() > shortOpt.size() && arg[shortOpt.size()] == '=')
|
||||
{
|
||||
value = std::string_view(arg).substr(shortOpt.size() + 1);
|
||||
}
|
||||
|
||||
if (!value.empty())
|
||||
policy = ApplyPolicyString(policy, value);
|
||||
}
|
||||
}
|
||||
|
||||
return policy;
|
||||
}
|
||||
|
||||
void AddKey(std::string const& optionName, std::string const& optionKey, std::string_view fileName, bool isOptional, [[maybe_unused]] bool isReload)
|
||||
{
|
||||
auto const& itr = _configOptions.find(optionName);
|
||||
@ -86,7 +246,7 @@ namespace
|
||||
{
|
||||
if (!IsLoggingSystemOptions(optionName) && !isReload)
|
||||
{
|
||||
PrintError(fileName, "> Config::LoadFile: Found incorrect option '{}' in config file '{}'. Skip", optionName, fileName);
|
||||
LogWithSeverity(_policy.unknownOptionSeverity, fileName, "> Config::LoadFile: Found incorrect option '{}' in config file '{}'. Skip", optionName, fileName);
|
||||
|
||||
#ifdef CONFIG_ABORT_INCORRECT_OPTIONS
|
||||
ABORT("> Core can't start if found incorrect options");
|
||||
@ -111,13 +271,10 @@ namespace
|
||||
|
||||
if (in.fail())
|
||||
{
|
||||
if (isOptional)
|
||||
{
|
||||
// No display erorr if file optional
|
||||
return false;
|
||||
}
|
||||
|
||||
throw ConfigException(Acore::StringFormat("Config::LoadFile: Failed open {}file '{}'", isOptional ? "optional " : "", file));
|
||||
ConfigSeverity severity = isOptional ? ConfigSeverity::Skip : _policy.missingFileSeverity;
|
||||
LogWithSeverity(severity, file, "> Config::LoadFile: Failed open {}file '{}'", isOptional ? "optional " : "", file);
|
||||
// Treat SKIP as a successful no-op so the app can proceed
|
||||
return severity == ConfigSeverity::Skip;
|
||||
}
|
||||
|
||||
uint32 count = 0;
|
||||
@ -181,13 +338,10 @@ namespace
|
||||
// No lines read
|
||||
if (!count)
|
||||
{
|
||||
if (isOptional)
|
||||
{
|
||||
// No display erorr if file optional
|
||||
return false;
|
||||
}
|
||||
|
||||
throw ConfigException(Acore::StringFormat("Config::LoadFile: Empty file '{}'", file));
|
||||
ConfigSeverity severity = isOptional ? ConfigSeverity::Skip : _policy.missingFileSeverity;
|
||||
LogWithSeverity(severity, file, "> Config::LoadFile: Empty file '{}'", file);
|
||||
// Treat SKIP as a successful no-op
|
||||
return severity == ConfigSeverity::Skip;
|
||||
}
|
||||
|
||||
// Add correct keys if file load without errors
|
||||
@ -382,7 +536,6 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog
|
||||
std::string strValue;
|
||||
|
||||
auto const& itr = _configOptions.find(name);
|
||||
bool fatalConfig = false;
|
||||
bool notFound = itr == _configOptions.end();
|
||||
auto envVarName = GetEnvVarName(name);
|
||||
Optional<std::string> envVar = GetEnvFromCache(name, envVarName);
|
||||
@ -401,23 +554,23 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
for (std::string s : _fatalConfigOptions)
|
||||
if (s == name)
|
||||
{
|
||||
fatalConfig = true;
|
||||
break;
|
||||
}
|
||||
bool isCritical = _criticalConfigOptions.find(name) != _criticalConfigOptions.end();
|
||||
ConfigSeverity severity = isCritical ? _policy.criticalOptionSeverity : _policy.missingOptionSeverity;
|
||||
|
||||
if (fatalConfig)
|
||||
LOG_FATAL("server.loading", "> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable\n\nYour server cannot start without this option!",
|
||||
if (isCritical)
|
||||
{
|
||||
LogWithSeverity(severity, _filename,
|
||||
"> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable\n\nYour server cannot start without this option!",
|
||||
name, _filename, name, Acore::ToString(def), envVarName);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string configs = _filename;
|
||||
if (!_moduleConfigFiles.empty())
|
||||
configs += " or module config";
|
||||
|
||||
LOG_WARN("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
|
||||
LogWithSeverity(severity, _filename,
|
||||
"> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
|
||||
name, configs, name, def, envVarName);
|
||||
}
|
||||
}
|
||||
@ -433,7 +586,8 @@ T ConfigMgr::GetValueDefault(std::string const& name, T const& def, bool showLog
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
LOG_ERROR("server.loading", "> Config: Bad value defined for name '{}', going to use '{}' instead",
|
||||
LogWithSeverity(_policy.valueErrorSeverity, _filename,
|
||||
"> Config: Bad value defined for name '{}', going to use '{}' instead",
|
||||
name, Acore::ToString(def));
|
||||
}
|
||||
|
||||
@ -447,7 +601,6 @@ template<>
|
||||
std::string ConfigMgr::GetValueDefault<std::string>(std::string const& name, std::string const& def, bool showLogs /*= true*/) const
|
||||
{
|
||||
auto const& itr = _configOptions.find(name);
|
||||
bool fatalConfig = false;
|
||||
bool notFound = itr == _configOptions.end();
|
||||
auto envVarName = GetEnvVarName(name);
|
||||
Optional<std::string> envVar = GetEnvFromCache(name, envVarName);
|
||||
@ -466,23 +619,23 @@ std::string ConfigMgr::GetValueDefault<std::string>(std::string const& name, std
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
for (std::string s : _fatalConfigOptions)
|
||||
if (s == name)
|
||||
{
|
||||
fatalConfig = true;
|
||||
break;
|
||||
}
|
||||
bool isCritical = _criticalConfigOptions.find(name) != _criticalConfigOptions.end();
|
||||
ConfigSeverity severity = isCritical ? _policy.criticalOptionSeverity : _policy.missingOptionSeverity;
|
||||
|
||||
if (fatalConfig)
|
||||
LOG_FATAL("server.loading", "> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.\n\nYour server cannot start without this option!",
|
||||
if (isCritical)
|
||||
{
|
||||
LogWithSeverity(severity, _filename,
|
||||
"> Config:\n\nFATAL ERROR: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.\n\nYour server cannot start without this option!",
|
||||
name, _filename, name, def, envVarName);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string configs = _filename;
|
||||
if (!_moduleConfigFiles.empty())
|
||||
configs += " or module config";
|
||||
|
||||
LOG_WARN("server.loading", "> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
|
||||
LogWithSeverity(severity, _filename,
|
||||
"> Config: Missing property {} in config file {}, add \"{} = {}\" to this file or define '{}' as an environment variable.",
|
||||
name, configs, name, def, envVarName);
|
||||
}
|
||||
}
|
||||
@ -509,7 +662,8 @@ bool ConfigMgr::GetOption<bool>(std::string const& name, bool const& def, bool s
|
||||
{
|
||||
if (showLogs)
|
||||
{
|
||||
LOG_ERROR("server.loading", "> Config: Bad value defined for name '{}', going to use '{}' instead",
|
||||
LogWithSeverity(_policy.valueErrorSeverity, _filename,
|
||||
"> Config: Bad value defined for name '{}', going to use '{}' instead",
|
||||
name, def ? "true" : "false");
|
||||
}
|
||||
|
||||
@ -558,17 +712,27 @@ std::string const ConfigMgr::GetConfigPath()
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConfigMgr::Configure(std::string const& initFileName, std::vector<std::string> args, std::string_view modulesConfigList /*= {}*/)
|
||||
void ConfigMgr::Configure(std::string const& initFileName, std::vector<std::string> args, std::string_view modulesConfigList /*= {}*/, ConfigPolicy policy /*= {}*/)
|
||||
{
|
||||
_filename = initFileName;
|
||||
_args = std::move(args);
|
||||
_policy = policy;
|
||||
|
||||
if (char const* env = std::getenv("AC_CONFIG_POLICY"))
|
||||
_policy = ApplyPolicyString(_policy, env);
|
||||
|
||||
_policy = ApplyPolicyFromArgs(_policy, _args);
|
||||
|
||||
_additonalFiles.clear();
|
||||
_moduleConfigFiles.clear();
|
||||
|
||||
// Add modules config if exist
|
||||
if (!modulesConfigList.empty())
|
||||
{
|
||||
for (auto const& itr : Acore::Tokenize(modulesConfigList, ',', false))
|
||||
{
|
||||
_additonalFiles.emplace_back(itr);
|
||||
if (!itr.empty())
|
||||
_additonalFiles.emplace_back(itr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,10 +18,29 @@
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
enum class ConfigSeverity : uint8_t
|
||||
{
|
||||
Skip,
|
||||
Warn,
|
||||
Error,
|
||||
Fatal
|
||||
};
|
||||
|
||||
struct ConfigPolicy
|
||||
{
|
||||
ConfigSeverity defaultSeverity = ConfigSeverity::Warn;
|
||||
ConfigSeverity missingFileSeverity = ConfigSeverity::Error;
|
||||
ConfigSeverity missingOptionSeverity = ConfigSeverity::Warn;
|
||||
ConfigSeverity criticalOptionSeverity = ConfigSeverity::Fatal;
|
||||
ConfigSeverity unknownOptionSeverity = ConfigSeverity::Error;
|
||||
ConfigSeverity valueErrorSeverity = ConfigSeverity::Error;
|
||||
};
|
||||
|
||||
class ConfigMgr
|
||||
{
|
||||
ConfigMgr() = default;
|
||||
@ -32,7 +51,7 @@ class ConfigMgr
|
||||
public:
|
||||
bool LoadAppConfigs(bool isReload = false);
|
||||
bool LoadModulesConfigs(bool isReload = false, bool isNeedPrintInfo = true);
|
||||
void Configure(std::string const& initFileName, std::vector<std::string> args, std::string_view modulesConfigList = {});
|
||||
void Configure(std::string const& initFileName, std::vector<std::string> args, std::string_view modulesConfigList = {}, ConfigPolicy policy = {});
|
||||
|
||||
static ConfigMgr* instance();
|
||||
|
||||
|
||||
@ -211,13 +211,16 @@ void Log::ReadLoggersFromConfig()
|
||||
AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, {});
|
||||
appenders[appender->getId()].reset(appender);
|
||||
|
||||
Logger* rootLogger = new Logger(LOGGER_ROOT, LOG_LEVEL_ERROR);
|
||||
Logger* rootLogger = new Logger(LOGGER_ROOT, LOG_LEVEL_WARN);
|
||||
rootLogger->addAppender(appender->getId(), appender);
|
||||
loggers[LOGGER_ROOT].reset(rootLogger);
|
||||
|
||||
Logger* serverLogger = new Logger("server", LOG_LEVEL_INFO);
|
||||
serverLogger->addAppender(appender->getId(), appender);
|
||||
loggers["server"].reset(serverLogger);
|
||||
|
||||
highestLogLevel = LOG_LEVEL_INFO;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -278,7 +278,8 @@ variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile)
|
||||
("help,h", "print usage message")
|
||||
("version,v", "print version build info")
|
||||
("dry-run,d", "Dry run")
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_REALM_CONFIG))), "use <arg> as configuration file");
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_REALM_CONFIG))), "use <arg> as configuration file")
|
||||
("config-policy", value<std::string>()->value_name("policy"), "override config severity policy (e.g. default=skip,critical_option=fatal)");
|
||||
|
||||
variables_map variablesMap;
|
||||
|
||||
|
||||
@ -423,7 +423,7 @@ bool StartDB()
|
||||
MySQL::Library_Init();
|
||||
|
||||
// Load databases
|
||||
DatabaseLoader loader("server.worldserver", DatabaseLoader::DATABASE_NONE, AC_MODULES_LIST);
|
||||
DatabaseLoader loader("server.worldserver", DatabaseLoader::DATABASE_MASK_ALL, AC_MODULES_LIST);
|
||||
loader
|
||||
.AddDatabase(LoginDatabase, "Login")
|
||||
.AddDatabase(CharacterDatabase, "Character")
|
||||
@ -433,7 +433,7 @@ bool StartDB()
|
||||
return false;
|
||||
|
||||
///- Get the realm Id from the configuration file
|
||||
realm.Id.Realm = sConfigMgr->GetOption<uint32>("RealmID", 0);
|
||||
realm.Id.Realm = sConfigMgr->GetOption<uint32>("RealmID", 1);
|
||||
if (!realm.Id.Realm)
|
||||
{
|
||||
LOG_ERROR("server.worldserver", "Realm ID not defined in configuration file");
|
||||
@ -710,7 +710,8 @@ variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile, [
|
||||
("help,h", "print usage message")
|
||||
("version,v", "print version build info")
|
||||
("dry-run,d", "Dry run")
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_CORE_CONFIG))), "use <arg> as configuration file");
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_CORE_CONFIG))), "use <arg> as configuration file")
|
||||
("config-policy", value<std::string>()->value_name("policy"), "override config severity policy (e.g. default=skip,critical_option=fatal)");
|
||||
|
||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||
options_description win("Windows platform specific options");
|
||||
|
||||
@ -24,6 +24,24 @@
|
||||
#include <errmsg.h>
|
||||
#include <mysqld_error.h>
|
||||
#include <thread>
|
||||
#include <string_view>
|
||||
namespace
|
||||
{
|
||||
std::string const EMPTY_DATABASE_INFO;
|
||||
std::string const LOGIN_DATABASE_INFO_DEFAULT = "127.0.0.1;3306;acore;acore;acore_auth";
|
||||
std::string const WORLD_DATABASE_INFO_DEFAULT = "127.0.0.1;3306;acore;acore;acore_world";
|
||||
std::string const CHARACTER_DATABASE_INFO_DEFAULT = "127.0.0.1;3306;acore;acore;acore_characters";
|
||||
std::string const& GetDefaultDatabaseInfo(std::string_view name)
|
||||
{
|
||||
if (name == "Login")
|
||||
return LOGIN_DATABASE_INFO_DEFAULT;
|
||||
if (name == "World")
|
||||
return WORLD_DATABASE_INFO_DEFAULT;
|
||||
if (name == "Character")
|
||||
return CHARACTER_DATABASE_INFO_DEFAULT;
|
||||
return EMPTY_DATABASE_INFO;
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseLoader::DatabaseLoader(std::string const& logger, uint32 const defaultUpdateMask, std::string_view modulesList)
|
||||
: _logger(logger),
|
||||
@ -38,7 +56,8 @@ DatabaseLoader& DatabaseLoader::AddDatabase(DatabaseWorkerPool<T>& pool, std::st
|
||||
|
||||
_open.push([this, name, updatesEnabledForThis, &pool]() -> bool
|
||||
{
|
||||
std::string const dbString = sConfigMgr->GetOption<std::string>(name + "DatabaseInfo", "");
|
||||
std::string const& defaultDatabaseInfo = GetDefaultDatabaseInfo(name);
|
||||
std::string const dbString = sConfigMgr->GetOption<std::string>(name + "DatabaseInfo", defaultDatabaseInfo);
|
||||
if (dbString.empty())
|
||||
{
|
||||
LOG_ERROR(_logger, "Database {} not specified in configuration file!", name);
|
||||
|
||||
@ -1999,7 +1999,7 @@ void Creature::setDeathState(DeathState state, bool despawn)
|
||||
|
||||
bool needsFalling = !despawn && (IsFlying() || IsHovering()) && !IsUnderWater();
|
||||
SetHover(false);
|
||||
SetDisableGravity(false, false, false);
|
||||
SetDisableGravity(false);
|
||||
|
||||
if (needsFalling)
|
||||
GetMotionMaster()->MoveFall(0, true);
|
||||
@ -3230,47 +3230,6 @@ bool Creature::SetWalk(bool enable)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the creature's fly mode by adding or removing: MOVEMENTFLAG_FLYING. Infom also the client
|
||||
*/
|
||||
bool Creature::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool updateAnimationTier /*= true*/)
|
||||
{
|
||||
//! It's possible only a packet is sent but moveflags are not updated
|
||||
//! Need more research on this
|
||||
if (!packetOnly && !Unit::SetDisableGravity(disable))
|
||||
return false;
|
||||
|
||||
if (m_movedByPlayer)
|
||||
{
|
||||
WorldPacket data(disable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, 12);
|
||||
data << GetPackGUID();
|
||||
data << m_movedByPlayer->ToPlayer()->GetSession()->GetOrderCounter(); // movement counter
|
||||
m_movedByPlayer->ToPlayer()->SendDirectMessage(&data);
|
||||
m_movedByPlayer->ToPlayer()->GetSession()->IncrementOrderCounter();
|
||||
|
||||
data.Initialize(MSG_MOVE_GRAVITY_CHNG, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
m_movedByPlayer->ToPlayer()->SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (updateAnimationTier && IsAlive() && !HasUnitState(UNIT_STATE_ROOT) && !IsRooted())
|
||||
{
|
||||
if (IsLevitating())
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_FLY);
|
||||
else if (IsHovering())
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_HOVER);
|
||||
else
|
||||
SetByteValue(UNIT_FIELD_BYTES_1, UNIT_BYTES_1_OFFSET_ANIM_TIER, UNIT_BYTE1_FLAG_GROUND);
|
||||
}
|
||||
|
||||
WorldPacket data(disable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Creature::SetSwim(bool enable)
|
||||
{
|
||||
if (!Unit::SetSwim(enable))
|
||||
@ -3385,19 +3344,23 @@ void Creature::UpdateMovementFlags()
|
||||
|
||||
if (GetMovementTemplate().IsFlightAllowed() && isInAir && !IsFalling())
|
||||
{
|
||||
if (GetMovementTemplate().Flight == CreatureFlightMovementType::CanFly)
|
||||
if (GetMovementTemplate().Flight == CreatureFlightMovementType::CanFly && !m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY))
|
||||
SetCanFly(true);
|
||||
else
|
||||
else if (!IsLevitating())
|
||||
SetDisableGravity(true);
|
||||
|
||||
if (!HasHoverAura())
|
||||
if (!HasHoverAura() && IsHovering())
|
||||
SetHover(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetCanFly(false);
|
||||
SetDisableGravity(false);
|
||||
if (IsAlive() && (CanHover() || HasHoverAura()))
|
||||
if (m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY))
|
||||
SetCanFly(false);
|
||||
|
||||
if (IsLevitating())
|
||||
SetDisableGravity(false);
|
||||
|
||||
if (IsAlive() && (GetMovementTemplate().Ground == CreatureGroundMovementType::Hover || HasHoverAura()) && !IsHovering())
|
||||
SetHover(true);
|
||||
}
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@ public:
|
||||
[[nodiscard]] bool CanWalk() const { return GetMovementTemplate().IsGroundAllowed(); }
|
||||
[[nodiscard]] bool CanSwim() const override;
|
||||
[[nodiscard]] bool CanEnterWater() const override;
|
||||
[[nodiscard]] bool CanFly() const override { return GetMovementTemplate().IsFlightAllowed() || IsFlying(); }
|
||||
[[nodiscard]] bool CanFly() const override { return GetMovementTemplate().IsFlightAllowed() || IsFlying(); }
|
||||
[[nodiscard]] bool CanHover() const { return GetMovementTemplate().Ground == CreatureGroundMovementType::Hover || IsHovering(); }
|
||||
[[nodiscard]] bool IsRooted() const { return GetMovementTemplate().IsRooted(); }
|
||||
|
||||
@ -145,7 +145,6 @@ public:
|
||||
[[nodiscard]] CreatureAI* AI() const { return (CreatureAI*)i_AI; }
|
||||
|
||||
bool SetWalk(bool enable) override;
|
||||
bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override;
|
||||
bool SetSwim(bool enable) override;
|
||||
bool HasSpellFocus(Spell const* focusSpell = nullptr) const;
|
||||
|
||||
|
||||
@ -1466,7 +1466,7 @@ void GameObject::Use(Unit* user)
|
||||
// by default spell caster is user
|
||||
Unit* spellCaster = user;
|
||||
uint32 spellId = 0;
|
||||
bool triggered = false;
|
||||
uint32 triggeredFlags = TRIGGERED_NONE;
|
||||
|
||||
if (Player* playerUser = user->ToPlayer())
|
||||
{
|
||||
@ -1486,6 +1486,10 @@ void GameObject::Use(Unit* user)
|
||||
m_cooldownTime = GameTime::GetGameTimeMS().count() + cooldown * IN_MILLISECONDS;
|
||||
}
|
||||
|
||||
if (user->IsPlayer() && GetGoType() != GAMEOBJECT_TYPE_TRAP) // workaround for GO casting
|
||||
if (!m_goInfo->IsUsableMounted())
|
||||
user->RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
|
||||
switch (GetGoType())
|
||||
{
|
||||
case GAMEOBJECT_TYPE_DOOR: //0
|
||||
@ -1886,7 +1890,6 @@ void GameObject::Use(Unit* user)
|
||||
}
|
||||
}
|
||||
|
||||
user->RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
spellId = info->spellcaster.spellId;
|
||||
break;
|
||||
}
|
||||
@ -2056,12 +2059,15 @@ void GameObject::Use(Unit* user)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_goInfo->IsUsableMounted())
|
||||
triggeredFlags |= TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE;
|
||||
|
||||
if (Player* player = user->ToPlayer())
|
||||
sOutdoorPvPMgr->HandleCustomSpell(player, spellId, this);
|
||||
|
||||
if (spellCaster)
|
||||
{
|
||||
if ((spellCaster->CastSpell(user, spellInfo, triggered) == SPELL_CAST_OK) && GetGoType() == GAMEOBJECT_TYPE_SPELLCASTER)
|
||||
if ((spellCaster->CastSpell(user, spellInfo, TriggerCastFlags(triggeredFlags)) == SPELL_CAST_OK) && GetGoType() == GAMEOBJECT_TYPE_SPELLCASTER)
|
||||
AddUse();
|
||||
}
|
||||
else
|
||||
|
||||
@ -417,6 +417,8 @@ Player::Player(WorldSession* session): Unit(), m_mover(this)
|
||||
GetObjectVisibilityContainer().InitForPlayer();
|
||||
|
||||
sScriptMgr->OnConstructPlayer(this);
|
||||
|
||||
m_expectingChangeTransport = false;
|
||||
}
|
||||
|
||||
Player::~Player()
|
||||
@ -1573,17 +1575,6 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
if (oldmap)
|
||||
oldmap->RemovePlayerFromMap(this, false);
|
||||
|
||||
// xinef: do this before setting fall information!
|
||||
if (IsMounted() && (!GetMap()->GetEntry()->IsDungeon() && !GetMap()->GetEntry()->IsBattlegroundOrArena()) && !m_transport)
|
||||
{
|
||||
AuraEffectList const& auras = GetAuraEffectsByType(SPELL_AURA_MOUNTED);
|
||||
if (!auras.empty())
|
||||
{
|
||||
SetMountBlockId((*auras.begin())->GetId());
|
||||
RemoveAurasByType(SPELL_AURA_MOUNTED);
|
||||
}
|
||||
}
|
||||
|
||||
teleportStore_dest = WorldLocation(mapid, x, y, z, orientation);
|
||||
SetFallInformation(GameTime::GetGameTime().count(), z);
|
||||
// if the player is saved before worldportack (at logout for example)
|
||||
@ -11704,7 +11695,7 @@ void Player::SendInitialPacketsAfterAddToMap()
|
||||
// manual send package (have code in HandleEffect(this, AURA_EFFECT_HANDLE_SEND_FOR_CLIENT, true); that must not be re-applied.
|
||||
if (IsImmobilizedState())
|
||||
{
|
||||
auto const counter = GetSession()->GetOrderCounter();
|
||||
uint32 const counter = GetSession()->GetOrderCounter();
|
||||
setCompoundState << uint8(2 + GetPackGUID().size() + 4);
|
||||
setCompoundState << uint16(SMSG_FORCE_MOVE_ROOT);
|
||||
setCompoundState << GetPackGUID();
|
||||
@ -11714,7 +11705,7 @@ void Player::SendInitialPacketsAfterAddToMap()
|
||||
|
||||
if (HasAuraType(SPELL_AURA_FEATHER_FALL))
|
||||
{
|
||||
auto const counter = GetSession()->GetOrderCounter();
|
||||
uint32 const counter = GetSession()->GetOrderCounter();
|
||||
setCompoundState << uint8(2 + GetPackGUID().size() + 4);
|
||||
setCompoundState << uint16(SMSG_MOVE_FEATHER_FALL);
|
||||
setCompoundState << GetPackGUID();
|
||||
@ -11724,7 +11715,7 @@ void Player::SendInitialPacketsAfterAddToMap()
|
||||
|
||||
if (HasAuraType(SPELL_AURA_WATER_WALK))
|
||||
{
|
||||
auto const counter = GetSession()->GetOrderCounter();
|
||||
uint32 const counter = GetSession()->GetOrderCounter();
|
||||
setCompoundState << uint8(2 + GetPackGUID().size() + 4);
|
||||
setCompoundState << uint16(SMSG_MOVE_WATER_WALK);
|
||||
setCompoundState << GetPackGUID();
|
||||
@ -11734,7 +11725,7 @@ void Player::SendInitialPacketsAfterAddToMap()
|
||||
|
||||
if (HasAuraType(SPELL_AURA_HOVER))
|
||||
{
|
||||
auto const counter = GetSession()->GetOrderCounter();
|
||||
uint32 const counter = GetSession()->GetOrderCounter();
|
||||
setCompoundState << uint8(2 + GetPackGUID().size() + 4);
|
||||
setCompoundState << uint16(SMSG_MOVE_SET_HOVER);
|
||||
setCompoundState << GetPackGUID();
|
||||
@ -16034,24 +16025,6 @@ bool Player::IsInWhisperWhiteList(ObjectGuid guid)
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Player::SetDisableGravity(bool disable, bool packetOnly /*= false*/, bool /*updateAnimationTier = true*/)
|
||||
{
|
||||
if (!packetOnly && !Unit::SetDisableGravity(disable))
|
||||
return false;
|
||||
|
||||
WorldPacket data(disable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, 12);
|
||||
data << GetPackGUID();
|
||||
data << GetSession()->GetOrderCounter(); // movement counter
|
||||
SendDirectMessage(&data);
|
||||
GetSession()->IncrementOrderCounter();
|
||||
|
||||
data.Initialize(MSG_MOVE_GRAVITY_CHNG, 64);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
SendMessageToSet(&data, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
Guild* Player::GetGuild() const
|
||||
{
|
||||
uint32 guildId = GetGuildId();
|
||||
|
||||
@ -2566,8 +2566,6 @@ public:
|
||||
bool IsInWhisperWhiteList(ObjectGuid guid);
|
||||
void RemoveFromWhisperWhiteList(ObjectGuid guid) { WhisperList.remove(guid); }
|
||||
|
||||
bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true) override;
|
||||
|
||||
[[nodiscard]] bool CanFly() const override { return m_movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY); }
|
||||
[[nodiscard]] bool CanEnterWater() const override { return true; }
|
||||
bool IsFreeFlying() const { return HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || HasAuraType(SPELL_AURA_FLY); }
|
||||
@ -2635,6 +2633,9 @@ public:
|
||||
|
||||
std::string GetDebugInfo() const override;
|
||||
|
||||
bool IsExpectingChangeTransport() const { return m_expectingChangeTransport; }
|
||||
void SetExpectingChangeTransport(bool state) { m_expectingChangeTransport = state; }
|
||||
|
||||
/*********************************************************/
|
||||
/*** SPELL QUEUE SYSTEM ***/
|
||||
/*********************************************************/
|
||||
@ -3015,6 +3016,8 @@ private:
|
||||
PlayerSettingMap m_charSettingsMap;
|
||||
|
||||
Seconds m_creationTime;
|
||||
|
||||
bool m_expectingChangeTransport;
|
||||
};
|
||||
|
||||
void AddItemsSetItem(Player* player, Item* item);
|
||||
|
||||
@ -14523,116 +14523,55 @@ void Unit::SetSpeed(UnitMoveType mtype, float rate, bool forced)
|
||||
|
||||
propagateSpeedChange();
|
||||
|
||||
WorldPacket data;
|
||||
if (!forced)
|
||||
{
|
||||
switch (mtype)
|
||||
{
|
||||
case MOVE_WALK:
|
||||
data.Initialize(MSG_MOVE_SET_WALK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
case MOVE_RUN:
|
||||
data.Initialize(MSG_MOVE_SET_RUN_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
case MOVE_RUN_BACK:
|
||||
data.Initialize(MSG_MOVE_SET_RUN_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
case MOVE_SWIM:
|
||||
data.Initialize(MSG_MOVE_SET_SWIM_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
case MOVE_SWIM_BACK:
|
||||
data.Initialize(MSG_MOVE_SET_SWIM_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
case MOVE_TURN_RATE:
|
||||
data.Initialize(MSG_MOVE_SET_TURN_RATE, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
case MOVE_FLIGHT:
|
||||
data.Initialize(MSG_MOVE_SET_FLIGHT_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
case MOVE_FLIGHT_BACK:
|
||||
data.Initialize(MSG_MOVE_SET_FLIGHT_BACK_SPEED, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
case MOVE_PITCH_RATE:
|
||||
data.Initialize(MSG_MOVE_SET_PITCH_RATE, 8 + 4 + 2 + 4 + 4 + 4 + 4 + 4 + 4 + 4);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type ({}), data not sent to client.", mtype);
|
||||
return;
|
||||
}
|
||||
SpeedOpcodePair const& speedOpcodes = SetSpeed2Opc_table[mtype];
|
||||
|
||||
if (forced && IsClientControlled())
|
||||
{
|
||||
Player* player = const_cast<Player*>(GetClientControlling());
|
||||
uint32 const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
// register forced speed changes for WorldSession::HandleForceSpeedChangeAck
|
||||
// and do it only for real sent packets and use run for run/mounted as client expected
|
||||
++player->m_forced_speed_changes[mtype];
|
||||
|
||||
WorldPacket data(speedOpcodes[static_cast<size_t>(SpeedOpcodeIndex::PC)], 18);
|
||||
data << GetPackGUID();
|
||||
data << counter;
|
||||
if (mtype == MOVE_RUN)
|
||||
data << uint8(0); // new 2.1.0
|
||||
|
||||
data << GetSpeed(mtype);
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
}
|
||||
else if (forced)
|
||||
{
|
||||
WorldPacket data(speedOpcodes[static_cast<size_t>(SpeedOpcodeIndex::NPC)], 12);
|
||||
data << GetPackGUID();
|
||||
BuildMovementPacket(&data);
|
||||
data << float(GetSpeed(mtype));
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
else
|
||||
|
||||
if (IsPlayer())
|
||||
{
|
||||
if (IsPlayer())
|
||||
// Xinef: update speed of pet also
|
||||
if (!IsInCombat())
|
||||
{
|
||||
// register forced speed changes for WorldSession::HandleForceSpeedChangeAck
|
||||
// and do it only for real sent packets and use run for run/mounted as client expected
|
||||
++ToPlayer()->m_forced_speed_changes[mtype];
|
||||
Unit* pet = ToPlayer()->GetPet();
|
||||
if (!pet)
|
||||
pet = GetCharm();
|
||||
|
||||
// Xinef: update speed of pet also
|
||||
if (!IsInCombat())
|
||||
{
|
||||
Unit* pet = ToPlayer()->GetPet();
|
||||
if (!pet)
|
||||
pet = GetCharm();
|
||||
// xinef: do not affect vehicles and possesed pets
|
||||
if (pet && (pet->HasUnitFlag(UNIT_FLAG_POSSESSED) || pet->IsVehicle()))
|
||||
pet = nullptr;
|
||||
|
||||
// xinef: do not affect vehicles and possesed pets
|
||||
if (pet && (pet->HasUnitFlag(UNIT_FLAG_POSSESSED) || pet->IsVehicle()))
|
||||
pet = nullptr;
|
||||
if (pet && pet->IsCreature() && !pet->IsInCombat() && pet->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE)
|
||||
pet->UpdateSpeed(mtype, forced);
|
||||
|
||||
if (pet && pet->IsCreature() && !pet->IsInCombat() && pet->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE)
|
||||
pet->UpdateSpeed(mtype, forced);
|
||||
if (Unit* critter = ObjectAccessor::GetUnit(*this, GetCritterGUID()))
|
||||
critter->UpdateSpeed(mtype, forced);
|
||||
}
|
||||
ToPlayer()->SetCanTeleport(true);
|
||||
if (Unit* critter = ObjectAccessor::GetUnit(*this, GetCritterGUID()))
|
||||
critter->UpdateSpeed(mtype, forced);
|
||||
}
|
||||
|
||||
switch (mtype)
|
||||
{
|
||||
case MOVE_WALK:
|
||||
data.Initialize(SMSG_FORCE_WALK_SPEED_CHANGE, 16);
|
||||
break;
|
||||
case MOVE_RUN:
|
||||
data.Initialize(SMSG_FORCE_RUN_SPEED_CHANGE, 17);
|
||||
break;
|
||||
case MOVE_RUN_BACK:
|
||||
data.Initialize(SMSG_FORCE_RUN_BACK_SPEED_CHANGE, 16);
|
||||
break;
|
||||
case MOVE_SWIM:
|
||||
data.Initialize(SMSG_FORCE_SWIM_SPEED_CHANGE, 16);
|
||||
break;
|
||||
case MOVE_SWIM_BACK:
|
||||
data.Initialize(SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, 16);
|
||||
break;
|
||||
case MOVE_TURN_RATE:
|
||||
data.Initialize(SMSG_FORCE_TURN_RATE_CHANGE, 16);
|
||||
break;
|
||||
case MOVE_FLIGHT:
|
||||
data.Initialize(SMSG_FORCE_FLIGHT_SPEED_CHANGE, 16);
|
||||
break;
|
||||
case MOVE_FLIGHT_BACK:
|
||||
data.Initialize(SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, 16);
|
||||
break;
|
||||
case MOVE_PITCH_RATE:
|
||||
data.Initialize(SMSG_FORCE_PITCH_RATE_CHANGE, 16);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("entities.unit", "Unit::SetSpeed: Unsupported move type ({}), data not sent to client.", mtype);
|
||||
return;
|
||||
}
|
||||
data << GetPackGUID();
|
||||
data << (IsPlayer() ? ToPlayer()->GetSession()->GetOrderCounter() : uint32(0)); // movement counter
|
||||
if (mtype == MOVE_RUN)
|
||||
data << uint8(0); // new 2.1.0
|
||||
data << float(GetSpeed(mtype));
|
||||
SendMessageToSet(&data, true);
|
||||
if (IsPlayer()) // TODO: Resolve this mess
|
||||
ToPlayer()->GetSession()->IncrementOrderCounter();
|
||||
ToPlayer()->SetCanTeleport(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -18343,7 +18282,7 @@ void Unit::SendMoveRoot(bool apply)
|
||||
// Wrath+ force root: when unit is controlled by a player
|
||||
else
|
||||
{
|
||||
auto const counter = client->GetSession()->GetOrderCounter();
|
||||
uint32 const counter = client->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(apply ? SMSG_FORCE_MOVE_ROOT : SMSG_FORCE_MOVE_UNROOT, guid.size() + 4);
|
||||
data << guid;
|
||||
@ -19603,6 +19542,9 @@ void Unit::_ExitVehicle(Position const* exitPosition)
|
||||
if (!vehicleBase)
|
||||
return;
|
||||
|
||||
if (IsPlayer())
|
||||
ToPlayer()->SetExpectingChangeTransport(true);
|
||||
|
||||
SetControlled(false, UNIT_STATE_ROOT); // SMSG_MOVE_FORCE_UNROOT, ~MOVEMENTFLAG_ROOT
|
||||
|
||||
Position pos;
|
||||
@ -20381,22 +20323,39 @@ bool Unit::SetWalk(bool enable)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Unit::SetDisableGravity(bool disable, bool /*packetOnly = false*/, bool /*updateAnimationTier = true*/)
|
||||
void Unit::SetDisableGravity(bool enable)
|
||||
{
|
||||
if (disable == IsLevitating())
|
||||
return false;
|
||||
bool isClientControlled = IsClientControlled();
|
||||
|
||||
if (disable)
|
||||
if (!isClientControlled)
|
||||
{
|
||||
AddUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_FALLING);
|
||||
}
|
||||
else
|
||||
{
|
||||
RemoveUnitMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
if (enable)
|
||||
m_movementInfo.AddMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
else
|
||||
m_movementInfo.RemoveMovementFlag(MOVEMENTFLAG_DISABLE_GRAVITY);
|
||||
}
|
||||
|
||||
return true;
|
||||
if (!IsInWorld()) // is sent on add to map
|
||||
return;
|
||||
|
||||
if (isClientControlled)
|
||||
{
|
||||
if (Player const* player = GetClientControlling())
|
||||
{
|
||||
uint32 const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(enable ? SMSG_MOVE_GRAVITY_DISABLE : SMSG_MOVE_GRAVITY_ENABLE, GetPackGUID().size() + 4);
|
||||
data << GetPackGUID();
|
||||
data << counter;
|
||||
player->GetSession()->SendPacket(&data);
|
||||
player->GetSession()->IncrementOrderCounter();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
WorldPacket data(enable ? SMSG_SPLINE_MOVE_GRAVITY_DISABLE : SMSG_SPLINE_MOVE_GRAVITY_ENABLE, 9);
|
||||
data << GetPackGUID();
|
||||
SendMessageToSet(&data, true);
|
||||
}
|
||||
|
||||
bool Unit::SetSwim(bool enable)
|
||||
@ -20443,7 +20402,7 @@ void Unit::SetCanFly(bool enable)
|
||||
{
|
||||
if (Player const* player = GetClientControlling())
|
||||
{
|
||||
auto const counter = player->GetSession()->GetOrderCounter();
|
||||
uint32 const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(enable ? SMSG_MOVE_SET_CAN_FLY : SMSG_MOVE_UNSET_CAN_FLY, GetPackGUID().size() + 4);
|
||||
data << GetPackGUID();
|
||||
@ -20478,7 +20437,7 @@ void Unit::SetFeatherFall(bool enable)
|
||||
{
|
||||
if (Player const* player = GetClientControlling())
|
||||
{
|
||||
auto const counter = player->GetSession()->GetOrderCounter();
|
||||
uint32 const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(enable ? SMSG_MOVE_FEATHER_FALL : SMSG_MOVE_NORMAL_FALL, GetPackGUID().size() + 4);
|
||||
|
||||
@ -20538,7 +20497,7 @@ void Unit::SetHover(bool enable)
|
||||
{
|
||||
WorldPacket data(enable ? SMSG_MOVE_SET_HOVER : SMSG_MOVE_UNSET_HOVER, GetPackGUID().size() + 4);
|
||||
|
||||
auto const counter = player->GetSession()->GetOrderCounter();
|
||||
uint32 const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
data << GetPackGUID();
|
||||
data << counter;
|
||||
@ -20572,7 +20531,7 @@ void Unit::SetWaterWalking(bool enable)
|
||||
{
|
||||
if (Player const* player = GetClientControlling())
|
||||
{
|
||||
auto const counter = player->GetSession()->GetOrderCounter();
|
||||
uint32 const counter = player->GetSession()->GetOrderCounter();
|
||||
|
||||
WorldPacket data(enable ? SMSG_MOVE_WATER_WALK : SMSG_MOVE_LAND_WALK, GetPackGUID().size() + 4);
|
||||
data << GetPackGUID();
|
||||
|
||||
@ -624,6 +624,28 @@ typedef std::unordered_map<uint32, uint32> PacketCooldowns;
|
||||
|
||||
struct SpellProcEventEntry; // used only privately
|
||||
|
||||
enum class SpeedOpcodeIndex : uint32
|
||||
{
|
||||
PC,
|
||||
NPC,
|
||||
ACK_RESPONSE,
|
||||
MAX
|
||||
};
|
||||
|
||||
typedef const Opcodes SpeedOpcodePair[static_cast<size_t>(SpeedOpcodeIndex::MAX)];
|
||||
SpeedOpcodePair SetSpeed2Opc_table[MAX_MOVE_TYPE] =
|
||||
{
|
||||
{SMSG_FORCE_WALK_SPEED_CHANGE, SMSG_SPLINE_SET_WALK_SPEED, MSG_MOVE_SET_WALK_SPEED},
|
||||
{SMSG_FORCE_RUN_SPEED_CHANGE, SMSG_SPLINE_SET_RUN_SPEED, MSG_MOVE_SET_RUN_SPEED},
|
||||
{SMSG_FORCE_RUN_BACK_SPEED_CHANGE, SMSG_SPLINE_SET_RUN_BACK_SPEED, MSG_MOVE_SET_RUN_BACK_SPEED},
|
||||
{SMSG_FORCE_SWIM_SPEED_CHANGE, SMSG_SPLINE_SET_SWIM_SPEED, MSG_MOVE_SET_SWIM_SPEED},
|
||||
{SMSG_FORCE_SWIM_BACK_SPEED_CHANGE, SMSG_SPLINE_SET_SWIM_BACK_SPEED, MSG_MOVE_SET_SWIM_BACK_SPEED},
|
||||
{SMSG_FORCE_TURN_RATE_CHANGE, SMSG_SPLINE_SET_TURN_RATE, MSG_MOVE_SET_TURN_RATE},
|
||||
{SMSG_FORCE_FLIGHT_SPEED_CHANGE, SMSG_SPLINE_SET_FLIGHT_SPEED, MSG_MOVE_SET_FLIGHT_SPEED},
|
||||
{SMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE, SMSG_SPLINE_SET_FLIGHT_BACK_SPEED, MSG_MOVE_SET_FLIGHT_BACK_SPEED},
|
||||
{SMSG_FORCE_PITCH_RATE_CHANGE, SMSG_SPLINE_SET_PITCH_RATE, MSG_MOVE_SET_PITCH_RATE},
|
||||
};
|
||||
|
||||
class Unit : public WorldObject
|
||||
{
|
||||
public:
|
||||
@ -1681,7 +1703,7 @@ public:
|
||||
void MonsterMoveWithSpeed(float x, float y, float z, float speed); // Not to be used outside of cinematics
|
||||
|
||||
virtual bool SetWalk(bool enable);
|
||||
virtual bool SetDisableGravity(bool disable, bool packetOnly = false, bool updateAnimationTier = true);
|
||||
void SetDisableGravity(bool disable);
|
||||
virtual bool SetSwim(bool enable);
|
||||
void SetCanFly(bool enable);
|
||||
void SetWaterWalking(bool enable);
|
||||
|
||||
@ -423,7 +423,9 @@ bool Vehicle::AddPassenger(Unit* unit, int8 seatId)
|
||||
if (_me->IsInWorld())
|
||||
{
|
||||
unit->SendClearTarget(); // SMSG_BREAK_TARGET
|
||||
unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
|
||||
unit->SetControlled(true, UNIT_STATE_ROOT); // SMSG_FORCE_ROOT - In some cases we send SMSG_SPLINE_MOVE_ROOT here (for creatures)
|
||||
if (unit->IsPlayer())
|
||||
unit->ToPlayer()->SetExpectingChangeTransport(true);
|
||||
// also adds MOVEMENTFLAG_ROOT
|
||||
Movement::MoveSplineInit init(unit);
|
||||
init.DisableTransportPathTransformations();
|
||||
|
||||
@ -1490,6 +1490,8 @@ void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data)
|
||||
{
|
||||
LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging((Opcodes)recv_data.GetOpcode()));
|
||||
|
||||
Opcodes opcode = (Opcodes)recv_data.GetOpcode();
|
||||
|
||||
ObjectGuid guid;
|
||||
uint32 counter;
|
||||
uint32 isApplied;
|
||||
@ -1507,7 +1509,8 @@ void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data)
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recv_data, &movementInfo);
|
||||
|
||||
recv_data >> isApplied;
|
||||
if (opcode != CMSG_MOVE_GRAVITY_DISABLE_ACK && opcode != CMSG_MOVE_GRAVITY_ENABLE_ACK)
|
||||
recv_data >> isApplied;
|
||||
|
||||
sScriptMgr->AnticheatSetCanFlybyServer(_player, movementInfo.HasMovementFlag(MOVEMENTFLAG_CAN_FLY));
|
||||
|
||||
@ -1516,6 +1519,12 @@ void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data)
|
||||
|
||||
mover->m_movementInfo.flags = movementInfo.GetMovementFlags();
|
||||
|
||||
if (!ProcessMovementInfo(movementInfo, mover, plrMover, recv_data))
|
||||
{
|
||||
recv_data.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
Opcodes response;
|
||||
|
||||
switch (recv_data.GetOpcode())
|
||||
@ -1524,17 +1533,12 @@ void WorldSession::HandleMoveFlagChangeOpcode(WorldPacket& recv_data)
|
||||
case CMSG_MOVE_FEATHER_FALL_ACK: response = MSG_MOVE_FEATHER_FALL; break;
|
||||
case CMSG_MOVE_WATER_WALK_ACK: response = MSG_MOVE_WATER_WALK; break;
|
||||
case CMSG_MOVE_SET_CAN_FLY_ACK: response = MSG_MOVE_UPDATE_CAN_FLY; break;
|
||||
case CMSG_MOVE_GRAVITY_DISABLE_ACK: response = MSG_MOVE_GRAVITY_CHNG; break;
|
||||
case CMSG_MOVE_GRAVITY_ENABLE_ACK: response = MSG_MOVE_GRAVITY_CHNG; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
if (!ProcessMovementInfo(movementInfo, mover, plrMover, recv_data))
|
||||
{
|
||||
recv_data.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
WorldPacket data(response, 8);
|
||||
data << guid.WriteAsPacked();
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
_player->m_mover->SendMessageToSet(&data, _player);
|
||||
}
|
||||
|
||||
@ -376,9 +376,11 @@ void WorldSession::HandleMovementOpcodes(WorldPacket& recvData)
|
||||
return;
|
||||
}
|
||||
|
||||
if (opcode == CMSG_MOVE_FALL_RESET || opcode == CMSG_MOVE_CHNG_TRANSPORT)
|
||||
return;
|
||||
|
||||
/* process position-change */
|
||||
WorldPacket data(opcode, recvData.size());
|
||||
movementInfo.guid = mover->GetGUID();
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
}
|
||||
@ -517,7 +519,10 @@ bool WorldSession::VerifyMovementInfo(MovementInfo const& movementInfo, Player*
|
||||
}
|
||||
|
||||
if (!mover->movespline->Finalized())
|
||||
return false;
|
||||
{
|
||||
if (!mover->movespline->isBoarding() || (opcode != CMSG_FORCE_MOVE_UNROOT_ACK && opcode != CMSG_FORCE_MOVE_ROOT_ACK))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Xinef: do not allow to move with UNIT_FLAG_DISABLE_MOVE
|
||||
if (mover->HasUnitFlag(UNIT_FLAG_DISABLE_MOVE))
|
||||
@ -655,26 +660,39 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData)
|
||||
|
||||
/* extract packet */
|
||||
ObjectGuid guid;
|
||||
uint32 unk1;
|
||||
uint32 counter;
|
||||
MovementInfo movementInfo;
|
||||
float newspeed;
|
||||
|
||||
recvData >> guid.ReadAsPacked();
|
||||
recvData >> counter; // counter or moveEvent
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
recvData >> newspeed;
|
||||
|
||||
Unit* mover = _player->m_mover;
|
||||
|
||||
// pussywizard: special check, only player mover allowed here
|
||||
if (guid != _player->m_mover->GetGUID() || guid != _player->GetGUID())
|
||||
if (guid != mover->GetGUID() || guid != _player->GetGUID())
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
// continue parse packet
|
||||
recvData >> unk1; // counter or moveEvent
|
||||
if (!ProcessMovementInfo(movementInfo, mover, _player, recvData))
|
||||
{
|
||||
recvData.rfinish(); // prevent warnings spam
|
||||
return;
|
||||
}
|
||||
|
||||
MovementInfo movementInfo;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
recvData >> newspeed;
|
||||
if (opcode == CMSG_MOVE_SET_COLLISION_HGT_ACK)
|
||||
{
|
||||
WorldPacket data(MSG_MOVE_SET_COLLISION_HGT, 18);
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
data << newspeed; // new collision height
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
return;
|
||||
}
|
||||
|
||||
// client ACK send one packet for mounted/run case and need skip all except last from its
|
||||
// in other cases anti-cheat check can be fail in false case
|
||||
@ -685,42 +703,15 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData)
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case CMSG_FORCE_WALK_SPEED_CHANGE_ACK:
|
||||
move_type = MOVE_WALK;
|
||||
force_move_type = MOVE_WALK;
|
||||
break;
|
||||
case CMSG_FORCE_RUN_SPEED_CHANGE_ACK:
|
||||
move_type = MOVE_RUN;
|
||||
force_move_type = MOVE_RUN;
|
||||
break;
|
||||
case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK:
|
||||
move_type = MOVE_RUN_BACK;
|
||||
force_move_type = MOVE_RUN_BACK;
|
||||
break;
|
||||
case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK:
|
||||
move_type = MOVE_SWIM;
|
||||
force_move_type = MOVE_SWIM;
|
||||
break;
|
||||
case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK:
|
||||
move_type = MOVE_SWIM_BACK;
|
||||
force_move_type = MOVE_SWIM_BACK;
|
||||
break;
|
||||
case CMSG_FORCE_TURN_RATE_CHANGE_ACK:
|
||||
move_type = MOVE_TURN_RATE;
|
||||
force_move_type = MOVE_TURN_RATE;
|
||||
break;
|
||||
case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK:
|
||||
move_type = MOVE_FLIGHT;
|
||||
force_move_type = MOVE_FLIGHT;
|
||||
break;
|
||||
case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK:
|
||||
move_type = MOVE_FLIGHT_BACK;
|
||||
force_move_type = MOVE_FLIGHT_BACK;
|
||||
break;
|
||||
case CMSG_FORCE_PITCH_RATE_CHANGE_ACK:
|
||||
move_type = MOVE_PITCH_RATE;
|
||||
force_move_type = MOVE_PITCH_RATE;
|
||||
break;
|
||||
case CMSG_FORCE_WALK_SPEED_CHANGE_ACK: move_type = MOVE_WALK; force_move_type = MOVE_WALK; break;
|
||||
case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: move_type = MOVE_RUN; force_move_type = MOVE_RUN; break;
|
||||
case CMSG_FORCE_RUN_BACK_SPEED_CHANGE_ACK: move_type = MOVE_RUN_BACK; force_move_type = MOVE_RUN_BACK; break;
|
||||
case CMSG_FORCE_SWIM_SPEED_CHANGE_ACK: move_type = MOVE_SWIM; force_move_type = MOVE_SWIM; break;
|
||||
case CMSG_FORCE_SWIM_BACK_SPEED_CHANGE_ACK: move_type = MOVE_SWIM_BACK; force_move_type = MOVE_SWIM_BACK; break;
|
||||
case CMSG_FORCE_TURN_RATE_CHANGE_ACK: move_type = MOVE_TURN_RATE; force_move_type = MOVE_TURN_RATE; break;
|
||||
case CMSG_FORCE_FLIGHT_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT; force_move_type = MOVE_FLIGHT; break;
|
||||
case CMSG_FORCE_FLIGHT_BACK_SPEED_CHANGE_ACK: move_type = MOVE_FLIGHT_BACK; force_move_type = MOVE_FLIGHT_BACK; break;
|
||||
case CMSG_FORCE_PITCH_RATE_CHANGE_ACK: move_type = MOVE_PITCH_RATE; force_move_type = MOVE_PITCH_RATE; break;
|
||||
default:
|
||||
LOG_ERROR("network.opcode", "WorldSession::HandleForceSpeedChangeAck: Unknown move type opcode: {}", opcode);
|
||||
return;
|
||||
@ -728,6 +719,12 @@ void WorldSession::HandleForceSpeedChangeAck(WorldPacket& recvData)
|
||||
|
||||
sScriptMgr->AnticheatSetUnderACKmount(_player);
|
||||
|
||||
SpeedOpcodePair const& speedOpcodes = SetSpeed2Opc_table[move_type];
|
||||
WorldPacket data(speedOpcodes[static_cast<size_t>(SpeedOpcodeIndex::ACK_RESPONSE)], 18);
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
data << newspeed;
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
|
||||
// skip all forced speed changes except last and unexpected
|
||||
// in run/mounted case used one ACK and it must be skipped.m_forced_speed_changes[MOVE_RUN} store both.
|
||||
if (_player->m_forced_speed_changes[force_move_type] > 0)
|
||||
@ -967,13 +964,15 @@ void WorldSession::ComputeNewClockDelta()
|
||||
|
||||
void WorldSession::HandleMoveRootAck(WorldPacket& recvData)
|
||||
{
|
||||
LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging((Opcodes)recvData.GetOpcode()));
|
||||
Opcodes opcode = (Opcodes)recvData.GetOpcode();
|
||||
LOG_DEBUG("network", "WORLD: {}", GetOpcodeNameForLogging(opcode));
|
||||
|
||||
ObjectGuid guid;
|
||||
uint32 counter;
|
||||
MovementInfo movementInfo;
|
||||
recvData >> guid.ReadAsPacked();
|
||||
recvData >> counter;
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
|
||||
Unit* mover = _player->m_mover;
|
||||
@ -981,7 +980,7 @@ void WorldSession::HandleMoveRootAck(WorldPacket& recvData)
|
||||
if (mover->GetGUID() != guid)
|
||||
return;
|
||||
|
||||
if (recvData.GetOpcode() == CMSG_FORCE_MOVE_UNROOT_ACK) // unroot case
|
||||
if (opcode == CMSG_FORCE_MOVE_UNROOT_ACK) // unroot case
|
||||
{
|
||||
if (!mover->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT))
|
||||
return;
|
||||
@ -995,8 +994,10 @@ void WorldSession::HandleMoveRootAck(WorldPacket& recvData)
|
||||
if (!ProcessMovementInfo(movementInfo, mover, _player, recvData))
|
||||
return;
|
||||
|
||||
WorldPacket data(recvData.GetOpcode() == CMSG_FORCE_MOVE_UNROOT_ACK ? MSG_MOVE_UNROOT : MSG_MOVE_ROOT);
|
||||
data << guid.WriteAsPacked();
|
||||
if (_player->IsExpectingChangeTransport())
|
||||
return;
|
||||
|
||||
WorldPacket data(opcode == CMSG_FORCE_MOVE_UNROOT_ACK ? MSG_MOVE_UNROOT : MSG_MOVE_ROOT);
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
}
|
||||
|
||||
@ -198,54 +198,70 @@ void WorldSession::HandleActivateTaxiExpressOpcode(WorldPacket& recvData)
|
||||
|
||||
void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
|
||||
{
|
||||
ObjectGuid guid; // used only for proper packet read
|
||||
ObjectGuid guid; // used only for proper packet read
|
||||
MovementInfo movementInfo; // used only for proper packet read
|
||||
uint32 movementCounter; // spline counter
|
||||
|
||||
Unit* mover = _player->m_mover;
|
||||
|
||||
recvData >> guid.ReadAsPacked();
|
||||
|
||||
MovementInfo movementInfo; // used only for proper packet read
|
||||
movementInfo.guid = guid;
|
||||
ReadMovementInfo(recvData, &movementInfo);
|
||||
recvData >> movementCounter;
|
||||
|
||||
recvData.read_skip<uint32>(); // spline id
|
||||
|
||||
// in taxi flight packet received in 2 case:
|
||||
// 1) end taxi path in far (multi-node) flight
|
||||
// 2) switch from one map to other in case multim-map taxi path
|
||||
// we need process only (1)
|
||||
|
||||
uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination();
|
||||
if (curDest)
|
||||
if (_player->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_TAXI_FLIGHT)) // taxi spline case
|
||||
{
|
||||
TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
|
||||
// in taxi flight packet received in 2 case:
|
||||
// 1) end taxi path in far (multi-node) flight
|
||||
// 2) switch from one map to other in case multim-map taxi path
|
||||
// we need process only (1)
|
||||
|
||||
// far teleport case
|
||||
if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId() && GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
|
||||
uint32 curDest = GetPlayer()->m_taxi.GetTaxiDestination();
|
||||
if (curDest)
|
||||
{
|
||||
if (FlightPathMovementGenerator* flight = dynamic_cast<FlightPathMovementGenerator*>(GetPlayer()->GetMotionMaster()->top()))
|
||||
{
|
||||
// short preparations to continue flight
|
||||
flight->SetCurrentNodeAfterTeleport();
|
||||
TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()];
|
||||
flight->SkipCurrentNode();
|
||||
TaxiNodesEntry const* curDestNode = sTaxiNodesStore.LookupEntry(curDest);
|
||||
|
||||
GetPlayer()->TeleportTo(curDestNode->map_id, node->x, node->y, node->z, GetPlayer()->GetOrientation(), TELE_TO_NOT_LEAVE_TAXI);
|
||||
// far teleport case
|
||||
if (curDestNode && curDestNode->map_id != GetPlayer()->GetMapId() && GetPlayer()->GetMotionMaster()->GetCurrentMovementGeneratorType() == FLIGHT_MOTION_TYPE)
|
||||
{
|
||||
if (FlightPathMovementGenerator* flight = dynamic_cast<FlightPathMovementGenerator*>(GetPlayer()->GetMotionMaster()->top()))
|
||||
{
|
||||
// short preparations to continue flight
|
||||
flight->SetCurrentNodeAfterTeleport();
|
||||
TaxiPathNodeEntry const* node = flight->GetPath()[flight->GetCurrentNode()];
|
||||
flight->SkipCurrentNode();
|
||||
|
||||
GetPlayer()->TeleportTo(curDestNode->map_id, node->x, node->y, node->z, GetPlayer()->GetOrientation(), TELE_TO_NOT_LEAVE_TAXI);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// at this point only 1 node is expected (final destination)
|
||||
if (GetPlayer()->m_taxi.GetPath().size() != 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetPlayer()->CleanupAfterTaxiFlight();
|
||||
GetPlayer()->SetFallInformation(GameTime::GetGameTime().count(), GetPlayer()->GetPositionZ());
|
||||
if (GetPlayer()->pvpInfo.IsHostile)
|
||||
{
|
||||
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// at this point only 1 node is expected (final destination)
|
||||
if (GetPlayer()->m_taxi.GetPath().size() != 1)
|
||||
{
|
||||
if (mover->GetGUID() != guid)
|
||||
return;
|
||||
}
|
||||
|
||||
GetPlayer()->CleanupAfterTaxiFlight();
|
||||
GetPlayer()->SetFallInformation(GameTime::GetGameTime().count(), GetPlayer()->GetPositionZ());
|
||||
if (GetPlayer()->pvpInfo.IsHostile)
|
||||
{
|
||||
GetPlayer()->CastSpell(GetPlayer(), 2479, true);
|
||||
}
|
||||
if (!_player->IsExpectingChangeTransport() || !mover->movespline || mover->movespline->GetId() != movementCounter)
|
||||
return;
|
||||
|
||||
_player->SetExpectingChangeTransport(false);
|
||||
WorldPacket data(_player->m_movementInfo.HasMovementFlag(MOVEMENTFLAG_ROOT) ? MSG_MOVE_ROOT : MSG_MOVE_UNROOT, recvData.size());
|
||||
WriteMovementInfo(&data, &movementInfo);
|
||||
mover->SendMessageToSet(&data, _player);
|
||||
}
|
||||
|
||||
void WorldSession::HandleActivateTaxiOpcode(WorldPacket& recvData)
|
||||
|
||||
@ -117,6 +117,7 @@ namespace Movement
|
||||
[[nodiscard]] bool isCyclic() const { return splineflags.cyclic; }
|
||||
[[nodiscard]] bool isFalling() const { return splineflags.falling; }
|
||||
[[nodiscard]] bool isWalking() const { return splineflags.walkmode; }
|
||||
[[nodiscard]] bool isBoarding() const { return splineflags.transportEnter || splineflags.transportExit; }
|
||||
[[nodiscard]] Vector3 FinalDestination() const { return Initialized() ? spline.getPoint(spline.last()) : Vector3(); }
|
||||
[[nodiscard]] Vector3 CurrentDestination() const { return Initialized() ? spline.getPoint(point_Idx + 1) : Vector3(); }
|
||||
[[nodiscard]] int32 currentPathIdx() const;
|
||||
|
||||
@ -1245,7 +1245,7 @@ void OpcodeTable::Initialize()
|
||||
/*0x45A*/ DEFINE_HANDLER(MSG_MOVE_SET_PITCH_RATE_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x45B*/ DEFINE_HANDLER(MSG_MOVE_SET_PITCH_RATE, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x45C*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_FORCE_PITCH_RATE_CHANGE, STATUS_NEVER);
|
||||
/*0x45D*/ DEFINE_HANDLER(CMSG_FORCE_PITCH_RATE_CHANGE_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x45D*/ DEFINE_HANDLER(CMSG_FORCE_PITCH_RATE_CHANGE_ACK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleForceSpeedChangeAck );
|
||||
/*0x45E*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPLINE_SET_PITCH_RATE, STATUS_NEVER);
|
||||
/*0x45F*/ DEFINE_HANDLER(CMSG_CALENDAR_EVENT_INVITE_NOTES, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x460*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_CALENDAR_EVENT_INVITE_NOTES, STATUS_NEVER);
|
||||
@ -1359,9 +1359,9 @@ void OpcodeTable::Initialize()
|
||||
/*0x4CC*/ DEFINE_HANDLER(CMSG_END_BATTLEFIELD_CHEAT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x4CD*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MULTIPLE_PACKETS, STATUS_NEVER);
|
||||
/*0x4CE*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_GRAVITY_DISABLE, STATUS_NEVER);
|
||||
/*0x4CF*/ DEFINE_HANDLER(CMSG_MOVE_GRAVITY_DISABLE_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x4CF*/ DEFINE_HANDLER(CMSG_MOVE_GRAVITY_DISABLE_ACK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveFlagChangeOpcode );
|
||||
/*0x4D0*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_GRAVITY_ENABLE, STATUS_NEVER);
|
||||
/*0x4D1*/ DEFINE_HANDLER(CMSG_MOVE_GRAVITY_ENABLE_ACK, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x4D1*/ DEFINE_HANDLER(CMSG_MOVE_GRAVITY_ENABLE_ACK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleMoveFlagChangeOpcode );
|
||||
/*0x4D2*/ DEFINE_SERVER_OPCODE_HANDLER(MSG_MOVE_GRAVITY_CHNG, STATUS_NEVER);
|
||||
/*0x4D3*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_DISABLE, STATUS_NEVER);
|
||||
/*0x4D4*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SPLINE_MOVE_GRAVITY_ENABLE, STATUS_NEVER);
|
||||
@ -1431,7 +1431,7 @@ void OpcodeTable::Initialize()
|
||||
/*0x514*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_SEND_ALL_COMBAT_LOG, STATUS_NEVER);
|
||||
/*0x515*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_OPEN_LFG_DUNGEON_FINDER, STATUS_NEVER);
|
||||
/*0x516*/ DEFINE_SERVER_OPCODE_HANDLER(SMSG_MOVE_SET_COLLISION_HGT, STATUS_NEVER);
|
||||
/*0x517*/ DEFINE_HANDLER(CMSG_MOVE_SET_COLLISION_HGT_ACK, STATUS_UNHANDLED, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x517*/ DEFINE_HANDLER(CMSG_MOVE_SET_COLLISION_HGT_ACK, STATUS_LOGGEDIN, PROCESS_INPLACE, &WorldSession::HandleForceSpeedChangeAck );
|
||||
/*0x518*/ DEFINE_HANDLER(MSG_MOVE_SET_COLLISION_HGT, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x519*/ DEFINE_HANDLER(CMSG_CLEAR_RANDOM_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
/*0x51A*/ DEFINE_HANDLER(CMSG_CLEAR_HOLIDAY_BG_WIN_TIME, STATUS_NEVER, PROCESS_INPLACE, &WorldSession::Handle_NULL );
|
||||
|
||||
@ -417,10 +417,10 @@ public:
|
||||
if (CheckModifySpeed(handler, target, allSpeed, 0.1f, 50.0f))
|
||||
{
|
||||
NotifyModification(handler, target, LANG_YOU_CHANGE_ASPEED, LANG_YOURS_ASPEED_CHANGED, allSpeed);
|
||||
target->SetSpeed(MOVE_WALK, allSpeed);
|
||||
target->SetSpeed(MOVE_RUN, allSpeed);
|
||||
target->SetSpeed(MOVE_SWIM, allSpeed);
|
||||
target->SetSpeed(MOVE_FLIGHT, allSpeed);
|
||||
target->SetSpeed(MOVE_WALK, allSpeed, true);
|
||||
target->SetSpeed(MOVE_RUN, allSpeed, true);
|
||||
target->SetSpeed(MOVE_SWIM, allSpeed, true);
|
||||
target->SetSpeed(MOVE_FLIGHT, allSpeed, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -2566,7 +2566,7 @@ public:
|
||||
me->SetCanFly(false);
|
||||
me->SetDisableGravity(false);
|
||||
me->GetMotionMaster()->MovePoint(POINT_DROP_PLAYER, _destPoint, FORCED_MOVEMENT_NONE, 0.f, false);
|
||||
me->SetDisableGravity(true, true);
|
||||
me->SetDisableGravity(true);
|
||||
me->RemoveUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
break;
|
||||
case EVENT_MOVE_TO_SIPHON_POS:
|
||||
@ -2732,7 +2732,7 @@ class spell_the_lich_king_valkyr_target_search : public SpellScript
|
||||
if (Unit* target = GetHitUnit())
|
||||
{
|
||||
GetCaster()->GetMotionMaster()->MoveCharge(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ() + 4.0f, 42.0f, EVENT_CHARGE);
|
||||
GetCaster()->SetDisableGravity(true, true);
|
||||
GetCaster()->SetDisableGravity(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -528,9 +528,7 @@ public:
|
||||
init.Launch();
|
||||
|
||||
pPlayer->SetUnitMovementFlags(MOVEMENTFLAG_NONE);
|
||||
pPlayer->SetDisableGravity(true, true);
|
||||
|
||||
sScriptMgr->AnticheatSetCanFlybyServer(pPlayer, true);
|
||||
pPlayer->SetDisableGravity(true);
|
||||
|
||||
WorldPacket data(SMSG_SPLINE_MOVE_UNROOT, 8);
|
||||
data << pPlayer->GetPackGUID();
|
||||
@ -941,10 +939,7 @@ public:
|
||||
if (!bUpdatedFlying && timer)
|
||||
{
|
||||
bUpdatedFlying = true;
|
||||
plr->SetDisableGravity(true, true);
|
||||
|
||||
sScriptMgr->AnticheatSetCanFlybyServer(plr, true);
|
||||
sScriptMgr->AnticheatSetUnderACKmount(plr);
|
||||
plr->SetDisableGravity(true);
|
||||
}
|
||||
|
||||
plr->SendMonsterMove(me->GetPositionX() + dist * cos(arcangle), me->GetPositionY() + dist * std::sin(arcangle), me->GetPositionZ(), VORTEX_DEFAULT_DIFF * 2, SPLINEFLAG_FLYING);
|
||||
|
||||
@ -347,7 +347,7 @@ struct boss_kaelthas : public BossAI
|
||||
}
|
||||
else if (point == POINT_AIR)
|
||||
{
|
||||
me->SetDisableGravity(true, false, false); // updating AnimationTier will break drowning animation later
|
||||
me->SetDisableGravity(true); // updating AnimationTier will break drowning animation later
|
||||
}
|
||||
else if (point == POINT_START_LAST_PHASE)
|
||||
{
|
||||
|
||||
@ -109,8 +109,8 @@ bool StartDB()
|
||||
|
||||
DatabaseLoader loader =
|
||||
modules.empty() ? DatabaseLoader("dbimport") :
|
||||
(modules == "all") ? DatabaseLoader("dbimport", DatabaseLoader::DATABASE_NONE, AC_MODULES_LIST) :
|
||||
DatabaseLoader("dbimport", DatabaseLoader::DATABASE_NONE, modules);
|
||||
(modules == "all") ? DatabaseLoader("dbimport", DatabaseLoader::DATABASE_MASK_ALL, AC_MODULES_LIST) :
|
||||
DatabaseLoader("dbimport", DatabaseLoader::DATABASE_MASK_ALL, modules);
|
||||
|
||||
loader
|
||||
.AddDatabase(LoginDatabase, "Login")
|
||||
@ -140,7 +140,8 @@ variables_map GetConsoleArguments(int argc, char** argv, fs::path& configFile)
|
||||
("help,h", "print usage message")
|
||||
("version,v", "print version build info")
|
||||
("dry-run,d", "Dry run")
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_DB_IMPORT_CONFIG))), "use <arg> as configuration file");
|
||||
("config,c", value<fs::path>(&configFile)->default_value(fs::path(sConfigMgr->GetConfigPath() + std::string(_ACORE_DB_IMPORT_CONFIG))), "use <arg> as configuration file")
|
||||
("config-policy", value<std::string>()->value_name("policy"), "override config severity policy (e.g. default=skip,critical_option=fatal)");
|
||||
|
||||
variables_map variablesMap;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user